qpuiq 0.12__py3-none-any.whl → 0.14__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/base.py +3 -3
- PUI/PySide6/canvas.py +38 -2
- PUI/PySide6/combobox.py +12 -2
- PUI/PySide6/image.py +20 -2
- PUI/PySide6/layout.py +8 -8
- PUI/PySide6/tree.py +35 -22
- PUI/__init__.py +1 -1
- PUI/common.py +6 -0
- PUI/textual/__init__.py +1 -0
- PUI/textual/base.py +94 -59
- PUI/textual/label.py +2 -2
- PUI/textual/layout.py +4 -0
- PUI/textual/scroll.py +6 -4
- PUI/tkinter/canvas.py +3 -0
- PUI/wx/base.py +109 -65
- PUI/wx/canvas.py +2 -2
- PUI/wx/combobox.py +13 -4
- PUI/wx/layout.py +6 -0
- PUI/wx/scroll.py +13 -2
- {qpuiq-0.12.dist-info → qpuiq-0.14.dist-info}/METADATA +12 -4
- {qpuiq-0.12.dist-info → qpuiq-0.14.dist-info}/RECORD +24 -24
- {qpuiq-0.12.dist-info → qpuiq-0.14.dist-info}/WHEEL +1 -1
- {qpuiq-0.12.dist-info → qpuiq-0.14.dist-info/licenses}/LICENSE.txt +0 -0
- {qpuiq-0.12.dist-info → qpuiq-0.14.dist-info}/top_level.txt +0 -0
PUI/PySide6/base.py
CHANGED
|
@@ -193,20 +193,20 @@ class QtBaseLayout(PUINode):
|
|
|
193
193
|
from .modal import Modal
|
|
194
194
|
from .layout import Spacer
|
|
195
195
|
if isinstance(child, Spacer):
|
|
196
|
-
self.
|
|
196
|
+
self.qtlayout.insertItem(idx, child.outer)
|
|
197
197
|
elif isinstance(child, Modal):
|
|
198
198
|
pass
|
|
199
199
|
elif isinstance(child, QtBaseWidget) or isinstance(child, QtBaseLayout):
|
|
200
200
|
params = {}
|
|
201
201
|
if not child.layout_weight is None:
|
|
202
202
|
params["stretch"] = child.layout_weight
|
|
203
|
-
self.
|
|
203
|
+
self.qtlayout.insertWidget(idx, child.outer, **params)
|
|
204
204
|
|
|
205
205
|
def removeChild(self, idx, child):
|
|
206
206
|
from .modal import Modal
|
|
207
207
|
from .layout import Spacer
|
|
208
208
|
if isinstance(child, Spacer):
|
|
209
|
-
self.
|
|
209
|
+
self.qtlayout.removeItem(child.outer)
|
|
210
210
|
elif isinstance(child, Modal):
|
|
211
211
|
pass
|
|
212
212
|
elif isinstance(child, QtBaseWidget) or isinstance(child, QtBaseLayout):
|
PUI/PySide6/canvas.py
CHANGED
|
@@ -2,8 +2,7 @@ from .. import *
|
|
|
2
2
|
from .base import *
|
|
3
3
|
|
|
4
4
|
from PySide6 import QtWidgets, QtGui
|
|
5
|
-
from PySide6.QtGui import QPainter, QColor, QPainterPath
|
|
6
|
-
from PySide6.QtCore import QPoint
|
|
5
|
+
from PySide6.QtGui import QPainter, QColor, QPainterPath, QImage
|
|
7
6
|
|
|
8
7
|
class PUIQtCanvas(QtWidgets.QWidget):
|
|
9
8
|
def __init__(self, node, width=None, height=None):
|
|
@@ -46,6 +45,17 @@ class PUIQtCanvas(QtWidgets.QWidget):
|
|
|
46
45
|
e.x_delta = event.pixelDelta().x()
|
|
47
46
|
e.v_delta = event.angleDelta().y()
|
|
48
47
|
e.h_delta = event.angleDelta().x()
|
|
48
|
+
modifier = 0
|
|
49
|
+
emodifiers = event.modifiers()
|
|
50
|
+
if emodifiers & QtCore.Qt.ShiftModifier:
|
|
51
|
+
modifier |= KeyModifier.SHIFT
|
|
52
|
+
if emodifiers & QtCore.Qt.ControlModifier:
|
|
53
|
+
modifier |= KeyModifier.CTRL
|
|
54
|
+
if emodifiers & QtCore.Qt.AltModifier:
|
|
55
|
+
modifier |= KeyModifier.ALT
|
|
56
|
+
if emodifiers & QtCore.Qt.MetaModifier:
|
|
57
|
+
modifier |= KeyModifier.META
|
|
58
|
+
e.modifiers = modifier
|
|
49
59
|
self.node._wheel(e)
|
|
50
60
|
|
|
51
61
|
def paintEvent(self, event):
|
|
@@ -61,6 +71,8 @@ class PUIQtCanvas(QtWidgets.QWidget):
|
|
|
61
71
|
rect = QtCore.QRect(0, 0, self.width or self.geometry().width(), self.height or self.geometry().height())
|
|
62
72
|
node.qpainter.fillRect(rect, bgBrush)
|
|
63
73
|
|
|
74
|
+
node.width = self.geometry().width()
|
|
75
|
+
node.height = self.geometry().height()
|
|
64
76
|
node.painter(node, *node.args)
|
|
65
77
|
|
|
66
78
|
node.qpainter.end()
|
|
@@ -286,3 +298,27 @@ class Canvas(QtBaseWidget):
|
|
|
286
298
|
self.drawPolyline(shape.coords, color=stroke, width=width)
|
|
287
299
|
else:
|
|
288
300
|
raise RuntimeError(f"Not implemented: drawShapely({type(shape).__name__}) {dir(shape)}")
|
|
301
|
+
|
|
302
|
+
def loadImage(self, image_path):
|
|
303
|
+
return QImage(image_path)
|
|
304
|
+
|
|
305
|
+
def drawImage(self, image, x=0, y=0, width=None, height=None, src_x=0, src_y=0, src_width=None, src_height=None, opacity=1.0):
|
|
306
|
+
if image.isNull():
|
|
307
|
+
return
|
|
308
|
+
|
|
309
|
+
if src_width is None:
|
|
310
|
+
src_width = image.width() - src_x
|
|
311
|
+
if src_height is None:
|
|
312
|
+
src_height = image.height() - src_y
|
|
313
|
+
|
|
314
|
+
source_rect = QtCore.QRect(src_x, src_y, src_width, src_height)
|
|
315
|
+
|
|
316
|
+
if width is None:
|
|
317
|
+
width = src_width
|
|
318
|
+
if height is None:
|
|
319
|
+
height = src_height
|
|
320
|
+
|
|
321
|
+
dest_rect = QtCore.QRect(x, y, width, height)
|
|
322
|
+
self.qpainter.setOpacity(opacity)
|
|
323
|
+
self.qpainter.drawImage(dest_rect, image, source_rect)
|
|
324
|
+
self.qpainter.setOpacity(1.0)
|
PUI/PySide6/combobox.py
CHANGED
|
@@ -24,13 +24,16 @@ class ComboBox(QtBaseWidget):
|
|
|
24
24
|
super().update(prev)
|
|
25
25
|
|
|
26
26
|
def postSync(self):
|
|
27
|
+
index = 0
|
|
28
|
+
text = ""
|
|
29
|
+
|
|
27
30
|
if self.index_model:
|
|
28
31
|
index = self.index_model.value
|
|
29
32
|
text = self.children[index].text
|
|
30
33
|
elif self.text_model:
|
|
31
34
|
text = str(self.text_model.value)
|
|
32
35
|
try:
|
|
33
|
-
index = [c.
|
|
36
|
+
index = [c.value for c in self.children].index(text)
|
|
34
37
|
except:
|
|
35
38
|
index = 0
|
|
36
39
|
|
|
@@ -51,11 +54,15 @@ class ComboBox(QtBaseWidget):
|
|
|
51
54
|
def on_currentIndexChanged(self, idx):
|
|
52
55
|
if self.index_model:
|
|
53
56
|
self.index_model.value = idx
|
|
57
|
+
if self.text_model:
|
|
58
|
+
self.text_model.value = self.children[idx].value
|
|
54
59
|
e = PUIEvent()
|
|
55
60
|
e.value = idx
|
|
56
61
|
self._change(e)
|
|
57
62
|
|
|
58
63
|
def on_currentTextChanged(self, text):
|
|
64
|
+
if not self.editable:
|
|
65
|
+
return
|
|
59
66
|
if self.text_model:
|
|
60
67
|
self.text_model.value = text
|
|
61
68
|
e = PUIEvent()
|
|
@@ -69,7 +76,10 @@ class ComboBox(QtBaseWidget):
|
|
|
69
76
|
self.ui.removeItem(idx)
|
|
70
77
|
|
|
71
78
|
class ComboBoxItem(PUINode):
|
|
72
|
-
def __init__(self, text):
|
|
79
|
+
def __init__(self, text, value=None):
|
|
73
80
|
super().__init__()
|
|
74
81
|
self.id(text)
|
|
75
82
|
self.text = text
|
|
83
|
+
if value is None:
|
|
84
|
+
value = text
|
|
85
|
+
self.value = value
|
PUI/PySide6/image.py
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
from .. import *
|
|
2
2
|
from .base import *
|
|
3
|
+
from .label import ClickableQLabel
|
|
4
|
+
from PySide6.QtWidgets import QSizePolicy
|
|
5
|
+
import os
|
|
3
6
|
|
|
4
7
|
class Image(QtBaseWidget):
|
|
5
8
|
def __init__(self, path):
|
|
@@ -10,13 +13,28 @@ class Image(QtBaseWidget):
|
|
|
10
13
|
def update(self, prev):
|
|
11
14
|
if prev and prev.ui:
|
|
12
15
|
self.ui = prev.ui
|
|
16
|
+
self.eventFilter = prev.eventFilter
|
|
13
17
|
self.curr_path = prev.curr_path
|
|
18
|
+
self.curr_path_mtime = prev.curr_path_mtime
|
|
14
19
|
self.pixmap = prev.pixmap
|
|
15
20
|
else:
|
|
16
|
-
self.ui =
|
|
21
|
+
self.ui = ClickableQLabel()
|
|
22
|
+
self.ui.clicked.connect(self._clicked)
|
|
17
23
|
self.curr_path = Prop()
|
|
24
|
+
self.curr_path_mtime = Prop()
|
|
18
25
|
|
|
19
|
-
if self.
|
|
26
|
+
if self._onClicked:
|
|
27
|
+
self.ui.setCursor(QtCore.Qt.PointingHandCursor)
|
|
28
|
+
|
|
29
|
+
if self.layout_weight:
|
|
30
|
+
# XXX keep aspect ratio
|
|
31
|
+
self.ui.setScaledContents(True)
|
|
32
|
+
self.ui.setSizePolicy(QSizePolicy(QSizePolicy.Policy.Ignored, QSizePolicy.Policy.Ignored))
|
|
33
|
+
else:
|
|
34
|
+
self.ui.setScaledContents(False)
|
|
35
|
+
self.ui.setSizePolicy(QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Preferred))
|
|
36
|
+
|
|
37
|
+
if self.curr_path.set(self.path) or self.curr_path_mtime.set(os.path.getmtime(self.path)):
|
|
20
38
|
self.pixmap = QtGui.QPixmap(self.path)
|
|
21
39
|
if self.layout_width is not None and self.layout_height is not None:
|
|
22
40
|
self.pixmap = self.pixmap.scaled(self.layout_width, self.layout_height, QtCore.Qt.KeepAspectRatio, mode=QtCore.Qt.SmoothTransformation)
|
PUI/PySide6/layout.py
CHANGED
|
@@ -5,24 +5,24 @@ class HBox(QtBaseLayout):
|
|
|
5
5
|
def update(self, prev):
|
|
6
6
|
if prev and prev.ui:
|
|
7
7
|
self.ui = prev.ui
|
|
8
|
-
self.
|
|
8
|
+
self.qtlayout = prev.qtlayout
|
|
9
9
|
else:
|
|
10
10
|
self.ui = QtWidgets.QWidget()
|
|
11
|
-
self.
|
|
12
|
-
self.
|
|
13
|
-
self.ui.setLayout(self.
|
|
11
|
+
self.qtlayout = QtWidgets.QHBoxLayout()
|
|
12
|
+
self.qtlayout.setContentsMargins(0,0,0,0)
|
|
13
|
+
self.ui.setLayout(self.qtlayout)
|
|
14
14
|
super().update(prev)
|
|
15
15
|
|
|
16
16
|
class VBox(QtBaseLayout):
|
|
17
17
|
def update(self, prev):
|
|
18
18
|
if prev and prev.ui:
|
|
19
19
|
self.ui = prev.ui
|
|
20
|
-
self.
|
|
20
|
+
self.qtlayout = prev.qtlayout
|
|
21
21
|
else:
|
|
22
22
|
self.ui = QtWidgets.QWidget()
|
|
23
|
-
self.
|
|
24
|
-
self.
|
|
25
|
-
self.ui.setLayout(self.
|
|
23
|
+
self.qtlayout = QtWidgets.QVBoxLayout()
|
|
24
|
+
self.qtlayout.setContentsMargins(0,0,0,0)
|
|
25
|
+
self.ui.setLayout(self.qtlayout)
|
|
26
26
|
super().update(prev)
|
|
27
27
|
|
|
28
28
|
class Spacer(PUINode):
|
PUI/PySide6/tree.py
CHANGED
|
@@ -2,6 +2,9 @@ from .. import *
|
|
|
2
2
|
from .base import *
|
|
3
3
|
from PySide6.QtCore import Qt, QModelIndex, QAbstractItemModel
|
|
4
4
|
|
|
5
|
+
# XXX
|
|
6
|
+
# If click handler triggers a model reset, dblclick handler will not be called
|
|
7
|
+
|
|
5
8
|
class QAbstractItemModelAdapter(QtCore.QAbstractItemModel):
|
|
6
9
|
def __init__(self, model: "BaseTreeAdapter"):
|
|
7
10
|
super().__init__()
|
|
@@ -21,7 +24,7 @@ class QAbstractItemModelAdapter(QtCore.QAbstractItemModel):
|
|
|
21
24
|
|
|
22
25
|
defaultFlags = super().flags(index)
|
|
23
26
|
|
|
24
|
-
return defaultFlags | QtCore.Qt.ItemIsDragEnabled | QtCore.Qt.ItemIsDropEnabled
|
|
27
|
+
return defaultFlags | QtCore.Qt.ItemIsDragEnabled | QtCore.Qt.ItemIsDropEnabled
|
|
25
28
|
|
|
26
29
|
def canDropMimeData(self, data, action, row, column, parent):
|
|
27
30
|
if parent.isValid():
|
|
@@ -77,13 +80,12 @@ class QAbstractItemModelAdapter(QtCore.QAbstractItemModel):
|
|
|
77
80
|
self.model.collapsed(node)
|
|
78
81
|
|
|
79
82
|
class QTreeNodeModelAdapter(QtCore.QAbstractItemModel):
|
|
80
|
-
def __init__(self
|
|
83
|
+
def __init__(self):
|
|
81
84
|
super().__init__()
|
|
82
85
|
self.node = None
|
|
83
|
-
self.rootnode = rootnode
|
|
84
86
|
|
|
85
87
|
def index(self, row, column, parent = QtCore.QModelIndex()):
|
|
86
|
-
parent_node = parent.internalPointer() if parent.isValid() else self.
|
|
88
|
+
parent_node = parent.internalPointer() if parent.isValid() else self.node
|
|
87
89
|
if 0 <= row and row < len(parent_node.children):
|
|
88
90
|
child = parent_node.children[row]
|
|
89
91
|
return self.createIndex(row, column, child)
|
|
@@ -95,7 +97,7 @@ class QTreeNodeModelAdapter(QtCore.QAbstractItemModel):
|
|
|
95
97
|
|
|
96
98
|
defaultFlags = super().flags(index)
|
|
97
99
|
|
|
98
|
-
return defaultFlags | QtCore.Qt.ItemIsDragEnabled | QtCore.Qt.ItemIsDropEnabled
|
|
100
|
+
return defaultFlags | QtCore.Qt.ItemIsDragEnabled | QtCore.Qt.ItemIsDropEnabled
|
|
99
101
|
|
|
100
102
|
def canDropMimeData(self, data, action, row, column, parent):
|
|
101
103
|
if parent.isValid():
|
|
@@ -115,6 +117,8 @@ class QTreeNodeModelAdapter(QtCore.QAbstractItemModel):
|
|
|
115
117
|
return QModelIndex()
|
|
116
118
|
node = index.internalPointer()
|
|
117
119
|
parent_node = node.parent
|
|
120
|
+
if not isinstance(parent_node, TreeNode):
|
|
121
|
+
parent_node = None
|
|
118
122
|
if parent_node:
|
|
119
123
|
return self.createIndex(0, 0, parent_node)
|
|
120
124
|
return QModelIndex()
|
|
@@ -128,14 +132,14 @@ class QTreeNodeModelAdapter(QtCore.QAbstractItemModel):
|
|
|
128
132
|
return None
|
|
129
133
|
|
|
130
134
|
def rowCount(self, parent):
|
|
131
|
-
parent_node = parent.internalPointer() if parent.isValid() else self.
|
|
135
|
+
parent_node = parent.internalPointer() if parent.isValid() else self.node
|
|
132
136
|
return len(parent_node.children)
|
|
133
137
|
|
|
134
138
|
def columnCount(self, parent):
|
|
135
139
|
return 1
|
|
136
140
|
|
|
137
141
|
def hasChildren(self, parent):
|
|
138
|
-
parent_node = parent.internalPointer() if parent.isValid() else self.
|
|
142
|
+
parent_node = parent.internalPointer() if parent.isValid() else self.node
|
|
139
143
|
return len(parent_node.children) > 0
|
|
140
144
|
|
|
141
145
|
def clicked(self, node):
|
|
@@ -157,21 +161,29 @@ class Tree(QtBaseWidget):
|
|
|
157
161
|
self.model = model
|
|
158
162
|
self.curr_model = None
|
|
159
163
|
self.pendings = []
|
|
164
|
+
self._expand_callback = None
|
|
165
|
+
self._collapse_callback = None
|
|
160
166
|
|
|
161
167
|
def update(self, prev):
|
|
162
168
|
if prev and prev.ui:
|
|
163
169
|
self.ui = prev.ui
|
|
164
170
|
self.qt_model = prev.qt_model
|
|
165
171
|
self.curr_model = prev.curr_model
|
|
172
|
+
|
|
173
|
+
self.ui.clicked.disconnect()
|
|
174
|
+
self.ui.doubleClicked.disconnect()
|
|
175
|
+
self.ui.expanded.disconnect()
|
|
176
|
+
self.ui.collapsed.disconnect()
|
|
166
177
|
else:
|
|
167
178
|
self.qt_model = None
|
|
168
179
|
self.curr_model = Prop()
|
|
169
180
|
self.ui = QtWidgets.QTreeView()
|
|
170
181
|
self.ui.setHeaderHidden(True)
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
182
|
+
|
|
183
|
+
self.ui.clicked.connect(self.on_item_clicked)
|
|
184
|
+
self.ui.doubleClicked.connect(self.on_item_double_clicked)
|
|
185
|
+
self.ui.expanded.connect(self.on_item_expanded)
|
|
186
|
+
self.ui.collapsed.connect(self.on_item_collapsed)
|
|
175
187
|
|
|
176
188
|
if self.model:
|
|
177
189
|
if self.curr_model.set(self.model):
|
|
@@ -181,9 +193,14 @@ class Tree(QtBaseWidget):
|
|
|
181
193
|
else:
|
|
182
194
|
self.qt_model.modelReset.emit()
|
|
183
195
|
else:
|
|
184
|
-
self.qt_model
|
|
185
|
-
|
|
186
|
-
|
|
196
|
+
if not self.qt_model:
|
|
197
|
+
self.qt_model = QTreeNodeModelAdapter()
|
|
198
|
+
self.qt_model.node = self
|
|
199
|
+
self.ui.setModel(self.qt_model)
|
|
200
|
+
else:
|
|
201
|
+
self.qt_model.beginResetModel()
|
|
202
|
+
self.qt_model.node = self
|
|
203
|
+
self.qt_model.endResetModel()
|
|
187
204
|
|
|
188
205
|
for pending in self.pendings:
|
|
189
206
|
pending[0](*pending[1:])
|
|
@@ -231,24 +248,20 @@ class Tree(QtBaseWidget):
|
|
|
231
248
|
cb(*args, **kwargs)
|
|
232
249
|
|
|
233
250
|
def on_item_clicked(self, index):
|
|
234
|
-
node = self.get_node()
|
|
235
251
|
treenode = index.internalPointer()
|
|
236
|
-
self.qt_model.clicked(treenode)
|
|
252
|
+
self.get_node().qt_model.clicked(treenode)
|
|
237
253
|
|
|
238
254
|
def on_item_double_clicked(self, index):
|
|
239
|
-
node = self.get_node()
|
|
240
255
|
treenode = index.internalPointer()
|
|
241
|
-
self.qt_model.dblclicked(treenode)
|
|
256
|
+
self.get_node().qt_model.dblclicked(treenode)
|
|
242
257
|
|
|
243
258
|
def on_item_expanded(self, index):
|
|
244
|
-
node = self.get_node()
|
|
245
259
|
treenode = index.internalPointer()
|
|
246
|
-
self.qt_model.expanded(treenode)
|
|
260
|
+
self.get_node().qt_model.expanded(treenode)
|
|
247
261
|
|
|
248
262
|
def on_item_collapsed(self, index):
|
|
249
|
-
node = self.get_node()
|
|
250
263
|
treenode = index.internalPointer()
|
|
251
|
-
self.qt_model.collapsed(treenode)
|
|
264
|
+
self.get_node().qt_model.collapsed(treenode)
|
|
252
265
|
|
|
253
266
|
class TreeNode(PUINode):
|
|
254
267
|
def __init__(self, data=""):
|
PUI/__init__.py
CHANGED
PUI/common.py
CHANGED
PUI/textual/__init__.py
CHANGED
PUI/textual/base.py
CHANGED
|
@@ -3,24 +3,57 @@ from textual import widgets, containers
|
|
|
3
3
|
|
|
4
4
|
class TBase(PUINode):
|
|
5
5
|
scroll = False
|
|
6
|
-
container_x = False
|
|
7
|
-
container_y = False
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
|
16
19
|
|
|
17
20
|
@property
|
|
18
21
|
def expand_x(self):
|
|
19
|
-
|
|
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
|
|
20
38
|
|
|
21
39
|
@property
|
|
22
40
|
def expand_y(self):
|
|
23
|
-
|
|
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
|
|
24
57
|
|
|
25
58
|
def tremove(self):
|
|
26
59
|
self.ui.remove()
|
|
@@ -30,57 +63,58 @@ class TBase(PUINode):
|
|
|
30
63
|
return super().destroy(direct)
|
|
31
64
|
|
|
32
65
|
def update(self, prev):
|
|
33
|
-
|
|
66
|
+
super().update(prev)
|
|
67
|
+
|
|
68
|
+
self.cached_tparent = parent = self.tparent
|
|
34
69
|
if parent:
|
|
35
|
-
if
|
|
36
|
-
if parent.
|
|
37
|
-
self.
|
|
38
|
-
if parent.
|
|
39
|
-
self.
|
|
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
|
|
40
93
|
|
|
41
|
-
|
|
94
|
+
def postUpdate(self):
|
|
95
|
+
super().postUpdate()
|
|
96
|
+
parent = self.cached_tparent
|
|
97
|
+
if parent:
|
|
42
98
|
if parent.container_x:
|
|
43
|
-
if parent.
|
|
44
|
-
self.
|
|
45
|
-
if self.
|
|
46
|
-
self.
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
p.weak_expand_x = True
|
|
52
|
-
if p==p.parent:
|
|
53
|
-
break
|
|
54
|
-
p = p.parent
|
|
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
|
|
55
107
|
|
|
56
108
|
if parent.container_y:
|
|
57
|
-
if parent.
|
|
58
|
-
self.
|
|
59
|
-
if self.
|
|
60
|
-
self.
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
|
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
|
|
79
117
|
|
|
80
|
-
super().update(prev)
|
|
81
|
-
|
|
82
|
-
def postUpdate(self):
|
|
83
|
-
super().postUpdate()
|
|
84
118
|
self.t_update_layout()
|
|
85
119
|
|
|
86
120
|
@property
|
|
@@ -106,8 +140,9 @@ class TBase(PUINode):
|
|
|
106
140
|
height = "1fr"
|
|
107
141
|
|
|
108
142
|
if self._debug:
|
|
109
|
-
print("layout", self.key, f"{width}:{height} expand_x={self.expand_x}", f"expand_y={self.expand_y}", f"
|
|
110
|
-
self.ui.
|
|
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
|
|
111
146
|
|
|
112
147
|
class TPUIView(PUIView):
|
|
113
148
|
pui_virtual = True
|
PUI/textual/label.py
CHANGED
|
@@ -13,13 +13,12 @@ class Label(TBase):
|
|
|
13
13
|
self.widget = prev.widget
|
|
14
14
|
else:
|
|
15
15
|
self.ui = containers.Container()
|
|
16
|
-
self.ui.set_styles("width: auto; height: auto;")
|
|
17
16
|
if self._onClicked:
|
|
18
17
|
if self.widget is None or not isinstance(self.widget, widgets.Button):
|
|
19
18
|
if self.widget:
|
|
20
19
|
self.widget.remove()
|
|
21
20
|
self.widget = widgets.Button(self.text)
|
|
22
|
-
self.widget.set_styles("
|
|
21
|
+
self.widget.set_styles("border-top: none; border-bottom: none;")
|
|
23
22
|
self.widget.puinode = self
|
|
24
23
|
else:
|
|
25
24
|
self.widget.label = self.text
|
|
@@ -33,4 +32,5 @@ class Label(TBase):
|
|
|
33
32
|
super().update(prev)
|
|
34
33
|
|
|
35
34
|
def postUpdate(self):
|
|
35
|
+
super().postUpdate()
|
|
36
36
|
self.ui.mount(self.widget)
|
PUI/textual/layout.py
CHANGED
|
@@ -3,6 +3,8 @@ from .base import *
|
|
|
3
3
|
|
|
4
4
|
class VBox(TBase):
|
|
5
5
|
container_y = True
|
|
6
|
+
expand_x_prio = 1
|
|
7
|
+
expand_y_prio = 2
|
|
6
8
|
def update(self, prev):
|
|
7
9
|
if prev and prev.ui:
|
|
8
10
|
self.ui = prev.ui
|
|
@@ -20,6 +22,8 @@ class VBox(TBase):
|
|
|
20
22
|
|
|
21
23
|
class HBox(TBase):
|
|
22
24
|
container_x = True
|
|
25
|
+
expand_x_prio = 2
|
|
26
|
+
expand_y_prio = 1
|
|
23
27
|
def update(self, prev):
|
|
24
28
|
if prev and prev.ui:
|
|
25
29
|
self.ui = prev.ui
|
PUI/textual/scroll.py
CHANGED
|
@@ -4,8 +4,6 @@ import math
|
|
|
4
4
|
|
|
5
5
|
class Scroll(TBase):
|
|
6
6
|
END = -0.0
|
|
7
|
-
weak_expand_x = True
|
|
8
|
-
weak_expand_y = True
|
|
9
7
|
scroll = True
|
|
10
8
|
def __init__(self, vertical=None, horizontal=False):
|
|
11
9
|
self.vertical = vertical
|
|
@@ -19,23 +17,27 @@ class Scroll(TBase):
|
|
|
19
17
|
self.ui = prev.ui
|
|
20
18
|
else:
|
|
21
19
|
self.ui = containers.ScrollableContainer()
|
|
20
|
+
|
|
22
21
|
v = "auto"
|
|
23
22
|
self.container_y = True
|
|
23
|
+
self.expand_y_prio = 3
|
|
24
24
|
if self.vertical is True:
|
|
25
25
|
v = "scroll"
|
|
26
26
|
elif self.vertical is False:
|
|
27
27
|
v = "hidden"
|
|
28
28
|
self.container_y = False
|
|
29
|
-
self.
|
|
29
|
+
self.expand_y_prio = 1
|
|
30
30
|
|
|
31
31
|
h = "auto"
|
|
32
32
|
self.container_x = True
|
|
33
|
+
self.expand_x_prio = 3
|
|
33
34
|
if self.horizontal is True:
|
|
34
35
|
h = "scroll"
|
|
35
36
|
elif self.horizontal is False:
|
|
36
37
|
h = "hidden"
|
|
37
38
|
self.container_x = False
|
|
38
|
-
self.
|
|
39
|
+
self.expand_x_prio = 1
|
|
40
|
+
|
|
39
41
|
self.ui.set_styles(f"overflow-x: {h}; overflow-y: {v};")
|
|
40
42
|
|
|
41
43
|
super().update(prev)
|
PUI/tkinter/canvas.py
CHANGED
PUI/wx/base.py
CHANGED
|
@@ -45,74 +45,86 @@ class WxPUIView(PUIView):
|
|
|
45
45
|
|
|
46
46
|
class WXBase(PUINode):
|
|
47
47
|
scroll = False
|
|
48
|
-
container_x = False
|
|
49
|
-
container_y = False
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
|
58
61
|
|
|
59
62
|
@property
|
|
60
63
|
def expand_x(self):
|
|
61
|
-
return self.
|
|
64
|
+
return self.expand_x_prio
|
|
62
65
|
|
|
63
66
|
@property
|
|
64
67
|
def expand_y(self):
|
|
65
|
-
return self.
|
|
68
|
+
return self.expand_y_prio
|
|
66
69
|
|
|
67
70
|
def update(self, prev):
|
|
71
|
+
self.cached_wxparent = parent = self.wxparent
|
|
72
|
+
|
|
68
73
|
parent = self.wxparent
|
|
69
74
|
if parent:
|
|
70
|
-
if
|
|
71
|
-
if parent.
|
|
72
|
-
self.
|
|
73
|
-
if parent.
|
|
74
|
-
self.
|
|
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)
|
|
75
100
|
|
|
76
|
-
|
|
101
|
+
def postUpdate(self):
|
|
102
|
+
parent = self.cached_wxparent
|
|
103
|
+
if parent:
|
|
77
104
|
if parent.container_x:
|
|
78
|
-
if parent.
|
|
79
|
-
self.
|
|
80
|
-
if self.
|
|
81
|
-
self.
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
p.weak_expand_x = True
|
|
87
|
-
if p==p.parent:
|
|
88
|
-
break
|
|
89
|
-
p = p.parent
|
|
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
|
|
90
113
|
|
|
91
114
|
if parent.container_y:
|
|
92
|
-
if parent.
|
|
93
|
-
self.
|
|
94
|
-
if self.
|
|
95
|
-
self.
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
|
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
|
|
109
123
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
self.strong_expand_x = True
|
|
113
|
-
self.strong_expand_y = True
|
|
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}")
|
|
114
126
|
|
|
115
|
-
super().
|
|
127
|
+
super().postUpdate()
|
|
116
128
|
|
|
117
129
|
@property
|
|
118
130
|
def wxparent(self):
|
|
@@ -153,6 +165,7 @@ class WxBaseWidget(WXBase):
|
|
|
153
165
|
class WxBaseLayout(WXBase):
|
|
154
166
|
def __init__(self):
|
|
155
167
|
super().__init__()
|
|
168
|
+
self.relayout = False
|
|
156
169
|
if not isinstance(self.non_virtual_parent, WxBaseLayout):
|
|
157
170
|
self.layout_padding = (11,11,11,11)
|
|
158
171
|
|
|
@@ -161,8 +174,38 @@ class WxBaseLayout(WXBase):
|
|
|
161
174
|
self.ui = None
|
|
162
175
|
super().destroy(direct)
|
|
163
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
|
+
|
|
164
205
|
def addChild(self, idx, child):
|
|
165
206
|
from .layout import Spacer
|
|
207
|
+
self.relayout = True
|
|
208
|
+
|
|
166
209
|
weight = child.layout_weight
|
|
167
210
|
if weight is None:
|
|
168
211
|
weight = 0
|
|
@@ -170,33 +213,34 @@ class WxBaseLayout(WXBase):
|
|
|
170
213
|
weight = 1
|
|
171
214
|
if not weight and self.container_y and child.expand_y:
|
|
172
215
|
weight = 1
|
|
173
|
-
flag = wx.ALL
|
|
174
216
|
|
|
175
|
-
p = 0
|
|
176
|
-
if child.layout_padding:
|
|
177
|
-
p = max(child.layout_padding)
|
|
178
217
|
if isinstance(child, WxBaseLayout):
|
|
179
|
-
self.ui.Insert(idx, child.outer
|
|
218
|
+
si = self.ui.Insert(idx, child.outer)
|
|
219
|
+
self.sizerItems.insert(idx, (child, si))
|
|
180
220
|
elif isinstance(child, WxBaseWidget):
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
else:
|
|
184
|
-
flag |= wx.ALIGN_CENTER
|
|
185
|
-
self.ui.Insert(idx, child.outer, proportion=weight, flag=flag, border=p)
|
|
221
|
+
si = self.ui.Insert(idx, child.outer)
|
|
222
|
+
self.sizerItems.insert(idx, (child, si))
|
|
186
223
|
elif isinstance(child, Spacer):
|
|
187
|
-
self.ui.InsertStretchSpacer(idx
|
|
224
|
+
si = self.ui.InsertStretchSpacer(idx)
|
|
225
|
+
self.sizerItems.insert(idx, (child, si))
|
|
188
226
|
|
|
189
227
|
def removeChild(self, idx, child):
|
|
228
|
+
self.relayout = True
|
|
229
|
+
|
|
190
230
|
from .layout import Spacer
|
|
191
231
|
if isinstance(child, WxBaseLayout):
|
|
192
232
|
self.ui.Detach(idx)
|
|
233
|
+
self.sizerItems.pop(idx)
|
|
193
234
|
elif isinstance(child, WxBaseWidget):
|
|
194
235
|
self.ui.Detach(idx)
|
|
236
|
+
self.sizerItems.pop(idx)
|
|
195
237
|
elif isinstance(child, Spacer):
|
|
196
238
|
self.ui.Detach(idx)
|
|
239
|
+
self.sizerItems.pop(idx)
|
|
197
240
|
|
|
198
241
|
def postSync(self):
|
|
199
|
-
if self.ui:
|
|
242
|
+
if self.relayout and self.ui:
|
|
243
|
+
self.relayout = False
|
|
200
244
|
self.ui.Layout()
|
|
201
|
-
self.ui.Fit(getWindow(self.parent))
|
|
245
|
+
# self.ui.Fit(getWindow(self.parent))
|
|
202
246
|
super().postSync()
|
PUI/wx/canvas.py
CHANGED
PUI/wx/combobox.py
CHANGED
|
@@ -17,20 +17,23 @@ class ComboBox(WxBaseWidget):
|
|
|
17
17
|
else:
|
|
18
18
|
self.curr_index = Prop()
|
|
19
19
|
self.curr_text = Prop()
|
|
20
|
-
self.ui = wx.ComboBox(getWindow(self.parent), choices=[])
|
|
20
|
+
self.ui = wx.ComboBox(getWindow(self.parent), choices=[], style=0 if self.editable else wx.CB_READONLY)
|
|
21
21
|
self.ui.Bind(wx.EVT_COMBOBOX, self._combobox)
|
|
22
22
|
self.ui.Bind(wx.EVT_TEXT, self._text)
|
|
23
23
|
|
|
24
24
|
super().update(prev)
|
|
25
25
|
|
|
26
26
|
def postSync(self):
|
|
27
|
+
index = 0
|
|
28
|
+
text = ""
|
|
29
|
+
|
|
27
30
|
if self.index_model:
|
|
28
31
|
index = self.index_model.value
|
|
29
32
|
text = self.children[index].text
|
|
30
33
|
elif self.text_model:
|
|
31
34
|
text = str(self.text_model.value)
|
|
32
35
|
try:
|
|
33
|
-
index = [c.
|
|
36
|
+
index = [c.value for c in self.children].index(text)
|
|
34
37
|
except:
|
|
35
38
|
index = 0
|
|
36
39
|
|
|
@@ -45,11 +48,15 @@ class ComboBox(WxBaseWidget):
|
|
|
45
48
|
idx = self.ui.GetSelection()
|
|
46
49
|
if node.index_model:
|
|
47
50
|
node.index_model.value = idx
|
|
51
|
+
if node.text_model:
|
|
52
|
+
node.text_model.value = self.children[idx].value
|
|
48
53
|
e = PUIEvent()
|
|
49
54
|
e.value = idx
|
|
50
55
|
node._change(e)
|
|
51
56
|
|
|
52
57
|
def _text(self, *args, **kwargs):
|
|
58
|
+
if not self.editable:
|
|
59
|
+
return
|
|
53
60
|
node = self.get_node()
|
|
54
61
|
text = self.ui.GetValue()
|
|
55
62
|
if node.text_model:
|
|
@@ -64,9 +71,11 @@ class ComboBox(WxBaseWidget):
|
|
|
64
71
|
def removeChild(self, idx, child):
|
|
65
72
|
self.ui.Delete(idx)
|
|
66
73
|
|
|
67
|
-
|
|
68
74
|
class ComboBoxItem(PUINode):
|
|
69
|
-
def __init__(self, text):
|
|
75
|
+
def __init__(self, text, value=None):
|
|
70
76
|
super().__init__()
|
|
71
77
|
self.id(text)
|
|
72
78
|
self.text = text
|
|
79
|
+
if value is None:
|
|
80
|
+
value = text
|
|
81
|
+
self.value = value
|
PUI/wx/layout.py
CHANGED
|
@@ -3,6 +3,9 @@ from .base import *
|
|
|
3
3
|
|
|
4
4
|
class HBox(WxBaseLayout):
|
|
5
5
|
container_x = True
|
|
6
|
+
expand_x_prio = 2
|
|
7
|
+
expand_y_prio = 1
|
|
8
|
+
|
|
6
9
|
def update(self, prev):
|
|
7
10
|
if prev and prev.ui:
|
|
8
11
|
self.ui = prev.ui
|
|
@@ -12,6 +15,9 @@ class HBox(WxBaseLayout):
|
|
|
12
15
|
|
|
13
16
|
class VBox(WxBaseLayout):
|
|
14
17
|
container_y = True
|
|
18
|
+
expand_x_prio = 1
|
|
19
|
+
expand_y_prio = 2
|
|
20
|
+
|
|
15
21
|
def update(self, prev):
|
|
16
22
|
if prev and prev.ui:
|
|
17
23
|
self.ui = prev.ui
|
PUI/wx/scroll.py
CHANGED
|
@@ -4,8 +4,6 @@ import wx.lib.scrolledpanel as scrolled
|
|
|
4
4
|
|
|
5
5
|
class Scroll(WxBaseWidget):
|
|
6
6
|
pui_terminal = False
|
|
7
|
-
weak_expand_x = True
|
|
8
|
-
weak_expand_y = True
|
|
9
7
|
scroll = True
|
|
10
8
|
|
|
11
9
|
END = -0.0
|
|
@@ -20,6 +18,19 @@ class Scroll(WxBaseWidget):
|
|
|
20
18
|
self.ui = prev.ui
|
|
21
19
|
else:
|
|
22
20
|
self.ui = scrolled.ScrolledPanel(getWindow(self.parent))
|
|
21
|
+
|
|
22
|
+
self.container_y = True
|
|
23
|
+
self.expand_y_prio = 3
|
|
24
|
+
if self.vertical is False:
|
|
25
|
+
self.container_y = False
|
|
26
|
+
self.expand_y_prio = 1
|
|
27
|
+
|
|
28
|
+
self.container_x = True
|
|
29
|
+
self.expand_x_prio = 3
|
|
30
|
+
if self.horizontal is False:
|
|
31
|
+
self.container_x = False
|
|
32
|
+
self.expand_x_prio = 1
|
|
33
|
+
|
|
23
34
|
super().update(prev)
|
|
24
35
|
|
|
25
36
|
def addChild(self, idx, child):
|
|
@@ -1,12 +1,19 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: qpuiq
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.14
|
|
4
4
|
Summary: "PUI" Python Declarative UI Framework
|
|
5
5
|
Home-page: https://github.com/buganini/PUI
|
|
6
6
|
Author: Buganini Chiu
|
|
7
7
|
Author-email: buganini@b612.tw
|
|
8
8
|
Description-Content-Type: text/markdown
|
|
9
9
|
License-File: LICENSE.txt
|
|
10
|
+
Dynamic: author
|
|
11
|
+
Dynamic: author-email
|
|
12
|
+
Dynamic: description
|
|
13
|
+
Dynamic: description-content-type
|
|
14
|
+
Dynamic: home-page
|
|
15
|
+
Dynamic: license-file
|
|
16
|
+
Dynamic: summary
|
|
10
17
|
|
|
11
18
|
# What is PUI
|
|
12
19
|
PUI is a reactive/declarative UI framework with two-way data binding.
|
|
@@ -205,8 +212,9 @@ Then PUI will take care of view update [(code)](https://github.com/buganini/PUI/
|
|
|
205
212
|
* textual (Text Mode)
|
|
206
213
|
* no canvas
|
|
207
214
|
|
|
208
|
-
#
|
|
209
|
-
[Reference](REFERENCE.md)
|
|
215
|
+
# Documents
|
|
216
|
+
* [Components Reference](REFERENCE.md)
|
|
217
|
+
* [Sizing Strategy](https://html-preview.github.io/?url=https://github.com/buganini/PUI/blob/main/doc/Sizing.html)
|
|
210
218
|
|
|
211
219
|
# Used by
|
|
212
220
|
* https://github.com/buganini/kikit-ui
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
PUI/__init__.py,sha256=
|
|
2
|
-
PUI/common.py,sha256=
|
|
1
|
+
PUI/__init__.py,sha256=1cYRM8ouBVNa_BIQAMNzSyQJ5Ym-NMT-IL5Zp5mctfk,966
|
|
2
|
+
PUI/common.py,sha256=fUJmHOu5lSCeiOhFDF6YqulJxFqWmsneqnDZ2kZFFmM,581
|
|
3
3
|
PUI/decorator.py,sha256=BN3POYv69QCDomoHENN-UA-d4wY_vfARIb5RJ2qEnS8,483
|
|
4
4
|
PUI/dom.py,sha256=RgdDyv6vSFgkCoj9G2cjzQQOiymG8DwmmSoAZfxYvJM,10141
|
|
5
5
|
PUI/interfaces.py,sha256=rGUciM3S6ICEVgVoahkva8yXUGpweqy1kAzhUQut40E,2182
|
|
@@ -10,16 +10,16 @@ PUI/utils.py,sha256=canb7_Uz0sQ1UZDzyDuIsfAVXzEfZCkc9F81sMY4rTE,505
|
|
|
10
10
|
PUI/view.py,sha256=Oe6sXLHD554GnlLlO5QpY7kegngkzrmMEYRHrdzGZUQ,4623
|
|
11
11
|
PUI/PySide6/__init__.py,sha256=z895ldBVUaEqfGQW4CvYhWh2F6L0qGQA1MXUHVMf9Ms,1110
|
|
12
12
|
PUI/PySide6/application.py,sha256=OsIE47efST4I13txD-7rS1cTWAGhynckl45Wdb1bafk,1471
|
|
13
|
-
PUI/PySide6/base.py,sha256=
|
|
13
|
+
PUI/PySide6/base.py,sha256=bhIxbw16l78lgkSpN4_s2cV33pObj3O3yGhtiNIJ10w,7916
|
|
14
14
|
PUI/PySide6/button.py,sha256=mHfcH98dABYgksuT58fK0amSwtCM9aaYwr7Y2EArEJA,561
|
|
15
|
-
PUI/PySide6/canvas.py,sha256=
|
|
15
|
+
PUI/PySide6/canvas.py,sha256=Qad87bLpQJoh8U5hjqH3g3mSbodPwweT0TOqnB5LPyI,10416
|
|
16
16
|
PUI/PySide6/checkbox.py,sha256=Rsns0BleE4g9yTDdlsD8IADU3qcQkVO2VsFVvYlNL88,900
|
|
17
|
-
PUI/PySide6/combobox.py,sha256=
|
|
17
|
+
PUI/PySide6/combobox.py,sha256=mAfJ_7m-jTWBAh2Sng-BslY-_7EjIwRLbrx5IHik13I,2501
|
|
18
18
|
PUI/PySide6/dialog.py,sha256=4rAyLMqd47ALDxrBGLFHS5FD75SP1I8tkMSKBdaPkv0,2364
|
|
19
19
|
PUI/PySide6/divider.py,sha256=jRR8Qtdil-8JTxj8SyJydzRB_MGTKa_TxegsqkYKcXc,733
|
|
20
|
-
PUI/PySide6/image.py,sha256=
|
|
20
|
+
PUI/PySide6/image.py,sha256=uORM63K6v-1Ug4KpRJW3YHc-PpICqmRxmAzcEL6MaME,1969
|
|
21
21
|
PUI/PySide6/label.py,sha256=_G8bckRPPQdzZTS3j9JaOmfRAnLragBXnyJUG9_kblU,1038
|
|
22
|
-
PUI/PySide6/layout.py,sha256=
|
|
22
|
+
PUI/PySide6/layout.py,sha256=lEr37sxpYWHSo_d-8asPRVjnJsiePP4g9SaKFGLCpJs,2637
|
|
23
23
|
PUI/PySide6/matplotlib.py,sha256=fzVfwgmEX7s_WDtc_JULRdBOfZgcBewiH79f4ahZHQ4,825
|
|
24
24
|
PUI/PySide6/mdi.py,sha256=OGE2-5--Cy-srAzM-ZexnJ1efeORQvlsH2UA7qp18iE,805
|
|
25
25
|
PUI/PySide6/menu.py,sha256=Qbw_0WX56vzC2vkvn-4DXzYX0vZ-4Rq6tW1Kj_M-Qb8,2806
|
|
@@ -33,7 +33,7 @@ PUI/PySide6/table.py,sha256=TTCMf_YNKmkFiqs_qLqw3qbvFsxoBNnz9VMObx_2l3s,4800
|
|
|
33
33
|
PUI/PySide6/text.py,sha256=4kRRZiuH-bLLJMNZ6hK9zAWOorsG-l4uujHbG6I5S20,1069
|
|
34
34
|
PUI/PySide6/textfield.py,sha256=Us-UZMDCwrREwFLjPKKa3e3c_1U4WWD2kzFCe3xiY0k,2140
|
|
35
35
|
PUI/PySide6/toolbar.py,sha256=NPkn99D5xK4RLBA0vxLD7EqYu5eh9ucCL2y1vSJWQl4,1800
|
|
36
|
-
PUI/PySide6/tree.py,sha256=
|
|
36
|
+
PUI/PySide6/tree.py,sha256=skMsCykh8kWXFTg4Yv--PevJ58fqEeZV566ICjBVO4E,9324
|
|
37
37
|
PUI/PySide6/window.py,sha256=CpkIFpleVr3oXOM6vdukahWtX5SV6cWNc1TUW84JPM4,2694
|
|
38
38
|
PUI/flet/__init__.py,sha256=3YzGA0oPfu9eW8DtKQSoAsa8o6ZTGKWakYBTxGaaH8Y,438
|
|
39
39
|
PUI/flet/application.py,sha256=3ZGZrAngSEkVK-WseOV-n_6ljhd86ZKBgO6Jp2PmsJA,937
|
|
@@ -50,16 +50,16 @@ PUI/flet/tab.py,sha256=T26PZ-Ma_LPUx7u9qbxEnYqxuR1-qlytWiB9TDpu7G8,997
|
|
|
50
50
|
PUI/flet/text.py,sha256=HGnhOTDwG5pqceK8x_C6wCZj1AKuqZ9vEZB_NFwXZo4,1465
|
|
51
51
|
PUI/flet/textfield.py,sha256=7BPRrdf4pv8rDM5BpZzMQ9b456kZpXm81y7sVW3K4XM,1802
|
|
52
52
|
PUI/flet/window.py,sha256=NqUnGYvhk2Mpo_G2WthZOEvlU6VMx6AM-jWMKcUqGDM,650
|
|
53
|
-
PUI/textual/__init__.py,sha256=
|
|
53
|
+
PUI/textual/__init__.py,sha256=cPf0_BXd2Q-6w-0UHyxFQ6QLfTVDaoo7XmSCW_1kpyc,732
|
|
54
54
|
PUI/textual/application.py,sha256=FNpZ1j05EbE3XNxqMBDfsU_IPQ1k2Y7xw-5KLtwuFnI,2514
|
|
55
|
-
PUI/textual/base.py,sha256=
|
|
55
|
+
PUI/textual/base.py,sha256=W0tfxGlZErrsCoLb9IuFjgmNa93vZFCYNgZr1V6VEjE,4821
|
|
56
56
|
PUI/textual/button.py,sha256=VF7fmgi5mHeOzptZzy4oBfcuCeUURq5eFrLvN4Fgg30,436
|
|
57
57
|
PUI/textual/checkbox.py,sha256=pkBxZz0qXl2KUz2-Lqap-r2Y3DBI0CET3wQgEpYKb7U,518
|
|
58
|
-
PUI/textual/label.py,sha256=
|
|
59
|
-
PUI/textual/layout.py,sha256=
|
|
58
|
+
PUI/textual/label.py,sha256=3kwUerDSbyUPPEkLsjs0qDcyyhgOvUws2wtjovyf0_k,1220
|
|
59
|
+
PUI/textual/layout.py,sha256=xS3xa7UHyfKT93zW2592lV7iu6POuRJKLGyvRvtHIlQ,1302
|
|
60
60
|
PUI/textual/progressbar.py,sha256=aeLiXzLOj3VWR-KUEBmmEOxJR0LACr1_-MDMOYDHx9c,501
|
|
61
61
|
PUI/textual/radiobutton.py,sha256=zFKG2LeUnPXnxpxeW3cYqPwd91DQZWFUctundau-4b0,621
|
|
62
|
-
PUI/textual/scroll.py,sha256=
|
|
62
|
+
PUI/textual/scroll.py,sha256=u6-tFygXZR_giVsCaePahKxTb0xTbdBHCNisQA9jpWc,1974
|
|
63
63
|
PUI/textual/tab.py,sha256=wcvyH1MZZNwwout8iJDifty_lqe6YuhfRpE3F0lUTBM,2158
|
|
64
64
|
PUI/textual/text.py,sha256=BHvgK3JqBU_LrnWbaaKBFxQ_50Z9lFhcdEJoVJqbcSc,782
|
|
65
65
|
PUI/textual/textfield.py,sha256=u01i-fhtSEMi_6F_bPWgf5TvRUQvuudaxi58Yp6WTbg,1412
|
|
@@ -68,7 +68,7 @@ PUI/tkinter/__init__.py,sha256=VQjdak9UO-zI7n9Kr4q_B-kgCXgag2DVoWWP_QdH2uk,982
|
|
|
68
68
|
PUI/tkinter/application.py,sha256=NxWfU9NHJuceKMdLiGeklUKU5WjYVUomGL_hJpRtrbs,1141
|
|
69
69
|
PUI/tkinter/base.py,sha256=jSOKxd2uMOhVvDjBOloxdiHeNvKwEoWJo0fyVH49ttI,2663
|
|
70
70
|
PUI/tkinter/button.py,sha256=zRGt_jVY6q74Jer5jm4q4H-_LznrXUzfEQwiMWtQboI,467
|
|
71
|
-
PUI/tkinter/canvas.py,sha256=
|
|
71
|
+
PUI/tkinter/canvas.py,sha256=nLi46ZhgEvpZz8_aUy1DwfKct4zdABjqL-9ObS1CCMM,1654
|
|
72
72
|
PUI/tkinter/checkbox.py,sha256=TOYOCKx9ux58YdYWXLkjguFG3NsgVaYlFOIrZ9ukcwI,741
|
|
73
73
|
PUI/tkinter/label.py,sha256=o6hj-8qX0ZwDDbYaNsTz5oUIXKJFr-HctTeZW2NfhHE,555
|
|
74
74
|
PUI/tkinter/layout.py,sha256=q1NgGlPd_dn1avIzJBeO_46NyBPCQyh3VcQ56YmUUKE,3576
|
|
@@ -81,23 +81,23 @@ PUI/tkinter/textfield.py,sha256=-jab7t5-wpIejINRftXczv0685cze-H7pm3lWigOT5w,1788
|
|
|
81
81
|
PUI/tkinter/window.py,sha256=IIieSxxanhGIvPy0krQuLrStsL_jTUdx6TKbEf64nyQ,1606
|
|
82
82
|
PUI/wx/__init__.py,sha256=j8L1kzL4CK_xeF0x5_NZekGETYP_1Dhq3-BuV1LtXoY,391
|
|
83
83
|
PUI/wx/application.py,sha256=Ku_mloCyiw-KTl8a09uTIhV7uupG_7urqw8jXIwQMLc,965
|
|
84
|
-
PUI/wx/base.py,sha256=
|
|
84
|
+
PUI/wx/base.py,sha256=3NKfMbfuH9qClFBP5bVIQtJyhnGRqsNuXwY0vvlyFnU,7596
|
|
85
85
|
PUI/wx/button.py,sha256=ww3Iyn16zomP4zkQhvXTirmHBvlVMJxmiV1pfXtgrSo,447
|
|
86
|
-
PUI/wx/canvas.py,sha256=
|
|
86
|
+
PUI/wx/canvas.py,sha256=uL4z0ghM15IWNlvmDyV3lVw8Li4RNMJWXHvwd7jZSiw,8487
|
|
87
87
|
PUI/wx/checkbox.py,sha256=XgLxsi-tk2f9bnlEvhvEZV4boBGFB3u62ZE1cs8X9tU,674
|
|
88
|
-
PUI/wx/combobox.py,sha256=
|
|
88
|
+
PUI/wx/combobox.py,sha256=FoYn6AkPpxH2jHcZEp20a_peC7MbTx4MUPtbGzOskcI,2363
|
|
89
89
|
PUI/wx/dialog.py,sha256=HVLVdzRkZhRndkHTYl0RgNfzIQBdtik7DIDg93Dp9JA,2572
|
|
90
90
|
PUI/wx/divider.py,sha256=qnaUVpspAOND6YhZyQsZeos1LC02L-ljfdAtVp1vdzw,516
|
|
91
91
|
PUI/wx/label.py,sha256=qr3hGfHtjvYjeXJSB2cD5u30LYodEzix4Q0FYw8p6p0,509
|
|
92
|
-
PUI/wx/layout.py,sha256=
|
|
92
|
+
PUI/wx/layout.py,sha256=nVO31_Xu4aDcTLxlz66DJ5PK2RPHk0yq6qdzyWuGVz8,1460
|
|
93
93
|
PUI/wx/progressbar.py,sha256=gj5j6f-zG78XW1mEIRqiOEYMoYjG16jzS44Vnh4i148,472
|
|
94
94
|
PUI/wx/radiobutton.py,sha256=x7WnCGXuNPV98MqF-tRLzMOOExim22rayNL8jAYVZWk,769
|
|
95
|
-
PUI/wx/scroll.py,sha256=
|
|
95
|
+
PUI/wx/scroll.py,sha256=pvRmt04XEgObpIgwl9i52Kf1wI9ubUfZM77fPHGW9zU,1494
|
|
96
96
|
PUI/wx/text.py,sha256=YeIyDyHH0xBcD_iXbYSTtvL25YDtug1QJNVPvCSAqEk,544
|
|
97
97
|
PUI/wx/textfield.py,sha256=BmMebfqlDJqacaKdh2SON88xF73l0csC7L7hoNjz-qs,1778
|
|
98
98
|
PUI/wx/window.py,sha256=juAsn3W4SzmH8f5LDGvjwppvPD8fDObRUJ_MkQFKCIE,1847
|
|
99
|
-
qpuiq-0.
|
|
100
|
-
qpuiq-0.
|
|
101
|
-
qpuiq-0.
|
|
102
|
-
qpuiq-0.
|
|
103
|
-
qpuiq-0.
|
|
99
|
+
qpuiq-0.14.dist-info/licenses/LICENSE.txt,sha256=1Xwik2AmLNGoIYhAPzvNC28M08Q3EvkOe4TtlQuSd_E,1072
|
|
100
|
+
qpuiq-0.14.dist-info/METADATA,sha256=EkKi_IUa4vM9PyZY2A8n5vTgZLXCnDnR8QGX1cZQR1s,5994
|
|
101
|
+
qpuiq-0.14.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
|
|
102
|
+
qpuiq-0.14.dist-info/top_level.txt,sha256=zMudhifPite0CEVGYvdi-5W3P_dpum71xjU7_g-ZHS0,4
|
|
103
|
+
qpuiq-0.14.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|