Skip to content

Commit fef1b70

Browse files
committed
Checkbox
1 parent edabac0 commit fef1b70

File tree

6 files changed

+182
-11
lines changed

6 files changed

+182
-11
lines changed

client/lib/controls/checkbox.dart

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_redux/flutter_redux.dart';
3+
4+
import '../actions.dart';
5+
import '../models/app_state.dart';
6+
import '../models/control.dart';
7+
import '../protocol/update_control_props_payload.dart';
8+
import '../web_socket_client.dart';
9+
import 'create_control.dart';
10+
11+
enum LabelPosition { right, left }
12+
13+
class CheckboxControl extends StatefulWidget {
14+
final Control? parent;
15+
final Control control;
16+
final bool parentDisabled;
17+
18+
const CheckboxControl(
19+
{Key? key,
20+
this.parent,
21+
required this.control,
22+
required this.parentDisabled})
23+
: super(key: key);
24+
25+
@override
26+
State<CheckboxControl> createState() => _CheckboxControlState();
27+
}
28+
29+
class _CheckboxControlState extends State<CheckboxControl> {
30+
bool? _value;
31+
32+
@override
33+
void initState() {
34+
super.initState();
35+
}
36+
37+
@override
38+
void dispose() {
39+
super.dispose();
40+
}
41+
42+
@override
43+
Widget build(BuildContext context) {
44+
debugPrint("Checkbox build: ${widget.control.id}");
45+
46+
String label = widget.control.attrString("label", "")!;
47+
LabelPosition labelPosition = LabelPosition.values.firstWhere(
48+
(p) =>
49+
p.name.toLowerCase() ==
50+
widget.control.attrString("labelPosition", "")!.toLowerCase(),
51+
orElse: () => LabelPosition.right);
52+
bool tristate = widget.control.attrBool("tristate", false)!;
53+
bool disabled = widget.control.isDisabled || widget.parentDisabled;
54+
55+
return StoreConnector<AppState, Function>(
56+
distinct: true,
57+
converter: (store) => store.dispatch,
58+
builder: (context, dispatch) {
59+
debugPrint("Checkbox StoreConnector build: ${widget.control.id}");
60+
61+
bool? value =
62+
widget.control.attrBool("value", tristate ? null : false);
63+
if (_value != value) {
64+
_value = value;
65+
}
66+
67+
onChange(bool? value) {
68+
debugPrint(value?.toString());
69+
setState(() {
70+
_value = value;
71+
});
72+
List<Map<String, String>> props = [
73+
{
74+
"i": widget.control.id,
75+
"value": value != null ? value.toString() : ""
76+
}
77+
];
78+
dispatch(UpdateControlPropsAction(
79+
UpdateControlPropsPayload(props: props)));
80+
ws.updateControlProps(props: props);
81+
}
82+
83+
var checkbox = Checkbox(
84+
value: _value,
85+
tristate: tristate,
86+
onChanged: !disabled
87+
? (bool? value) {
88+
onChange(value);
89+
}
90+
: null);
91+
92+
Widget result = checkbox;
93+
if (label != "") {
94+
var labelWidget = disabled
95+
? Text(label,
96+
style: TextStyle(color: Theme.of(context).disabledColor))
97+
: MouseRegion(
98+
cursor: SystemMouseCursors.click, child: Text(label));
99+
result = GestureDetector(
100+
onTap: !disabled
101+
? () {
102+
bool? newValue;
103+
if (!tristate) {
104+
newValue = !_value!;
105+
} else if (tristate && _value == null) {
106+
newValue = false;
107+
} else if (tristate && _value == false) {
108+
newValue = true;
109+
}
110+
onChange(newValue);
111+
}
112+
: null,
113+
child: labelPosition == LabelPosition.right
114+
? Row(children: [checkbox, labelWidget])
115+
: Row(children: [labelWidget, checkbox]));
116+
}
117+
118+
return constrainedControl(result, widget.parent, widget.control);
119+
});
120+
}
121+
}

