widgets: init choice_toggle widget

parent 0cb2d2c1
...@@ -144,7 +144,7 @@ class BaseSetting: ...@@ -144,7 +144,7 @@ class BaseSetting:
) )
def _needs_range_map(self): def _needs_range_map(self):
return self.type in ("choice", "choice_entry", "choice_radio", "list_dual", "number") return self.type in ("choice", "choice_entry", "choice_radio", "choice_toggle", "list_dual", "number")
def _build_map_from_range(self, range_value): def _build_map_from_range(self, range_value):
if range_value is None: if range_value is None:
......
from gi.repository import Gtk, Gdk, Adw, GObject
from .BaseWidget import BaseWidget
_css_provider = None
def _ensure_css():
global _css_provider
if _css_provider is not None:
return
_css_provider = Gtk.CssProvider()
_css_provider.load_from_string(
".toggle-choice { min-height: 0; min-width: 0; padding: 5px 12px; }"
)
Gtk.StyleContext.add_provider_for_display(
Gdk.Display.get_default(),
_css_provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION,
)
class _BalancedFlowBox(Gtk.FlowBox):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self._balanced_max = 0
def do_size_allocate(self, width, height, baseline):
first = self.get_first_child()
if first:
_, nat = first.get_preferred_size()
n = 0
child = first
while child:
n += 1
child = child.get_next_sibling()
if n > 1 and nat.width > 0:
spacing = self.get_column_spacing()
m = max(1, (width + spacing) // (nat.width + spacing))
target = n if m >= n else -(-n // -(-n // m))
if target != self._balanced_max:
self._balanced_max = target
self.set_max_children_per_line(target)
Gtk.FlowBox.do_size_allocate(self, width, height, baseline)
class ToggleChoiceWidget(BaseWidget):
def create_row(self):
_ensure_css()
self.row = Adw.PreferencesRow(
activatable=False,
focusable=False
)
content_box = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL,
spacing=6,
margin_top=8,
margin_bottom=8,
margin_start=12,
margin_end=12
)
self.row.set_child(content_box)
title_horizontal_box = Gtk.Box(
orientation=Gtk.Orientation.HORIZONTAL,
hexpand=True,
)
content_box.append(title_horizontal_box)
title_box = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL,
hexpand=True,
spacing=1,
)
title_horizontal_box.append(title_box)
title_label = Gtk.Label(
label=self.setting.name,
halign=Gtk.Align.START,
)
title_box.append(title_label)
if self.setting.help:
subtitle_label = Gtk.Label(
label=self.setting.help,
halign=Gtk.Align.START,
wrap=True,
margin_bottom=4
)
subtitle_label.add_css_class("caption")
subtitle_label.add_css_class("dim-label")
title_box.append(subtitle_label)
self.reset_prefix.set_halign(Gtk.Align.END)
title_horizontal_box.append(self.reset_prefix)
self.flow_box = _BalancedFlowBox(
homogeneous=True,
selection_mode=Gtk.SelectionMode.NONE,
column_spacing=6,
row_spacing=6,
)
content_box.append(self.flow_box)
self.toggle_buttons = {}
self._build_toggles()
self._update_reset_visibility()
return self.row
def on_map_updated(self):
self.toggle_buttons = {}
while child := self.flow_box.get_first_child():
self.flow_box.remove(child)
self._build_toggles()
self._update_reset_visibility()
def _build_toggles(self):
if not self.setting.map:
return
current_value = self.setting._get_backend_value()
group = None
for label, value in self.setting.map.items():
btn = Gtk.ToggleButton(label=str(label), active=(value == current_value))
btn.add_css_class("toggle-choice")
btn.set_hexpand(True)
if group:
btn.set_group(group)
else:
group = btn
handler_id = btn.connect("toggled", self._on_toggled, value)
self.toggle_buttons[value] = (btn, handler_id)
self.flow_box.append(btn)
def update_display(self):
if not self.setting.map:
return
current_value = self.setting._get_backend_value()
for value, (btn, handler_id) in self.toggle_buttons.items():
with GObject.signal_handler_block(btn, handler_id):
btn.set_active(value == current_value)
self._update_reset_visibility()
def _on_toggled(self, button, value):
if button.get_active():
self.setting._set_backend_value(value)
def _on_reset_clicked(self, button):
if self.setting.default is not None:
self.setting._set_backend_value(self.setting.default)
def _update_reset_visibility(self):
if not self.setting.map:
self.reset_button.set_sensitive(False)
return
current_value = self.setting._get_backend_value()
default_value = self.setting.default
self.reset_button.set_sensitive(
current_value != default_value if default_value is not None else False
)
...@@ -18,6 +18,7 @@ from .DualListWidget import DualListWidget ...@@ -18,6 +18,7 @@ from .DualListWidget import DualListWidget
from .ImageChooserWidget import ImageChooserWidget from .ImageChooserWidget import ImageChooserWidget
from .DualImageChooserWidget import DualImageChooserWidget from .DualImageChooserWidget import DualImageChooserWidget
from .FontWidget import FontWidget from .FontWidget import FontWidget
from .ToggleChoiceWidget import ToggleChoiceWidget
import logging import logging
logger = logging.getLogger(f"{__name__}") logger = logging.getLogger(f"{__name__}")
...@@ -31,6 +32,7 @@ class WidgetFactory: ...@@ -31,6 +32,7 @@ class WidgetFactory:
'choice': ChoiceWidget, 'choice': ChoiceWidget,
'choice_entry': ChoiceEntryWidget, 'choice_entry': ChoiceEntryWidget,
'choice_radio': RadioChoiceWidget, 'choice_radio': RadioChoiceWidget,
'choice_toggle': ToggleChoiceWidget,
'theme_chooser': ThemeChooserWidget, 'theme_chooser': ThemeChooserWidget,
'accent_color': AccentColorWidget, 'accent_color': AccentColorWidget,
'boolean': BooleanWidget, 'boolean': BooleanWidget,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment