qpuiq 0.10__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of qpuiq might be problematic. Click here for more details.

Files changed (103) hide show
  1. PUI/PySide6/__init__.py +49 -0
  2. PUI/PySide6/application.py +58 -0
  3. PUI/PySide6/base.py +222 -0
  4. PUI/PySide6/button.py +21 -0
  5. PUI/PySide6/canvas.py +288 -0
  6. PUI/PySide6/checkbox.py +32 -0
  7. PUI/PySide6/combobox.py +75 -0
  8. PUI/PySide6/dialog.py +72 -0
  9. PUI/PySide6/divider.py +23 -0
  10. PUI/PySide6/image.py +30 -0
  11. PUI/PySide6/label.py +33 -0
  12. PUI/PySide6/layout.py +72 -0
  13. PUI/PySide6/matplotlib.py +23 -0
  14. PUI/PySide6/mdi.py +33 -0
  15. PUI/PySide6/menu.py +85 -0
  16. PUI/PySide6/modal.py +132 -0
  17. PUI/PySide6/progressbar.py +17 -0
  18. PUI/PySide6/radiobutton.py +29 -0
  19. PUI/PySide6/scroll.py +153 -0
  20. PUI/PySide6/splitter.py +25 -0
  21. PUI/PySide6/tab.py +39 -0
  22. PUI/PySide6/table.py +89 -0
  23. PUI/PySide6/text.py +35 -0
  24. PUI/PySide6/textfield.py +62 -0
  25. PUI/PySide6/toolbar.py +57 -0
  26. PUI/PySide6/tree.py +120 -0
  27. PUI/PySide6/window.py +81 -0
  28. PUI/__init__.py +46 -0
  29. PUI/common.py +20 -0
  30. PUI/decorator.py +20 -0
  31. PUI/dom.py +238 -0
  32. PUI/flet/__init__.py +21 -0
  33. PUI/flet/application.py +42 -0
  34. PUI/flet/base.py +37 -0
  35. PUI/flet/button.py +20 -0
  36. PUI/flet/canvas.py +86 -0
  37. PUI/flet/checkbox.py +23 -0
  38. PUI/flet/label.py +27 -0
  39. PUI/flet/layout.py +50 -0
  40. PUI/flet/progressbar.py +21 -0
  41. PUI/flet/radiobutton.py +27 -0
  42. PUI/flet/scroll.py +83 -0
  43. PUI/flet/tab.py +42 -0
  44. PUI/flet/text.py +55 -0
  45. PUI/flet/textfield.py +58 -0
  46. PUI/flet/window.py +25 -0
  47. PUI/interfaces.py +97 -0
  48. PUI/node.py +407 -0
  49. PUI/state.py +698 -0
  50. PUI/textual/__init__.py +34 -0
  51. PUI/textual/application.py +82 -0
  52. PUI/textual/base.py +113 -0
  53. PUI/textual/button.py +17 -0
  54. PUI/textual/checkbox.py +21 -0
  55. PUI/textual/label.py +36 -0
  56. PUI/textual/layout.py +48 -0
  57. PUI/textual/progressbar.py +17 -0
  58. PUI/textual/radiobutton.py +24 -0
  59. PUI/textual/scroll.py +72 -0
  60. PUI/textual/tab.py +75 -0
  61. PUI/textual/text.py +32 -0
  62. PUI/textual/textfield.py +49 -0
  63. PUI/textual/window.py +7 -0
  64. PUI/timeline.py +36 -0
  65. PUI/tkinter/__init__.py +43 -0
  66. PUI/tkinter/application.py +49 -0
  67. PUI/tkinter/base.py +68 -0
  68. PUI/tkinter/button.py +15 -0
  69. PUI/tkinter/canvas.py +49 -0
  70. PUI/tkinter/checkbox.py +27 -0
  71. PUI/tkinter/label.py +17 -0
  72. PUI/tkinter/layout.py +114 -0
  73. PUI/tkinter/progressbar.py +17 -0
  74. PUI/tkinter/radiobutton.py +26 -0
  75. PUI/tkinter/scroll.py +201 -0
  76. PUI/tkinter/tab.py +52 -0
  77. PUI/tkinter/text.py +20 -0
  78. PUI/tkinter/textfield.py +53 -0
  79. PUI/tkinter/window.py +51 -0
  80. PUI/utils.py +15 -0
  81. PUI/view.py +161 -0
  82. PUI/wx/__init__.py +19 -0
  83. PUI/wx/application.py +44 -0
  84. PUI/wx/base.py +202 -0
  85. PUI/wx/button.py +16 -0
  86. PUI/wx/canvas.py +255 -0
  87. PUI/wx/checkbox.py +25 -0
  88. PUI/wx/combobox.py +72 -0
  89. PUI/wx/dialog.py +66 -0
  90. PUI/wx/divider.py +19 -0
  91. PUI/wx/label.py +18 -0
  92. PUI/wx/layout.py +46 -0
  93. PUI/wx/progressbar.py +17 -0
  94. PUI/wx/radiobutton.py +27 -0
  95. PUI/wx/scroll.py +44 -0
  96. PUI/wx/text.py +23 -0
  97. PUI/wx/textfield.py +56 -0
  98. PUI/wx/window.py +58 -0
  99. qpuiq-0.10.dist-info/LICENSE.txt +21 -0
  100. qpuiq-0.10.dist-info/METADATA +227 -0
  101. qpuiq-0.10.dist-info/RECORD +103 -0
  102. qpuiq-0.10.dist-info/WHEEL +5 -0
  103. qpuiq-0.10.dist-info/top_level.txt +1 -0
