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/__init__.py
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from .application import *
|
|
2
|
+
from .button import *
|
|
3
|
+
from .canvas import *
|
|
4
|
+
from .checkbox import *
|
|
5
|
+
from .label import *
|
|
6
|
+
from .layout import *
|
|
7
|
+
from .progressbar import *
|
|
8
|
+
from .radiobutton import *
|
|
9
|
+
from .scroll import *
|
|
10
|
+
from .tab import *
|
|
11
|
+
from .text import *
|
|
12
|
+
from .textfield import *
|
|
13
|
+
from .window import *
|
|
14
|
+
|
|
15
|
+
PUIView = TPUIView
|
|
16
|
+
|
|
17
|
+
def PUI(func):
|
|
18
|
+
"""
|
|
19
|
+
PUI.tkinter.PUI triggers update() by .after()
|
|
20
|
+
"""
|
|
21
|
+
def func_wrapper(*args, **kwargs):
|
|
22
|
+
class PUIViewWrapper(TPUIView):
|
|
23
|
+
pui_virtual = True
|
|
24
|
+
def __init__(self, name):
|
|
25
|
+
self.name = name
|
|
26
|
+
super().__init__()
|
|
27
|
+
|
|
28
|
+
def content(self):
|
|
29
|
+
return func(*args, **kwargs)
|
|
30
|
+
|
|
31
|
+
ret = PUIViewWrapper(func.__name__)
|
|
32
|
+
return ret
|
|
33
|
+
|
|
34
|
+
return func_wrapper
|
|
35
|
+
class DummyWidget(PUINode):
|
|
36
|
+
pui_supported = False
|
|
37
|
+
def __init__(self, *args, **kwargs):
|
|
38
|
+
super().__init__()
|
|
39
|
+
|
|
40
|
+
Combobox = DummyWidget
|
|
41
|
+
ComboboxItem = DummyWidget
|
|
42
|
+
|
|
43
|
+
PUI_BACKEND = "tkinter"
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
|
|
4
|
+
class Application(TPUIView):
|
|
5
|
+
def __init__(self, *args, **kwargs):
|
|
6
|
+
super().__init__(*args, **kwargs)
|
|
7
|
+
self.theme = None
|
|
8
|
+
|
|
9
|
+
def tkinter(self, theme=None, **kwargs):
|
|
10
|
+
super().tkinter(**kwargs)
|
|
11
|
+
self.theme = theme
|
|
12
|
+
return self
|
|
13
|
+
|
|
14
|
+
def update(self, prev=None):
|
|
15
|
+
if prev and prev.ui:
|
|
16
|
+
self.ui = prev.ui
|
|
17
|
+
else:
|
|
18
|
+
self.ui = tk.Tk()
|
|
19
|
+
ttkStyle = ttk.Style(self.ui)
|
|
20
|
+
if self.theme:
|
|
21
|
+
ttkStyle.theme_use(self.theme)
|
|
22
|
+
self.ui.withdraw()
|
|
23
|
+
|
|
24
|
+
super().update(prev)
|
|
25
|
+
|
|
26
|
+
def addChild(self, idx, child):
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
def removeChild(self, idx, child):
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
def start(self):
|
|
33
|
+
self.ui.mainloop()
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def PUIApp(func):
|
|
37
|
+
def func_wrapper(*args, **kwargs):
|
|
38
|
+
class PUIAppWrapper(Application):
|
|
39
|
+
def __init__(self, name):
|
|
40
|
+
self.name = name
|
|
41
|
+
super().__init__()
|
|
42
|
+
|
|
43
|
+
def content(self):
|
|
44
|
+
return func(*args, **kwargs)
|
|
45
|
+
|
|
46
|
+
ret = PUIAppWrapper(func.__name__)
|
|
47
|
+
return ret
|
|
48
|
+
|
|
49
|
+
return func_wrapper
|
PUI/tkinter/base.py
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
import tkinter as tk
|
|
3
|
+
from tkinter import ttk
|
|
4
|
+
from tkinter import font as tkFont
|
|
5
|
+
import functools
|
|
6
|
+
|
|
7
|
+
class TPUIView(PUIView):
|
|
8
|
+
pui_virtual = True
|
|
9
|
+
def redraw(self):
|
|
10
|
+
if self.ui:
|
|
11
|
+
self.ui.after(0, self.sync)
|
|
12
|
+
else:
|
|
13
|
+
self.sync()
|
|
14
|
+
|
|
15
|
+
class TkBaseWidget(PUINode):
|
|
16
|
+
use_ttk = False
|
|
17
|
+
pui_terminal = True
|
|
18
|
+
def __init__(self, layout=None, side=None):
|
|
19
|
+
super().__init__()
|
|
20
|
+
self.layout_type = layout
|
|
21
|
+
self.side = side
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def tkparent(self):
|
|
25
|
+
parent = self.parent
|
|
26
|
+
while not isinstance(parent, TkBaseWidget) and not isinstance(parent, TPUIView):
|
|
27
|
+
parent = parent.parent
|
|
28
|
+
if parent==parent.parent:
|
|
29
|
+
return None
|
|
30
|
+
return parent
|
|
31
|
+
|
|
32
|
+
def destroy(self, direct):
|
|
33
|
+
if self.ui:
|
|
34
|
+
self.ui.destroy() # tk's destroy
|
|
35
|
+
self.ui = None
|
|
36
|
+
|
|
37
|
+
def update(self, prev):
|
|
38
|
+
if not self.layout_width is None:
|
|
39
|
+
self.ui.configure(width=self.layout_width)
|
|
40
|
+
if not self.layout_height is None:
|
|
41
|
+
self.ui.configure(height=self.layout_height)
|
|
42
|
+
|
|
43
|
+
if self.use_ttk:
|
|
44
|
+
styleKey = f"S{id(self.ui)}.{self.use_ttk}"
|
|
45
|
+
tkstyle = ttk.Style()
|
|
46
|
+
if not self.style_color is None:
|
|
47
|
+
tkstyle.configure(styleKey, foreground=f"#{self.style_color:06X}")
|
|
48
|
+
if not self.style_bgcolor is None:
|
|
49
|
+
tkstyle.configure(styleKey, background=f"#{self.style_bgcolor:06X}")
|
|
50
|
+
if self.style_fontfamily or self.style_fontsize:
|
|
51
|
+
default = tkFont.nametofont('TkDefaultFont').actual()
|
|
52
|
+
font_family = self.style_fontfamily or default["family"]
|
|
53
|
+
font_size = self.style_fontsize or default["size"]
|
|
54
|
+
font_weight = self.style_fontweight or default["weight"]
|
|
55
|
+
tkstyle.configure(styleKey, font=(font_family, font_size, font_weight))
|
|
56
|
+
self.ui.configure(style=styleKey)
|
|
57
|
+
else:
|
|
58
|
+
if not self.style_color is None:
|
|
59
|
+
self.ui.configure(fg=f"#{self.style_color:06X}")
|
|
60
|
+
if not self.style_bgcolor is None:
|
|
61
|
+
self.ui.configure(bg=f"#{self.style_bgcolor:06X}")
|
|
62
|
+
if self.style_fontfamily or self.style_fontsize:
|
|
63
|
+
default = tkFont.nametofont('TkDefaultFont').actual()
|
|
64
|
+
font_family = self.style_fontfamily or default["family"]
|
|
65
|
+
font_size = self.style_fontsize or default["size"]
|
|
66
|
+
font_weight = self.style_fontweight or default["weight"]
|
|
67
|
+
self.ui.configure(font=(font_family, font_size, font_weight))
|
|
68
|
+
super().update(prev)
|
PUI/tkinter/button.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
class Button(TkBaseWidget):
|
|
4
|
+
def __init__(self, text):
|
|
5
|
+
super().__init__()
|
|
6
|
+
self.text = text
|
|
7
|
+
|
|
8
|
+
def update(self, prev):
|
|
9
|
+
if prev and prev.ui:
|
|
10
|
+
self.ui = prev.ui
|
|
11
|
+
self.ui.config(text = self.text)
|
|
12
|
+
self.ui.config(command = self._clicked)
|
|
13
|
+
else:
|
|
14
|
+
self.ui = tk.Button(self.tkparent.inner, text=self.text, command=self._clicked)
|
|
15
|
+
super().update(prev)
|
PUI/tkinter/canvas.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
import itertools
|
|
4
|
+
class Canvas(TkBaseWidget):
|
|
5
|
+
pui_terminal = True
|
|
6
|
+
def __init__(self, painter, *args):
|
|
7
|
+
super().__init__()
|
|
8
|
+
self.painter = painter
|
|
9
|
+
self.args = args
|
|
10
|
+
|
|
11
|
+
def update(self, prev):
|
|
12
|
+
if prev and prev.ui:
|
|
13
|
+
self.ui = prev.ui
|
|
14
|
+
else:
|
|
15
|
+
self.ui = tk.Canvas(self.tkparent.inner)
|
|
16
|
+
self.ui.delete("all")
|
|
17
|
+
|
|
18
|
+
self.painter(self, *self.args)
|
|
19
|
+
super().update(prev)
|
|
20
|
+
|
|
21
|
+
def drawText(self, x, y, text, w=None, h=None, rotate=0, anchor=Anchor.LEFT_TOP):
|
|
22
|
+
if rotate !=0:
|
|
23
|
+
print("drawText: rotate not implemented")
|
|
24
|
+
self.ui.create_text(x, y, text=text)
|
|
25
|
+
|
|
26
|
+
def drawLine(self, x1, y1, x2, y2, color=None, width=None):
|
|
27
|
+
params = {}
|
|
28
|
+
if not color is None:
|
|
29
|
+
params["fill"] = f"#{color:06X}"
|
|
30
|
+
if not width is None:
|
|
31
|
+
params["width"] = width
|
|
32
|
+
self.ui.create_line(x1, y1, x2, y2, **params)
|
|
33
|
+
|
|
34
|
+
def drawPolyline(self, coords, color=None, width=None):
|
|
35
|
+
params = {}
|
|
36
|
+
if not color is None:
|
|
37
|
+
params["fill"] = f"#{color:06X}"
|
|
38
|
+
if not width is None:
|
|
39
|
+
params["width"] = width
|
|
40
|
+
self.ui.create_line(*itertools.chain(*coords), **params)
|
|
41
|
+
|
|
42
|
+
def drawPolygon(self, coords, fill=None, stroke=None, width=1):
|
|
43
|
+
print("drawPolygon not implemented")
|
|
44
|
+
|
|
45
|
+
def drawRect(self, x1, y1, x2, y2, fill=None, stroke=None, width=1):
|
|
46
|
+
print("drawRect not implemented")
|
|
47
|
+
|
|
48
|
+
def drawEllipse(self, x, y, rx, ry, fill=None, stroke=None, width=1):
|
|
49
|
+
print("drawEllipse not implemented")
|
PUI/tkinter/checkbox.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
|
|
4
|
+
class Checkbox(TkBaseWidget):
|
|
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.var = prev.var
|
|
13
|
+
self.ui = prev.ui
|
|
14
|
+
else:
|
|
15
|
+
self.var = tk.IntVar()
|
|
16
|
+
self.ui = tk.Checkbutton(self.tkparent.inner, text=self.text, variable=self.var, anchor="w")
|
|
17
|
+
self.ui.configure(command=self._select)
|
|
18
|
+
if self.model.value:
|
|
19
|
+
self.ui.select()
|
|
20
|
+
else:
|
|
21
|
+
self.ui.deselect()
|
|
22
|
+
|
|
23
|
+
super().update(prev)
|
|
24
|
+
|
|
25
|
+
def _select(self):
|
|
26
|
+
node = self.get_node()
|
|
27
|
+
self.model.value = node.var.get() != 0
|
PUI/tkinter/label.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
class Label(TkBaseWidget):
|
|
4
|
+
def __init__(self, text, selectable=False):
|
|
5
|
+
super().__init__()
|
|
6
|
+
self.text = text
|
|
7
|
+
|
|
8
|
+
def update(self, prev):
|
|
9
|
+
if prev and prev.ui:
|
|
10
|
+
self.ui = prev.ui
|
|
11
|
+
self.ui.config(text = self.text)
|
|
12
|
+
else:
|
|
13
|
+
self.ui = tk.Label(self.tkparent.inner, text=self.text, anchor="w", justify="left")
|
|
14
|
+
self.ui.bind("<Button-1>", self._clicked)
|
|
15
|
+
if self._onClicked:
|
|
16
|
+
self.ui.config(cursor="")
|
|
17
|
+
super().update(prev)
|
PUI/tkinter/layout.py
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
|
|
4
|
+
class HBox(TkBaseWidget):
|
|
5
|
+
pui_terminal = False
|
|
6
|
+
|
|
7
|
+
use_ttk = "TFrame"
|
|
8
|
+
def update(self, prev):
|
|
9
|
+
if prev and prev.ui:
|
|
10
|
+
self.ui = prev.ui
|
|
11
|
+
self.ui_children = prev.ui_children
|
|
12
|
+
self.ui_gridmap = prev.ui_gridmap
|
|
13
|
+
else:
|
|
14
|
+
self.ui = ttk.Frame(self.tkparent.inner)
|
|
15
|
+
self.ui.grid_rowconfigure(0, weight=1)
|
|
16
|
+
self.ui_children = []
|
|
17
|
+
self.ui_gridmap = set()
|
|
18
|
+
super().update(prev)
|
|
19
|
+
|
|
20
|
+
def addChild(self, idx, child):
|
|
21
|
+
self.ui_children.insert(idx, child)
|
|
22
|
+
|
|
23
|
+
def removeChild(self, idx, child):
|
|
24
|
+
self.ui_children.pop(idx)
|
|
25
|
+
if isinstance(child, TkBaseWidget):
|
|
26
|
+
child_outer = child.outer
|
|
27
|
+
if child_outer:
|
|
28
|
+
child_outer.grid_forget()
|
|
29
|
+
|
|
30
|
+
def putChild(self, idx, child):
|
|
31
|
+
if isinstance(child, TkBaseWidget):
|
|
32
|
+
child.outer.grid(row=0, column=idx, sticky='nsew')
|
|
33
|
+
if child.layout_weight is None:
|
|
34
|
+
self.ui.grid_columnconfigure(idx, weight=0)
|
|
35
|
+
self.ui_gridmap.discard(idx)
|
|
36
|
+
else:
|
|
37
|
+
self.ui.grid_columnconfigure(idx, weight=child.layout_weight, uniform=".")
|
|
38
|
+
self.ui_gridmap.add(idx)
|
|
39
|
+
|
|
40
|
+
def postSync(self):
|
|
41
|
+
n = len(self.ui_children)
|
|
42
|
+
tbd = []
|
|
43
|
+
for i in self.ui_gridmap:
|
|
44
|
+
if i >= n:
|
|
45
|
+
self.ui.grid_columnconfigure(i, weight=0)
|
|
46
|
+
tbd.append(i)
|
|
47
|
+
for i in tbd:
|
|
48
|
+
self.ui_gridmap.discard(i)
|
|
49
|
+
|
|
50
|
+
for i,child in enumerate(self.ui_children):
|
|
51
|
+
self.putChild(i, child)
|
|
52
|
+
super().postSync()
|
|
53
|
+
|
|
54
|
+
class VBox(TkBaseWidget):
|
|
55
|
+
pui_terminal = False
|
|
56
|
+
|
|
57
|
+
use_ttk = "TFrame"
|
|
58
|
+
def update(self, prev):
|
|
59
|
+
if prev and prev.ui:
|
|
60
|
+
self.ui = prev.ui
|
|
61
|
+
self.ui_children = prev.ui_children
|
|
62
|
+
self.ui_gridmap = prev.ui_gridmap
|
|
63
|
+
else:
|
|
64
|
+
self.ui = ttk.Frame(self.tkparent.inner)
|
|
65
|
+
self.ui.grid_columnconfigure(0, weight=1)
|
|
66
|
+
self.ui_children = []
|
|
67
|
+
self.ui_gridmap = set()
|
|
68
|
+
super().update(prev)
|
|
69
|
+
|
|
70
|
+
def addChild(self, idx, child):
|
|
71
|
+
self.ui_children.insert(idx, child)
|
|
72
|
+
|
|
73
|
+
def removeChild(self, idx, child):
|
|
74
|
+
self.ui_children.pop(idx)
|
|
75
|
+
if isinstance(child, TkBaseWidget):
|
|
76
|
+
child_outer = child.outer
|
|
77
|
+
if child_outer:
|
|
78
|
+
child_outer.grid_forget()
|
|
79
|
+
|
|
80
|
+
def putChild(self, idx, child):
|
|
81
|
+
if isinstance(child, TkBaseWidget):
|
|
82
|
+
child.outer.grid(row=idx, column=0, sticky='nsew')
|
|
83
|
+
if child.layout_weight is None:
|
|
84
|
+
self.ui.grid_rowconfigure(idx, weight=0)
|
|
85
|
+
self.ui_gridmap.discard(idx)
|
|
86
|
+
else:
|
|
87
|
+
self.ui.grid_rowconfigure(idx, weight=child.layout_weight, uniform=".")
|
|
88
|
+
self.ui_gridmap.add(idx)
|
|
89
|
+
|
|
90
|
+
def postSync(self):
|
|
91
|
+
n = len(self.ui_children)
|
|
92
|
+
tbd = []
|
|
93
|
+
for i in self.ui_gridmap:
|
|
94
|
+
if i >= n:
|
|
95
|
+
self.ui.grid_rowconfigure(i, weight=0)
|
|
96
|
+
tbd.append(i)
|
|
97
|
+
for i in tbd:
|
|
98
|
+
self.ui_gridmap.discard(i)
|
|
99
|
+
|
|
100
|
+
for i,child in enumerate(self.ui_children):
|
|
101
|
+
self.putChild(i, child)
|
|
102
|
+
super().postSync()
|
|
103
|
+
|
|
104
|
+
class Spacer(TkBaseWidget):
|
|
105
|
+
use_ttk = "TFrame"
|
|
106
|
+
def __init__(self, *args):
|
|
107
|
+
super().__init__(*args)
|
|
108
|
+
self.layout_weight = 1
|
|
109
|
+
|
|
110
|
+
def update(self, prev):
|
|
111
|
+
if prev and prev.ui:
|
|
112
|
+
self.ui = prev.ui
|
|
113
|
+
else:
|
|
114
|
+
self.ui = ttk.Frame(self.tkparent.inner)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
|
|
4
|
+
class ProgressBar(TkBaseWidget):
|
|
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 = ttk.Progressbar(self.tkparent.inner)
|
|
15
|
+
self.ui["maximum"] = self.maximum
|
|
16
|
+
self.ui["value"] = self.progress
|
|
17
|
+
super().update(prev)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
|
|
4
|
+
class RadioButton(TkBaseWidget):
|
|
5
|
+
def __init__(self, text, value, model):
|
|
6
|
+
super().__init__()
|
|
7
|
+
self.var = None
|
|
8
|
+
self.text = text
|
|
9
|
+
self.value = value
|
|
10
|
+
self.model = model
|
|
11
|
+
|
|
12
|
+
def update(self, prev):
|
|
13
|
+
if prev and prev.ui:
|
|
14
|
+
self.var = prev.var
|
|
15
|
+
self.ui = prev.ui
|
|
16
|
+
else:
|
|
17
|
+
self.var = tk.StringVar()
|
|
18
|
+
self.ui = tk.Radiobutton(self.tkparent.inner, text=self.text, variable=self.var, value=self.value, anchor="w")
|
|
19
|
+
|
|
20
|
+
self.var.set(self.model.value)
|
|
21
|
+
self.ui.configure(command=self._select)
|
|
22
|
+
super().update(prev)
|
|
23
|
+
|
|
24
|
+
def _select(self):
|
|
25
|
+
node = self.get_node()
|
|
26
|
+
self.model.value = node.value
|
PUI/tkinter/scroll.py
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
from .. import *
|
|
2
|
+
from .base import *
|
|
3
|
+
import math
|
|
4
|
+
|
|
5
|
+
class ScrollableFrame(ttk.Frame):
|
|
6
|
+
def __init__(self, parent):
|
|
7
|
+
self.vertical = None
|
|
8
|
+
self.horizontal = False
|
|
9
|
+
|
|
10
|
+
self.container = ttk.Frame(parent)
|
|
11
|
+
self.container.rowconfigure(0, weight=1)
|
|
12
|
+
self.container.columnconfigure(0, weight=1)
|
|
13
|
+
|
|
14
|
+
self.scroll_y = tk.Scrollbar(self.container, orient=tk.VERTICAL)
|
|
15
|
+
self.scroll_x = tk.Scrollbar(self.container, orient=tk.HORIZONTAL)
|
|
16
|
+
self.should_scroll_y = False
|
|
17
|
+
self.should_scroll_x = False
|
|
18
|
+
self.last_bbox = None
|
|
19
|
+
self.last_scroll_x = None
|
|
20
|
+
self.last_scroll_y = None
|
|
21
|
+
|
|
22
|
+
self.canvas = tk.Canvas(self.container)
|
|
23
|
+
self.canvas.grid(row=0, column=0, sticky="nsew")
|
|
24
|
+
super().__init__(self.canvas)
|
|
25
|
+
self.canvas.create_window(0, 0, window=self, anchor="nw")
|
|
26
|
+
|
|
27
|
+
self.bind("<Configure>", self._on_configure)
|
|
28
|
+
|
|
29
|
+
def set_scroll(self, vertical, horizontal):
|
|
30
|
+
self.vertical = vertical
|
|
31
|
+
self.horizontal = horizontal
|
|
32
|
+
|
|
33
|
+
self.update_scroller()
|
|
34
|
+
|
|
35
|
+
def grid(self, *args, **kwargs):
|
|
36
|
+
self.container.grid(*args, **kwargs)
|
|
37
|
+
|
|
38
|
+
def configure(self, *args, **kwargs):
|
|
39
|
+
self.container.configure(*args, **kwargs)
|
|
40
|
+
|
|
41
|
+
def _on_configure(self, event):
|
|
42
|
+
self.update_scroller()
|
|
43
|
+
|
|
44
|
+
def update_scroller(self):
|
|
45
|
+
bbox = self.canvas.bbox("all")
|
|
46
|
+
_, _, w, h = bbox
|
|
47
|
+
self.canvas.configure(scrollregion=bbox)
|
|
48
|
+
if self.horizontal is False:
|
|
49
|
+
self.canvas.configure(width=w)
|
|
50
|
+
if self.vertical is False:
|
|
51
|
+
self.canvas.configure(height=h)
|
|
52
|
+
|
|
53
|
+
self.should_scroll_y = self.vertical or (self.vertical is None and h > self.canvas.winfo_height())
|
|
54
|
+
if self.should_scroll_y:
|
|
55
|
+
self.scroll_y.config(command=self.canvas.yview)
|
|
56
|
+
self.canvas.config(yscrollcommand=self._on_scroll_y)
|
|
57
|
+
self.scroll_y.grid(row=0, column=1, sticky="ns")
|
|
58
|
+
|
|
59
|
+
self.canvas.bind_all("<MouseWheel>", self._on_mousewheel_y)
|
|
60
|
+
self.canvas.bind("<Button-4>", self._on_mousewheel_y)
|
|
61
|
+
self.canvas.bind("<Button-5>", self._on_mousewheel_y)
|
|
62
|
+
else:
|
|
63
|
+
self.scroll_y.grid_forget()
|
|
64
|
+
|
|
65
|
+
self.should_scroll_x = self.horizontal or (self.horizontal is None and w > self.canvas.winfo_width())
|
|
66
|
+
if self.should_scroll_x:
|
|
67
|
+
self.scroll_x.config(command=self.canvas.xview)
|
|
68
|
+
self.canvas.config(xscrollcommand=self._on_scroll_x)
|
|
69
|
+
self.scroll_x.grid(row=1, column=0, sticky="ew")
|
|
70
|
+
else:
|
|
71
|
+
self.scroll_x.grid_forget()
|
|
72
|
+
|
|
73
|
+
def _on_scroll_x(self, first, last):
|
|
74
|
+
self.scroll_x.set(first, last)
|
|
75
|
+
bbox = self.canvas.bbox("all")
|
|
76
|
+
if self.last_bbox == bbox and self.last_scroll_x != (first,last):
|
|
77
|
+
if float(first) < 0.05:
|
|
78
|
+
self.puinode.align_x = 0
|
|
79
|
+
elif float(last) > 0.95:
|
|
80
|
+
self.puinode.align_x = 1
|
|
81
|
+
else:
|
|
82
|
+
self.last_bbox = bbox
|
|
83
|
+
self.last_scroll_x = (first,last)
|
|
84
|
+
|
|
85
|
+
def _on_scroll_y(self, first, last):
|
|
86
|
+
self.scroll_y.set(first, last)
|
|
87
|
+
bbox = self.canvas.bbox("all")
|
|
88
|
+
if self.last_bbox == bbox and self.last_scroll_y != (first,last):
|
|
89
|
+
if float(first) < 0.05:
|
|
90
|
+
self.puinode.align_y = 0
|
|
91
|
+
elif float(last) > 0.95:
|
|
92
|
+
self.puinode.align_y = 1
|
|
93
|
+
else:
|
|
94
|
+
self.last_bbox = bbox
|
|
95
|
+
self.last_scroll_y = (first,last)
|
|
96
|
+
|
|
97
|
+
def _on_mousewheel_y(self, event):
|
|
98
|
+
if not self.should_scroll_y:
|
|
99
|
+
return
|
|
100
|
+
if event.num == 5:
|
|
101
|
+
delta = 1
|
|
102
|
+
elif event.num == 4:
|
|
103
|
+
delta = -1
|
|
104
|
+
elif event.delta > 0:
|
|
105
|
+
delta = 1
|
|
106
|
+
elif event.delta < 0:
|
|
107
|
+
delta = -1
|
|
108
|
+
self.canvas.yview_scroll(delta, "units")
|
|
109
|
+
|
|
110
|
+
class Scroll(TkBaseWidget):
|
|
111
|
+
pui_terminal = False
|
|
112
|
+
|
|
113
|
+
use_ttk = "TFrame"
|
|
114
|
+
END = -0.0
|
|
115
|
+
def __init__(self, vertical=None, horizontal=False):
|
|
116
|
+
self.vertical = vertical
|
|
117
|
+
self.horizontal = horizontal
|
|
118
|
+
self.align_x = 0
|
|
119
|
+
self.align_y = 0
|
|
120
|
+
super().__init__()
|
|
121
|
+
self.layout_weight = 1
|
|
122
|
+
|
|
123
|
+
def update(self, prev):
|
|
124
|
+
if prev and prev.ui:
|
|
125
|
+
self.ui = prev.ui
|
|
126
|
+
self.align_x = prev.align_x
|
|
127
|
+
self.align_y = prev.align_y
|
|
128
|
+
else:
|
|
129
|
+
self.ui = ScrollableFrame(self.tkparent.inner)
|
|
130
|
+
self.ui.puinode = self
|
|
131
|
+
self.ui.set_scroll(self.vertical, self.horizontal)
|
|
132
|
+
|
|
133
|
+
super().update(prev)
|
|
134
|
+
|
|
135
|
+
def preSync(self):
|
|
136
|
+
bbox = self.ui.canvas.bbox("all")
|
|
137
|
+
_, _, w, h = bbox
|
|
138
|
+
hsb = self.ui.scroll_x
|
|
139
|
+
if self.align_x == 0:
|
|
140
|
+
self.hsb_offset = hsb.get()[0] * w
|
|
141
|
+
else:
|
|
142
|
+
self.hsb_offset = w - hsb.get()[1] * w
|
|
143
|
+
vsb = self.ui.scroll_y
|
|
144
|
+
if self.align_y == 0:
|
|
145
|
+
self.vsb_offset = vsb.get()[0] * h
|
|
146
|
+
else:
|
|
147
|
+
self.vsb_offset = h - vsb.get()[1] * h
|
|
148
|
+
|
|
149
|
+
def postSync(self):
|
|
150
|
+
self.ui.winfo_toplevel().update_idletasks()
|
|
151
|
+
|
|
152
|
+
oldincx = self.ui.canvas["xscrollincrement"]
|
|
153
|
+
oldincy = self.ui.canvas["yscrollincrement"]
|
|
154
|
+
self.ui.canvas["xscrollincrement"] = 1
|
|
155
|
+
self.ui.canvas["yscrollincrement"] = 1
|
|
156
|
+
|
|
157
|
+
bbox = self.ui.canvas.bbox("all")
|
|
158
|
+
_, _, w, h = bbox
|
|
159
|
+
if self.align_x == 0:
|
|
160
|
+
self.ui.canvas.xview_moveto(0.0)
|
|
161
|
+
self.ui.canvas.xview_scroll(int(self.hsb_offset), "units")
|
|
162
|
+
else:
|
|
163
|
+
self.ui.canvas.xview_moveto(1.0)
|
|
164
|
+
self.ui.canvas.xview_scroll(int(-self.hsb_offset), "units")
|
|
165
|
+
if self.align_y == 0:
|
|
166
|
+
self.ui.canvas.yview_moveto(0.0)
|
|
167
|
+
self.ui.canvas.yview_scroll(int(self.vsb_offset), "units")
|
|
168
|
+
else:
|
|
169
|
+
self.ui.canvas.yview_moveto(1.0)
|
|
170
|
+
self.ui.canvas.yview_scroll(int(-self.vsb_offset), "units")
|
|
171
|
+
|
|
172
|
+
self.ui.canvas["xscrollincrement"] = oldincx
|
|
173
|
+
self.ui.canvas["yscrollincrement"] = oldincy
|
|
174
|
+
|
|
175
|
+
def addChild(self, idx, child):
|
|
176
|
+
if idx:
|
|
177
|
+
return
|
|
178
|
+
child_outer = child.outer
|
|
179
|
+
if child_outer:
|
|
180
|
+
child_outer.grid(row=idx, column=0, sticky='nsew')
|
|
181
|
+
|
|
182
|
+
def removeChild(self, idx, child):
|
|
183
|
+
child.outer.grid_forget()
|
|
184
|
+
|
|
185
|
+
def scrollX(self, pos=0):
|
|
186
|
+
if math.copysign(1, pos) >= 0:
|
|
187
|
+
self.align_x = 0
|
|
188
|
+
self.hsb_offset = pos
|
|
189
|
+
else:
|
|
190
|
+
self.align_x = 1
|
|
191
|
+
self.hsb_offset = abs(pos)
|
|
192
|
+
return self
|
|
193
|
+
|
|
194
|
+
def scrollY(self, pos=0):
|
|
195
|
+
if math.copysign(1, pos) >= 0:
|
|
196
|
+
self.align_y = 0
|
|
197
|
+
self.vsb_offset = pos
|
|
198
|
+
else:
|
|
199
|
+
self.align_y = 1
|
|
200
|
+
self.vsb_offset = abs(pos)
|
|
201
|
+
return self
|
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
|
+
|