Skip to content

Commit 2d114d7

Browse files
SplitStack control and TextBox control improvements (#66)
* SplitStack control * Dialog, Panel - default 'bool' props * New TextBox props: rows, shift_enter, resizable * SplitStack.on_resize event * Examples updated * Use Pglet 0.7.0 * BorderStyle allows arrays Affected controls: Image, IFrame, Stack, Text * 0.7.0 added to Changelog * Fix changelog [skip ci]
1 parent e4ef197 commit 2d114d7

17 files changed

Lines changed: 464 additions & 47 deletions

CHANGELOG.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,26 @@
11
# Change Log - Pglet client for Python
22

3+
## [0.7.0](https://pypi.org/project/pglet/0.7.0) - Feb 17, 2022
4+
5+
Works with [Pglet Server 0.7.0](https://github.com/pglet/pglet/releases/tag/v0.7.0).
6+
7+
New `SplitStack` control (based on [split.js](https://split.js.org/)) which could be used as a drop-in replacement for `Stack`, but with resize gutters instead of gaps. Check out [SplitStack control example](https://github.com/pglet/examples/blob/main/python/controls/split.py).
8+
9+
New `TextBox` control properties:
10+
* `shiftEnter` (bool) - blocks ENTER button in `multiline` TextBox, but pops up the event, so `Stack.submit` could be triggered. New line could still be entered with SHIFT+ENTER. This is to build Discord-like message box.
11+
* `rows` (int) - sets initial size in rows of `multiline` TextBox.
12+
* `resizable` (bool) - controls whether `multiline` TextBox is resizable by the user. Default is `true`. `autoAdjustHeight` is still respected even if `resizable` is `false`.
13+
14+
`Panel` control changes:
15+
* `blocking` (bool) is now `true` by default.
16+
17+
`border_style` property in `Image`, `IFrame`, `Stack` and `Text` allows lists, for example:
18+
19+
```python
20+
stack.border_style = ["solid", "double"] # top and bottom borders are solid, left and right are double
21+
```
22+
23+
324
## [0.6.0](https://pypi.org/project/pglet/0.6.0) - Feb 13, 2022
425

526
* Works with [Pglet Server 0.6.0](https://github.com/pglet/pglet/releases/tag/v0.6.0).

examples/chat.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,14 @@ def main(page):
3131
vertical_align="end",
3232
controls=[messages],
3333
)
34-
message = Textbox(width="100%")
34+
message = Textbox(
35+
width="100%",
36+
multiline=True,
37+
rows=1,
38+
auto_adjust_height=True,
39+
shift_enter=True,
40+
resizable=True,
41+
)
3542

3643
def on_message(user, message):
3744
if user:

examples/panel.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import pglet
2+
from pglet import Button, Checkbox, Panel, Text
3+
4+
with pglet.page("panel-custom") as page:
5+
6+
def button_clicked(e):
7+
8+
p.light_dismiss = light_dismiss.value
9+
p.auto_dismiss = auto_dismiss.value
10+
p.blocking = blocking.value
11+
values.value = (
12+
f"Panel properties are: {p.light_dismiss}, {p.auto_dismiss}, {p.blocking}."
13+
)
14+
p.open = True
15+
page.update()
16+
17+
values = Text()
18+
light_dismiss = Checkbox(label="Light dismiss", value=False)
19+
auto_dismiss = Checkbox(label="Auto-dismiss", value=True)
20+
blocking = Checkbox(label="Blocking", value=True)
21+
b = Button(text="Open panel", on_click=button_clicked)
22+
page.add(light_dismiss, auto_dismiss, blocking, b, values)
23+
24+
t = Text("Content goes here")
25+
26+
p = Panel(
27+
title="Panel with dismiss options",
28+
controls=[t],
29+
)
30+
31+
page.add(p)
32+
33+
input()

examples/split.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import logging
2+
3+
import pglet
4+
from pglet import SplitStack, Stack, Text
5+
from pglet.button import Button
6+
7+
logging.basicConfig(level=logging.DEBUG)
8+
9+
10+
def split_resize(e):
11+
for c in e.control.controls:
12+
print("size", c.width if e.control.horizontal else c.height)
13+
14+
15+
page = pglet.page("split1")
16+
page.title = "Split test"
17+
page.horizontal_align = "stretch"
18+
page.vertical_fill = True
19+
st = SplitStack(
20+
height="100%",
21+
horizontal=True,
22+
# gutter_color="#eee",
23+
gutter_size=10,
24+
on_resize=split_resize,
25+
controls=[
26+
Stack(width="200", min_width="200", height="100%", controls=[Text("Column A")]),
27+
Stack(height="100%", controls=[Text("Column B")]),
28+
Stack(
29+
height="100%",
30+
width="30%",
31+
controls=[
32+
SplitStack(
33+
height="100%",
34+
gutter_color="yellow",
35+
gutter_hover_color="orange",
36+
gutter_drag_color="blue",
37+
on_resize=split_resize,
38+
controls=[
39+
Stack(
40+
width="100%",
41+
bgcolor="lightGreen",
42+
controls=[Text("Row A")],
43+
),
44+
Stack(
45+
width="100%",
46+
height="200",
47+
max_height="400",
48+
bgcolor="lightGreen",
49+
controls=[Text("Row B")],
50+
),
51+
],
52+
)
53+
],
54+
),
55+
],
56+
)
57+
58+
59+
def btn_click(e):
60+
st.height = "90%"
61+
st.update()
62+
63+
64+
btn = Button("Click me!", on_click=btn_click)
65+
page.add(btn, st)
66+
67+
input()

pglet/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from pglet.slider import Slider
2929
from pglet.spinbutton import SpinButton
3030
from pglet.spinner import Spinner
31+
from pglet.splitstack import SplitStack
3132
from pglet.stack import Stack
3233
from pglet.tabs import Tab, Tabs
3334
from pglet.text import Text

pglet/constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
PGLET_SERVER_VERSION = "0.6.0"
1+
PGLET_SERVER_VERSION = "0.7.0"
22
PGLET_SERVER_DEFAULT_PORT = 8550
33
HOSTED_SERVICE_URL = "https://app.pglet.io"
44
CONNECT_TIMEOUT_SECONDS = 30

pglet/control.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,33 @@
11
import datetime as dt
22
import threading
3-
from typing import Optional
43
from difflib import SequenceMatcher
4+
from typing import List, Optional, Union
5+
6+
from beartype import beartype
7+
8+
from pglet.protocol import Command
59

610
try:
711
from typing import Literal
812
except:
913
from typing_extensions import Literal
1014

11-
from beartype import beartype
12-
13-
from pglet.protocol import Command
1415

15-
BorderStyle = Literal[
16-
None, "dotted", "dashed", "solid", "double", "groove", "ridge", "inset", "outset"
16+
BorderStyles = Literal[
17+
"none",
18+
"hidden",
19+
"dotted",
20+
"dashed",
21+
"solid",
22+
"double",
23+
"groove",
24+
"ridge",
25+
"inset",
26+
"outset",
1727
]
1828

29+
BorderStyle = Union[None, BorderStyles, List[BorderStyles]]
30+
1931
TextSize = Literal[
2032
None,
2133
"tiny",

pglet/dialog.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
from typing import Optional
2+
3+
from beartype import beartype
4+
5+
from pglet.control import Control
6+
27
try:
38
from typing import Literal
49
except:
510
from typing_extensions import Literal
611

7-
from beartype import beartype
8-
9-
from pglet.control import Control
1012

1113
DialogType = Literal[None, "normal", "largeHeader", "close"]
1214

@@ -129,7 +131,7 @@ def type(self, value: DialogType):
129131
# auto_dismiss
130132
@property
131133
def auto_dismiss(self):
132-
return self._get_attr("autoDismiss")
134+
return self._get_attr("autoDismiss", data_type="bool", def_value=True)
133135

134136
@auto_dismiss.setter
135137
@beartype

pglet/iframe.py

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1+
from typing import List
2+
13
from beartype import beartype
2-
from pglet.control import Control, BorderStyle
4+
5+
from pglet.control import BorderStyle, Control
36

47

58
class IFrame(Control):
69
def __init__(
710
self,
811
id=None,
912
src=None,
10-
border=None,
1113
border_style: BorderStyle = None,
1214
border_width=None,
1315
border_color=None,
@@ -33,7 +35,6 @@ def __init__(
3335
)
3436

3537
self.src = src
36-
self.border = border
3738
self.border_style = border_style
3839
self.border_width = border_width
3940
self.border_color = border_color
@@ -52,23 +53,19 @@ def src(self):
5253
def src(self, value):
5354
self._set_attr("src", value)
5455

55-
# border
56-
@property
57-
def border(self):
58-
return self._get_attr("border")
59-
60-
@border.setter
61-
def border(self, value):
62-
self._set_attr("border", value)
63-
6456
# border_style
6557
@property
6658
def border_style(self):
67-
return self._get_attr("borderStyle")
59+
v = self._get_attr("borderStyle")
60+
if v:
61+
return [x.strip() for x in v.split(" ")]
62+
return v
6863

6964
@border_style.setter
7065
@beartype
7166
def border_style(self, value: BorderStyle):
67+
if isinstance(value, List):
68+
value = " ".join(value)
7269
self._set_attr("borderStyle", value)
7370

7471
# border_width

pglet/image.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
from typing import Optional
1+
from typing import List, Optional
2+
3+
from beartype import beartype
4+
5+
from pglet.control import BorderStyle, Control
6+
27
try:
38
from typing import Literal
49
except:
510
from typing_extensions import Literal
611

7-
from beartype import beartype
8-
9-
from pglet.control import Control, BorderStyle
1012

1113
Fit = Literal[
1214
None, "none", "contain", "cover", "center", "centerContain", "centerCover"
@@ -108,11 +110,16 @@ def fit(self, value: Fit):
108110
# border_style
109111
@property
110112
def border_style(self):
111-
return self._get_attr("borderStyle")
113+
v = self._get_attr("borderStyle")
114+
if v:
115+
return [x.strip() for x in v.split(" ")]
116+
return v
112117

113118
@border_style.setter
114119
@beartype
115120
def border_style(self, value: BorderStyle):
121+
if isinstance(value, List):
122+
value = " ".join(value)
116123
self._set_attr("borderStyle", value)
117124

118125
# border_width

0 commit comments

Comments
 (0)