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
PUI/tkinter/tab.py ADDED
@@ -0,0 +1,52 @@
1
+ from .. import *
2
+ from .base import *
3
+
4
+ class Tabs(TkBaseWidget):
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
+
14
+ def destroy(self, direct):
15
+ if direct:
16
+ for w in self.widgets:
17
+ if w:
18
+ w.deleteLater()
19
+ super().destroy(direct)
20
+
21
+ def update(self, prev):
22
+ if prev and prev.ui:
23
+ self.ui = prev.ui
24
+ self.childrenui = prev.childrenui
25
+ else:
26
+ self.ui = ttk.Notebook(self.tkparent.inner)
27
+ self.childrenui = []
28
+ super().update(prev)
29
+
30
+ def addChild(self, idx, child):
31
+ if idx < len(self.childrenui):
32
+ self.ui.insert(self.childrenui[idx], child.outer, text=child.parent.label)
33
+ self.childrenui.insert(idx, child.outer)
34
+ else:
35
+ self.ui.add(child.outer, text=child.parent.label)
36
+ self.childrenui.append(child.outer)
37
+
38
+ def removeChild(self, idx, child):
39
+ self.ui.forget(child.outer)
40
+ self.childrenui.pop(idx)
41
+
42
+ def postSync(self):
43
+ for i,c in enumerate(self.children):
44
+ self.ui.tab(i, text=c.label)
45
+ return super().postSync()
46
+
47
+ class Tab(PUINode):
48
+ pui_virtual = True
49
+ def __init__(self, label):
50
+ super().__init__()
51
+ self.label = label
52
+
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
@@ -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): # editing
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): # finish editing
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,246 @@
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 # axis
49
+ container_y = False # axis
50
+ expand_x_prio = 0
51
+ expand_y_prio = 0
52
+ expand_x1_children = 0
53
+ expand_x2_children = 0
54
+ expand_x3_children = 0
55
+ expand_x4_children = 0
56
+ expand_y1_children = 0
57
+ expand_y2_children = 0
58
+ expand_y3_children = 0
59
+ expand_y4_children = 0
60
+ cached_wxparent = None
61
+
62
+ @property
63
+ def expand_x(self):
64
+ return self.expand_x_prio
65
+
66
+ @property
67
+ def expand_y(self):
68
+ return self.expand_y_prio
69
+
70
+ def update(self, prev):
71
+ self.cached_wxparent = parent = self.wxparent
72
+
73
+ parent = self.wxparent
74
+ if parent:
75
+ if self.layout_weight:
76
+ if parent.container_x:
77
+ self.expand_x_prio = 4
78
+ if parent.container_y:
79
+ self.expand_y_prio = 4
80
+
81
+ if self.expand_x_prio >= 1:
82
+ parent.expand_x1_children += 1
83
+ if self.expand_x_prio >= 2:
84
+ parent.expand_x2_children += 1
85
+ if self.expand_x_prio >= 3:
86
+ parent.expand_x3_children += 1
87
+ if self.expand_x_prio >= 4:
88
+ parent.expand_x4_children += 1
89
+
90
+ if self.expand_y_prio >= 1:
91
+ parent.expand_y1_children += 1
92
+ if self.expand_y_prio >= 2:
93
+ parent.expand_y2_children += 1
94
+ if self.expand_y_prio >= 3:
95
+ parent.expand_y3_children += 1
96
+ if self.expand_y_prio >= 4:
97
+ parent.expand_y4_children += 1
98
+
99
+ super().update(prev)
100
+
101
+ def postUpdate(self):
102
+ parent = self.cached_wxparent
103
+ if parent:
104
+ if parent.container_x:
105
+ if self.expand_x_prio < 1 and parent.expand_x1_children > 0:
106
+ self.expand_x_prio = 0
107
+ if self.expand_x_prio < 2 and parent.expand_x2_children > 0:
108
+ self.expand_x_prio = 0
109
+ if self.expand_x_prio < 3 and parent.expand_x3_children > 0:
110
+ self.expand_x_prio = 0
111
+ if self.expand_x_prio < 4 and parent.expand_x4_children > 0:
112
+ self.expand_x_prio = 0
113
+
114
+ if parent.container_y:
115
+ if self.expand_y_prio < 1 and parent.expand_y1_children > 0:
116
+ self.expand_y_prio = 0
117
+ if self.expand_y_prio < 2 and parent.expand_y2_children > 0:
118
+ self.expand_y_prio = 0
119
+ if self.expand_y_prio < 3 and parent.expand_y3_children > 0:
120
+ self.expand_y_prio = 0
121
+ if self.expand_y_prio < 4 and parent.expand_y4_children > 0:
122
+ self.expand_y_prio = 0
123
+
124
+ if self._debug:
125
+ print("layout", self.key, f"weight={self.layout_weight}", f"expand_x={self.expand_x}", f"expand_y={self.expand_y}")
126
+
127
+ super().postUpdate()
128
+
129
+ @property
130
+ def wxparent(self):
131
+ parent = self.parent
132
+ while not isinstance(parent, WXBase):
133
+ if parent==parent.parent:
134
+ parent = None
135
+ break
136
+ parent = parent.parent
137
+ return parent
138
+
139
+
140
+ class WxBaseWidget(WXBase):
141
+ pui_terminal = True
142
+
143
+ def __init__(self):
144
+ super().__init__()
145
+ self.layout_padding = (3, 3, 3, 3)
146
+
147
+ def update(self, prev):
148
+ super().update(prev)
149
+
150
+ if self.style_fontsize:
151
+ font = self.ui.GetFont()
152
+ font.SetPointSize(self.style_fontsize)
153
+ self.ui.SetFont(font)
154
+
155
+ # Set font color if specified
156
+ if self.style_color:
157
+ self.ui.SetForegroundColour(int_to_wx_colour(self.style_color))
158
+
159
+ def destroy(self, direct):
160
+ if self.ui is not None:
161
+ self.ui.Destroy()
162
+ self.ui = None
163
+ super().destroy(direct)
164
+
165
+ class WxBaseLayout(WXBase):
166
+ def __init__(self):
167
+ super().__init__()
168
+ self.relayout = False
169
+ if not isinstance(self.non_virtual_parent, WxBaseLayout):
170
+ self.layout_padding = (11,11,11,11)
171
+
172
+ def destroy(self, direct):
173
+ # self.ui.Destroy()
174
+ self.ui = None
175
+ super().destroy(direct)
176
+
177
+ def update(self, prev):
178
+ if prev and prev.ui:
179
+ self.sizerItems = prev.sizerItems
180
+ else:
181
+ self.sizerItems = []
182
+ super().update(prev)
183
+
184
+ def postUpdate(self):
185
+ super().postUpdate()
186
+
187
+ for child, si in self.sizerItems:
188
+ if child.expand_x or child.expand_y:
189
+ si.SetFlag(wx.ALL | wx.EXPAND)
190
+ else:
191
+ # si.SetFlag(wx.ALL | wx.ALIGN_CENTER)
192
+ si.SetFlag(wx.ALL) # XXX
193
+
194
+ weight = child.layout_weight
195
+ if self.container_x and child.expand_x:
196
+ si.SetProportion(weight if weight else 1 if child.expand_x else 0)
197
+ elif self.container_y and child.expand_y:
198
+ si.SetProportion(weight if weight else 1 if child.expand_y else 0)
199
+
200
+ p = 0
201
+ if child.layout_padding:
202
+ p = max(child.layout_padding)
203
+ si.SetBorder(p)
204
+
205
+ def addChild(self, idx, child):
206
+ from .layout import Spacer
207
+ self.relayout = True
208
+
209
+ weight = child.layout_weight
210
+ if weight is None:
211
+ weight = 0
212
+ if not weight and self.container_x and child.expand_x:
213
+ weight = 1
214
+ if not weight and self.container_y and child.expand_y:
215
+ weight = 1
216
+
217
+ if isinstance(child, WxBaseLayout):
218
+ si = self.ui.Insert(idx, child.outer)
219
+ self.sizerItems.insert(idx, (child, si))
220
+ elif isinstance(child, WxBaseWidget):
221
+ si = self.ui.Insert(idx, child.outer)
222
+ self.sizerItems.insert(idx, (child, si))
223
+ elif isinstance(child, Spacer):
224
+ si = self.ui.InsertStretchSpacer(idx)
225
+ self.sizerItems.insert(idx, (child, si))
226
+
227
+ def removeChild(self, idx, child):
228
+ self.relayout = True
229
+
230
+ from .layout import Spacer
231
+ if isinstance(child, WxBaseLayout):
232
+ self.ui.Detach(idx)
233
+ self.sizerItems.pop(idx)
234
+ elif isinstance(child, WxBaseWidget):
235
+ self.ui.Detach(idx)
236
+ self.sizerItems.pop(idx)
237
+ elif isinstance(child, Spacer):
238
+ self.ui.Detach(idx)
239
+ self.sizerItems.pop(idx)
240
+
241
+ def postSync(self):
242
+ if self.relayout and self.ui:
243
+ self.relayout = False
244
+ self.ui.Layout()
245
+ # self.ui.Fit(getWindow(self.parent))
246
+ 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)