widgets: init accent_color widget

parent db6f1783
import math
from gi.repository import Gtk, Adw, Gdk
from .BaseWidget import BaseWidget
class AccentColorWidget(BaseWidget):
"""
Widget for choosing GNOME accent colors.
YAML usage:
- name: Accent Color
type: accent_color
gtype: s
backend: gsettings
key: org.gnome.desktop.interface.accent-color
default: blue
"""
ACCENT_COLORS = {
'blue': '#3584e4',
'teal': '#2190a4',
'green': '#3a944a',
'yellow': '#c88800',
'orange': '#ed5b00',
'red': '#e62d42',
'pink': '#d56199',
'purple': '#9141ac',
'slate': '#6f8396',
}
ACCENT_LABEL_KEYS = {
'blue': 'Blue',
'teal': 'Teal',
'green': 'Green',
'yellow': 'Yellow',
'orange': 'Orange',
'red': 'Red',
'pink': 'Pink',
'purple': 'Purple',
'slate': 'Slate',
}
# Максимальный размер кружка
MAX_CIRCLE_SIZE = 36
def create_row(self):
self.row = Adw.PreferencesRow(
activatable=False,
focusable=False
)
content_box = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL,
spacing=12,
margin_top=12,
margin_bottom=12,
margin_start=12,
margin_end=12
)
self.row.set_child(content_box)
header_box = Gtk.Box(
orientation=Gtk.Orientation.HORIZONTAL,
hexpand=True,
)
content_box.append(header_box)
title_box = Gtk.Box(
orientation=Gtk.Orientation.VERTICAL,
hexpand=True,
spacing=2,
)
header_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,
)
subtitle_label.add_css_class("caption")
subtitle_label.add_css_class("dim-label")
title_box.append(subtitle_label)
self.reset_revealer.set_halign(Gtk.Align.END)
header_box.append(self.reset_revealer)
self.circles_box = Gtk.Box(
orientation=Gtk.Orientation.HORIZONTAL,
homogeneous=True,
hexpand=True,
)
content_box.append(self.circles_box)
self.color_circles = {}
self._selected_key = None
self._build_circles()
self._update_reset_visibility()
return self.row
def _get_label(self, color_key):
label_key = self.ACCENT_LABEL_KEYS.get(color_key)
return _(label_key) if label_key else color_key
def _build_circles(self):
self.color_circles = {}
self._selected_key = self.setting._get_backend_value()
for color_key, hex_color in self.ACCENT_COLORS.items():
drawing = self._create_color_circle(color_key, hex_color)
self.circles_box.append(drawing)
self.color_circles[color_key] = drawing
def _create_color_circle(self, color_key, hex_color):
drawing = Gtk.DrawingArea(
hexpand=True,
vexpand=True,
focusable=True,
)
drawing.set_size_request(-1, self.MAX_CIRCLE_SIZE)
drawing.set_draw_func(self._draw_circle, color_key)
drawing.set_tooltip_text(self._get_label(color_key))
click = Gtk.GestureClick()
click.connect("pressed", self._on_circle_clicked, color_key)
drawing.add_controller(click)
key = Gtk.EventControllerKey()
key.connect("key-pressed", self._on_key_pressed, color_key)
drawing.add_controller(key)
drawing.color_key = color_key
drawing.hex_color = hex_color
return drawing
def _draw_circle(self, area, cr, width, height, color_key):
drawing = self.color_circles.get(color_key)
if not drawing:
return
hex_color = drawing.hex_color
is_selected = (color_key == self._selected_key)
rgba = Gdk.RGBA()
rgba.parse(hex_color)
size = min(width, height, self.MAX_CIRCLE_SIZE)
inner_radius = size * 0.375
outer_radius = size * 0.47
ring_width = max(size * 0.06, 1.5)
cx, cy = width / 2, height / 2
if is_selected:
cr.arc(cx, cy, outer_radius, 0, 2 * math.pi)
cr.set_source_rgba(rgba.red, rgba.green, rgba.blue, 1.0)
cr.set_line_width(ring_width)
cr.stroke()
cr.arc(cx, cy, inner_radius, 0, 2 * math.pi)
cr.set_source_rgba(rgba.red, rgba.green, rgba.blue, 1.0)
cr.fill()
def _on_circle_clicked(self, gesture, n_press, x, y, color_key):
self._select_color(color_key)
def _on_key_pressed(self, controller, keyval, keycode, state, color_key):
if keyval in (Gdk.KEY_Return, Gdk.KEY_KP_Enter, Gdk.KEY_space):
self._select_color(color_key)
return True
return False
def _select_color(self, color_key):
self._selected_key = color_key
self.setting._set_backend_value(color_key)
self._update_reset_visibility()
for drawing in self.color_circles.values():
drawing.queue_draw()
def update_display(self):
self._selected_key = self.setting._get_backend_value()
for drawing in self.color_circles.values():
drawing.queue_draw()
self._update_reset_visibility()
def _on_reset_clicked(self, button):
if self.setting.default is not None:
self._select_color(self.setting.default)
def _update_reset_visibility(self):
current_value = self.setting._get_backend_value()
default_value = self.setting.default
self.reset_revealer.set_reveal_child(
current_value != default_value if default_value is not None else False
)
...@@ -3,6 +3,7 @@ from .BooleanWidget import BooleanWidget ...@@ -3,6 +3,7 @@ from .BooleanWidget import BooleanWidget
from .ChoiceWidget import ChoiceWidget from .ChoiceWidget import ChoiceWidget
from .RadioChoiceWidget import RadioChoiceWidget from .RadioChoiceWidget import RadioChoiceWidget
from .ThemeChooserWidget import ThemeChooserWidget from .ThemeChooserWidget import ThemeChooserWidget
from .AccentColorWidget import AccentColorWidget
from .EntryWidget import EntryWidget from .EntryWidget import EntryWidget
from .NumStepper import NumStepper from .NumStepper import NumStepper
from .FileChooser import FileChooser from .FileChooser import FileChooser
...@@ -28,6 +29,7 @@ class WidgetFactory: ...@@ -28,6 +29,7 @@ class WidgetFactory:
'choice': ChoiceWidget, 'choice': ChoiceWidget,
'choice_radio': RadioChoiceWidget, 'choice_radio': RadioChoiceWidget,
'theme_chooser': ThemeChooserWidget, 'theme_chooser': ThemeChooserWidget,
'accent_color': AccentColorWidget,
'boolean': BooleanWidget, 'boolean': BooleanWidget,
'entry': EntryWidget, 'entry': EntryWidget,
'number': NumStepper, 'number': NumStepper,
......
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