qpuiq 0.23__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.
Files changed (104) hide show
  1. PUI/PySide6/__init__.py +49 -0
  2. PUI/PySide6/application.py +58 -0
  3. PUI/PySide6/base.py +285 -0
  4. PUI/PySide6/button.py +21 -0
  5. PUI/PySide6/canvas.py +345 -0
  6. PUI/PySide6/checkbox.py +32 -0
  7. PUI/PySide6/combobox.py +85 -0
  8. PUI/PySide6/dialog.py +72 -0
  9. PUI/PySide6/divider.py +23 -0
  10. PUI/PySide6/image.py +48 -0
  11. PUI/PySide6/label.py +33 -0
  12. PUI/PySide6/layout.py +141 -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 +155 -0
  20. PUI/PySide6/splitter.py +25 -0
  21. PUI/PySide6/tab.py +39 -0
  22. PUI/PySide6/table.py +147 -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 +290 -0
  27. PUI/PySide6/window.py +82 -0
  28. PUI/__init__.py +46 -0
  29. PUI/common.py +26 -0
  30. PUI/decorator.py +20 -0
  31. PUI/dom.py +263 -0
  32. PUI/flet/__init__.py +22 -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/divider.py +14 -0
  39. PUI/flet/label.py +27 -0
  40. PUI/flet/layout.py +50 -0
  41. PUI/flet/progressbar.py +21 -0
  42. PUI/flet/radiobutton.py +27 -0
  43. PUI/flet/scroll.py +83 -0
  44. PUI/flet/tab.py +42 -0
  45. PUI/flet/text.py +55 -0
  46. PUI/flet/textfield.py +58 -0
  47. PUI/flet/window.py +25 -0
  48. PUI/interfaces.py +97 -0
  49. PUI/node.py +432 -0
  50. PUI/state.py +711 -0
  51. PUI/textual/__init__.py +35 -0
  52. PUI/textual/application.py +82 -0
  53. PUI/textual/base.py +148 -0
  54. PUI/textual/button.py +17 -0
  55. PUI/textual/checkbox.py +21 -0
  56. PUI/textual/label.py +36 -0
  57. PUI/textual/layout.py +52 -0
  58. PUI/textual/progressbar.py +17 -0
  59. PUI/textual/radiobutton.py +24 -0
  60. PUI/textual/scroll.py +74 -0
  61. PUI/textual/tab.py +75 -0
  62. PUI/textual/text.py +32 -0
  63. PUI/textual/textfield.py +55 -0
  64. PUI/textual/window.py +7 -0
  65. PUI/timeline.py +36 -0
  66. PUI/tkinter/__init__.py +43 -0
  67. PUI/tkinter/application.py +49 -0
  68. PUI/tkinter/base.py +68 -0
  69. PUI/tkinter/button.py +15 -0
  70. PUI/tkinter/canvas.py +52 -0
  71. PUI/tkinter/checkbox.py +27 -0
  72. PUI/tkinter/label.py +17 -0
  73. PUI/tkinter/layout.py +114 -0
  74. PUI/tkinter/progressbar.py +17 -0
  75. PUI/tkinter/radiobutton.py +26 -0
  76. PUI/tkinter/scroll.py +201 -0
  77. PUI/tkinter/tab.py +52 -0
  78. PUI/tkinter/text.py +20 -0
  79. PUI/tkinter/textfield.py +53 -0
  80. PUI/tkinter/window.py +51 -0
  81. PUI/utils.py +15 -0
  82. PUI/view.py +161 -0
  83. PUI/wx/__init__.py +19 -0
  84. PUI/wx/application.py +44 -0
  85. PUI/wx/base.py +246 -0
  86. PUI/wx/button.py +16 -0
  87. PUI/wx/canvas.py +255 -0
  88. PUI/wx/checkbox.py +25 -0
  89. PUI/wx/combobox.py +81 -0
  90. PUI/wx/dialog.py +66 -0
  91. PUI/wx/divider.py +19 -0
  92. PUI/wx/label.py +18 -0
  93. PUI/wx/layout.py +52 -0
  94. PUI/wx/progressbar.py +19 -0
  95. PUI/wx/radiobutton.py +27 -0
  96. PUI/wx/scroll.py +55 -0
  97. PUI/wx/text.py +23 -0
  98. PUI/wx/textfield.py +66 -0
  99. PUI/wx/window.py +64 -0
  100. qpuiq-0.23.dist-info/LICENSE.txt +21 -0
  101. qpuiq-0.23.dist-info/METADATA +234 -0
  102. qpuiq-0.23.dist-info/RECORD +104 -0
  103. qpuiq-0.23.dist-info/WHEEL +5 -0
  104. qpuiq-0.23.dist-info/top_level.txt +1 -0
