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.
- PUI/PySide6/__init__.py +49 -0
- PUI/PySide6/application.py +58 -0
- PUI/PySide6/base.py +222 -0
- PUI/PySide6/button.py +21 -0
- PUI/PySide6/canvas.py +288 -0
- PUI/PySide6/checkbox.py +32 -0
- PUI/PySide6/combobox.py +75 -0
- PUI/PySide6/dialog.py +72 -0
- PUI/PySide6/divider.py +23 -0
- PUI/PySide6/image.py +30 -0
- PUI/PySide6/label.py +33 -0
- PUI/PySide6/layout.py +72 -0
- PUI/PySide6/matplotlib.py +23 -0
- PUI/PySide6/mdi.py +33 -0
- PUI/PySide6/menu.py +85 -0
- PUI/PySide6/modal.py +132 -0
- PUI/PySide6/progressbar.py +17 -0
- PUI/PySide6/radiobutton.py +29 -0
- PUI/PySide6/scroll.py +153 -0
- PUI/PySide6/splitter.py +25 -0
- PUI/PySide6/tab.py +39 -0
- PUI/PySide6/table.py +89 -0
- PUI/PySide6/text.py +35 -0
- PUI/PySide6/textfield.py +62 -0
- PUI/PySide6/toolbar.py +57 -0
- PUI/PySide6/tree.py +120 -0
- PUI/PySide6/window.py +81 -0
- PUI/__init__.py +46 -0
- PUI/common.py +20 -0
- PUI/decorator.py +20 -0
- PUI/dom.py +238 -0
- PUI/flet/__init__.py +21 -0
- PUI/flet/application.py +42 -0
- PUI/flet/base.py +37 -0
- PUI/flet/button.py +20 -0
- PUI/flet/canvas.py +86 -0
- PUI/flet/checkbox.py +23 -0
- PUI/flet/label.py +27 -0
- PUI/flet/layout.py +50 -0
- PUI/flet/progressbar.py +21 -0
- PUI/flet/radiobutton.py +27 -0
- PUI/flet/scroll.py +83 -0
- PUI/flet/tab.py +42 -0
- PUI/flet/text.py +55 -0
- PUI/flet/textfield.py +58 -0
- PUI/flet/window.py +25 -0
- PUI/interfaces.py +97 -0
- PUI/node.py +407 -0
- PUI/state.py +698 -0
- PUI/textual/__init__.py +34 -0
- PUI/textual/application.py +82 -0
- PUI/textual/base.py +113 -0
- PUI/textual/button.py +17 -0
- PUI/textual/checkbox.py +21 -0
- PUI/textual/label.py +36 -0
- PUI/textual/layout.py +48 -0
- PUI/textual/progressbar.py +17 -0
- PUI/textual/radiobutton.py +24 -0
- PUI/textual/scroll.py +72 -0
- PUI/textual/tab.py +75 -0
- PUI/textual/text.py +32 -0
- PUI/textual/textfield.py +49 -0
- PUI/textual/window.py +7 -0
- PUI/timeline.py +36 -0
- PUI/tkinter/__init__.py +43 -0
- PUI/tkinter/application.py +49 -0
- PUI/tkinter/base.py +68 -0
- PUI/tkinter/button.py +15 -0
- PUI/tkinter/canvas.py +49 -0
- PUI/tkinter/checkbox.py +27 -0
- PUI/tkinter/label.py +17 -0
- PUI/tkinter/layout.py +114 -0
- PUI/tkinter/progressbar.py +17 -0
- PUI/tkinter/radiobutton.py +26 -0
- PUI/tkinter/scroll.py +201 -0
- PUI/tkinter/tab.py +52 -0
- PUI/tkinter/text.py +20 -0
- PUI/tkinter/textfield.py +53 -0
- PUI/tkinter/window.py +51 -0
- PUI/utils.py +15 -0
- PUI/view.py +161 -0
- PUI/wx/__init__.py +19 -0
- PUI/wx/application.py +44 -0
- PUI/wx/base.py +202 -0
- PUI/wx/button.py +16 -0
- PUI/wx/canvas.py +255 -0
- PUI/wx/checkbox.py +25 -0
- PUI/wx/combobox.py +72 -0
- PUI/wx/dialog.py +66 -0
- PUI/wx/divider.py +19 -0
- PUI/wx/label.py +18 -0
- PUI/wx/layout.py +46 -0
- PUI/wx/progressbar.py +17 -0
- PUI/wx/radiobutton.py +27 -0
- PUI/wx/scroll.py +44 -0
- PUI/wx/text.py +23 -0
- PUI/wx/textfield.py +56 -0
- PUI/wx/window.py +58 -0
- qpuiq-0.10.dist-info/LICENSE.txt +21 -0
- qpuiq-0.10.dist-info/METADATA +227 -0
- qpuiq-0.10.dist-info/RECORD +103 -0
- qpuiq-0.10.dist-info/WHEEL +5 -0
- qpuiq-0.10.dist-info/top_level.txt +1 -0
PUI/tkinter/text.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
|
|
4
|
+
class Text(TkBaseWidget):
|
|
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.config(text = self.text)
|
|
13
|
+
else:
|
|
14
|
+
self.ui = tk.Label(self.tkparent.inner, text=self.text, anchor="w", justify="left")
|
|
15
|
+
|
|
16
|
+
class Html(Text):
|
|
17
|
+
pui_supported = False
|
|
18
|
+
|
|
19
|
+
class MarkDown(Text):
|
|
20
|
+
pui_supported = False
|
PUI/tkinter/textfield.py
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
|
|
4
|
+
class TextField(TkBaseWidget):
|
|
5
|
+
def __init__(self, model, edit_model=None):
|
|
6
|
+
super().__init__()
|
|
7
|
+
self.model = model
|
|
8
|
+
self.edit_model = edit_model
|
|
9
|
+
self.editing = False
|
|
10
|
+
|
|
11
|
+
def update(self, prev):
|
|
12
|
+
model_value = str(self.model.value)
|
|
13
|
+
if prev and prev.ui:
|
|
14
|
+
self.editing = prev.editing
|
|
15
|
+
self.variable = prev.variable
|
|
16
|
+
self.ui = prev.ui
|
|
17
|
+
self.curr_value = prev.curr_value
|
|
18
|
+
if self.curr_value.set(model_value) and not self.editing:
|
|
19
|
+
self.variable.set(model_value)
|
|
20
|
+
else:
|
|
21
|
+
self.variable = tk.StringVar(self.tkparent.inner, model_value)
|
|
22
|
+
self.variable.trace_add("write", self.on_variable_changed)
|
|
23
|
+
self.curr_value = Prop(model_value)
|
|
24
|
+
self.ui = tk.Entry(self.tkparent.inner, textvariable=self.variable)
|
|
25
|
+
self.ui.bind('<Return>', self.on_return)
|
|
26
|
+
self.ui.bind('<FocusOut>', self.on_focus_out)
|
|
27
|
+
|
|
28
|
+
if self.edit_model and not self.editing:
|
|
29
|
+
self.edit_model.value = model_value
|
|
30
|
+
|
|
31
|
+
super().update(prev)
|
|
32
|
+
|
|
33
|
+
def on_variable_changed(self, var, index, mode):
|
|
34
|
+
node = self.get_node()
|
|
35
|
+
node.editing = True
|
|
36
|
+
if node.edit_model:
|
|
37
|
+
node.edit_model.value = self.variable.get()
|
|
38
|
+
self._input()
|
|
39
|
+
|
|
40
|
+
def on_change(self):
|
|
41
|
+
node = self.get_node()
|
|
42
|
+
node.editing = False
|
|
43
|
+
value = self.variable.get()
|
|
44
|
+
node.model.value = value
|
|
45
|
+
if node.edit_model:
|
|
46
|
+
node.edit_model.value = value
|
|
47
|
+
self._change()
|
|
48
|
+
|
|
49
|
+
def on_return(self, e):
|
|
50
|
+
self.on_change()
|
|
51
|
+
|
|
52
|
+
def on_focus_out(self, e):
|
|
53
|
+
self.on_change()
|
PUI/tkinter/window.py
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
|
|
4
|
+
class Window(TkBaseWidget):
|
|
5
|
+
pui_terminal = False
|
|
6
|
+
def __init__(self, title=None, size=None, maximize=None, fullscreen=None):
|
|
7
|
+
super().__init__()
|
|
8
|
+
self.title = title
|
|
9
|
+
self.size = size
|
|
10
|
+
self.maximize = maximize
|
|
11
|
+
self.fullscreen = fullscreen
|
|
12
|
+
|
|
13
|
+
def update(self, prev):
|
|
14
|
+
if prev and prev.ui:
|
|
15
|
+
self.ui = prev.ui
|
|
16
|
+
self.curr_size = prev.curr_size
|
|
17
|
+
self.curr_maximize = prev.curr_maximize
|
|
18
|
+
self.curr_fullscreen = prev.curr_fullscreen
|
|
19
|
+
else:
|
|
20
|
+
self.ui = tk.Toplevel(self.parent.inner)
|
|
21
|
+
# self.ui.protocol("WM_DELETE_WINDOW", self.on_closing)
|
|
22
|
+
self.curr_size = Prop()
|
|
23
|
+
self.curr_maximize = Prop()
|
|
24
|
+
self.curr_fullscreen = Prop()
|
|
25
|
+
|
|
26
|
+
if self.curr_size.set(self.size):
|
|
27
|
+
self.ui.geometry("x".join([str(v) for v in self.size]))
|
|
28
|
+
|
|
29
|
+
if self.curr_maximize.set(self.maximize):
|
|
30
|
+
# https://stackoverflow.com/a/70061942
|
|
31
|
+
try:
|
|
32
|
+
self.ui.attributes('-zoomed', True)
|
|
33
|
+
except:
|
|
34
|
+
self.ui.state("zoomed")
|
|
35
|
+
|
|
36
|
+
if self.curr_fullscreen.set(self.fullscreen):
|
|
37
|
+
self.ui.attributes('-fullscreen', True)
|
|
38
|
+
|
|
39
|
+
if not self.title is None:
|
|
40
|
+
self.ui.title(self.title)
|
|
41
|
+
|
|
42
|
+
def on_closing(self):
|
|
43
|
+
self.get_node().tkparent.ui.destroy()
|
|
44
|
+
|
|
45
|
+
def addChild(self, idx, child):
|
|
46
|
+
if idx:
|
|
47
|
+
return
|
|
48
|
+
child.outer.pack(fill=tk.BOTH, expand=True)
|
|
49
|
+
|
|
50
|
+
def removeChild(self, idx, child):
|
|
51
|
+
child.outer.pack_forget()
|
PUI/utils.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
def trbl(d):
|
|
2
|
+
# https://www.w3schools.com/css/css_padding.asp
|
|
3
|
+
if isinstance(d, int) or isinstance(d, float):
|
|
4
|
+
return (d,d,d,d)
|
|
5
|
+
elif len(d) == 4: # top, right, bottom, left
|
|
6
|
+
return d
|
|
7
|
+
elif len(d) == 3: # top, right/left, bottom
|
|
8
|
+
return (d[0], d[1], d[2], d[1])
|
|
9
|
+
elif len(d) == 2: # top/bottom, right/left
|
|
10
|
+
return (d[0], d[1], d[0], d[1])
|
|
11
|
+
else:
|
|
12
|
+
raise RuntimeError(f"Unsupported format: {d}")
|
|
13
|
+
|
|
14
|
+
def trbl2ltrb(d):
|
|
15
|
+
return (d[3], d[0], d[1], d[2])
|
PUI/view.py
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
from .node import *
|
|
2
|
+
from .dom import *
|
|
3
|
+
from .state import StateMutationInViewBuilderError
|
|
4
|
+
import time
|
|
5
|
+
|
|
6
|
+
DEBUG = False
|
|
7
|
+
|
|
8
|
+
class PUIView(PUINode):
|
|
9
|
+
pui_virtual = True
|
|
10
|
+
pui_isview = True
|
|
11
|
+
__ALLVIEWS__ = []
|
|
12
|
+
|
|
13
|
+
@staticmethod
|
|
14
|
+
def reload():
|
|
15
|
+
for v in PUIView.__ALLVIEWS__:
|
|
16
|
+
if DEBUG:
|
|
17
|
+
print("reload", v.key)
|
|
18
|
+
v.redraw()
|
|
19
|
+
|
|
20
|
+
def __init__(self, *args):
|
|
21
|
+
self.frames = []
|
|
22
|
+
self.dirty = False
|
|
23
|
+
self.updating = False
|
|
24
|
+
super().__init__(*args)
|
|
25
|
+
PUIView.__ALLVIEWS__.append(self)
|
|
26
|
+
|
|
27
|
+
def __enter__(self):
|
|
28
|
+
if not hasattr(tls, "puistack"):
|
|
29
|
+
tls.puistack = []
|
|
30
|
+
tls.puistack.append(self)
|
|
31
|
+
# print("enter", type(self).__name__, id(self))
|
|
32
|
+
self.root.frames.append(self)
|
|
33
|
+
return self
|
|
34
|
+
|
|
35
|
+
def __exit__(self, ex_type, value, traceback):
|
|
36
|
+
tls.puistack.pop()
|
|
37
|
+
# print("exit", type(self).__name__, id(self))
|
|
38
|
+
self.root.frames.pop()
|
|
39
|
+
if ex_type is None: # don't consume exception
|
|
40
|
+
return self
|
|
41
|
+
|
|
42
|
+
def content(self):
|
|
43
|
+
return None
|
|
44
|
+
|
|
45
|
+
def dump(self):
|
|
46
|
+
if DEBUG:
|
|
47
|
+
print(f"content() start", self.key)
|
|
48
|
+
start = time.time()
|
|
49
|
+
with self as scope:
|
|
50
|
+
self.content()
|
|
51
|
+
if DEBUG:
|
|
52
|
+
print(f"content() time: {time.time()-start:.5f}", self.key)
|
|
53
|
+
return scope
|
|
54
|
+
|
|
55
|
+
def destroy(self, direct):
|
|
56
|
+
try:
|
|
57
|
+
PUIView.__ALLVIEWS__.remove(self)
|
|
58
|
+
except:
|
|
59
|
+
pass
|
|
60
|
+
return super().destroy(direct)
|
|
61
|
+
|
|
62
|
+
def redraw(self):
|
|
63
|
+
if self.retired_by or self.destroyed:
|
|
64
|
+
return
|
|
65
|
+
self.dirty = True
|
|
66
|
+
if self.updating:
|
|
67
|
+
return
|
|
68
|
+
self.updating = True
|
|
69
|
+
self.sync()
|
|
70
|
+
|
|
71
|
+
def wait(self):
|
|
72
|
+
"""
|
|
73
|
+
Wait for the view to be updated.
|
|
74
|
+
"""
|
|
75
|
+
while self.updating or self.dirty:
|
|
76
|
+
time.sleep(0.0001)
|
|
77
|
+
|
|
78
|
+
# Subview update entry point
|
|
79
|
+
def sync(self):
|
|
80
|
+
if not self.pui_virtual:
|
|
81
|
+
raise VDomError(f"sync() called on non-virtual node {self.key}")
|
|
82
|
+
if self.retired_by or self.destroyed:
|
|
83
|
+
return
|
|
84
|
+
self.dirty = False
|
|
85
|
+
|
|
86
|
+
dom_parent = (self.pui_dom_parent or self).get_node()
|
|
87
|
+
if DEBUG:
|
|
88
|
+
print(f"Sync subview {self.key}@{id(self)} retired_by={id(self.retired_by) if self.retired_by else None} destroyed={self.destroyed} dom_parent={dom_parent.key}@{id(dom_parent)}")
|
|
89
|
+
found, offset = dom_parent.findDomOffsetForNode(self)
|
|
90
|
+
if DEBUG:
|
|
91
|
+
print(f" found={found} offset={offset}")
|
|
92
|
+
if not found:
|
|
93
|
+
if DEBUG:
|
|
94
|
+
print(dom_parent.serialize(show_pyid=True, show_hierarchy=True))
|
|
95
|
+
offset = 0
|
|
96
|
+
|
|
97
|
+
last_children = self.children
|
|
98
|
+
try:
|
|
99
|
+
self.update()
|
|
100
|
+
except (StateMutationInViewBuilderError, VDomError):
|
|
101
|
+
raise
|
|
102
|
+
except:
|
|
103
|
+
# prevent crash in hot-reloading
|
|
104
|
+
self.children = last_children
|
|
105
|
+
import traceback
|
|
106
|
+
print("## <ERROR OF content() >", self.key, id(self))
|
|
107
|
+
traceback.print_exc()
|
|
108
|
+
print("## </ERROR OF content()>")
|
|
109
|
+
|
|
110
|
+
start = time.time()
|
|
111
|
+
if DEBUG:
|
|
112
|
+
print("sync() start", self.key)
|
|
113
|
+
|
|
114
|
+
if DEBUG:
|
|
115
|
+
print(f"offset for {self.key}@{id(self)} on {dom_parent.key}@{id(dom_parent)} is {offset}")
|
|
116
|
+
sync(self, dom_parent, offset, last_children, self.children)
|
|
117
|
+
if DEBUG:
|
|
118
|
+
print(f"sync() time: {time.time()-start:.5f}", self.key)
|
|
119
|
+
|
|
120
|
+
self.updating = False
|
|
121
|
+
if self.dirty:
|
|
122
|
+
self.redraw()
|
|
123
|
+
|
|
124
|
+
def update(self, prev=None):
|
|
125
|
+
if self.retired_by:
|
|
126
|
+
return
|
|
127
|
+
if self.destroyed:
|
|
128
|
+
return
|
|
129
|
+
if not prev:
|
|
130
|
+
if self.setup:
|
|
131
|
+
self.setup()
|
|
132
|
+
self.setup = None
|
|
133
|
+
else:
|
|
134
|
+
self.setup = None
|
|
135
|
+
|
|
136
|
+
if DEBUG:
|
|
137
|
+
print(f"update() {self.key}@{id(self)} prev={id(prev) if prev else None}")
|
|
138
|
+
|
|
139
|
+
if prev and prev is not self:
|
|
140
|
+
prev.retired_by = self
|
|
141
|
+
try:
|
|
142
|
+
print(f"retired {prev.key}@{id(prev)}")
|
|
143
|
+
PUIView.__ALLVIEWS__.remove(prev)
|
|
144
|
+
except:
|
|
145
|
+
pass
|
|
146
|
+
|
|
147
|
+
self.children = []
|
|
148
|
+
if DEBUG:
|
|
149
|
+
print(f"content() start", self.key)
|
|
150
|
+
start = time.time()
|
|
151
|
+
with self as scope: # init frame stack
|
|
152
|
+
self.content() # V-DOM builder
|
|
153
|
+
if DEBUG:
|
|
154
|
+
print(f"content() time: {time.time()-start:.5f}", self.key)
|
|
155
|
+
|
|
156
|
+
def setup(self):
|
|
157
|
+
pass
|
|
158
|
+
|
|
159
|
+
def run(self):
|
|
160
|
+
self.sync()
|
|
161
|
+
self.start()
|
PUI/wx/__init__.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from .application import *
|
|
2
|
+
from .button import *
|
|
3
|
+
from .canvas import *
|
|
4
|
+
from .checkbox import *
|
|
5
|
+
from .combobox import *
|
|
6
|
+
from .dialog import *
|
|
7
|
+
from .divider import *
|
|
8
|
+
from .label import *
|
|
9
|
+
from .layout import *
|
|
10
|
+
from .progressbar import *
|
|
11
|
+
from .radiobutton import *
|
|
12
|
+
from .scroll import *
|
|
13
|
+
from .text import *
|
|
14
|
+
from .textfield import *
|
|
15
|
+
from .window import *
|
|
16
|
+
|
|
17
|
+
PUIView = WxPUIView
|
|
18
|
+
|
|
19
|
+
PUI_BACKEND = "wx"
|
PUI/wx/application.py
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
|
|
4
|
+
class Application(WxPUIView):
|
|
5
|
+
def __init__(self, icon=None):
|
|
6
|
+
super().__init__()
|
|
7
|
+
self.ui = None
|
|
8
|
+
self.icon = icon
|
|
9
|
+
|
|
10
|
+
def redraw(self):
|
|
11
|
+
if self.ui:
|
|
12
|
+
super().redraw()
|
|
13
|
+
else:
|
|
14
|
+
self.update(None)
|
|
15
|
+
|
|
16
|
+
def update(self, prev=None):
|
|
17
|
+
if not self.ui:
|
|
18
|
+
self.ui = wx.App()
|
|
19
|
+
|
|
20
|
+
super().update(prev)
|
|
21
|
+
|
|
22
|
+
def addChild(self, idx, child):
|
|
23
|
+
child.outer.Show()
|
|
24
|
+
|
|
25
|
+
def removeChild(self, idx, child):
|
|
26
|
+
child.outer.Close()
|
|
27
|
+
|
|
28
|
+
def start(self):
|
|
29
|
+
self.ui.MainLoop()
|
|
30
|
+
|
|
31
|
+
def PUIApp(func):
|
|
32
|
+
def func_wrapper(*args, **kwargs):
|
|
33
|
+
class PUIAppWrapper(Application):
|
|
34
|
+
def __init__(self, name):
|
|
35
|
+
self.name = name
|
|
36
|
+
super().__init__()
|
|
37
|
+
|
|
38
|
+
def content(self):
|
|
39
|
+
return func(*args, **kwargs)
|
|
40
|
+
|
|
41
|
+
ret = PUIAppWrapper(func.__name__)
|
|
42
|
+
return ret
|
|
43
|
+
|
|
44
|
+
return func_wrapper
|
PUI/wx/base.py
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
|
|
3
|
+
import wx
|
|
4
|
+
|
|
5
|
+
def int_to_wx_colour(color_int):
|
|
6
|
+
red = (color_int >> 16) & 0xFF
|
|
7
|
+
green = (color_int >> 8) & 0xFF
|
|
8
|
+
blue = color_int & 0xFF
|
|
9
|
+
return wx.Colour(red, green, blue)
|
|
10
|
+
|
|
11
|
+
def getWindow(n):
|
|
12
|
+
from .window import Window
|
|
13
|
+
from .scroll import Scroll
|
|
14
|
+
p = n
|
|
15
|
+
while p:
|
|
16
|
+
if isinstance(p, Scroll):
|
|
17
|
+
return p.ui
|
|
18
|
+
if isinstance(p, Window):
|
|
19
|
+
return p.ui
|
|
20
|
+
p = p.parent
|
|
21
|
+
raise RuntimeError("!!! getWindow returns None for", n.key if n else None)
|
|
22
|
+
|
|
23
|
+
class WxPUIView(PUIView):
|
|
24
|
+
pui_virtual = True
|
|
25
|
+
def __init__(self):
|
|
26
|
+
super().__init__()
|
|
27
|
+
|
|
28
|
+
def destroy(self, direct):
|
|
29
|
+
if self.ui: # PUIView doesn't have ui
|
|
30
|
+
self.ui.Destroy()
|
|
31
|
+
self.ui = None
|
|
32
|
+
super().destroy(direct)
|
|
33
|
+
|
|
34
|
+
def redraw(self):
|
|
35
|
+
wx.CallAfter(self.sync)
|
|
36
|
+
|
|
37
|
+
def update(self, prev=None):
|
|
38
|
+
if self.retired_by:
|
|
39
|
+
return
|
|
40
|
+
self.dirty = False
|
|
41
|
+
super().update(prev)
|
|
42
|
+
self.updating = False
|
|
43
|
+
if self.dirty:
|
|
44
|
+
self.update(prev)
|
|
45
|
+
|
|
46
|
+
class WXBase(PUINode):
|
|
47
|
+
scroll = False
|
|
48
|
+
container_x = False
|
|
49
|
+
container_y = False
|
|
50
|
+
strong_expand_x = False
|
|
51
|
+
strong_expand_y = False
|
|
52
|
+
weak_expand_x = False
|
|
53
|
+
weak_expand_y = False
|
|
54
|
+
nweak_expand_x = False
|
|
55
|
+
nweak_expand_y = False
|
|
56
|
+
strong_expand_x_children = 0
|
|
57
|
+
strong_expand_y_children = 0
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def expand_x(self):
|
|
61
|
+
return self.strong_expand_x or (self.weak_expand_x and not self.nweak_expand_x)
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def expand_y(self):
|
|
65
|
+
return self.strong_expand_y or (self.weak_expand_y and not self.nweak_expand_y)
|
|
66
|
+
|
|
67
|
+
def update(self, prev):
|
|
68
|
+
parent = self.wxparent
|
|
69
|
+
if parent:
|
|
70
|
+
if not parent.scroll and len(parent.children) == 1:
|
|
71
|
+
if parent.expand_x:
|
|
72
|
+
self.strong_expand_x = True
|
|
73
|
+
if parent.expand_y:
|
|
74
|
+
self.strong_expand_y = True
|
|
75
|
+
|
|
76
|
+
# request expanding from inside
|
|
77
|
+
if parent.container_x:
|
|
78
|
+
if parent.expand_y:
|
|
79
|
+
self.strong_expand_y = True
|
|
80
|
+
if self.layout_weight:
|
|
81
|
+
self.strong_expand_x = True
|
|
82
|
+
parent.strong_expand_x_children += 1
|
|
83
|
+
p = parent
|
|
84
|
+
while p:
|
|
85
|
+
if isinstance(p, WXBase):
|
|
86
|
+
p.weak_expand_x = True
|
|
87
|
+
if p==p.parent:
|
|
88
|
+
break
|
|
89
|
+
p = p.parent
|
|
90
|
+
|
|
91
|
+
if parent.container_y:
|
|
92
|
+
if parent.expand_x:
|
|
93
|
+
self.strong_expand_x = True
|
|
94
|
+
if self.layout_weight:
|
|
95
|
+
self.strong_expand_y = True
|
|
96
|
+
parent.strong_expand_y_children += 1
|
|
97
|
+
p = parent
|
|
98
|
+
while p:
|
|
99
|
+
if isinstance(p, WXBase):
|
|
100
|
+
p.weak_expand_y = True
|
|
101
|
+
if p==p.parent:
|
|
102
|
+
break
|
|
103
|
+
p = p.parent
|
|
104
|
+
|
|
105
|
+
if parent.strong_expand_x_children > 0:
|
|
106
|
+
self.nweak_expand_x = True
|
|
107
|
+
if parent.strong_expand_y_children > 0:
|
|
108
|
+
self.nweak_expand_y = True
|
|
109
|
+
|
|
110
|
+
else:
|
|
111
|
+
# mark root node as expanding
|
|
112
|
+
self.strong_expand_x = True
|
|
113
|
+
self.strong_expand_y = True
|
|
114
|
+
|
|
115
|
+
super().update(prev)
|
|
116
|
+
|
|
117
|
+
@property
|
|
118
|
+
def wxparent(self):
|
|
119
|
+
parent = self.parent
|
|
120
|
+
while not isinstance(parent, WXBase):
|
|
121
|
+
if parent==parent.parent:
|
|
122
|
+
parent = None
|
|
123
|
+
break
|
|
124
|
+
parent = parent.parent
|
|
125
|
+
return parent
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class WxBaseWidget(WXBase):
|
|
129
|
+
pui_terminal = True
|
|
130
|
+
|
|
131
|
+
def __init__(self):
|
|
132
|
+
super().__init__()
|
|
133
|
+
self.layout_padding = (3, 3, 3, 3)
|
|
134
|
+
|
|
135
|
+
def update(self, prev):
|
|
136
|
+
super().update(prev)
|
|
137
|
+
|
|
138
|
+
if self.style_fontsize:
|
|
139
|
+
font = self.ui.GetFont()
|
|
140
|
+
font.SetPointSize(self.style_fontsize)
|
|
141
|
+
self.ui.SetFont(font)
|
|
142
|
+
|
|
143
|
+
# Set font color if specified
|
|
144
|
+
if self.style_color:
|
|
145
|
+
self.ui.SetForegroundColour(int_to_wx_colour(self.style_color))
|
|
146
|
+
|
|
147
|
+
def destroy(self, direct):
|
|
148
|
+
if self.ui is not None:
|
|
149
|
+
self.ui.Destroy()
|
|
150
|
+
self.ui = None
|
|
151
|
+
super().destroy(direct)
|
|
152
|
+
|
|
153
|
+
class WxBaseLayout(WXBase):
|
|
154
|
+
def __init__(self):
|
|
155
|
+
super().__init__()
|
|
156
|
+
if not isinstance(self.non_virtual_parent, WxBaseLayout):
|
|
157
|
+
self.layout_padding = (11,11,11,11)
|
|
158
|
+
|
|
159
|
+
def destroy(self, direct):
|
|
160
|
+
# self.ui.Destroy()
|
|
161
|
+
self.ui = None
|
|
162
|
+
super().destroy(direct)
|
|
163
|
+
|
|
164
|
+
def addChild(self, idx, child):
|
|
165
|
+
from .layout import Spacer
|
|
166
|
+
weight = child.layout_weight
|
|
167
|
+
if weight is None:
|
|
168
|
+
weight = 0
|
|
169
|
+
if not weight and self.container_x and child.expand_x:
|
|
170
|
+
weight = 1
|
|
171
|
+
if not weight and self.container_y and child.expand_y:
|
|
172
|
+
weight = 1
|
|
173
|
+
flag = wx.ALL
|
|
174
|
+
|
|
175
|
+
p = 0
|
|
176
|
+
if child.layout_padding:
|
|
177
|
+
p = max(child.layout_padding)
|
|
178
|
+
if isinstance(child, WxBaseLayout):
|
|
179
|
+
self.ui.Insert(idx, child.outer, proportion=weight, flag=flag|wx.EXPAND, border=p)
|
|
180
|
+
elif isinstance(child, WxBaseWidget):
|
|
181
|
+
if child.expand_x or child.expand_y or child.weak_expand_x or child.weak_expand_y:
|
|
182
|
+
flag |= wx.EXPAND
|
|
183
|
+
else:
|
|
184
|
+
flag |= wx.ALIGN_CENTER
|
|
185
|
+
self.ui.Insert(idx, child.outer, proportion=weight, flag=flag, border=p)
|
|
186
|
+
elif isinstance(child, Spacer):
|
|
187
|
+
self.ui.InsertStretchSpacer(idx, weight)
|
|
188
|
+
|
|
189
|
+
def removeChild(self, idx, child):
|
|
190
|
+
from .layout import Spacer
|
|
191
|
+
if isinstance(child, WxBaseLayout):
|
|
192
|
+
self.ui.Detach(idx)
|
|
193
|
+
elif isinstance(child, WxBaseWidget):
|
|
194
|
+
self.ui.Detach(idx)
|
|
195
|
+
elif isinstance(child, Spacer):
|
|
196
|
+
self.ui.Detach(idx)
|
|
197
|
+
|
|
198
|
+
def postSync(self):
|
|
199
|
+
if self.ui:
|
|
200
|
+
self.ui.Layout()
|
|
201
|
+
self.ui.Fit(getWindow(self.parent))
|
|
202
|
+
super().postSync()
|
PUI/wx/button.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
|
|
4
|
+
class Button(WxBaseWidget):
|
|
5
|
+
def __init__(self, text):
|
|
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.SetLabel(self.text)
|
|
13
|
+
else:
|
|
14
|
+
self.ui = wx.Button(getWindow(self.parent), label=self.text)
|
|
15
|
+
self.ui.Bind(wx.EVT_BUTTON, self._clicked)
|
|
16
|
+
super().update(prev)
|