def test_multiple_fixed_2(self): grid = GridLayout(column_count=2, row_count=2, spacing=5) grid.set_fixed_column_sizing(0, 101) grid.set_fixed_column_sizing(1, 0) grid.set_fixed_row_sizing(0, 0) grid.set_fixed_row_sizing(1, 93) def create_child(rect): child = self.gui.create(Panel) child.parent = self.parent child.padding = (10, 8, 6, 4) child.margins = (11, 16, 8, 2) child.size = (9999, 9999) grid.add_rect(child, rect) return child child_0_0 = create_child(Rect(0, 0, 1, 1)) child_1_0 = create_child(Rect(1, 0, 1, 1)) child_0_1 = create_child(Rect(0, 1, 1, 1)) child_1_1 = create_child(Rect(1, 1, 1, 1)) grid.layout(self.parent) self.assertEqual(Panel.Rect(2, 3, 101, 18), child_0_0.rect_outer) self.assertEqual(Panel.Rect(108, 3, 19, 18), child_1_0.rect_outer) self.assertEqual(Panel.Rect(2, 8, 101, 93), child_0_1.rect_outer) self.assertEqual(Panel.Rect(108, 8, 19, 93), child_1_1.rect_outer)
def test_multiple_child_2(self): grid = GridLayout(column_count=2, row_count=2, spacing=5) grid.set_child_column_sizing(0) grid.set_child_column_sizing(1) grid.set_child_row_sizing(0) grid.set_child_row_sizing(1) def create_child(rect, size): child = self.gui.create(Panel) child.parent = self.parent child.padding = (10, 8, 6, 4) child.margins = (11, 16, 8, 2) child.size = size grid.add_rect(child, rect) return child child_0_0 = create_child(Rect(0, 0, 1, 1), (58, 31)) child_0_1 = create_child(Rect(0, 1, 1, 1), (61, 31)) child_1_0 = create_child(Rect(1, 0, 1, 2), (25, 87)) grid.layout(self.parent) self.assertEqual(Panel.Rect(2, 3, 80, 50), child_0_0.rect_outer) self.assertEqual(Panel.Rect(2, 58, 80, 50), child_0_1.rect_outer) self.assertEqual(Panel.Rect(87, 3, 44, 105), child_1_0.rect_outer)
def test_single_custom(self): def custom_sizing(area_size, remaining_size): return area_size**0.5 def custom_extra(extra): return extra / 2 grid = GridLayout(spacing=5) grid.set_custom_column_sizing(0, custom_sizing, custom_extra) grid.set_custom_row_sizing(0, custom_sizing, custom_extra) child = self.gui.create(Panel) child.parent = self.parent child.padding = (10, 8, 6, 4) child.margins = (11, 16, 8, 2) child.size = (53, 81) grid.add(child, 0, 0) grid.layout(self.parent) root_width = int(194**0.5) root_height = int(292**0.5) final_width = root_width + int((194 - root_width) / 2) - 19 final_height = root_height + int((292 - root_height) / 2) - 18 self.assertEqual(Panel.Rect(13, 19, final_width, final_height), child.rect)
def test_multiple_custom(self): def custom_sizing_1(area_size, remaining_size): return area_size**0.8 def custom_sizing_2(area_size, remaining_size): return area_size - area_size**0.8 grid = GridLayout(column_count=2, row_count=2, spacing=5) grid.set_custom_column_sizing(0, custom_sizing_1, partial(min, 1)) grid.set_custom_column_sizing(1, custom_sizing_2, partial(min, 1)) grid.set_custom_row_sizing(0, custom_sizing_2, partial(min, 1)) grid.set_custom_row_sizing(1, custom_sizing_1, partial(min, 1)) def create_child(rect): child = self.gui.create(Panel) child.parent = self.parent child.padding = (10, 8, 6, 4) child.margins = (11, 16, 8, 2) child.size = (9999, 9999) grid.add_rect(child, rect) return child child_0_0 = create_child(Rect(0, 0, 1, 1)) child_0_1 = create_child(Rect(0, 1, 1, 1)) child_1_0 = create_child(Rect(1, 0, 1, 1)) child_1_1 = create_child(Rect(1, 1, 1, 1)) grid.layout(self.parent) width_0 = int(custom_sizing_1(189, None)) + 1 width_1 = int(custom_sizing_2(189, None)) height_0 = int(custom_sizing_2(287, None)) + 1 height_1 = int(custom_sizing_1(287, None)) self.assertEqual(Panel.Rect(2, 3, width_0, height_0), child_0_0.rect_outer) self.assertEqual(Panel.Rect(2, 8 + height_0, width_0, height_1), child_0_1.rect_outer) self.assertEqual(Panel.Rect(7 + width_0, 3, width_1, height_0), child_1_0.rect_outer) self.assertEqual( Panel.Rect(7 + width_0, 8 + height_0, width_1, height_1), child_1_1.rect_outer)
def test_bottom(self): self.child_bottom.parent = self.parent self.child_bottom.size = (33, 44) self.layout.dock_bottom(self.child_bottom) self.layout.layout(self.parent) self.assertEqual(Panel.Rect(13, 249, 175, 44), self.child_bottom.rect) self.gui.layout(1000, 1000) self.assertFalse(self.child_bottom.layout_dirty) self.layout.layout(self.parent) self.assertFalse(self.child_bottom.layout_dirty) self.assertFalse(self.parent.layout_dirty) self.assertFalse(self.gui.world.layout_dirty)
def test_top(self): self.child_top.parent = self.parent self.child_top.size = (33, 44) self.layout.dock_top(self.child_top) self.layout.layout(self.parent) self.assertEqual(Panel.Rect(13, 19, 175, 44), self.child_top.rect) self.gui.layout(1000, 1000) self.assertFalse(self.child_top.layout_dirty) self.layout.layout(self.parent) self.assertFalse(self.child_top.layout_dirty) self.assertFalse(self.parent.layout_dirty) self.assertFalse(self.gui.world.layout_dirty)
def test_right(self): self.child_right.parent = self.parent self.child_right.size = (33, 44) self.layout.dock_right(self.child_right) self.layout.layout(self.parent) self.assertEqual(Panel.Rect(155, 19, 33, 274), self.child_right.rect) self.gui.layout(1000, 1000) self.assertFalse(self.child_right.layout_dirty) self.layout.layout(self.parent) self.assertFalse(self.child_right.layout_dirty) self.assertFalse(self.parent.layout_dirty) self.assertFalse(self.gui.world.layout_dirty)
def test_multiple_fill(self): grid = GridLayout(column_count=2, row_count=2, spacing=5) grid.set_percentage_column_sizing(0, 0.3333) grid.set_fill_column_sizing(1) grid.set_fill_row_sizing(0) grid.set_fixed_row_sizing(1, 100) def create_child(rect): child = self.gui.create(Panel) child.parent = self.parent child.padding = (10, 8, 6, 4) child.margins = (11, 16, 8, 2) child.size = (9999, 9999) grid.add_rect(child, rect) return child child_0_0 = create_child(Rect(0, 0, 1, 1)) child_0_1 = create_child(Rect(0, 1, 1, 1)) child_1_0 = create_child(Rect(1, 0, 1, 1)) child_1_1 = create_child(Rect(1, 1, 1, 1)) grid.layout(self.parent) width_0 = int(189 * 0.3333) width_1 = 189 - int(189 * 0.3333) height_0 = 287 - 100 height_1 = 100 self.assertEqual(Panel.Rect(2, 3, width_0, height_0), child_0_0.rect_outer) self.assertEqual(Panel.Rect(2, 8 + height_0, width_0, height_1), child_0_1.rect_outer) self.assertEqual(Panel.Rect(7 + width_0, 3, width_1, height_0), child_1_0.rect_outer) self.assertEqual( Panel.Rect(7 + width_0, 8 + height_0, width_1, height_1), child_1_1.rect_outer)
def test_single_fill(self): grid = GridLayout(spacing=5) grid.set_fill_column_sizing(0) grid.set_fill_row_sizing(0) child = self.gui.create(Panel) child.parent = self.parent child.padding = (10, 8, 6, 4) child.margins = (11, 16, 8, 2) child.size = (53, 81) grid.add(child, 0, 0) grid.layout(self.parent) self.assertEqual(Panel.Rect(13, 19, 175, 274), child.rect)
def layout(self, panel): area = panel.rect_inner.move(-panel.x, -panel.y) for item in self.panels: child = item[0] side = item[1] if side == self.TOP: outer_h = child.rect_outer.h child.rect_outer = Panel.Rect(area.x, area.y, area.w, outer_h) area.shrink(0, outer_h, 0, 0) elif side == self.BOTTOM: outer_h = child.rect_outer.h child.rect_outer = Panel.Rect(area.x, area.bottom - outer_h, area.w, outer_h) area.shrink(0, 0, 0, outer_h) elif side == self.LEFT: outer_w = child.rect_outer.w child.rect_outer = Panel.Rect(area.x, area.y, outer_w, area.h) area.shrink(outer_w, 0, 0, 0) elif side == self.RIGHT: outer_w = child.rect_outer.w child.rect_outer = Panel.Rect(area.right - outer_w, area.y, outer_w, area.h) area.shrink(0, 0, outer_w, 0) elif side == self.FILL: child.rect_outer = Panel.Rect(area.x, area.y, area.w, area.h)
def test_single_percentage(self): grid = GridLayout(spacing=5) grid.set_percentage_column_sizing(0, 0.333) grid.set_percentage_row_sizing(0, 0.8) child = self.gui.create(Panel) child.parent = self.parent child.padding = (10, 8, 6, 4) child.margins = (11, 16, 8, 2) child.size = (53, 81) grid.add(child, 0, 0) grid.layout(self.parent) width = int(self.parent.rect_inner.w * 0.333) - 19 + 1 height = int(self.parent.rect_inner.h * 0.8) - 18 + 1 self.assertEqual(Panel.Rect(13, 19, width, height), child.rect)
def test_single_even(self): # Since even sizing is the default we should make sure it works even # when we don't excplicitly set the columns and rows to even sizing. for default in (True, False): with self.subTest(default=default): grid = GridLayout(spacing=5) if not default: grid.set_even_column_sizing(0) grid.set_even_row_sizing(0) child = self.gui.create(Panel) child.parent = self.parent child.padding = (10, 8, 6, 4) child.margins = (11, 16, 8, 2) child.size = (53, 81) grid.add(child, 0, 0) grid.layout(self.parent) self.assertEqual(Panel.Rect(13, 19, 175, 274), child.rect)
def layout(self, panel): area = (panel.rect_inner.move(-panel.x, -panel.y).shrink( 0, 0, (self.column_count - 1) * self.spacing, (self.row_count - 1) * self.spacing)) column_sizings_by_type = dict() row_sizings_by_type = dict() # Group columns and rows by their sizing types while preserving the order. for column in range(self.column_count): sizing = self.column_sizings.get(column, (self.EVEN, )) group = column_sizings_by_type.get(sizing[0], list()) group.append((column, sizing)) column_sizings_by_type[sizing[0]] = group for row in range(self.row_count): sizing = self.row_sizings.get(row, (self.EVEN, )) group = row_sizings_by_type.get(sizing[0], list()) group.append((row, sizing)) row_sizings_by_type[sizing[0]] = group # Determine column widths and row heights. column_widths = [0 for _ in range(self.column_count)] row_heights = [0 for _ in range(self.row_count)] def calculate_fixed_sizes(sizings_by_type, sizes): for sizing_tuple in sizings_by_type.get(self.FIXED, []): column_or_row, sizing = sizing_tuple sizes[column_or_row] = sizing[1] calculate_fixed_sizes(column_sizings_by_type, column_widths) calculate_fixed_sizes(row_sizings_by_type, row_heights) def calculate_child_sizes(sizings_by_type, sizes, largest_func): for sizing_tuple in sizings_by_type.get(self.CHILD, []): column_or_row, _ = sizing_tuple sizes[column_or_row] = largest_func(column_or_row) calculate_child_sizes(column_sizings_by_type, column_widths, self.widest_child_in_column) calculate_child_sizes(row_sizings_by_type, row_heights, self.tallest_child_in_row) def calculate_percentage_sizes(sizings_by_type, sizes, area_size): for sizing_tuple in sizings_by_type.get(self.PERCENTAGE, []): column_or_row, sizing = sizing_tuple sizes[column_or_row] = int(area_size * sizing[1]) calculate_percentage_sizes(column_sizings_by_type, column_widths, area.w) calculate_percentage_sizes(row_sizings_by_type, row_heights, area.h) def calculate_custom_sizes(sizings_by_type, sizes, area_size, remaining_size): for sizing_tuple in sizings_by_type.get(self.CUSTOM, []): column_or_row, sizing = sizing_tuple sizes[column_or_row] = int(sizing[1](area_size, remaining_size)) calculate_custom_sizes(column_sizings_by_type, column_widths, area.w, area.w - sum(column_widths)) calculate_custom_sizes(row_sizings_by_type, row_heights, area.h, area.h - sum(row_heights)) def calculate_even_sizes(sizings_by_type, sizes, remaining_size): size = int(remaining_size / len(sizings_by_type.get(self.EVEN, [1]))) for sizing_tuple in sizings_by_type.get(self.EVEN, []): column_or_row, _ = sizing_tuple sizes[column_or_row] = size calculate_even_sizes(column_sizings_by_type, column_widths, area.w - sum(column_widths)) calculate_even_sizes(row_sizings_by_type, row_heights, area.h - sum(row_heights)) fill_columns = column_sizings_by_type.get(self.FILL, []) if fill_columns: column_widths[fill_columns[0][0]] = area.w - sum(column_widths) fill_rows = row_sizings_by_type.get(self.FILL, []) if fill_rows: row_heights[fill_rows[0][0]] = area.h - sum(row_heights) # Allocate extra width and height to columns and rows. extra_width = max(area.w - sum(column_widths), 0) extra_height = max(area.h - sum(row_heights), 0) def allocate_extra_percentage(sizings_by_type, sizes, extra): for sizing_tuple in sizings_by_type.get(self.PERCENTAGE, []): column_or_row, _ = sizing_tuple amount = min(extra, 1) sizes[column_or_row] += amount extra -= amount return extra extra_width = allocate_extra_percentage(column_sizings_by_type, column_widths, extra_width) extra_height = allocate_extra_percentage(row_sizings_by_type, row_heights, extra_height) def allocate_extra_custom(sizings_by_type, sizes, extra): for sizing_tuple in sizings_by_type.get(self.CUSTOM, []): column_or_row, sizing = sizing_tuple amount = int(sizing[2](extra)) sizes[column_or_row] += amount extra -= amount return extra extra_width = allocate_extra_custom(column_sizings_by_type, column_widths, extra_width) extra_height = allocate_extra_custom(row_sizings_by_type, row_heights, extra_height) def allocate_extra_even(sizings_by_type, sizes, extra): for sizing_tuple in sizings_by_type.get(self.EVEN, []): column_or_row, _ = sizing_tuple amount = min(extra, 1) sizes[column_or_row] += amount extra -= amount return extra extra_width = allocate_extra_even(column_sizings_by_type, column_widths, extra_width) extra_height = allocate_extra_even(row_sizings_by_type, row_heights, extra_height) # Save column widths and row heights for users to access. self.column_widths = column_widths self.row_heights = row_heights # Position child panels. for rect, panel in self.panels.items(): x = area.x + sum(column_widths[:rect.x]) + rect.x * self.spacing y = area.y + sum(row_heights[:rect.y]) + rect.y * self.spacing width = sum( column_widths[rect.x:rect.right]) + (rect.w - 1) * self.spacing height = sum( row_heights[rect.y:rect.bottom]) + (rect.h - 1) * self.spacing panel.rect_outer = Panel.Rect(x, y, width, height)