native-ui/native_ui/abstract/__init__.py

110 lines
3.4 KiB
Python

import native_ui
from typing import Callable, Any
from collections import defaultdict
from enum import Enum
class Layout(Enum):
HORIZONTAL = 0
VERTICAL = 1
def abstract_property(function: Callable):
def fget(self):
return getattr(self, f"_{function.__name__}")
def fset(self, value):
function(self, value)
self.changed(function.__name__)
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
if not hasattr(self, "supported_platforms"):
self.supported_platforms = set()
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:
self.set_property(prop, kwargs[prop])
def set_property(self, property_name: str, value: Any, index: int = None):
if index is None:
setattr(self, property_name, value)
else:
getattr(self, property_name)[index] = value
self.changed(property_name, index=index)
def call(self, property_name: str, *args, **kwargs):
res = getattr(self, property_name)(*args, **kwargs)
self.called(property_name, res, *args, **kwargs)
return res
def native_call(self, property_name: str, *args, **kwargs):
if native_ui.runtime_platform is None:
print("No runtime platform set")
if native_ui.runtime_platform not in self.supported_platforms:
print(f"Platform {native_ui.runtime_platform} not supported by {type(self).__name__}")
else:
return getattr(self, f"{property_name}_{native_ui.runtime_platform}")(*args, **kwargs)
def changed(self, property_name: str, index: int = None):
if self.native is not None:
self.native_call("changed", property_name, index)
def called(self, property_name: str, res: Any, *args, **kwargs):
if self.native is not None:
self.native_call("called", property_name, res, *args, **kwargs)
def build(self, *args, **kwargs):
if self.native is not None:
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)
def __new__(meta, name, bases, dct):
klass = type.__new__(meta, name, bases, dct)
for base in klass.mro()[1:-1]:
meta.__inheritors__[base].append(klass)
return klass
from .button import Button
from .container import Container
from .window import Window
from .application import Application