112 lines
3.9 KiB
Python
112 lines
3.9 KiB
Python
import gi
|
|
from functools import partial, singledispatch
|
|
|
|
from typing import Callable, List
|
|
|
|
from astal.binding import Binding, bind
|
|
from astal.variable import Variable
|
|
|
|
gi.require_version("Astal", "3.0")
|
|
gi.require_version("AstalIO", "0.1")
|
|
gi.require_version("Gtk", "3.0")
|
|
gi.require_version("GObject", "2.0")
|
|
from gi.repository import Astal, Gtk, GObject
|
|
|
|
def astalify(widget: Gtk.Widget):
|
|
class Widget(widget):
|
|
class_name = ''
|
|
|
|
def hook(self, object: GObject.Object, signal_or_callback: str | Callable, callback: Callable = lambda _, x: x):
|
|
if isinstance(signal_or_callback, Callable):
|
|
callback = signal_or_callback
|
|
|
|
if isinstance(object, Variable):
|
|
unsubscribe = object.subscribe(callback)
|
|
|
|
else:
|
|
if isinstance(signal_or_callback, Callable): return
|
|
|
|
if 'notify::' in signal_or_callback:
|
|
id = object.connect(f'{signal_or_callback}', lambda obj, *_: callback(self, object.get_property(signal_or_callback.replace('notify::', '').replace('-', '_')) if signal_or_callback.replace('notify::', '') in [*map(lambda x: x.name, object.list_properties())] else None))
|
|
|
|
else:
|
|
id = object.connect(signal_or_callback, lambda _, value, *args: callback(self, value) if not args else callback(self, value, *args))
|
|
|
|
unsubscribe = lambda _=None: object.disconnect(id)
|
|
|
|
self.connect('destroy', unsubscribe)
|
|
|
|
def toggle_class_name(self, name: str, state: bool | None = None):
|
|
Astal.widget_toggle_class_name(self, name, state if state is not None else not name in Astal.widget_get_class_names(self))
|
|
|
|
@GObject.Property(type=str)
|
|
def class_name(self):
|
|
return ' '.join(Astal.widget_get_class_names(self))
|
|
|
|
@class_name.setter
|
|
def class_name(self, name):
|
|
Astal.widget_set_class_names(self, name.split(' '))
|
|
|
|
@GObject.Property(type=str)
|
|
def css(self):
|
|
return Astal.widget_get_css(self)
|
|
|
|
@css.setter
|
|
def css(self, css: str):
|
|
Astal.widget_set_css(self, css)
|
|
|
|
@GObject.Property(type=str)
|
|
def cursor(self):
|
|
return Astal.widget_get_cursor(self)
|
|
|
|
@cursor.setter
|
|
def cursor(self, cursor: str):
|
|
Astal.widget_set_cursor(self, cursor)
|
|
|
|
@GObject.Property(type=str)
|
|
def click_through(self):
|
|
return Astal.widget_get_click_through(self)
|
|
|
|
@click_through.setter
|
|
def click_through(self, click_through: str):
|
|
Astal.widget_set_click_through(self, click_through)
|
|
|
|
if widget == Astal.Box or widget == Gtk.Box:
|
|
@GObject.Property()
|
|
def children(self):
|
|
return Astal.Box.get_children(self)
|
|
|
|
@children.setter
|
|
def children(self, children):
|
|
Astal.Box.set_children(self, children)
|
|
|
|
def __init__(self, **props):
|
|
super().__init__()
|
|
|
|
if not 'show' in props:
|
|
self.show()
|
|
|
|
else:
|
|
if props['show']:
|
|
self.show()
|
|
|
|
for prop, value in props.items():
|
|
if isinstance(value, Binding):
|
|
self.set_property(prop, value.get())
|
|
unsubscribe = value.subscribe(partial(self.set_property, prop))
|
|
self.connect('destroy', unsubscribe)
|
|
|
|
elif 'on_' == prop[0:3] and isinstance(value, Callable):
|
|
self.connect(prop.replace('on_', '', 1), value)
|
|
|
|
elif prop.replace('_', '-') in map(lambda x: x.name, self.props):
|
|
self.set_property(prop.replace('_', '-'), value)
|
|
|
|
elif prop == 'setup' and isinstance(value, Callable):
|
|
value(self)
|
|
|
|
else:
|
|
self.__setattr__(prop, value)
|
|
|
|
return Widget
|