From 350296073134ef08090aab1e9790404777cdfc3e Mon Sep 17 00:00:00 2001 From: Surferlul Date: Sun, 31 Jul 2022 01:13:00 +0200 Subject: [PATCH] added runtime wiget data, container children setting & widget update function --- example.py | 28 ++++++++++++++++++++++---- native_ui/abstract/__init__.py | 27 +++++++++++++++++++++++++ native_ui/abstract/button.py | 24 +++++----------------- native_ui/abstract/container.py | 15 ++++++++++---- native_ui/abstract/window.py | 22 +++++++++++++++++++- native_ui/impl/gnome/application.py | 10 +++++++--- native_ui/impl/gnome/button.py | 12 ++++++++--- native_ui/impl/gnome/container.py | 29 ++++++++++++++++++--------- native_ui/impl/gnome/window.py | 31 +++++++++++++++++++++++++---- 9 files changed, 151 insertions(+), 47 deletions(-) diff --git a/example.py b/example.py index e4e5a63..854a2f3 100644 --- a/example.py +++ b/example.py @@ -13,6 +13,9 @@ def main(): app = native.Application( window=native.Window( + title="Example native-ui app", + width=350, + height=200, child=native.Container( layout=abstract.Layout.VERTICAL, ) @@ -20,19 +23,36 @@ def main(): ) cont = app.window.child - def on_pressed(button, container): + def window_update(self, container): + splt = self.title.split() + if self.title[-1].isdigit(): + splt = splt[:-1] + else: + splt.append("Buttons:") + splt.append(str(len(container.children))) + self.title = " ".join(splt) + + app.window.update = window_update + app.window.update_args = [cont] + + def on_pressed(self, container, window): print("Hello world") - container.call("add_child", + self.label = f"Clicked {self.runtime_data.get('clicked', 1)}" + self.runtime_data["clicked"] = self.runtime_data.get('clicked', 1) + 1 + container.add_child( native.Button( label="Hello", pressed=on_pressed, - pressed_args=[container] + pressed_args=[container, window] )) + # test removing container children feature + container.children = container.children + window.update() cont.add_child(native.Button( label="Hello", pressed=on_pressed, - pressed_args=[cont], + pressed_args=[cont, app.window], )) app.build() diff --git a/native_ui/abstract/__init__.py b/native_ui/abstract/__init__.py index aff9130..7f7f52f 100644 --- a/native_ui/abstract/__init__.py +++ b/native_ui/abstract/__init__.py @@ -20,6 +20,14 @@ def abstract_property(function: Callable): return property(fget, fset) +def abstract_method(function: Callable): + def wrapper(self, *args, **kwargs): + res = function(self, *args, **kwargs) + self.called(function.__name__, res, *args, **kwargs) + + return wrapper + + class Abstract(object): def __init__(self, platform: str = None): self.is_builder = False @@ -28,6 +36,14 @@ class Abstract(object): if platform is not None: self.supported_platforms.add(platform) self.native = None + if not hasattr(self, "runtime_data"): + self.runtime_data = {} + if not hasattr(self, "update"): + self._update = lambda *args, **kwargs: None + if not hasattr(self, "update_args"): + self.update_args = [] + if not hasattr(self, "update_kwargs"): + self.update_kwargs = {} def set(self, **kwargs): for prop in kwargs: @@ -66,6 +82,17 @@ class Abstract(object): return self.native return self.native_call("build", *args, **kwargs) + @property + def update(self): + def f(*args, **kwargs): + self.call("_update", self, *args, *self.update_args, **kwargs, **self.update_kwargs) + + return f + + @update.setter + def update(self, value): + self._update = value + class __metaclass__(type): __inheritors__ = defaultdict(list) diff --git a/native_ui/abstract/button.py b/native_ui/abstract/button.py index ea3b594..744cc3b 100644 --- a/native_ui/abstract/button.py +++ b/native_ui/abstract/button.py @@ -4,8 +4,8 @@ from typing import Callable class Button(Abstract): def __init__(self, - label: str = "", - pressed: Callable = lambda button: None, + label: str = None, + pressed: Callable = lambda *args, **kwargs: None, pressed_args: list = None, pressed_kwargs: dict = None, platform: str = None): @@ -16,8 +16,8 @@ class Button(Abstract): pressed_args = [] if pressed_kwargs is None: pressed_kwargs = {} - self._pressed_args = pressed_args - self._pressed_kwargs = pressed_kwargs + self.pressed_args = pressed_args + self.pressed_kwargs = pressed_kwargs @abstract_property def label(self, value): @@ -27,19 +27,5 @@ class Button(Abstract): def pressed(self, value): self._pressed = value - @abstract_property - def pressed_args(self, value): - self._pressed_args = value - - def add_pressed_arg(self, value): - self._pressed_args.append(value) - - @abstract_property - def pressed_kwargs(self, value): - self._pressed_kwargs = value - - def set_pressed_kwarg(self, key, value): - self._pressed_kwargs[key] = value - def press(self, *args, **kwargs): - self.call("pressed", *args, *self._pressed_args, **kwargs, **self._pressed_kwargs) + self.call("pressed", self, *args, *self.pressed_args, **kwargs, **self.pressed_kwargs) diff --git a/native_ui/abstract/container.py b/native_ui/abstract/container.py index d5beb65..accd05c 100644 --- a/native_ui/abstract/container.py +++ b/native_ui/abstract/container.py @@ -1,8 +1,8 @@ -from . import Abstract, Layout, abstract_property +from . import Abstract, Layout, abstract_property, abstract_method class Container(Abstract): - def __init__(self, layout: Layout = Layout.HORIZONTAL, children: list = None, platform: str = None): + def __init__(self, layout: Layout = None, children: list = None, platform: str = None): super().__init__(platform=platform) if children is None: children = [] @@ -13,11 +13,18 @@ class Container(Abstract): def layout(self, value): self._layout = value - def get_children(self): - return self._children + @abstract_property + def children(self, value): + # in case for loop manipulates value through reference + value = [child for child in value] + for _ in range(len(self._children)): + self.pop_child(0) + self._children = value + @abstract_method def add_child(self, child): self._children.append(child) + @abstract_method def pop_child(self, index): return self._children.pop(index) diff --git a/native_ui/abstract/window.py b/native_ui/abstract/window.py index 29a997c..f23e49f 100644 --- a/native_ui/abstract/window.py +++ b/native_ui/abstract/window.py @@ -2,10 +2,30 @@ from . import Abstract, abstract_property class Window(Abstract): - def __init__(self, child: Abstract = None, platform: str = None): + def __init__(self, + child: Abstract = None, + title: str = None, + width: int = None, + height: int = None, + platform: str = None): super().__init__(platform=platform) self._child = child + self._title = title + self._width = width + self._height = height @abstract_property def child(self, value): self._child = value + + @abstract_property + def title(self, value): + self._title = value + + @abstract_property + def width(self, value): + self._width = value + + @abstract_property + def height(self, value): + self._height = value diff --git a/native_ui/impl/gnome/application.py b/native_ui/impl/gnome/application.py index 1d46726..8800e2a 100644 --- a/native_ui/impl/gnome/application.py +++ b/native_ui/impl/gnome/application.py @@ -12,11 +12,16 @@ class Application(abstract.Application): super().__init__(*args, **kwargs, platform=platform) def changed_gnome(self, property_name: str, index: int = None): - pass + match property_name: + case "window": self.set_window_gnome() def called_gnome(self, property_name: str, res: Any, *args, **kwargs): pass + def set_window_gnome(self): + if self.window is not None: + self.native.abstract_window = self.window + def build_gnome(self): class GnomeApp(Adw.Application): def __init__(self, **kwargs): @@ -34,8 +39,7 @@ class Application(abstract.Application): self.window.present() self.native = GnomeApp(application_id=gnome.application_id) - if self.window is not None: - self.native.abstract_window = self.window + self.set_window_gnome() return self.native def run_gnome(self, *args, **kwargs): diff --git a/native_ui/impl/gnome/button.py b/native_ui/impl/gnome/button.py index 1964433..83e0777 100644 --- a/native_ui/impl/gnome/button.py +++ b/native_ui/impl/gnome/button.py @@ -11,15 +11,21 @@ class Button(abstract.Button): super().__init__(*args, **kwargs, platform=platform) def changed_gnome(self, property_name: str, index: int = None): - pass + match property_name: + case "label": self.set_label_gnome() def called_gnome(self, property_name: str, res: Any, *args, **kwargs): pass + def set_label_gnome(self): + if self.label is not None: + self.native.set_label(self.label) + def clicked(self, _native_button): - self.call("press", self) + self.call("press") def build_gnome(self): - self.native = Gtk.Button(label=self.label) + self.native = Gtk.Button() self.native.connect('clicked', self.clicked) + self.set_label_gnome() return self.native \ No newline at end of file diff --git a/native_ui/impl/gnome/container.py b/native_ui/impl/gnome/container.py index 6ca94cc..6263c3a 100644 --- a/native_ui/impl/gnome/container.py +++ b/native_ui/impl/gnome/container.py @@ -11,17 +11,28 @@ class Container(abstract.Container): super().__init__(*args, **kwargs, platform=platform) def changed_gnome(self, property_name: str, index: int = None): - pass + match property_name: + case "layout": self.set_layout_gnome() + case "children": self.set_children_gnome() def called_gnome(self, property_name: str, res: Any, *args, **kwargs): - if property_name == "add_child": - self.native.append(args[0].build()) + match property_name: + case "add_child": self.native.append(args[0].build()) + case "pop_child": self.native.remove(res.native) + + def set_layout_gnome(self): + if self.layout is not None: + match self.layout: + case abstract.Layout.HORIZONTAL: self.native.set_orientation(Gtk.Orientation.HORIZONTAL) + case abstract.Layout.VERTICAL: self.native.set_orientation(Gtk.Orientation.VERTICAL) + + def set_children_gnome(self): + for child in self.children: + self.native.append(child.build()) + def build_gnome(self): - orientation = Gtk.Orientation.VERTICAL - if self.layout == abstract.Layout.HORIZONTAL: - orientation = Gtk.Orientation.HORIZONTAL - self.native = Gtk.Box(orientation=orientation) - for child in self.call("get_children"): - self.native.append(child.build()) + self.native = Gtk.Box() + self.set_layout_gnome() + self.set_children_gnome() return self.native \ No newline at end of file diff --git a/native_ui/impl/gnome/window.py b/native_ui/impl/gnome/window.py index efc3e85..34cf5da 100644 --- a/native_ui/impl/gnome/window.py +++ b/native_ui/impl/gnome/window.py @@ -11,14 +11,37 @@ class Window(abstract.Window): super().__init__(*args, **kwargs, platform=platform) def changed_gnome(self, property_name: str, index: int = None): - if "property_name" == "child": - self.native.set_child(self.child.build()) + match property_name: + case "child": self.set_child_gnome() + case "title": self.set_title_gnome() + case "width": self.set_width_gnome() + case "height": self.set_height_gnome() def called_gnome(self, property_name: str, res: Any, *args, **kwargs): pass - def build_gnome(self, app: abstract.Application = None): - self.native = Gtk.ApplicationWindow(application=app) + def set_title_gnome(self): + if self.title is not None: + self.native.set_title(self.title) + + def set_width_gnome(self): + if self.width is not None: + self.native.set_default_size(self.width, + self.native.get_default_size()[1]) + + def set_height_gnome(self): + if self.height is not None: + self.native.set_default_size(self.native.get_default_size()[0], + self.height) + + def set_child_gnome(self): if self.child is not None: self.native.set_child(self.child.build()) + + def build_gnome(self, app: abstract.Application = None): + self.native = Gtk.ApplicationWindow(application=app) + self.set_child_gnome() + self.set_title_gnome() + self.set_width_gnome() + self.set_height_gnome() return self.native \ No newline at end of file