@@ -0,0 +1,34 @@
1
+ from .application import *
2
+ from .button import *
3
+ from .checkbox import *
4
+ from .label import *
5
+ from .layout import *
6
+ from .progressbar import *
7
+ from .radiobutton import *
8
+ from .scroll import *
9
+ from .tab import *
10
+ from .text import *
11
+ from .textfield import *
12
+ from .window import *
13
+ from .. import NotImplementedNode
14
+
15
+ PUIView = TPUIView
16
+
17
+ class DummyWidget(TBase):
18
+ pui_supported = False
19
+ def __init__(self, *args, **kwrgas):
20
+ super().__init__()
21
+
22
+ def update(self, prev):
23
+ if prev and prev.ui:
24
+ self.ui = prev.ui
25
+ else:
26
+ self.ui = widgets.Label("Not Implemented")
27
+
28
+
29
+
30
+ Canvas = DummyWidget
31
+ Combobox = DummyWidget
32
+ ComboboxItem = DummyWidget
33
+
34
+ PUI_BACKEND = "textual"
@@ -0,0 +1,82 @@
1
+ from typing import Type
2
+ from textual.driver import Driver
3
+ from .. import *
4
+ from .base import *
5
+ from textual.app import App, CSSPathType, ComposeResult
6
+ from textual.containers import Vertical
7
+ from textual.widgets import Button, Checkbox, Input, RadioButton, Tabs
8
+
9
+ class PUITextualApp(App):
10
+
11
+ def __init__(self, puiview, driver_class: Type[Driver] = None, css_path: CSSPathType = None, watch_css: bool = False):
12
+ super().__init__(driver_class, css_path, watch_css)
13
+ self.puiview = puiview
14
+
15
+ def on_mount(self) -> None:
16
+ self.puiview.redraw()
17
+
18
+ def on_button_pressed(self, event: Button.Pressed) -> None:
19
+ event.button.puinode.get_node()._clicked()
20
+
21
+ def on_radio_button_changed(self, event: RadioButton.Changed) -> None:
22
+ event.radio_button.puinode.get_node()._changed(event.value)
23
+
24
+ def on_input_changed(self, event: Input.Changed) -> None:
25
+ event.input.puinode.get_node()._changed(event.value)
26
+
27
+ def on_input_submitted(self, event: Input.Submitted) -> None:
28
+ event.input.puinode.get_node()._submitted(event.value)
29
+
30
+ def on_checkbox_changed(self, event: Checkbox.Changed) -> None:
31
+ event.checkbox.puinode.get_node()._changed(event.value)
32
+
33
+ def on_tabs_tab_activated(self, event: Tabs.TabActivated) -> None:
34
+ event.tabs.puinode.get_node()._tab_activated(event)
35
+
36
+ def compose(self) -> ComposeResult:
37
+ yield Vertical(id="frame")
38
+
39
+ class Application(PUIView):
40
+ def __init__(self):
41
+ super().__init__()
42
+ self.ui = PUITextualApp(self)
43
+
44
+ def addChild(self, idx, child):
45
+ if idx>0:
46
+ raise RuntimeError("Textual backend only support single window")
47
+ self.ui.query_one("#frame").mount(child.outer)
48
+
49
+ def redraw(self):
50
+ self.dirty = True
51
+ if self.updating:
52
+ return
53
+ self.updating = True
54
+ self.ui.call_next(self._redraw)
55
+
56
+ def _redraw(self):
57
+ with self.ui.batch_update():
58
+ self.sync()
59
+ self.updating = False
60
+
61
+ def run(self):
62
+ # self.redraw() # need to be after on_mount
63
+ self.start()
64
+
65
+ def start(self):
66
+ self.ui.run()
67
+
68
+
69
+ def PUIApp(func):
70
+ def func_wrapper(*args, **kwargs):
71
+ class PUIAppWrapper(Application):
72
+ def __init__(self, name):
73
+ self.name = name
74
+ super().__init__()
75
+
76
+ def content(self):
77
+ return func(*args, **kwargs)
78
+
79
+ ret = PUIAppWrapper(func.__name__)
80
+ return ret
81
+
82
+ return func_wrapper
PUI/textual/base.py ADDED
@@ -0,0 +1,113 @@
1
+ from .. import *
2
+ from textual import widgets, containers
3
+
4
+ class TBase(PUINode):
5
+ scroll = False
6
+ container_x = False
7
+ container_y = False
8
+ strong_expand_x = False
9
+ strong_expand_y = False
10
+ weak_expand_x = False
11
+ weak_expand_y = False
12
+ nweak_expand_x = False
13
+ nweak_expand_y = False
14
+ strong_expand_x_children = 0
15
+ strong_expand_y_children = 0
16
+
17
+ @property
18
+ def expand_x(self):
19
+ return self.strong_expand_x or (self.weak_expand_x and not self.nweak_expand_x)
20
+
21
+ @property
22
+ def expand_y(self):
23
+ return self.strong_expand_y or (self.weak_expand_y and not self.nweak_expand_y)
24
+
25
+ def tremove(self):
26
+ self.ui.remove()
27
+
28
+ def destroy(self, direct):
29
+ self.ui.remove()
30
+ return super().destroy(direct)
31
+
32
+ def update(self, prev):
33
+ parent = self.tparent
34
+ if parent:
35
+ if not parent.scroll and len(parent.children) == 1:
36
+ if parent.expand_x:
37
+ self.strong_expand_x = True
38
+ if parent.expand_y:
39
+ self.strong_expand_y = True
40
+
41
+ # request expanding from inside
42
+ if parent.container_x:
43
+ if parent.expand_y:
44
+ self.strong_expand_y = True
45
+ if self.layout_weight:
46
+ self.strong_expand_x = True
47
+ parent.strong_expand_x_children += 1
48
+ p = parent
49
+ while p:
50
+ if isinstance(p, TBase):
51
+ p.weak_expand_x = True
52
+ if p==p.parent:
53
+ break
54
+ p = p.parent
55
+
56
+ if parent.container_y:
57
+ if parent.expand_x:
58
+ self.strong_expand_x = True
59
+ if self.layout_weight:
60
+ self.strong_expand_y = True
61
+ parent.strong_expand_y_children += 1
62
+ p = parent
63
+ while p:
64
+ if isinstance(p, TBase):
65
+ p.weak_expand_y = True
66
+ if p==p.parent:
67
+ break
68
+ p = p.parent
69
+
70
+ if parent.strong_expand_x_children > 0:
71
+ self.nweak_expand_x = True
72
+ if parent.strong_expand_y_children > 0:
73
+ self.nweak_expand_y = True
74
+
75
+ else:
76
+ # mark root node as expanding
77
+ self.strong_expand_x = True
78
+ self.strong_expand_y = True
79
+
80
+ super().update(prev)
81
+
82
+ def postUpdate(self):
83
+ super().postUpdate()
84
+ self.t_update_layout()
85
+
86
+ @property
87
+ def tparent(self):
88
+ parent = self.parent
89
+ while not isinstance(parent, TBase):
90
+ if parent==parent.parent:
91
+ parent = None
92
+ break
93
+ parent = parent.parent
94
+ return parent
95
+
96
+ def t_update_layout(self):
97
+ if not self.ui:
98
+ return
99
+
100
+ width = "auto"
101
+ if self.expand_x:
102
+ width = "1fr"
103
+
104
+ height = "auto"
105
+ if self.expand_y:
106
+ height = "1fr"
107
+
108
+ if self._debug:
109
+ print("layout", self.key, f"{width}:{height} expand_x={self.expand_x}", f"expand_y={self.expand_y}", f"strong_x={self.strong_expand_x}", f"weak_x={self.weak_expand_x}", f"hug_x={self.nweak_expand_x}", f"strong_y={self.strong_expand_y}", f"weak_y={self.weak_expand_y}", f"hug_y={self.nweak_expand_y}")
110
+ self.ui.set_styles(f"width:{width};height:{height};")
111
+
112
+ class TPUIView(PUIView):
113
+ pui_virtual = True
PUI/textual/button.py ADDED
@@ -0,0 +1,17 @@
1
+ from .. import *
2
+ from .base import *
3
+
4
+ class Button(TBase):
5
+ def __init__(self, text, callback=None):
6
+ super().__init__()
7
+ self.text = text
8
+ self.callback = callback
9
+
10
+ def update(self, prev):
11
+ if prev and prev.ui:
12
+ self.ui = prev.ui
13
+ self.ui.label = self.text
14
+ else:
15
+ self.ui = widgets.Button(self.text)
16
+ self.ui.puinode = self
17
+ super().update(prev)
@@ -0,0 +1,21 @@
1
+ from .. import *
2
+ from .base import *
3
+
4
+ class Checkbox(TBase):
5
+ def __init__(self, text, model):
6
+ super().__init__()
7
+ self.text = text
8
+ self.model = model
9
+
10
+ def update(self, prev):
11
+ if prev and prev.ui:
12
+ self.ui = prev.ui
13
+ self.ui.value = self.model.value
14
+ else:
15
+ self.ui = widgets.Checkbox(self.text, self.model.value)
16
+
17
+ self.ui.puinode = self
18
+ super().update(prev)
19
+
20
+ def _changed(self, value):
21
+ self.model.value = value
PUI/textual/label.py ADDED
@@ -0,0 +1,36 @@
1
+ from .. import *
2
+ from .base import *
3
+
4
+ class Label(TBase):
5
+ def __init__(self, text, selectable=False):
6
+ super().__init__()
7
+ self.widget = None
8
+ self.text = text
9
+
10
+ def update(self, prev):
11
+ if prev and prev.ui:
12
+ self.ui = prev.ui
13
+ self.widget = prev.widget
14
+ else:
15
+ self.ui = containers.Container()
16
+ self.ui.set_styles("width: auto; height: auto;")
17
+ if self._onClicked:
18
+ if self.widget is None or not isinstance(self.widget, widgets.Button):
19
+ if self.widget:
20
+ self.widget.remove()
21
+ self.widget = widgets.Button(self.text)
22
+ self.widget.set_styles("height: auto; border-top: none; border-bottom: none;")
23
+ self.widget.puinode = self
24
+ else:
25
+ self.widget.label = self.text
26
+ else:
27
+ if self.widget is None or not isinstance(self.widget, widgets.Label):
28
+ if self.widget:
29
+ self.widget.remove()
30
+ self.widget = widgets.Label(self.text, markup=False)
31
+ else:
32
+ self.widget.update(self.text)
33
+ super().update(prev)
34
+
35
+ def postUpdate(self):
36
+ self.ui.mount(self.widget)
PUI/textual/layout.py ADDED
@@ -0,0 +1,48 @@
1
+ from .. import *
2
+ from .base import *
3
+
4
+ class VBox(TBase):
5
+ container_y = True
6
+ def update(self, prev):
7
+ if prev and prev.ui:
8
+ self.ui = prev.ui
9
+ else:
10
+ self.ui = containers.Vertical()
11
+ super().update(prev)
12
+
13
+ def addChild(self, idx, child):
14
+ if isinstance(child, TBase):
15
+ self.inner.mount(child.outer, before=idx)
16
+
17
+ def removeChild(self, idx, child):
18
+ if isinstance(child, TBase):
19
+ child.tremove()
20
+
21
+ class HBox(TBase):
22
+ container_x = True
23
+ def update(self, prev):
24
+ if prev and prev.ui:
25
+ self.ui = prev.ui
26
+ else:
27
+ self.ui = containers.Horizontal()
28
+ super().update(prev)
29
+
30
+ def addChild(self, idx, child):
31
+ if isinstance(child, TBase):
32
+ self.inner.mount(child.outer, before=idx)
33
+
34
+ def removeChild(self, idx, child):
35
+ if isinstance(child, TBase):
36
+ child.tremove()
37
+
38
+ class Spacer(TBase):
39
+ def __init__(self):
40
+ super().__init__()
41
+ self.layout_weight = 1
42
+
43
+ def update(self, prev):
44
+ if prev and prev.ui:
45
+ self.ui = prev.ui
46
+ else:
47
+ self.ui = widgets.Static("")
48
+ super().update(prev)
@@ -0,0 +1,17 @@
1
+ from .. import *
2
+ from .base import *
3
+
4
+ class ProgressBar(TBase):
5
+ def __init__(self, progress, maximum=1):
6
+ super().__init__()
7
+ self.progress = progress*100
8
+ self.maximum = maximum*100
9
+
10
+ def update(self, prev):
11
+ if prev and prev.ui:
12
+ self.ui = prev.ui
13
+ else:
14
+ self.ui = widgets.ProgressBar(total=self.maximum, show_eta=False)
15
+ self.ui.update(total=self.maximum)
16
+ self.ui.progress = self.progress
17
+ super().update(prev)
@@ -0,0 +1,24 @@
1
+ from .. import *
2
+ from .base import *
3
+
4
+ class RadioButton(TBase):
5
+ def __init__(self, text, value, model):
6
+ super().__init__()
7
+ self.text = text
8
+ self.value = value
9
+ self.model = model
10
+
11
+ def update(self, prev):
12
+ if prev and prev.ui:
13
+ self.ui = prev.ui
14
+ else:
15
+ self.ui = widgets.RadioButton(self.text)
16
+ self.ui.puinode = self
17
+ self.ui.value = self.value == self.model.value
18
+ super().update(prev)
19
+
20
+ def _changed(self, value):
21
+ if value:
22
+ self.model.value = self.value
23
+ else:
24
+ self.root.redraw()
PUI/textual/scroll.py ADDED
@@ -0,0 +1,72 @@
1
+ from .. import *
2
+ from .base import *
3
+ import math
4
+
5
+ class Scroll(TBase):
6
+ END = -0.0
7
+ weak_expand_x = True
8
+ weak_expand_y = True
9
+ scroll = True
10
+ def __init__(self, vertical=None, horizontal=False):
11
+ self.vertical = vertical
12
+ self.horizontal = horizontal
13
+ self.align_x = 0
14
+ self.align_y = 0
15
+ super().__init__()
16
+
17
+ def update(self, prev):
18
+ if prev and prev.ui:
19
+ self.ui = prev.ui
20
+ else:
21
+ self.ui = containers.ScrollableContainer()
22
+ v = "auto"
23
+ self.container_y = True
24
+ if self.vertical is True:
25
+ v = "scroll"
26
+ elif self.vertical is False:
27
+ v = "hidden"
28
+ self.container_y = False
29
+ self.nweak_expand_y = True # discard weak_expand_x from self
30
+
31
+ h = "auto"
32
+ self.container_x = True
33
+ if self.horizontal is True:
34
+ h = "scroll"
35
+ elif self.horizontal is False:
36
+ h = "hidden"
37
+ self.container_x = False
38
+ self.nweak_expand_x = True # discard weak_expand_y from self
39
+ self.ui.set_styles(f"overflow-x: {h}; overflow-y: {v};")
40
+
41
+ super().update(prev)
42
+
43
+ def addChild(self, idx, child):
44
+ if isinstance(child, TBase):
45
+ self.inner.mount(child.outer)
46
+ self.t_update_layout()
47
+ else:
48
+ self.addChild(idx, child.children[0])
49
+
50
+ def removeChild(self, idx, child):
51
+ if isinstance(child, TBase):
52
+ child.tremove()
53
+ else:
54
+ self.removeChild(idx, child.children[0])
55
+
56
+ def scrollX(self, pos=0):
57
+ if math.copysign(1, pos) >= 0:
58
+ self.align_x = 0
59
+ self.hsb_offset = pos
60
+ else:
61
+ self.align_x = 1
62
+ self.hsb_offset = abs(pos)
63
+ return self
64
+
65
+ def scrollY(self, pos=0):
66
+ if math.copysign(1, pos) >= 0:
67
+ self.align_y = 0
68
+ self.vsb_offset = pos
69
+ else:
70
+ self.align_y = 1
71
+ self.vsb_offset = abs(pos)
72
+ return self
PUI/textual/tab.py ADDED
@@ -0,0 +1,75 @@
1
+ from .. import *
2
+ from .base import *
3
+
4
+ class Tabs(TBase):
5
+ NORTH = "n"
6
+ SOUTH = "s"
7
+ EAST = "e"
8
+ WEST = "w"
9
+ pui_terminal = False
10
+ def __init__(self, tabposition=NORTH):
11
+ super().__init__()
12
+ self.tabposition = tabposition
13
+ self.tabs = None
14
+ self.current_tab = None
15
+ self._dirty = False
16
+
17
+ def update(self, prev):
18
+ if prev and prev.ui:
19
+ self.current_tab = prev.current_tab
20
+ self.ui = prev.ui
21
+ self.tabhost = prev.tabhost
22
+ self.frame = prev.frame
23
+ self.tabs = prev.tabs
24
+ self.mounted = prev.mounted
25
+ else:
26
+ self.ui = containers.Vertical()
27
+ self.tabhost = containers.Container()
28
+ self.frame = containers.Container()
29
+ self.mounted = False
30
+ super().update(prev)
31
+
32
+ def addChild(self, idx, child):
33
+ if not self.mounted:
34
+ self.ui.mount(self.tabhost)
35
+ self.ui.mount(self.frame)
36
+ self.mounted = True
37
+ self._dirty = True
38
+ child.outer.display = False
39
+ self.frame.mount(child.outer, before=idx)
40
+
41
+
42
+ def removeChild(self, idx, child):
43
+ self.ui.removeTab(idx)
44
+ self._dirty = True
45
+ child.tremove()
46
+
47
+ def postSync(self):
48
+ if self._dirty:
49
+ if self.tabs:
50
+ self.tabs.remove()
51
+ tabs = []
52
+ for c in self.children:
53
+ tab = widgets.Tab(c.label)
54
+ tab.puinode = c
55
+ tabs.append(tab)
56
+ self.tabs = widgets.Tabs(*tabs)
57
+ self.tabs.puinode = self
58
+ self.tabhost.mount(self.tabs)
59
+ self._dirty = False
60
+ super().postSync()
61
+
62
+ def _tab_activated(self, event: widgets.Tabs.TabActivated):
63
+ node = self.get_node()
64
+ if node.current_tab:
65
+ node.current_tab.outer.display = False
66
+ if event.tab:
67
+ tab = event.tab.puinode.get_node()
68
+ tab.outer.display = True
69
+ self.current_tab = tab
70
+
71
+ class Tab(PUINode):
72
+ pui_virtual = True
73
+ def __init__(self, label):
74
+ super().__init__()
75
+ self.label = label
PUI/textual/text.py ADDED
@@ -0,0 +1,32 @@
1
+ from .. import *
2
+ from .base import *
3
+
4
+ class Text(TBase):
5
+ def __init__(self, text, selectable=False):
6
+ super().__init__()
7
+ self.text = text
8
+
9
+ def update(self, prev):
10
+ if prev and prev.ui:
11
+ self.ui = prev.ui
12
+ self.ui.update(self.text)
13
+ else:
14
+ self.ui = widgets.Label(self.text, markup=False)
15
+ super().update(prev)
16
+
17
+ class Html(Text):
18
+ pui_supported = False
19
+
20
+ class MarkDown(TBase):
21
+ weak_expand_x = True
22
+ def __init__(self, text):
23
+ super().__init__()
24
+ self.text = text
25
+
26
+ def update(self, prev):
27
+ if prev and prev.ui:
28
+ self.ui = prev.ui
29
+ self.ui.update(self.text)
30
+ else:
31
+ self.ui = widgets.Markdown(self.text)
32
+ super().update(prev)
@@ -0,0 +1,49 @@
1
+ from .. import *
2
+ from .base import *
3
+
4
+ class TextField(TBase):
5
+ content_width = None
6
+ def __init__(self, model, edit_model=None):
7
+ super().__init__()
8
+ self.model = model
9
+ self.edit_model = edit_model
10
+ self.editing = False
11
+
12
+ def update(self, prev):
13
+ model_value = str(self.model.value)
14
+ if prev and prev.ui:
15
+ self.editing = prev.editing
16
+ self.ui = prev.ui
17
+ self.curr_value = prev.curr_value
18
+
19
+ if self.curr_value.set(model_value) and not self.editing:
20
+ self.ui.value = model_value
21
+ else:
22
+ self.ui = widgets.Input(model_value)
23
+ self.curr_value = Prop(model_value)
24
+
25
+ if self.edit_model and not self.editing:
26
+ self.edit_model.value = model_value
27
+
28
+ self.ui.puinode = self
29
+ super().update(prev)
30
+
31
+
32
+ def _changed(self, value):
33
+ node = self.get_node()
34
+ node.editing = True
35
+ if node.edit_model:
36
+ node.edit_model.value = value
37
+ e = PUIEvent()
38
+ e.value = value
39
+ self._input(e)
40
+
41
+ def _submitted(self, value):
42
+ node = self.get_node()
43
+ node.editing = False
44
+ node.model.value = value
45
+ if node.edit_model:
46
+ node.edit_model.value = value
47
+ e = PUIEvent()
48
+ e.value = value
49
+ self._change(e)
PUI/textual/window.py ADDED
@@ -0,0 +1,7 @@
1
+ from .. import *
2
+ import sys
3
+
4
+ class Window(PUINode):
5
+ pui_virtual = True
6
+ def __init__(self, title=None, size=None, maximize=None, fullscreen=None):
7
+ super().__init__()
PUI/timeline.py ADDED
@@ -0,0 +1,36 @@
1
+ from threading import Timer
2
+ from .view import *
3
+
4
+ class TimelineView(PUINode):
5
+ pui_virtual = True
6
+ def __init__(self, ttl_sec):
7
+ super().__init__()
8
+ self.timer = None
9
+ self.ttl_sec = ttl_sec
10
+
11
+ def update(self, prev):
12
+ if prev and hasattr(prev, "timer"):
13
+ self.timer = prev.timer
14
+ else:
15
+ self.timer = Timer(self.ttl_sec, self.timer_cb)
16
+ self.timer.setDaemon(True)
17
+ self.timer.start()
18
+
19
+ def timer_cb(self):
20
+ if not self.timer:
21
+ return
22
+ node = self.get_node()
23
+ root = node.root
24
+ if not root:
25
+ return
26
+ root.redraw()
27
+ node.timer = Timer(self.ttl_sec, self.timer_cb)
28
+ node.timer.setDaemon(True)
29
+ node.timer.start()
30
+
31
+ def destroy(self, direct):
32
+ timer = self.timer
33
+ self.timer = None
34
+ if timer:
35
+ timer.cancel()
36
+ super().destroy(direct)