584 lines
22 KiB
Python
584 lines
22 KiB
Python
import os
|
|
from typing import Any, Final, Sequence
|
|
|
|
from gi.repository import Gtk, GLib, Gdk
|
|
|
|
from .theme_model import get_theme_model
|
|
from .color import (
|
|
convert_theme_color_to_gdk, mix_theme_colors, mix_gdk_colors, hex_lightness,
|
|
)
|
|
from .gtk_helpers import ScaledImage
|
|
from .preview_terminal import TerminalThemePreview
|
|
from .preview_icons import IconThemePreview
|
|
from .config import FALLBACK_COLOR, DEFAULT_ENCODING
|
|
from .i18n import translate
|
|
from .theme_file import ThemeT
|
|
from .plugin_api import OomoxThemePlugin, OomoxIconsPlugin
|
|
|
|
|
|
WIDGET_SPACING: Final = 10
|
|
|
|
|
|
class CssProviders():
|
|
theme: dict[str, Gtk.CssProvider]
|
|
border: dict[str, Gtk.CssProvider]
|
|
gradient: dict[str, Gtk.CssProvider]
|
|
headerbar_border: Gtk.CssProvider
|
|
wm_border: Gtk.CssProvider
|
|
caret: Gtk.CssProvider
|
|
reset_style: Gtk.CssProvider
|
|
|
|
def __init__(self) -> None:
|
|
self.theme = {}
|
|
self.border = {}
|
|
self.gradient = {}
|
|
self.headerbar_border = Gtk.CssProvider()
|
|
self.headerbar_border.load_from_data((
|
|
"""
|
|
headerbar {
|
|
border: none;
|
|
border-radius: 0;
|
|
}
|
|
"""
|
|
).encode('ascii'))
|
|
self.wm_border = Gtk.CssProvider()
|
|
self.caret = Gtk.CssProvider()
|
|
self.reset_style = Gtk.CssProvider()
|
|
self.reset_style.load_from_data((
|
|
"""
|
|
* {
|
|
box-shadow:none;
|
|
border: none;
|
|
}
|
|
"""
|
|
).encode('ascii'))
|
|
|
|
|
|
class PreviewHeaderbar(Gtk.HeaderBar):
|
|
|
|
title: Gtk.Label
|
|
button: Gtk.Button
|
|
|
|
def __init__(self) -> None:
|
|
super().__init__()
|
|
self.set_show_close_button(False) # type: ignore[arg-type]
|
|
self.title = Gtk.Label(label=translate("Headerbar"))
|
|
self.props.custom_title = self.title # type: ignore[attr-defined]
|
|
self.button = Gtk.Button(label=f' {translate("Button")} ')
|
|
self.pack_end(self.button) # type: ignore[arg-type]
|
|
|
|
|
|
class PreviewWidgets(Gtk.Box):
|
|
|
|
# gtk preview widgets:
|
|
headerbar: PreviewHeaderbar
|
|
menubar: Gtk.MenuBar
|
|
label: Gtk.Label
|
|
sel_label: Gtk.Label
|
|
entry: Gtk.Entry
|
|
preview_imageboxes: dict[str, ScaledImage]
|
|
preview_imageboxes_templates: dict[str, str]
|
|
button: Gtk.Button
|
|
|
|
def __init__(self) -> None:
|
|
super().__init__(orientation=Gtk.Orientation.VERTICAL)
|
|
|
|
self.grid = Gtk.Grid(row_spacing=6, column_spacing=6)
|
|
self.grid.set_margin_top(WIDGET_SPACING // 2)
|
|
self.grid.set_halign(Gtk.Align.CENTER)
|
|
|
|
headerbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
|
|
|
|
self.headerbar = PreviewHeaderbar()
|
|
|
|
self.menubar = Gtk.MenuBar()
|
|
menuitem1 = Gtk.MenuItem(label=translate('File'))
|
|
menuitem1.set_submenu(self.create_menu(3, True))
|
|
self.menubar.append(menuitem1) # type: ignore[attr-defined]
|
|
menuitem2 = Gtk.MenuItem(label=translate('Edit'))
|
|
menuitem2.set_submenu(self.create_menu(6, True))
|
|
self.menubar.append(menuitem2) # type: ignore[attr-defined]
|
|
|
|
headerbox.pack_start(self.headerbar, True, True, 0)
|
|
headerbox.pack_start(self.menubar, True, True, 0) # type: ignore[arg-type]
|
|
|
|
self.label = Gtk.Label(label=translate("This is a label"))
|
|
self.sel_label = Gtk.Label(label=translate("Selected item"))
|
|
self.entry = Gtk.Entry(text=translate("Text entry")) # type: ignore[call-arg]
|
|
self.button = Gtk.Button(label=translate("Button"))
|
|
|
|
self.preview_imageboxes = {}
|
|
self.preview_imageboxes_templates = {}
|
|
self.preview_imageboxes['CHECKBOX'] = ScaledImage(width=16)
|
|
|
|
fake_checkbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
|
|
fake_checkbox.pack_start(self.preview_imageboxes['CHECKBOX'], False, False, 0)
|
|
fake_checkbox.pack_start(self.label, False, False, 0)
|
|
fake_checkbox.set_margin_left(WIDGET_SPACING // 2)
|
|
|
|
self.grid.set_margin_left(WIDGET_SPACING)
|
|
self.grid.set_margin_right(WIDGET_SPACING)
|
|
self.grid.attach(fake_checkbox, 3, 3, 1, 1)
|
|
self.grid.attach_next_to(
|
|
self.sel_label, fake_checkbox, Gtk.PositionType.BOTTOM, 1, 1
|
|
)
|
|
self.grid.attach_next_to(
|
|
self.entry, self.sel_label, Gtk.PositionType.BOTTOM, 1, 1
|
|
)
|
|
self.grid.attach_next_to(
|
|
self.button, self.entry, Gtk.PositionType.BOTTOM, 1, 1
|
|
)
|
|
self.pack_start(headerbox, True, True, 0)
|
|
self.pack_start(self.grid, True, True, 0)
|
|
|
|
def create_menu(self, n_items: int, has_submenus: bool = False) -> Gtk.Menu:
|
|
menu = Gtk.Menu()
|
|
for i in range(0, n_items):
|
|
sensitive = (i + 1) % 3 != 0
|
|
label = translate('Item {id}') if sensitive else translate('Insensitive Item {id}')
|
|
item = Gtk.MenuItem( # type: ignore[call-arg]
|
|
label=label.format(id=i + 1),
|
|
sensitive=sensitive
|
|
)
|
|
menu.append(item)
|
|
if has_submenus and (i + 1) % 2 == 0:
|
|
item.set_submenu(self.create_menu(2))
|
|
return menu
|
|
|
|
def load_imageboxes_templates(self, theme_plugin: OomoxThemePlugin) -> None:
|
|
for icon in theme_plugin.PreviewImageboxesNames:
|
|
template_path = f"{icon.value}.svg.template"
|
|
with open(
|
|
os.path.join(
|
|
theme_plugin.gtk_preview_dir, template_path
|
|
), "rb"
|
|
) as file_object:
|
|
self.preview_imageboxes_templates[icon.name] = \
|
|
file_object.read().decode(DEFAULT_ENCODING)
|
|
|
|
def update_preview_imageboxes(
|
|
self, colorscheme: ThemeT, theme_plugin: OomoxThemePlugin
|
|
) -> None:
|
|
transform_function = theme_plugin.preview_transform_function
|
|
self.load_imageboxes_templates(theme_plugin)
|
|
for icon in theme_plugin.PreviewImageboxesNames:
|
|
new_svg_image = transform_function(
|
|
self.preview_imageboxes_templates[icon.name],
|
|
colorscheme
|
|
).encode('ascii')
|
|
self.preview_imageboxes[icon.name].set_from_bytes(
|
|
new_svg_image, width=theme_plugin.preview_sizes[icon.name]
|
|
)
|
|
|
|
|
|
def _get_menu_widgets(shell: Gtk.MenuShell) -> Sequence[Gtk.Menu | Gtk.MenuShell]:
|
|
""" gets a menu shell (menu or menubar) and all its children """
|
|
children = [shell]
|
|
for child in shell: # type: ignore[attr-defined]
|
|
children.append(child)
|
|
submenu = child.get_submenu()
|
|
if submenu:
|
|
children.extend(_get_menu_widgets(submenu))
|
|
return children
|
|
|
|
|
|
class ThemePreview(Gtk.Grid):
|
|
|
|
BG = 'bg' # pylint: disable=invalid-name
|
|
FG = 'fg' # pylint: disable=invalid-name
|
|
|
|
WM_BORDER_WIDTH: int = 2
|
|
|
|
theme_plugin_name: str | None = None
|
|
css_providers: CssProviders
|
|
|
|
# widget sections:
|
|
background: Gtk.Grid
|
|
gtk_preview: PreviewWidgets
|
|
icons_preview: IconThemePreview | None = None
|
|
terminal_preview: TerminalThemePreview | None = None
|
|
|
|
def __init__(self) -> None:
|
|
super().__init__(row_spacing=6, column_spacing=6)
|
|
self.set_border_width(10)
|
|
self.css_providers = CssProviders()
|
|
self.init_widgets()
|
|
|
|
def init_widgets(self) -> None:
|
|
self.gtk_preview = PreviewWidgets()
|
|
self.background = Gtk.Grid(row_spacing=WIDGET_SPACING, column_spacing=6)
|
|
self.attach(self.background, 1, 1, 3, 1)
|
|
|
|
self.gtk_preview.set_margin_bottom(WIDGET_SPACING)
|
|
self.background.attach(self.gtk_preview, 1, 3, 1, 1)
|
|
|
|
if self.icons_preview:
|
|
self.icons_preview.destroy()
|
|
self.icons_preview = IconThemePreview()
|
|
self.background.attach_next_to(
|
|
self.icons_preview, self.gtk_preview,
|
|
Gtk.PositionType.BOTTOM, 1, 1
|
|
)
|
|
|
|
if self.terminal_preview:
|
|
self.terminal_preview.destroy()
|
|
self.terminal_preview = TerminalThemePreview()
|
|
self.terminal_preview.set_margin_bottom(WIDGET_SPACING)
|
|
self.background.attach_next_to(
|
|
self.terminal_preview, self.icons_preview,
|
|
Gtk.PositionType.BOTTOM, 1, 1
|
|
)
|
|
self.background.set_margin_bottom(WIDGET_SPACING)
|
|
|
|
self.gtk_preview.button.connect("style-updated", self._queue_resize)
|
|
|
|
def override_widget_color(
|
|
self,
|
|
widget: Gtk.Widget,
|
|
value: str,
|
|
color: Gdk.RGBA,
|
|
state: Gtk.StateFlags = Gtk.StateFlags.NORMAL
|
|
) -> None:
|
|
if value == self.BG:
|
|
widget.override_background_color(state, color) # type: ignore[arg-type]
|
|
return
|
|
if value == self.FG:
|
|
widget.override_color(state, color) # type: ignore[arg-type]
|
|
return
|
|
raise NotImplementedError()
|
|
|
|
def update_preview_carets(self, colorscheme: ThemeT) -> None:
|
|
self.css_providers.caret.load_from_data((
|
|
(Gtk.get_minor_version() >= 20 and """
|
|
* {{
|
|
caret-color: #{primary_caret_color};
|
|
-gtk-secondary-caret-color: #{secondary_caret_color};
|
|
-GtkWidget-cursor-aspect-ratio: {caret_aspect_ratio};
|
|
}}
|
|
""" or """
|
|
* {{
|
|
-GtkWidget-cursor-color: #{primary_caret_color};
|
|
-GtkWidget-secondary-cursor-color: #{secondary_caret_color};
|
|
-GtkWidget-cursor-aspect-ratio: {caret_aspect_ratio};
|
|
}}
|
|
""").format(
|
|
primary_caret_color=colorscheme['CARET1_FG'],
|
|
secondary_caret_color=colorscheme['CARET2_FG'],
|
|
caret_aspect_ratio=colorscheme['CARET_SIZE']
|
|
)
|
|
).encode('ascii'))
|
|
Gtk.StyleContext.add_provider(
|
|
self.gtk_preview.entry.get_style_context(),
|
|
self.css_providers.caret,
|
|
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
|
)
|
|
|
|
def update_preview_gradients(self, colorscheme: ThemeT) -> None:
|
|
gradient: float = colorscheme['GRADIENT'] # type: ignore[assignment]
|
|
if gradient == 0:
|
|
self.reset_gradients()
|
|
return
|
|
for widget, color_key in zip(
|
|
[
|
|
self.gtk_preview.button,
|
|
self.gtk_preview.headerbar.button,
|
|
self.gtk_preview.entry,
|
|
self.gtk_preview.headerbar,
|
|
],
|
|
[
|
|
"BTN_BG",
|
|
"HDR_BTN_BG",
|
|
"TXT_BG",
|
|
"HDR_BG"
|
|
]
|
|
):
|
|
color = colorscheme[color_key]
|
|
css_provider_gradient = self.css_providers.gradient.get(color_key)
|
|
if not css_provider_gradient:
|
|
css_provider_gradient = \
|
|
self.css_providers.gradient[color_key] = \
|
|
Gtk.CssProvider()
|
|
css_provider_gradient.load_from_data((
|
|
"""
|
|
* {{
|
|
background-image: linear-gradient(to bottom,
|
|
shade(#{color}, {amount1}),
|
|
shade(#{color}, {amount2})
|
|
);
|
|
}}
|
|
""".format(
|
|
color=color,
|
|
amount1=1 + gradient / 2,
|
|
amount2=1 - gradient / 2,
|
|
)
|
|
).encode('ascii'))
|
|
Gtk.StyleContext.add_provider(
|
|
widget.get_style_context(),
|
|
css_provider_gradient,
|
|
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
|
)
|
|
|
|
def reset_gradients(self) -> None:
|
|
css_provider_gradient = self.css_providers.gradient.get("reset")
|
|
if not css_provider_gradient:
|
|
css_provider_gradient = \
|
|
self.css_providers.gradient["reset"] = \
|
|
Gtk.CssProvider()
|
|
css_provider_gradient.load_from_data((
|
|
"""
|
|
* {
|
|
background-image: none;
|
|
}
|
|
"""
|
|
).encode('ascii'))
|
|
for widget in [
|
|
self.gtk_preview.button,
|
|
self.gtk_preview.headerbar.button,
|
|
self.gtk_preview.entry,
|
|
self.gtk_preview.headerbar,
|
|
]:
|
|
Gtk.StyleContext.add_provider(
|
|
widget.get_style_context(),
|
|
css_provider_gradient,
|
|
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
|
)
|
|
|
|
def update_preview_borders(self, colorscheme: ThemeT) -> None:
|
|
for widget_name, widget, fg, bg, ratio in ( # pylint: disable=invalid-name
|
|
(
|
|
'button',
|
|
self.gtk_preview.button,
|
|
colorscheme['BTN_FG'],
|
|
colorscheme['BTN_BG'],
|
|
0.22
|
|
), (
|
|
'headerbar_button',
|
|
self.gtk_preview.headerbar.button,
|
|
colorscheme['HDR_BTN_FG'],
|
|
colorscheme['HDR_BTN_BG'],
|
|
0.22
|
|
), (
|
|
'entry',
|
|
self.gtk_preview.entry,
|
|
colorscheme['TXT_BG'],
|
|
colorscheme['TXT_FG'],
|
|
0.8 * (0.7 + (
|
|
0 if hex_lightness(colorscheme['TXT_BG']) > 0.66 else ( # type: ignore[arg-type]
|
|
0.1 if hex_lightness(colorscheme['TXT_BG']) > 0.33 else 0.3 # type: ignore[arg-type]
|
|
)
|
|
))
|
|
),
|
|
):
|
|
border_color = mix_theme_colors(fg, bg, ratio) # type: ignore[arg-type]
|
|
css_provider_border_color = self.css_providers.border.get(widget_name)
|
|
if not css_provider_border_color:
|
|
css_provider_border_color = \
|
|
self.css_providers.border[widget_name] = \
|
|
Gtk.CssProvider()
|
|
css_provider_border_color.load_from_data(
|
|
f"""
|
|
* {{
|
|
border-color: #{border_color};
|
|
border-radius: {colorscheme["ROUNDNESS"]}px;
|
|
}}
|
|
""".encode('ascii')
|
|
)
|
|
Gtk.StyleContext.add_provider(
|
|
widget.get_style_context(),
|
|
css_provider_border_color,
|
|
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
|
)
|
|
|
|
def update_preview_colors(self, colorscheme: ThemeT) -> None:
|
|
|
|
converted = {
|
|
theme_value['key']: convert_theme_color_to_gdk(
|
|
colorscheme[theme_value['key']] # type: ignore[arg-type]
|
|
)
|
|
for section in get_theme_model().values()
|
|
for theme_value in section if (
|
|
theme_value['type'] == 'color' and
|
|
not theme_value['key'].startswith('TERMINAL_')
|
|
)
|
|
}
|
|
|
|
def mix(color_id1: str, color_id2: str, amount: float) -> Gdk.RGBA:
|
|
return mix_gdk_colors(converted[color_id2], converted[color_id1], amount)
|
|
|
|
self.override_widget_color(self.background, self.BG, converted["BG"])
|
|
self.override_widget_color(self.gtk_preview.label, self.FG, converted["FG"])
|
|
self.override_widget_color(self.gtk_preview.sel_label, self.FG, converted["SEL_FG"])
|
|
self.override_widget_color(self.gtk_preview.sel_label, self.BG, converted["SEL_BG"])
|
|
self.override_widget_color(self.gtk_preview.entry, self.FG, converted["TXT_FG"])
|
|
self.override_widget_color(self.gtk_preview.entry, self.BG, converted["TXT_BG"])
|
|
self.override_widget_color(
|
|
self.gtk_preview.entry, self.FG, converted["SEL_FG"],
|
|
state=Gtk.StateFlags.SELECTED
|
|
)
|
|
self.override_widget_color(
|
|
self.gtk_preview.entry, self.BG, converted["SEL_BG"],
|
|
state=Gtk.StateFlags.SELECTED
|
|
)
|
|
self.override_widget_color(self.gtk_preview.button, self.FG, converted["BTN_FG"])
|
|
self.override_widget_color(self.gtk_preview.button, self.BG, converted["BTN_BG"])
|
|
for item in self.gtk_preview.menubar.get_children(): # type: ignore[attr-defined]
|
|
self.override_widget_color(item, self.FG, converted["HDR_FG"])
|
|
self.override_widget_color(
|
|
item, self.BG, mix("HDR_BG", "HDR_FG", 0.21),
|
|
state=Gtk.StateFlags.PRELIGHT
|
|
)
|
|
for widget in _get_menu_widgets(item.get_submenu()):
|
|
if isinstance(widget, Gtk.MenuShell):
|
|
self.override_widget_color(widget, self.BG, converted["HDR_BG"])
|
|
self.override_widget_color(widget, self.FG, converted["HDR_FG"])
|
|
else:
|
|
if not widget.get_sensitive(): # :disabled
|
|
color = mix("HDR_FG", "HDR_BG", 0.5)
|
|
else:
|
|
color = converted["HDR_FG"]
|
|
self.override_widget_color(widget, self.FG, color)
|
|
self.override_widget_color(
|
|
widget, self.BG, converted["SEL_BG"],
|
|
state=Gtk.StateFlags.PRELIGHT
|
|
)
|
|
self.override_widget_color(
|
|
widget, self.FG, converted["SEL_FG"],
|
|
state=Gtk.StateFlags.PRELIGHT
|
|
)
|
|
self.override_widget_color(
|
|
self.gtk_preview.menubar, self.BG, converted["HDR_BG"] # type: ignore[arg-type]
|
|
)
|
|
self.override_widget_color(self.gtk_preview.headerbar, self.BG, converted["HDR_BG"])
|
|
self.override_widget_color(self.gtk_preview.headerbar.title, self.FG, converted["HDR_FG"])
|
|
self.override_widget_color(
|
|
self.gtk_preview.headerbar.button, self.FG,
|
|
converted["HDR_BTN_FG"]
|
|
)
|
|
self.override_widget_color(
|
|
self.gtk_preview.headerbar.button, self.BG,
|
|
converted["HDR_BTN_BG"]
|
|
)
|
|
|
|
if self.icons_preview:
|
|
self.override_widget_color(
|
|
self.icons_preview, self.BG,
|
|
converted["TXT_BG"]
|
|
)
|
|
|
|
self.css_providers.wm_border.load_from_data(
|
|
f"""
|
|
* {{
|
|
border-color: #{colorscheme['WM_BORDER_FOCUS']};
|
|
/*border-radius: {colorscheme['ROUNDNESS']}px;*/
|
|
border-width: {self.WM_BORDER_WIDTH}px;
|
|
border-style: solid;
|
|
}}
|
|
""".encode('ascii')
|
|
)
|
|
Gtk.StyleContext.add_provider(
|
|
self.background.get_style_context(),
|
|
self.css_providers.wm_border,
|
|
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
|
)
|
|
|
|
def update_preview(
|
|
self,
|
|
colorscheme: ThemeT,
|
|
theme_plugin: OomoxThemePlugin | None,
|
|
icons_plugin: OomoxIconsPlugin | None,
|
|
) -> None:
|
|
colorscheme_with_fallbacks: ThemeT = {}
|
|
for section in get_theme_model().values():
|
|
for theme_value in section:
|
|
if 'key' not in theme_value:
|
|
continue
|
|
result = colorscheme.get(theme_value['key'])
|
|
if not result and theme_value['type'] == 'color':
|
|
result = FALLBACK_COLOR
|
|
colorscheme_with_fallbacks[theme_value['key']] = result # type: ignore[assignment]
|
|
|
|
if not theme_plugin:
|
|
self.gtk_preview.hide()
|
|
else:
|
|
theme_plugin.preview_before_load_callback(self, colorscheme_with_fallbacks)
|
|
|
|
self.override_css_style(colorscheme_with_fallbacks, theme_plugin)
|
|
self.update_preview_colors(colorscheme_with_fallbacks)
|
|
self.update_preview_borders(colorscheme_with_fallbacks)
|
|
self.update_preview_carets(colorscheme_with_fallbacks)
|
|
self.update_preview_gradients(colorscheme_with_fallbacks)
|
|
self.gtk_preview.update_preview_imageboxes(colorscheme_with_fallbacks, theme_plugin)
|
|
self.gtk_preview.show()
|
|
|
|
if not self.icons_preview:
|
|
raise RuntimeError("Icon preview widget failed to load")
|
|
if not icons_plugin:
|
|
self.icons_preview.hide()
|
|
else:
|
|
self.icons_preview.update_preview(colorscheme_with_fallbacks, icons_plugin)
|
|
self.icons_preview.show()
|
|
|
|
if not self.terminal_preview:
|
|
raise RuntimeError("Terminal preview widget failed to load")
|
|
self.terminal_preview.update_preview(colorscheme_with_fallbacks)
|
|
|
|
def get_theme_css_provider(self, theme_plugin: OomoxThemePlugin) -> Gtk.CssProvider:
|
|
css_dir = theme_plugin.gtk_preview_dir
|
|
|
|
_css_postfix = '20' if Gtk.get_minor_version() >= 20 else ''
|
|
css_name = f"theme{_css_postfix}.css"
|
|
css_path = os.path.join(css_dir, css_name)
|
|
if not os.path.exists(css_path):
|
|
css_path = os.path.join(css_dir, "theme.css")
|
|
|
|
css_provider = self.css_providers.theme.get(css_path)
|
|
if css_provider:
|
|
return css_provider
|
|
css_provider = Gtk.CssProvider()
|
|
try:
|
|
css_provider.load_from_path(css_path) # type: ignore[arg-type]
|
|
except GLib.Error as exc:
|
|
print(exc)
|
|
self.css_providers.theme[css_path] = css_provider
|
|
return css_provider
|
|
|
|
def override_css_style(self, colorscheme: ThemeT, theme_plugin: OomoxThemePlugin) -> None:
|
|
new_theme_plugin_name: str = colorscheme["THEME_STYLE"] # type: ignore[assignment]
|
|
if new_theme_plugin_name == self.theme_plugin_name:
|
|
return
|
|
if self.theme_plugin_name:
|
|
for child in self.get_children():
|
|
self.remove(child)
|
|
child.destroy()
|
|
self.init_widgets()
|
|
self.theme_plugin_name = new_theme_plugin_name
|
|
base_theme_css_provider = self.get_theme_css_provider(theme_plugin)
|
|
|
|
def apply_css(widget: Gtk.Widget) -> None:
|
|
widget_style_context = widget.get_style_context()
|
|
Gtk.StyleContext.add_provider(
|
|
widget_style_context,
|
|
self.css_providers.reset_style,
|
|
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
|
)
|
|
Gtk.StyleContext.add_provider(
|
|
widget_style_context,
|
|
base_theme_css_provider,
|
|
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
|
)
|
|
if isinstance(widget, Gtk.Container):
|
|
widget.forall(apply_css) # type: ignore[arg-type]
|
|
apply_css(self)
|
|
|
|
Gtk.StyleContext.add_provider(
|
|
self.gtk_preview.headerbar.get_style_context(),
|
|
self.css_providers.headerbar_border,
|
|
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
|
|
)
|
|
|
|
self.show_all()
|
|
|
|
def _queue_resize(self, *_args: Any) -> None:
|
|
# print(args)
|
|
self.queue_resize()
|