@@ -0,0 +1,35 @@
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
+ Divider = lambda: None
34
+
35
+ 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()._tchanged(event.value)
26
+
27
+ def on_input_submitted(self, event: Input.Submitted) -> None:
28
+ event.input.puinode.get_node()._tsubmitted(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,148 @@
1
+ from .. import *
2
+ from textual import widgets, containers
3
+
4
+ class TBase(PUINode):
5
+ scroll = False
6
+ container_x = False # axis
7
+ container_y = False # axis
8
+ expand_x_prio = 0
9
+ expand_y_prio = 0
10
+ expand_x1_children = 0
11
+ expand_x2_children = 0
12
+ expand_x3_children = 0
13
+ expand_x4_children = 0
14
+ expand_y1_children = 0
15
+ expand_y2_children = 0
16
+ expand_y3_children = 0
17
+ expand_y4_children = 0
18
+ cached_tparent = None
19
+
20
+ @property
21
+ def expand_x(self):
22
+ parent = self.cached_tparent
23
+ expand = self.expand_x_prio
24
+ if not parent:
25
+ return False
26
+
27
+ # textual handles 1fr as shrinkable, but we need scrolller's content not to shrink
28
+ # See Exp.1 in refs/textual_layout.py
29
+ if parent.scroll:
30
+ return False
31
+
32
+ # textual populates auto(1fr) to be 1fr(1fr), but we require expanding not to go over the container
33
+ # See Exp.2 in refs/textual_layout.py
34
+ if not parent.expand_x and expand < 3:
35
+ return False
36
+
37
+ return expand
38
+
39
+ @property
40
+ def expand_y(self):
41
+ parent = self.cached_tparent
42
+ expand = self.expand_y_prio
43
+ if not parent:
44
+ return False
45
+
46
+ # textual handles 1fr as shrinkable, but we need scrolller's content not to shrink
47
+ # See Exp.1 in refs/textual_layout.py
48
+ if parent.scroll:
49
+ return False
50
+
51
+ # textual populates auto(1fr) to be 1fr(1fr), but we require expanding not to go over the container
52
+ # See Exp.2 in refs/textual_layout.py
53
+ if not parent.expand_y and expand < 3:
54
+ return False
55
+
56
+ return expand
57
+
58
+ def tremove(self):
59
+ self.ui.remove()
60
+
61
+ def destroy(self, direct):
62
+ self.ui.remove()
63
+ return super().destroy(direct)
64
+
65
+ def update(self, prev):
66
+ super().update(prev)
67
+
68
+ self.cached_tparent = parent = self.tparent
69
+ if parent:
70
+ if self.layout_weight:
71
+ if parent.container_x:
72
+ self.expand_x_prio = 4
73
+ if parent.container_y:
74
+ self.expand_y_prio = 4
75
+
76
+ if self.expand_x_prio >= 1:
77
+ parent.expand_x1_children += 1
78
+ if self.expand_x_prio >= 2:
79
+ parent.expand_x2_children += 1
80
+ if self.expand_x_prio >= 3:
81
+ parent.expand_x3_children += 1
82
+ if self.expand_x_prio >= 4:
83
+ parent.expand_x4_children += 1
84
+
85
+ if self.expand_y_prio >= 1:
86
+ parent.expand_y1_children += 1
87
+ if self.expand_y_prio >= 2:
88
+ parent.expand_y2_children += 1
89
+ if self.expand_y_prio >= 3:
90
+ parent.expand_y3_children += 1
91
+ if self.expand_y_prio >= 4:
92
+ parent.expand_y4_children += 1
93
+
94
+ def postUpdate(self):
95
+ super().postUpdate()
96
+ parent = self.cached_tparent
97
+ if parent:
98
+ if parent.container_x:
99
+ if self.expand_x_prio < 1 and parent.expand_x1_children > 0:
100
+ self.expand_x_prio = 0
101
+ if self.expand_x_prio < 2 and parent.expand_x2_children > 0:
102
+ self.expand_x_prio = 0
103
+ if self.expand_x_prio < 3 and parent.expand_x3_children > 0:
104
+ self.expand_x_prio = 0
105
+ if self.expand_x_prio < 4 and parent.expand_x4_children > 0:
106
+ self.expand_x_prio = 0
107
+
108
+ if parent.container_y:
109
+ if self.expand_y_prio < 1 and parent.expand_y1_children > 0:
110
+ self.expand_y_prio = 0
111
+ if self.expand_y_prio < 2 and parent.expand_y2_children > 0:
112
+ self.expand_y_prio = 0
113
+ if self.expand_y_prio < 3 and parent.expand_y3_children > 0:
114
+ self.expand_y_prio = 0
115
+ if self.expand_y_prio < 4 and parent.expand_y4_children > 0:
116
+ self.expand_y_prio = 0
117
+
118
+ self.t_update_layout()
119
+
120
+ @property
121
+ def tparent(self):
122
+ parent = self.parent
123
+ while not isinstance(parent, TBase):
124
+ if parent==parent.parent:
125
+ parent = None
126
+ break
127
+ parent = parent.parent
128
+ return parent
129
+
130
+ def t_update_layout(self):
131
+ if not self.ui:
132
+ return
133
+
134
+ width = "auto"
135
+ if self.expand_x:
136
+ width = "1fr"
137
+
138
+ height = "auto"
139
+ if self.expand_y:
140
+ height = "1fr"
141
+
142
+ if self._debug:
143
+ print("layout", self.key, f"{width}:{height} expand_x={self.expand_x}", f"expand_y={self.expand_y}", f"expand_x_prio={self.expand_x_prio}", f"expand_y_prio={self.expand_y_prio}")
144
+ self.ui.styles.width = width
145
+ self.ui.styles.height = height
146
+
147
+ class TPUIView(PUIView):
148
+ 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
+ if self._onClicked:
17
+ if self.widget is None or not isinstance(self.widget, widgets.Button):
18
+ if self.widget:
19
+ self.widget.remove()
20
+ self.widget = widgets.Button(self.text)
21
+ self.widget.set_styles("border-top: none; border-bottom: none;")
22
+ self.widget.puinode = self
23
+ else:
24
+ self.widget.label = self.text
25
+ else:
26
+ if self.widget is None or not isinstance(self.widget, widgets.Label):
27
+ if self.widget:
28
+ self.widget.remove()
29
+ self.widget = widgets.Label(self.text, markup=False)
30
+ else:
31
+ self.widget.update(self.text)
32
+ super().update(prev)
33
+
34
+ def postUpdate(self):
35
+ super().postUpdate()
36
+ self.ui.mount(self.widget)
PUI/textual/layout.py ADDED
@@ -0,0 +1,52 @@
1
+ from .. import *
2
+ from .base import *
3
+
4
+ class VBox(TBase):
5
+ container_y = True
6
+ expand_x_prio = 1
7
+ expand_y_prio = 2
8
+ def update(self, prev):
9
+ if prev and prev.ui:
10
+ self.ui = prev.ui
11
+ else:
12
+ self.ui = containers.Vertical()
13
+ super().update(prev)
14
+
15
+ def addChild(self, idx, child):
16
+ if isinstance(child, TBase):
17
+ self.inner.mount(child.outer, before=idx)
18
+
19
+ def removeChild(self, idx, child):
20
+ if isinstance(child, TBase):
21
+ child.tremove()
22
+
23
+ class HBox(TBase):
24
+ container_x = True
25
+ expand_x_prio = 2
26
+ expand_y_prio = 1
27
+ def update(self, prev):
28
+ if prev and prev.ui:
29
+ self.ui = prev.ui
30
+ else:
31
+ self.ui = containers.Horizontal()
32
+ super().update(prev)
33
+
34
+ def addChild(self, idx, child):
35
+ if isinstance(child, TBase):
36
+ self.inner.mount(child.outer, before=idx)
37
+
38
+ def removeChild(self, idx, child):
39
+ if isinstance(child, TBase):
40
+ child.tremove()
41
+
42
+ class Spacer(TBase):
43
+ def __init__(self):
44
+ super().__init__()
45
+ self.layout_weight = 1
46
+
47
+ def update(self, prev):
48
+ if prev and prev.ui:
49
+ self.ui = prev.ui
50
+ else:
51
+ self.ui = widgets.Static("")
52
+ 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,74 @@
1
+ from .. import *
2
+ from .base import *
3
+ import math
4
+
5
+ class Scroll(TBase):
6
+ END = -0.0
7
+ scroll = True
8
+ def __init__(self, vertical=None, horizontal=False):
9
+ self.vertical = vertical
10
+ self.horizontal = horizontal
11
+ self.align_x = 0
12
+ self.align_y = 0
13
+ super().__init__()
14
+
15
+ def update(self, prev):
16
+ if prev and prev.ui:
17
+ self.ui = prev.ui
18
+ else:
19
+ self.ui = containers.ScrollableContainer()
20
+
21
+ v = "auto"
22
+ self.container_y = True
23
+ self.expand_y_prio = 3
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.expand_y_prio = 1
30
+
31
+ h = "auto"
32
+ self.container_x = True
33
+ self.expand_x_prio = 3
34
+ if self.horizontal is True:
35
+ h = "scroll"
36
+ elif self.horizontal is False:
37
+ h = "hidden"
38
+ self.container_x = False
39
+ self.expand_x_prio = 1
40
+
41
+ self.ui.set_styles(f"overflow-x: {h}; overflow-y: {v};")
42
+
43
+ super().update(prev)
44
+
45
+ def addChild(self, idx, child):
46
+ if isinstance(child, TBase):
47
+ self.inner.mount(child.outer)
48
+ self.t_update_layout()
49
+ else:
50
+ self.addChild(idx, child.children[0])
51
+
52
+ def removeChild(self, idx, child):
53
+ if isinstance(child, TBase):
54
+ child.tremove()
55
+ else:
56
+ self.removeChild(idx, child.children[0])
57
+
58
+ def scrollX(self, pos=0):
59
+ if math.copysign(1, pos) >= 0:
60
+ self.align_x = 0
61
+ self.hsb_offset = pos
62
+ else:
63
+ self.align_x = 1
64
+ self.hsb_offset = abs(pos)
65
+ return self
66
+
67
+ def scrollY(self, pos=0):
68
+ if math.copysign(1, pos) >= 0:
69
+ self.align_y = 0
70
+ self.vsb_offset = pos
71
+ else:
72
+ self.align_y = 1
73
+ self.vsb_offset = abs(pos)
74
+ 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,55 @@
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
+
15
+ if prev and prev.ui:
16
+ self.editing = prev.editing
17
+ self.ui = prev.ui
18
+ self.curr_value = prev.curr_value
19
+ self.changing = prev.changing
20
+
21
+ if self.curr_value.set(model_value) and not self.editing:
22
+ self.changing = True # block changed event from next line
23
+ self.ui.value = model_value
24
+ else:
25
+ self.ui = widgets.Input(model_value)
26
+ self.curr_value = Prop(model_value)
27
+ self.changing = True # block changed event from initialization
28
+
29
+ if self.edit_model and not self.editing:
30
+ self.edit_model.value = model_value
31
+
32
+ self.ui.puinode = self
33
+ super().update(prev)
34
+
35
+ def _tchanged(self, value): # editing
36
+ if self.changing:
37
+ self.changing = False
38
+ return
39
+ node = self.get_node()
40
+ node.editing = True
41
+ if node.edit_model:
42
+ node.edit_model.value = value
43
+ e = PUIEvent()
44
+ e.value = value
45
+ self._input(e)
46
+
47
+ def _tsubmitted(self, value): # finish editing
48
+ node = self.get_node()
49
+ node.editing = False
50
+ node.model.value = value
51
+ if node.edit_model:
52
+ node.edit_model.value = value
53
+ e = PUIEvent()
54
+ e.value = value
55
+ 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__()