diff --git a/ks_includes/widgets/autogrid.py b/ks_includes/widgets/autogrid.py new file mode 100644 index 00000000..b4b90e48 --- /dev/null +++ b/ks_includes/widgets/autogrid.py @@ -0,0 +1,52 @@ +import gi + +gi.require_version("Gtk", "3.0") +from gi.repository import Gtk + + +class AutoGrid(Gtk.Grid): + """ + A subclass of Gtk.Grid that auto-arranges its children on init + + Args: + items (list): All the widgets to be arranged. + max_columns (int: 4): The maximum number of columns, up to 4. + expand_last (bool: False): expand the last widget to double width. + vertical (bool: False): optimize for vertical orientation. + + Example: + grid = Autogrid([Gtk.Button(), Gtk.Button()]) + """ + + def __init__(self, items=None, max_columns=None, expand_last=False, vertical=False): + super().__init__(row_homogeneous=True, column_homogeneous=True) + if not max_columns: + max_columns = 3 if vertical else 4 + self.expand_last = expand_last + if not items: + return + length = len(items) + if vertical and length < 4: + # Arrange 1 x 4 + columns = 1 + elif length in {4, 2}: + # Arrange 2 x 2 + columns = min(2, max_columns) + elif length in {3, 5, 6}: + # Arrange 3 x 2 + columns = min(3, max_columns) + else: + # Arrange 4 x n + columns = min(4, max_columns) + + for i, widget in enumerate(items): + col = i % columns + row = int(i / columns) + if self.expand_last and (i + 1) == length and length % 2 == 1: + self.attach(widget, col, row, 2, 1) + else: + self.attach(widget, col, row, 1, 1) + + def clear(self): + for i in self.get_children(): + self.remove(i) diff --git a/panels/extrude.py b/panels/extrude.py index b02c331a..39a3a486 100644 --- a/panels/extrude.py +++ b/panels/extrude.py @@ -6,6 +6,7 @@ gi.require_version("Gtk", "3.0") from gi.repository import Gtk, Pango from ks_includes.KlippyGcodes import KlippyGcodes from ks_includes.screen_panel import ScreenPanel +from ks_includes.widgets.autogrid import AutoGrid class Panel(ScreenPanel): @@ -54,14 +55,10 @@ class Panel(ScreenPanel): "panel": "spoolman" }) - self.labels['extruders_menu'] = self._gtk.ScrolledWindow() - self.labels['extruders'] = Gtk.FlowBox(hexpand=True, vexpand=True, homogeneous=True, - selection_mode=Gtk.SelectionMode.NONE, max_children_per_line=4) - self.labels['extruders_menu'].add(self.labels['extruders']) - xbox = Gtk.Box(homogeneous=True) limit = 4 i = 0 + extruder_buttons = [] for extruder in self._printer.get_tools(): if self._printer.extrudercount == 1: self.labels[extruder] = self._gtk.Button("extruder", "") @@ -75,7 +72,11 @@ class Panel(ScreenPanel): xbox.add(self.labels[extruder]) i += 1 else: - self.labels['extruders'].add(self.labels[extruder]) + extruder_buttons.append(self.labels[extruder]) + if extruder_buttons: + self.labels['extruders'] = AutoGrid(extruder_buttons, vertical=self._screen.vertical_mode) + self.labels['extruders_menu'] = self._gtk.ScrolledWindow() + self.labels['extruders_menu'].add(self.labels['extruders']) if self._printer.extrudercount > limit: changer = self._gtk.Button("toolchanger") changer.connect("clicked", self.load_menu, 'extruders', _('Extruders')) diff --git a/panels/menu.py b/panels/menu.py index 344d3306..6294595f 100644 --- a/panels/menu.py +++ b/panels/menu.py @@ -6,6 +6,7 @@ gi.require_version("Gtk", "3.0") from gi.repository import Gtk from jinja2 import Template from ks_includes.screen_panel import ScreenPanel +from ks_includes.widgets.autogrid import AutoGrid class Panel(ScreenPanel): @@ -15,9 +16,9 @@ class Panel(ScreenPanel): self.items = items self.j2_data = self._printer.get_printer_status_data() self.create_menu_items() - self.grid = Gtk.Grid(row_homogeneous=True, column_homogeneous=True) self.scroll = self._gtk.ScrolledWindow() self.scroll.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) + self.autogrid = AutoGrid() def activate(self): self.j2_data = self._printer.get_printer_status_data() @@ -26,42 +27,21 @@ class Panel(ScreenPanel): def add_content(self): for child in self.scroll.get_children(): self.scroll.remove(child) - if self._screen.vertical_mode: - self.scroll.add(self.arrangeMenuItems(self.items, 3)) - else: - self.scroll.add(self.arrangeMenuItems(self.items, 4)) + self.scroll.add(self.arrangeMenuItems(self.items)) if not self.content.get_children(): self.content.add(self.scroll) - def arrangeMenuItems(self, items, columns, expand_last=False): - for child in self.grid.get_children(): - self.grid.remove(child) - length = len(items) - i = 0 + def arrangeMenuItems(self, items, columns=None, expand_last=False): + self.autogrid.clear() + enabled = [] for item in items: key = list(item)[0] if not self.evaluate_enable(item[key]['enable']): logging.debug(f"X > {key}") continue - - if columns == 4: - if length <= 4: - # Arrange 2 x 2 - columns = 2 - elif 4 < length <= 6: - # Arrange 3 x 2 - columns = 3 - - col = i % columns - row = int(i / columns) - - width = height = 1 - if expand_last is True and i + 1 == length and length % 2 == 1: - width = 2 - - self.grid.attach(self.labels[key], col, row, width, height) - i += 1 - return self.grid + enabled.append(self.labels[key]) + self.autogrid.__init__(enabled, columns, expand_last, self._screen.vertical_mode) + return self.autogrid def create_menu_items(self): count = sum(bool(self.evaluate_enable(i[next(iter(i))]['enable'])) for i in self.items) diff --git a/panels/printer_select.py b/panels/printer_select.py index 90556162..907ba7fa 100644 --- a/panels/printer_select.py +++ b/panels/printer_select.py @@ -3,6 +3,7 @@ import gi gi.require_version("Gtk", "3.0") from gi.repository import Gtk, GLib from ks_includes.screen_panel import ScreenPanel +from ks_includes.widgets.autogrid import AutoGrid class Panel(ScreenPanel): @@ -10,33 +11,18 @@ class Panel(ScreenPanel): super().__init__(screen, title) printers = self._config.get_printers() - grid = Gtk.Grid(row_homogeneous=True, column_homogeneous=True) - scroll = self._gtk.ScrolledWindow() - scroll.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) - scroll.add(grid) - self.content.add(scroll) - - length = len(printers) - if length == 4: - # Arrange 2 x 2 - columns = 2 - elif 4 < length <= 6: - # Arrange 3 x 2 - columns = 3 - else: - columns = 4 - + printer_buttons = [] for i, printer in enumerate(printers): name = list(printer)[0] self.labels[name] = self._gtk.Button("extruder", name, f"color{1 + i % 4}") self.labels[name].connect("clicked", self.connect_printer, name) - if self._screen.vertical_mode: - row = i % columns - col = int(i / columns) - else: - col = i % columns - row = int(i / columns) - grid.attach(self.labels[name], col, row, 1, 1) + printer_buttons.append(self.labels[name]) + grid = AutoGrid(printer_buttons, vertical=self._screen.vertical_mode) + + scroll = self._gtk.ScrolledWindow() + scroll.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC) + scroll.add(grid) + self.content.add(scroll) def connect_printer(self, widget, name): self._screen.connect_printer(name)