Skip to content

Commit ff9206d

Browse files
Control Refs (#70)
* Refs implementation draft * Ref added to all controls * Fixed tests
1 parent 09c670c commit ff9206d

39 files changed

+270
-46
lines changed

examples/chat-ref.py

+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# import logging
2+
3+
import pglet
4+
from pglet import Button, Dialog, Stack, Text, Textbox
5+
from pglet.ref import Ref
6+
7+
# logging.basicConfig(level=logging.DEBUG)
8+
9+
pub_sub = {}
10+
11+
12+
def broadcast(user, message):
13+
for session_id, handler in pub_sub.items():
14+
handler(user, message)
15+
16+
17+
def main(page):
18+
19+
page.padding = 10
20+
page.vertical_fill = True
21+
page.title = "Pglet Chat Example"
22+
page.bgcolor = "neutralLight"
23+
page.theme = "light" # "dark"
24+
25+
username_dialog = Ref[Dialog]()
26+
username = Ref[Textbox]()
27+
messages = Ref[Stack]()
28+
message = Ref[Textbox]()
29+
30+
def on_message(user, message):
31+
if user:
32+
messages.current.controls.append(Text(f"{user}: {message}"))
33+
else:
34+
messages.current.controls.append(
35+
Text(message, color="#888", size="small", italic=True)
36+
)
37+
page.update()
38+
39+
pub_sub[page.session_id] = on_message
40+
41+
def send_click(e):
42+
if message.current.value == "":
43+
return
44+
broadcast(page.user, message.current.value)
45+
message.current.value = ""
46+
page.update()
47+
48+
page.user = page.session_id
49+
50+
def join_click(e):
51+
if username.current.value == "":
52+
username.current.error_message = "Name cannot be blank!"
53+
username.current.update()
54+
else:
55+
page.user = username.current.value
56+
username_dialog.current.open = False
57+
# user_name.focused = False
58+
message.current.prefix = f"{page.user}:"
59+
message.current.focused = True
60+
page.update()
61+
broadcast(None, f"{page.user} entered the chat!")
62+
63+
# layout
64+
page.add(
65+
Stack(
66+
height="100%",
67+
width="100%",
68+
bgcolor="white",
69+
padding=10,
70+
border_radius=5,
71+
vertical_align="end",
72+
controls=[Stack(ref=messages, scroll_y=True, auto_scroll=True)],
73+
),
74+
Stack(
75+
horizontal=True,
76+
width="100%",
77+
controls=[
78+
Textbox(
79+
ref=message,
80+
width="100%",
81+
multiline=True,
82+
rows=1,
83+
auto_adjust_height=True,
84+
shift_enter=True,
85+
resizable=False,
86+
),
87+
Button("Send", primary=True, on_click=send_click),
88+
],
89+
on_submit=send_click,
90+
),
91+
Dialog(
92+
ref=username_dialog,
93+
open=True,
94+
blocking=True,
95+
auto_dismiss=False,
96+
title="Welcome!",
97+
controls=[Textbox(ref=username, label="Enter your name", focused=True)],
98+
footer=[Button(text="Join chat", primary=True, on_click=join_click)],
99+
),
100+
)
101+
102+
103+
pglet.app("chat", target=main, web=False)

pglet/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from pglet.piechart import PieChart
2525
from pglet.progress import Progress
2626
from pglet.reconnecting_websocket import *
27+
from pglet.ref import Ref
2728
from pglet.searchbox import SearchBox
2829
from pglet.slider import Slider
2930
from pglet.spinbutton import SpinButton

pglet/barchart.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class BarChart(Control):
1717
def __init__(
1818
self,
1919
id=None,
20+
ref=None,
2021
tooltips=None,
2122
data_mode: DataMode = None,
2223
points=None,
@@ -31,6 +32,7 @@ def __init__(
3132
Control.__init__(
3233
self,
3334
id=id,
35+
ref=ref,
3436
width=width,
3537
height=height,
3638
padding=padding,
@@ -80,8 +82,8 @@ def _get_children(self):
8082

8183

8284
class Data(Control):
83-
def __init__(self, id=None, points=None):
84-
Control.__init__(self, id=id)
85+
def __init__(self, id=None, ref=None, points=None):
86+
Control.__init__(self, id=id, ref=ref)
8587

8688
self.__points = []
8789
if points != None:
@@ -108,14 +110,15 @@ class Point(Control):
108110
def __init__(
109111
self,
110112
id=None,
113+
ref=None,
111114
x=None,
112115
y=None,
113116
legend=None,
114117
color=None,
115118
x_tooltip=None,
116119
y_tooltip=None,
117120
):
118-
Control.__init__(self, id=id)
121+
Control.__init__(self, id=id, ref=ref)
119122

120123
self.x = x
121124
self.y = y

pglet/button.py

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ def __init__(
1010
self,
1111
text=None,
1212
id=None,
13+
ref=None,
1314
primary=None,
1415
compound=None,
1516
action=None,
@@ -37,6 +38,7 @@ def __init__(
3738
Control.__init__(
3839
self,
3940
id=id,
41+
ref=ref,
4042
width=width,
4143
height=height,
4244
padding=padding,
@@ -239,6 +241,7 @@ def __init__(
239241
self,
240242
text=None,
241243
id=None,
244+
ref=None,
242245
secondary_text=None,
243246
url=None,
244247
new_window=None,
@@ -260,6 +263,7 @@ def __init__(
260263
Control.__init__(
261264
self,
262265
id=id,
266+
ref=ref,
263267
width=width,
264268
height=height,
265269
padding=padding,

pglet/callout.py

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class Callout(Control):
3333
def __init__(
3434
self,
3535
id=None,
36+
ref=None,
3637
target=None,
3738
position: Position = None,
3839
gap=None,
@@ -54,6 +55,7 @@ def __init__(
5455
Control.__init__(
5556
self,
5657
id=id,
58+
ref=ref,
5759
width=width,
5860
height=height,
5961
padding=padding,

pglet/checkbox.py

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ def __init__(
1818
self,
1919
label=None,
2020
id=None,
21+
ref=None,
2122
value=None,
2223
value_field=None,
2324
box_side: BoxSide = None,
@@ -34,6 +35,7 @@ def __init__(
3435
Control.__init__(
3536
self,
3637
id=id,
38+
ref=ref,
3739
width=width,
3840
height=height,
3941
padding=padding,

pglet/choicegroup.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ def __init__(
1010
self,
1111
label=None,
1212
id=None,
13+
ref=None,
1314
value=None,
1415
data=None,
1516
options=None,
@@ -27,6 +28,7 @@ def __init__(
2728
Control.__init__(
2829
self,
2930
id=id,
31+
ref=ref,
3032
width=width,
3133
height=height,
3234
padding=padding,
@@ -118,8 +120,8 @@ def on_blur(self, handler):
118120

119121

120122
class Option(Control):
121-
def __init__(self, key=None, text=None, icon=None, icon_color=None):
122-
Control.__init__(self)
123+
def __init__(self, key=None, text=None, icon=None, icon_color=None, ref=None):
124+
Control.__init__(self, ref=ref)
123125
assert key != None or text != None, "key or text must be specified"
124126

125127
self.key = key

pglet/combobox.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ def __init__(
1919
self,
2020
label=None,
2121
id=None,
22+
ref=None,
2223
value: ComboBoxValue = None,
2324
placeholder=None,
2425
error_message=None,
@@ -41,6 +42,7 @@ def __init__(
4142
Control.__init__(
4243
self,
4344
id=id,
45+
ref=ref,
4446
width=width,
4547
height=height,
4648
padding=padding,
@@ -186,8 +188,10 @@ def on_blur(self, handler):
186188

187189

188190
class Option(Control):
189-
def __init__(self, key=None, text=None, item_type: ItemType = None, disabled=None):
190-
Control.__init__(self, disabled=disabled)
191+
def __init__(
192+
self, key=None, text=None, item_type: ItemType = None, disabled=None, ref=None
193+
):
194+
Control.__init__(self, ref=ref, disabled=disabled)
191195
assert key != None or text != None, "key or text must be specified"
192196
self.key = key
193197
self.text = text

pglet/control.py

+10-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from beartype import beartype
77

88
from pglet.protocol import Command
9+
from pglet.ref import Ref
910

1011
try:
1112
from typing import Literal
@@ -27,9 +28,9 @@
2728
]
2829

2930
BorderStyle = Union[None, BorderStyles, List[BorderStyles]]
30-
BorderWidth = Union[None, str, List[str]]
31+
BorderWidth = Union[None, str, int, float, List[str], List[int], List[float]]
3132
BorderColor = Union[None, str, List[str]]
32-
BorderRadius = Union[None, str, List[str]]
33+
BorderRadius = Union[None, str, int, float, List[str], List[int], List[float]]
3334

3435
TextSize = Literal[
3536
None,
@@ -53,6 +54,7 @@ class Control:
5354
def __init__(
5455
self,
5556
id=None,
57+
ref: Ref = None,
5658
width=None,
5759
height=None,
5860
padding=None,
@@ -77,6 +79,11 @@ def __init__(
7779
self.data = data
7880
self.__event_handlers = {}
7981
self._lock = threading.Lock()
82+
if ref:
83+
ref.current = self
84+
85+
def _assign(self, variable):
86+
variable = self
8087

8188
def _get_children(self):
8289
return []
@@ -114,7 +121,7 @@ def _get_value_or_list_attr(self, name, delimiter):
114121

115122
def _set_value_or_list_attr(self, name, value, delimiter):
116123
if isinstance(value, List):
117-
value = delimiter.join(value)
124+
value = delimiter.join([str(x) for x in value])
118125
self._set_attr(name, value)
119126

120127
def _set_attr_internal(self, name, value, dirty=True):

pglet/datepicker.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ def __init__(
1111
self,
1212
label=None,
1313
id=None,
14+
ref=None,
1415
value=None,
1516
placeholder=None,
1617
required=None,
@@ -25,7 +26,9 @@ def __init__(
2526
visible=None,
2627
disabled=None,
2728
):
28-
Control.__init__(self, id=id, width=width, visible=visible, disabled=disabled)
29+
Control.__init__(
30+
self, id=id, ref=ref, width=width, visible=visible, disabled=disabled
31+
)
2932
self.label = label
3033
self.value = value
3134
self.placeholder = placeholder

pglet/dialog.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class Dialog(Control):
1717
def __init__(
1818
self,
1919
id=None,
20+
ref=None,
2021
open=None,
2122
title=None,
2223
sub_text=None,
@@ -40,6 +41,7 @@ def __init__(
4041
Control.__init__(
4142
self,
4243
id=id,
44+
ref=ref,
4345
width=width,
4446
height=height,
4547
padding=padding,
@@ -177,8 +179,8 @@ def _get_children(self):
177179

178180

179181
class Footer(Control):
180-
def __init__(self, id=None, controls=None):
181-
Control.__init__(self, id=id)
182+
def __init__(self, id=None, ref=None, controls=None):
183+
Control.__init__(self, id=id, ref=ref)
182184

183185
self.__controls = []
184186
if controls != None:

pglet/dropdown.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ def __init__(
1818
self,
1919
label=None,
2020
id=None,
21+
ref=None,
2122
value=None,
2223
placeholder=None,
2324
error_message=None,
@@ -37,6 +38,7 @@ def __init__(
3738
Control.__init__(
3839
self,
3940
id=id,
41+
ref=ref,
4042
width=width,
4143
height=height,
4244
padding=padding,
@@ -148,8 +150,10 @@ def on_blur(self, handler):
148150

149151

150152
class Option(Control):
151-
def __init__(self, key=None, text=None, item_type: ItemType = None, disabled=None):
152-
Control.__init__(self, disabled=disabled)
153+
def __init__(
154+
self, key=None, text=None, item_type: ItemType = None, disabled=None, ref=None
155+
):
156+
Control.__init__(self, ref=ref, disabled=disabled)
153157
assert key != None or text != None, "key or text must be specified"
154158
self.key = key
155159
self.text = text

0 commit comments

Comments
 (0)