client/lib/controls/create_control.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import '../models/app_state.dart';
55
import '../models/control.dart';
66
import '../models/control_type.dart';
77
import '../models/control_view_model.dart';
8+
import 'checkbox.dart';
89
import 'column.dart';
910
import 'container.dart';
1011
import 'dropdown.dart';
@@ -116,6 +117,11 @@ Widget createControl(Control? parent, String id, bool parentDisabled) {
116117
parent: parent,
117118
control: controlView.control,
118119
parentDisabled: parentDisabled);
120+
case ControlType.checkbox:
121+
return CheckboxControl(
122+
parent: parent,
123+
control: controlView.control,
124+
parentDisabled: parentDisabled);
119125
case ControlType.dropdown:
120126
return DropdownControl(
121127
parent: parent,

docs/roadmap.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
* [x] Text
1818
* [x] Icon
1919
* [x] Image (+custom assets directory for Flet server [see here](https://docs.flutter.dev/development/platform-integration/web-images)).
20-
* [ ] ProgressBar
21-
* [ ] ProgressRing
20+
* [x] ProgressBar
21+
* [x] ProgressRing
2222
* Buttons
2323
* [x] ElevatedButton
2424
* [x] OutlinedButton
@@ -759,9 +759,10 @@ Docs: https://api.flutter.dev/flutter/material/Checkbox-class.html
759759

760760
Properties:
761761

762+
- value
763+
- tristate
762764
- label
763765
- labelPosition
764-
- value
765766

766767
Events:
767768

sdk/python/flet/checkbox.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ def __init__(
3232
label: str = None,
3333
label_position: LabelPosition = None,
3434
value: bool = None,
35+
tristate: bool = None,
3536
on_change=None,
3637
):
3738
ConstrainedControl.__init__(
@@ -46,6 +47,7 @@ def __init__(
4647
data=data,
4748
)
4849
self.value = value
50+
self.tristate = tristate
4951
self.label = label
5052
self.label_position = label_position
5153
self.on_change = on_change
@@ -63,6 +65,16 @@ def value(self):
6365
def value(self, value: Optional[bool]):
6466
self._set_attr("value", value)
6567

68+
# tristate
69+
@property
70+
def tristate(self):
71+
return self._get_attr("tristate", data_type="bool", def_value=False)
72+
73+
@tristate.setter
74+
@beartype
75+
def tristate(self, value: Optional[bool]):
76+
self._set_attr("tristate", value)
77+
6678
# label
6779
@property
6880
def label(self):

sdk/python/playground/form-test.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import logging
2+
from datetime import datetime
3+
from time import sleep
4+
5+
import flet
6+
from flet import Column, ElevatedButton, Image, Page, Row, Text, Theme, padding
7+
from flet.checkbox import Checkbox
8+
from flet.stack import Stack
9+
10+
logging.basicConfig(level=logging.DEBUG)
11+
12+
13+
def main(page: Page):
14+
page.title = "Form Example"
15+
page.theme_mode = "light"
16+
page.padding = padding.all(20)
17+
18+
page.add(
19+
Checkbox(value=True),
20+
Checkbox(label="A simple checkbox with a label"),
21+
Checkbox(label="Checkbox with tristate", tristate=True),
22+
Checkbox(label="Disabled checkbox", disabled=True),
23+
Checkbox(label="Label on the left", label_position="left"),
24+
)
25+
26+
27+
flet.app(name="test1", port=8550, target=main, view=flet.WEB_BROWSER)

sdk/python/playground/progress-indicators.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import flet
66
from flet import Column, ElevatedButton, Image, Page, Row, Text, Theme, padding
7+
from flet.progress_bar import ProgressBar
78
from flet.progress_ring import ProgressRing
89
from flet.stack import Stack
910

@@ -17,22 +18,25 @@ def main(page: Page):
1718
page.update()
1819

1920
pr = ProgressRing(width=16, height=16, stroke_width=2)
20-
r = Row([pr, Text("Wait for the completion...")])
21-
22-
pr2 = ProgressRing()
23-
c = Column(
24-
[pr2, Text("I'm going to run for ages...")], horizontal_alignment="center"
25-
)
21+
pb = ProgressBar(width=400)
2622

2723
page.add(
2824
Text("Circle progress indicator", style="headlineSmall"),
29-
r,
25+
Row([pr, Text("Wait for the completion...")]),
3026
Text("Indeterminate cicrular progress", style="headlineSmall"),
31-
c,
27+
Column(
28+
[ProgressRing(), Text("I'm going to run for ages...")],
29+
horizontal_alignment="center",
30+
),
31+
Text("Linear progress indicator", style="headlineSmall"),
32+
Column([Text("Doing something..."), pb]),
33+
Text("Indeterminated progress bar", style="headlineSmall"),
34+
ProgressBar(width=400, color="amber", bgcolor="#eeeeee"),
3235
)
3336

3437
for i in range(0, 101):
3538
pr.value = i * 0.01
39+
pb.value = i * 0.01
3640
sleep(0.1)
3741
page.update()
3842

0 commit comments

Comments
 (0)