From a3b3f48741c763fd3acfe08bde5a60f7d69735ad Mon Sep 17 00:00:00 2001 From: Rodja Trappe Date: Sat, 4 Feb 2023 10:20:45 +0100 Subject: [PATCH] manipulating props through looks --- examples/custom_vue_component/counter.py | 2 +- looks_demo.py | 6 ++--- nicegui/__init__.py | 2 +- nicegui/element.py | 11 ++++---- nicegui/elements/audio.py | 10 ++++---- nicegui/elements/badge.py | 6 ++--- nicegui/elements/button.py | 9 +++++-- nicegui/elements/chart.py | 8 +++--- nicegui/elements/choice_element.py | 2 +- nicegui/elements/color_input.py | 4 +-- nicegui/elements/colors.py | 14 +++++------ nicegui/elements/date.py | 2 +- nicegui/elements/expansion.py | 4 +-- nicegui/elements/icon.py | 2 +- nicegui/elements/input.py | 8 +++--- nicegui/elements/interactive_image.py | 4 +-- nicegui/elements/joystick.py | 2 +- nicegui/elements/keyboard.py | 4 +-- nicegui/elements/link.py | 6 ++--- nicegui/elements/log.py | 6 ++--- nicegui/elements/markdown.py | 4 +-- nicegui/elements/menu.py | 4 +-- nicegui/elements/mixins/content_element.py | 2 +- nicegui/elements/mixins/source_element.py | 4 +-- nicegui/elements/mixins/value_element.py | 6 ++--- nicegui/elements/number.py | 6 ++--- nicegui/elements/plot.py | 2 +- nicegui/elements/progress.py | 14 +++++------ nicegui/elements/scene.py | 4 +-- nicegui/elements/select.py | 2 +- nicegui/elements/slider.py | 6 ++--- nicegui/elements/table.py | 6 ++--- nicegui/elements/time.py | 2 +- nicegui/elements/tree.py | 18 +++++++------- nicegui/elements/upload.py | 12 ++++----- nicegui/elements/video.py | 10 ++++---- nicegui/looks.py | 29 ++++++++++++++++++++-- nicegui/page_layout.py | 16 ++++++------ 38 files changed, 144 insertions(+), 115 deletions(-) diff --git a/examples/custom_vue_component/counter.py b/examples/custom_vue_component/counter.py index 5b086118f..589faf5b3 100644 --- a/examples/custom_vue_component/counter.py +++ b/examples/custom_vue_component/counter.py @@ -10,7 +10,7 @@ class Counter(Element): def __init__(self, title: str, *, on_change: Optional[Callable] = None) -> None: super().__init__('counter') - self._props['title'] = title + self.looks._props['title'] = title self.on('change', on_change) def reset(self) -> None: diff --git a/looks_demo.py b/looks_demo.py index ff713460f..ada938070 100755 --- a/looks_demo.py +++ b/looks_demo.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -from nicegui import Looks, ui +from nicegui import ButtonLooks, Looks, ui shared = Looks().width.full().background.secondary() @@ -8,11 +8,11 @@ with ui.card(): ui.label(str(i)) -button_looks = Looks().background.teal(0.9) +button_looks = ButtonLooks().rounded().background.teal(0.9) hover = Looks().text.gray(0.6) with ui.row().looks.add(shared).height.fixed.twenty().background.grey(0.4).align.main_axis.evenly().align.cross_axis.center().element: - ui.button('12').looks.width.fixed.twelve().add(button_looks) + ui.button('12').looks.square().width.fixed.twelve().add(button_looks) ui.button('64').looks.width.fixed.sixty_four().add(button_looks).height.fractional.two_thirds() ui.button('1/6').looks.width.fractional.one_sixth().add(button_looks).on_hover(hover) diff --git a/nicegui/__init__.py b/nicegui/__init__.py index e53ea25ed..8b8e44624 100644 --- a/nicegui/__init__.py +++ b/nicegui/__init__.py @@ -1,4 +1,4 @@ from . import elements, globals, ui from .client import Client -from .looks import Looks +from .looks import ButtonLooks, Looks from .nicegui import app diff --git a/nicegui/element.py b/nicegui/element.py index 49bc17d2e..a3e94de61 100644 --- a/nicegui/element.py +++ b/nicegui/element.py @@ -26,7 +26,6 @@ def __init__(self, tag: str, *, _client: Optional[Client] = None) -> None: self.tag = tag self.looks = Looks(self) self._style: Dict[str, str] = {} - self._props: Dict[str, Any] = {} self._event_listeners: List[EventListener] = [] self._text: str = '' self.slots: Dict[str, Slot] = {} @@ -72,7 +71,7 @@ def to_dict(self) -> Dict: 'tag': self.tag, 'class': self.looks.classes, 'style': self._style, - 'props': self._props, + 'props': self.looks._props, 'events': events, 'text': self._text, 'slots': {name: [child.id for child in slot.children] for name, slot in self.slots.items()}, @@ -138,13 +137,13 @@ def props(self, add: Optional[str] = None, *, remove: Optional[str] = None): ''' needs_update = False for key in self._parse_props(remove): - if key in self._props: + if key in self.looks._props: needs_update = True - del self._props[key] + del self.looks._props[key] for key, value in self._parse_props(add).items(): - if self._props.get(key) != value: + if self.looks._props.get(key) != value: needs_update = True - self._props[key] = value + self.looks._props[key] = value if needs_update: self.update() return self diff --git a/nicegui/elements/audio.py b/nicegui/elements/audio.py index 9ff102604..af18063b8 100644 --- a/nicegui/elements/audio.py +++ b/nicegui/elements/audio.py @@ -20,8 +20,8 @@ def __init__(self, src: str, *, for a list of events you can subscribe to using the generic event subscription `on()`. """ super().__init__('audio') - self._props['src'] = src - self._props['type'] = type - self._props['controls'] = controls - self._props['autoplay'] = autoplay - self._props['muted'] = muted + self.looks._props['src'] = src + self.looks._props['type'] = type + self.looks._props['controls'] = controls + self.looks._props['autoplay'] = autoplay + self.looks._props['muted'] = muted diff --git a/nicegui/elements/badge.py b/nicegui/elements/badge.py index 03d13c44f..ed081ff0e 100644 --- a/nicegui/elements/badge.py +++ b/nicegui/elements/badge.py @@ -16,6 +16,6 @@ def __init__(self, text: str = '', *, :param outline: use 'outline' design (colored text and borders only) (default: False) """ super().__init__(tag='q-badge', text=text) - self._props['color'] = color - self._props['text_color'] = text_color - self._props['outline'] = outline + self.looks._props['color'] = color + self.looks._props['text_color'] = text_color + self.looks._props['outline'] = outline diff --git a/nicegui/elements/button.py b/nicegui/elements/button.py index 0b6f25d4c..d7fe9269b 100644 --- a/nicegui/elements/button.py +++ b/nicegui/elements/button.py @@ -1,6 +1,7 @@ from typing import Callable, Optional from ..events import ClickEventArguments, handle_event +from ..looks import ButtonLooks from .mixins.text_element import TextElement @@ -13,9 +14,13 @@ def __init__(self, text: str = '', *, on_click: Optional[Callable] = None) -> No :param on_click: callback which is invoked when button is pressed """ super().__init__(tag='q-btn', text=text) - self._props['color'] = 'primary' + orig = self.looks + self.looks = ButtonLooks(self) + self.looks.classes = orig.classes + self.looks._props = orig._props + self.looks._props['color'] = 'primary' self.on('click', lambda _: handle_event(on_click, ClickEventArguments(sender=self, client=self.client))) def _text_to_model_text(self, text: str) -> None: - self._props['label'] = text + self.looks._props['label'] = text diff --git a/nicegui/elements/chart.py b/nicegui/elements/chart.py index 6841378fe..17ddb2155 100644 --- a/nicegui/elements/chart.py +++ b/nicegui/elements/chart.py @@ -99,9 +99,9 @@ def __init__(self, options: Dict, *, type: str = 'chart', extras: List[str] = [] :param extras: list of extra dependencies to include (e.g. "annotations", "arc-diagram", "solid-gauge", ...) """ super().__init__('chart') - self._props['type'] = type - self._props['options'] = options - self._props['extras'] = [ + self.looks._props['type'] = type + self.looks._props['options'] = options + self.looks._props['extras'] = [ dependency.import_path for dependency in js_dependencies.values() if dependency.optional and dependency.path.stem in extras and 'chart' in dependency.dependents @@ -109,7 +109,7 @@ def __init__(self, options: Dict, *, type: str = 'chart', extras: List[str] = [] @property def options(self) -> Dict: - return self._props['options'] + return self.looks._props['options'] def update(self) -> None: super().update() diff --git a/nicegui/elements/choice_element.py b/nicegui/elements/choice_element.py index 31ab788b9..ca93f4034 100644 --- a/nicegui/elements/choice_element.py +++ b/nicegui/elements/choice_element.py @@ -19,7 +19,7 @@ def _update_values_and_labels(self) -> None: self._labels = self.options if isinstance(self.options, list) else list(self.options.values()) def _update_options(self) -> None: - self._props['options'] = [{'value': index, 'label': option} for index, option in enumerate(self._labels)] + self.looks._props['options'] = [{'value': index, 'label': option} for index, option in enumerate(self._labels)] def update(self) -> None: self._update_values_and_labels() diff --git a/nicegui/elements/color_input.py b/nicegui/elements/color_input.py index fc6c260cc..0f93a884a 100644 --- a/nicegui/elements/color_input.py +++ b/nicegui/elements/color_input.py @@ -20,9 +20,9 @@ def __init__(self, label: Optional[str] = None, *, """ super().__init__(tag='q-input', value=value, on_value_change=on_change) if label is not None: - self._props['label'] = label + self.looks._props['label'] = label if placeholder is not None: - self._props['placeholder'] = placeholder + self.looks._props['placeholder'] = placeholder with self.add_slot('append'): self.picker = ColorPicker(on_pick=lambda e: self.set_value(e.color)) diff --git a/nicegui/elements/colors.py b/nicegui/elements/colors.py index 668e4a1a7..db746945b 100644 --- a/nicegui/elements/colors.py +++ b/nicegui/elements/colors.py @@ -19,11 +19,11 @@ def __init__(self, *, Sets the main colors (primary, secondary, accent, ...) used by `Quasar `_. """ super().__init__('colors') - self._props['primary'] = primary - self._props['secondary'] = secondary - self._props['accent'] = accent - self._props['positive'] = positive - self._props['negative'] = negative - self._props['info'] = info - self._props['warning'] = warning + self.looks._props['primary'] = primary + self.looks._props['secondary'] = secondary + self.looks._props['accent'] = accent + self.looks._props['positive'] = positive + self.looks._props['negative'] = negative + self.looks._props['info'] = info + self.looks._props['warning'] = warning self.update() diff --git a/nicegui/elements/date.py b/nicegui/elements/date.py index 44be6a0d9..f475861c1 100644 --- a/nicegui/elements/date.py +++ b/nicegui/elements/date.py @@ -27,4 +27,4 @@ def __init__(self, :param on_change: callback to execute when changing the date """ super().__init__(tag='q-date', value=value, on_value_change=on_change) - self._props['mask'] = mask + self.looks._props['mask'] = mask diff --git a/nicegui/elements/expansion.py b/nicegui/elements/expansion.py index a6041a0cc..884eef622 100644 --- a/nicegui/elements/expansion.py +++ b/nicegui/elements/expansion.py @@ -15,8 +15,8 @@ def __init__(self, text: str, *, icon: Optional[str] = None, value: bool = False :param value: whether the expansion should be opened on creation (default: `False`) ''' super().__init__(tag='q-expansion-item', value=value, on_value_change=None) - self._props['label'] = text - self._props['icon'] = icon + self.looks._props['label'] = text + self.looks._props['icon'] = icon def open(self) -> None: self.value = True diff --git a/nicegui/elements/icon.py b/nicegui/elements/icon.py index 9597128bd..52c121824 100644 --- a/nicegui/elements/icon.py +++ b/nicegui/elements/icon.py @@ -13,4 +13,4 @@ def __init__(self, name: str) -> None: :param name: the name of the icon """ super().__init__('q-icon') - self._props['name'] = name + self.looks._props['name'] = name diff --git a/nicegui/elements/input.py b/nicegui/elements/input.py index b2925d5dc..99d18986c 100644 --- a/nicegui/elements/input.py +++ b/nicegui/elements/input.py @@ -31,15 +31,15 @@ def __init__(self, """ super().__init__(tag='q-input', value=value, on_value_change=on_change) if label is not None: - self._props['label'] = label + self.looks._props['label'] = label if placeholder is not None: - self._props['placeholder'] = placeholder - self._props['type'] = 'password' if password else 'text' + self.looks._props['placeholder'] = placeholder + self.looks._props['type'] = 'password' if password else 'text' if password_toggle_button: with self.add_slot('append'): def toggle_type(_): - is_hidden = self._props.get('type') == 'password' + is_hidden = self.looks._props.get('type') == 'password' icon.props(f'name={"visibility" if is_hidden else "visibility_off"}') self.props(f'type={"text" if is_hidden else "password"}') icon = Icon('visibility_off').classes('cursor-pointer').on('click', toggle_type) diff --git a/nicegui/elements/interactive_image.py b/nicegui/elements/interactive_image.py index a5018ab44..a693490d5 100644 --- a/nicegui/elements/interactive_image.py +++ b/nicegui/elements/interactive_image.py @@ -31,8 +31,8 @@ def __init__(self, source: str = '', *, :param cross: whether to show crosshairs (default: `False`) """ super().__init__(tag='interactive_image', source=source, content=content) - self._props['events'] = events - self._props['cross'] = cross + self.looks._props['events'] = events + self.looks._props['cross'] = cross def handle_mouse(msg: Dict) -> None: if on_mouse is None: diff --git a/nicegui/elements/joystick.py b/nicegui/elements/joystick.py index c91f9d774..1609279f9 100644 --- a/nicegui/elements/joystick.py +++ b/nicegui/elements/joystick.py @@ -42,4 +42,4 @@ def __init__(self, *, lambda _: handle_event(on_end, JoystickEventArguments(sender=self, client=self.client, action='end'))) - self._props['options'] = options + self.looks._props['options'] = options diff --git a/nicegui/elements/keyboard.py b/nicegui/elements/keyboard.py index 807e8071a..94e41114b 100644 --- a/nicegui/elements/keyboard.py +++ b/nicegui/elements/keyboard.py @@ -24,8 +24,8 @@ def __init__(self, on_key: Callable, *, active: bool = True, repeating: bool = T super().__init__('keyboard') self.key_handler = on_key self.active = active - self._props['events'] = ['keydown', 'keyup'] - self._props['repeating'] = repeating + self.looks._props['events'] = ['keydown', 'keyup'] + self.looks._props['repeating'] = repeating self.style('display: none') self.on('key', self.handle_key) diff --git a/nicegui/elements/link.py b/nicegui/elements/link.py index 0a60648be..50ba2140d 100644 --- a/nicegui/elements/link.py +++ b/nicegui/elements/link.py @@ -20,8 +20,8 @@ def __init__(self, text: str = '', target: Union[Callable, str] = '#', new_tab: :param new_tab: open link in new tab (default: False) """ super().__init__(tag='a', text=text) - self._props['href'] = target if isinstance(target, str) else globals.page_routes[target] - self._props['target'] = '_blank' if new_tab else '_self' + self.looks._props['href'] = target if isinstance(target, str) else globals.page_routes[target] + self.looks._props['target'] = '_blank' if new_tab else '_self' self.looks.classes.extend(['underline', 'text-blue-500']) @@ -35,4 +35,4 @@ def __init__(self, name: str) -> None: :param name: target name """ super().__init__('a') - self._props['name'] = name + self.looks._props['name'] = name diff --git a/nicegui/elements/log.py b/nicegui/elements/log.py index d092b3914..a16d724de 100644 --- a/nicegui/elements/log.py +++ b/nicegui/elements/log.py @@ -17,13 +17,13 @@ def __init__(self, max_lines: Optional[int] = None) -> None: :param max_lines: maximum number of lines before dropping oldest ones (default: `None`) """ super().__init__('log') - self._props['max_lines'] = max_lines - self._props['lines'] = '' + self.looks._props['max_lines'] = max_lines + self.looks._props['lines'] = '' self.classes('border whitespace-pre font-mono') self.style('opacity: 1 !important; cursor: text !important') self.lines: deque[str] = deque(maxlen=max_lines) def push(self, line: str) -> None: self.lines.extend(line.splitlines()) - self._props['lines'] = '\n'.join(self.lines) + self.looks._props['lines'] = '\n'.join(self.lines) self.run_method('push', line) diff --git a/nicegui/elements/markdown.py b/nicegui/elements/markdown.py index 7c5c8d3ac..4d03f929f 100644 --- a/nicegui/elements/markdown.py +++ b/nicegui/elements/markdown.py @@ -40,8 +40,8 @@ def __init__(self, content: str = '', *, extras: List[str] = ['fenced-code-block def on_content_change(self, content: str) -> None: html = prepare_content(content, extras=' '.join(self.extras)) - if self._props.get('innerHTML') != html: - self._props['innerHTML'] = html + if self.looks._props.get('innerHTML') != html: + self.looks._props['innerHTML'] = html self.update() diff --git a/nicegui/elements/menu.py b/nicegui/elements/menu.py index 8868ebd31..f91c436f1 100644 --- a/nicegui/elements/menu.py +++ b/nicegui/elements/menu.py @@ -16,7 +16,7 @@ def __init__(self, *, value: bool = False) -> None: :param value: whether the menu is already opened (default: `False`) """ super().__init__(tag='q-menu', value=value, on_value_change=None) - self._props['no-parent-event'] = True + self.looks._props['no-parent-event'] = True def open(self) -> None: self.value = True @@ -38,7 +38,7 @@ def __init__(self, text: str = '', on_click: Optional[Callable] = None, *, auto_ """ super().__init__(tag='q-item', text=text) self.menu = globals.get_slot().parent - self._props['clickable'] = True + self.looks._props['clickable'] = True def handle_click(_) -> None: handle_event(on_click, ClickEventArguments(sender=self, client=self.client)) diff --git a/nicegui/elements/mixins/content_element.py b/nicegui/elements/mixins/content_element.py index 9b494d350..2b0ec9640 100644 --- a/nicegui/elements/mixins/content_element.py +++ b/nicegui/elements/mixins/content_element.py @@ -32,5 +32,5 @@ def set_content(self, content: str) -> None: def on_content_change(self, content: str) -> None: if self.CONTENT_PROP == 'innerHTML' and '' in content: raise ValueError('HTML elements must not contain