Ver código fonte

#107: adding linear and circular progress components

Hannes Römer 2 anos atrás
pai
commit
78f3135368

+ 23 - 0
api_docs_and_examples.py

@@ -7,6 +7,7 @@ import docutils.core
 
 
 from nicegui import ui
 from nicegui import ui
 from nicegui.auto_context import Context
 from nicegui.auto_context import Context
+from nicegui.elements.div import Div
 from nicegui.task_logger import create_task
 from nicegui.task_logger import create_task
 
 
 REGEX_H4 = re.compile(r'<h4.*?>(.*?)</h4>')
 REGEX_H4 = re.compile(r'<h4.*?>(.*?)</h4>')
@@ -315,6 +316,12 @@ To overlay an SVG, make the `viewBox` exactly the size of the image and provide
         line_updates = ui.timer(0.1, update_line_plot, active=False)
         line_updates = ui.timer(0.1, update_line_plot, active=False)
         line_checkbox = ui.checkbox('active').bind_value(line_updates, 'active')
         line_checkbox = ui.checkbox('active').bind_value(line_updates, 'active')
 
 
+    with example(ui.linear_progress):
+        ui.linear_progress(value=0.3)
+
+    with example(ui.circular_progress):
+        ui.circular_progress(value=67.0)
+
     with example(ui.scene):
     with example(ui.scene):
         with ui.scene(width=225, height=225) as scene:
         with ui.scene(width=225, height=225) as scene:
             scene.sphere().material('#4488ff')
             scene.sphere().material('#4488ff')
@@ -540,6 +547,13 @@ Just pass a property of the model as parameter to these methods to create the bi
             def __init__(self):
             def __init__(self):
                 self.number = 1
                 self.number = 1
 
 
+            @property
+            def progress_float(self) -> float:
+                return (self.number - 1) / 2
+            @property
+            def progress(self) -> int:
+                return int(self.progress_float * 100)
+
         demo = Demo()
         demo = Demo()
         v = ui.checkbox('visible', value=True)
         v = ui.checkbox('visible', value=True)
         with ui.column().bind_visibility_from(v, 'value'):
         with ui.column().bind_visibility_from(v, 'value'):
@@ -547,6 +561,15 @@ Just pass a property of the model as parameter to these methods to create the bi
             ui.toggle({1: 'a', 2: 'b', 3: 'c'}).bind_value(demo, 'number')
             ui.toggle({1: 'a', 2: 'b', 3: 'c'}).bind_value(demo, 'number')
             ui.number().bind_value(demo, 'number')
             ui.number().bind_value(demo, 'number')
 
 
+            with ui.linear_progress(target_object=demo, target_name='progress_float') as progress:
+                with Div() as progress_lbl:
+                    progress_lbl.classes(add='absolute-full flex flex-center')
+                    lbl = ui.label(text='number')
+                    lbl.classes('text-center text-subtitle2 text-white')
+                    lbl.bind_text_from(demo, 'progress')
+
+            ui.circular_progress(target_object=demo, target_name='progress')
+
     ui_updates = '''#### UI Updates
     ui_updates = '''#### UI Updates
 
 
 NiceGUI tries to automatically synchronize the state of UI elements with the client, e.g. when a label text, an input value or style/classes/props of an element have changed.
 NiceGUI tries to automatically synchronize the state of UI elements with the client, e.g. when a label text, an input value or style/classes/props of an element have changed.

+ 17 - 0
nicegui/auto_context.py

@@ -74,3 +74,20 @@ class AutoUpdaterForAsyncs:
                 message = yield signal
                 message = yield signal
             except BaseException as err:
             except BaseException as err:
                 send, message = iter_throw, err
                 send, message = iter_throw, err
+
+
+class ContextMixin:
+    """
+    Mixin providing a context manager for additional components.
+    copied from nicegui.elements.group.Group
+    """
+
+    def __enter__(self):
+        self._child_count_on_enter = len(self.view)
+        get_view_stack().append(self.view)
+        return self
+
+    def __exit__(self, *_):
+        get_view_stack().pop()
+        if self._child_count_on_enter != len(self.view):
+            self.update()

+ 12 - 0
nicegui/elements/div.py

@@ -0,0 +1,12 @@
+import justpy as jp
+
+from .element import Element
+from ..auto_context import ContextMixin
+
+
+class Div(Element, ContextMixin):
+
+    def __init__(self, **kwargs):
+        """QDiv Container"""
+        view = jp.QDiv(temp=True, **kwargs)
+        super().__init__(view)

+ 44 - 0
nicegui/elements/progress.py

@@ -0,0 +1,44 @@
+import justpy as jp
+
+from .float_element import FloatElement
+from ..auto_context import ContextMixin
+
+
+class LinearProgress(FloatElement, ContextMixin):
+
+    def __init__(self, *, value: float = 0, target_object=None, target_name=None, **kwargs):
+        """LinearProgress
+
+        An element to create a linear progress bar wrapping
+        `Linear Progress <https://quasar.dev/vue-components/linear-progress>`_ component.
+
+        :param value: the initial value of the field
+        :param target_object: the object to data bind to
+        :param target_name: the field name of the data bound object
+        """
+        view = jp.QLinearProgress(color='primary', style="height: 6em;", value=value, temp=False)
+        super().__init__(view, value=value, on_change=None, **kwargs)
+        if target_object and target_name:
+            self.bind_value_from(target_object=target_object, target_name=target_name)
+
+
+class CircularProgress(FloatElement, ContextMixin):
+
+    def __init__(self, *, value: float = 0, target_object=None, target_name=None, show_value: bool = True,
+                 **kwargs):
+        """CircularProgress
+
+        An element to create a linear progress bar wrapping
+        `Circular Progress <https://quasar.dev/vue-components/circular-progress>`_ component.
+
+        :param value: the initial value of the field
+        :param target_object: the object to data bind to
+        :param target_name: the field name of the data bound object
+        """
+        view = jp.QCircularProgress(color='primary', value=value, temp=False,
+                                    track_color='grey-4',
+                                    center_color='transparent',
+                                    size='xl', show_value=show_value)
+        super().__init__(view, value=value, on_change=None, **kwargs)
+        if target_object and target_name:
+            self.bind_value_from(target_object=target_object, target_name=target_name)

+ 2 - 0
nicegui/ui.py

@@ -41,6 +41,8 @@ class Ui:
     from .elements.notify import Notify as notify
     from .elements.notify import Notify as notify
     from .elements.number import Number as number
     from .elements.number import Number as number
     from .elements.open import open, open_async
     from .elements.open import open, open_async
+    from .elements.progress import LinearProgress as linear_progress
+    from .elements.progress import CircularProgress as circular_progress
     from .elements.radio import Radio as radio
     from .elements.radio import Radio as radio
     from .elements.row import Row as row
     from .elements.row import Row as row
     from .elements.scene import Scene as scene
     from .elements.scene import Scene as scene