Skip to content

Commit 1e5bf3a

Browse files
committed
Banner control added
1 parent b8572de commit 1e5bf3a

File tree

4 files changed

+174
-1
lines changed

4 files changed

+174
-1
lines changed

client/lib/controls/banner.dart

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import 'package:flet_view/utils/colors.dart';
2+
import 'package:flutter/material.dart';
3+
import 'package:flutter_redux/flutter_redux.dart';
4+
5+
import '../models/app_state.dart';
6+
import '../models/control.dart';
7+
import '../utils/edge_insets.dart';
8+
import 'create_control.dart';
9+
import 'error.dart';
10+
11+
class BannerControl extends StatefulWidget implements ControlWidget {
12+
final Control? parent;
13+
final Control control;
14+
final List<Control> children;
15+
final bool parentDisabled;
16+
17+
const BannerControl(
18+
{Key? key,
19+
this.parent,
20+
required this.control,
21+
required this.children,
22+
required this.parentDisabled})
23+
: super(key: key);
24+
25+
@override
26+
State<BannerControl> createState() => _BannerControlState();
27+
}
28+
29+
class _BannerControlState extends State<BannerControl> {
30+
bool _open = false;
31+
32+
@override
33+
void initState() {
34+
super.initState();
35+
}
36+
37+
@override
38+
void dispose() {
39+
super.dispose();
40+
}
41+
42+
Widget _createBanner() {
43+
bool disabled = widget.control.isDisabled || widget.parentDisabled;
44+
var leadingCtrls = widget.children.where((c) => c.name == "leading");
45+
var contentCtrls = widget.children.where((c) => c.name == "content");
46+
var actionCtrls = widget.children.where((c) => c.name == "action");
47+
48+
if (contentCtrls.isEmpty) {
49+
return const ErrorControl("Banner does not have any content.");
50+
} else if (actionCtrls.isEmpty) {
51+
return const ErrorControl("Banner should have at least one action.");
52+
}
53+
54+
return MaterialBanner(
55+
leading: leadingCtrls.isNotEmpty
56+
? createControl(widget.control, leadingCtrls.first.id, disabled)
57+
: null,
58+
leadingPadding: parseEdgeInsets(widget.control, "leadingPadding"),
59+
content: createControl(widget.control, contentCtrls.first.id, disabled),
60+
padding: parseEdgeInsets(widget.control, "contentPadding"),
61+
actions: actionCtrls
62+
.map((c) => createControl(widget.control, c.id, disabled))
63+
.toList(),
64+
forceActionsBelow: widget.control.attrBool("forceActionsBelow", false)!,
65+
backgroundColor: HexColor.fromString(
66+
context, widget.control.attrString("bgcolor", "")!),
67+
);
68+
}
69+
70+
@override
71+
Widget build(BuildContext context) {
72+
debugPrint("Banner build: ${widget.control.id}");
73+
74+
return StoreConnector<AppState, Function>(
75+
distinct: true,
76+
converter: (store) => store.dispatch,
77+
builder: (context, dispatch) {
78+
debugPrint("Banner StoreConnector build: ${widget.control.id}");
79+
80+
var open = widget.control.attrBool("open", false)!;
81+
82+
debugPrint("Current open state: $_open");
83+
debugPrint("New open state: $open");
84+
85+
if (open && (open != _open)) {
86+
var banner = _createBanner();
87+
if (banner is ErrorControl) {
88+
return banner;
89+
}
90+
91+
WidgetsBinding.instance!.addPostFrameCallback((_) {
92+
ScaffoldMessenger.of(context).removeCurrentMaterialBanner();
93+
94+
ScaffoldMessenger.of(context)
95+
.showMaterialBanner(banner as MaterialBanner);
96+
});
97+
} else if (open != _open && _open) {
98+
WidgetsBinding.instance!.addPostFrameCallback((_) {
99+
ScaffoldMessenger.of(context).removeCurrentMaterialBanner();
100+
});
101+
}
102+
103+
_open = open;
104+
105+
return const SizedBox.shrink();
106+
});
107+
}
108+
}

client/lib/controls/create_control.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import '../models/control.dart';
66
import '../models/control_type.dart';
77
import '../models/control_view_model.dart';
88
import 'alert_dialog.dart';
9+
import 'banner.dart';
910
import 'checkbox.dart';
1011
import 'column.dart';
1112
import 'container.dart';
@@ -31,6 +32,16 @@ import 'text.dart';
3132
import 'text_button.dart';
3233
import 'textfield.dart';
3334

35+
abstract class ControlWidget extends Widget {
36+
const ControlWidget(
37+
{Key? key,
38+
required Control parent,
39+
required Control control,
40+
required List<Control> children,
41+
required bool parentDisabled})
42+
: super(key: key);
43+
}
44+
3445
Widget createControl(Control? parent, String id, bool parentDisabled) {
3546
return StoreConnector<AppState, ControlViewModel>(
3647
distinct: true,
@@ -166,6 +177,13 @@ Widget createControl(Control? parent, String id, bool parentDisabled) {
166177
control: controlView.control,
167178
children: controlView.children,
168179
parentDisabled: parentDisabled);
180+
case ControlType.banner:
181+
ControlWidget w = BannerControl(
182+
parent: parent,
183+
control: controlView.control,
184+
children: controlView.children,
185+
parentDisabled: parentDisabled);
186+
return w;
169187
default:
170188
throw Exception("Unknown control type: ${controlView.control.type}");
171189
}

sdk/python/flet/banner.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@ def _get_children(self):
6666
if self.__content:
6767
self.__content._set_attr_internal("n", "content")
6868
children.append(self.__content)
69-
children.extend(a._set_attr_internal("n", "action") for a in self.__actions)
69+
for action in self.__actions:
70+
action._set_attr_internal("n", "action")
71+
children.append(action)
7072
return children
7173

7274
# open
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import logging
2+
3+
import flet
4+
from flet import Banner, ElevatedButton, Icon, Text, TextButton, colors, icons
5+
6+
logging.basicConfig(level=logging.DEBUG)
7+
8+
9+
class Data:
10+
def __init__(self) -> None:
11+
self.counter = 0
12+
13+
14+
d = Data()
15+
16+
17+
def main(page):
18+
page.title = "SnackBar Example"
19+
page.update()
20+
21+
def close_banner(e):
22+
page.banner.open = False
23+
page.update()
24+
25+
page.banner = Banner(
26+
bgcolor=colors.AMBER_100,
27+
leading=Icon(icons.WARNING_AMBER_ROUNDED, color=colors.AMBER, size=40),
28+
content=Text(
29+
"Oops, there were some errors while trying to delete the file. What would you like me to do?"
30+
),
31+
actions=[
32+
TextButton("Retry", on_click=close_banner),
33+
TextButton("Ignore", on_click=close_banner),
34+
TextButton("Cancel", on_click=close_banner),
35+
],
36+
)
37+
38+
def show_banner_click(e):
39+
page.banner.open = True
40+
page.update()
41+
42+
page.add(ElevatedButton("Show Banner", on_click=show_banner_click))
43+
44+
45+
flet.app(name="test1", port=8550, target=main, view=flet.WEB_BROWSER)

0 commit comments

Comments
 (0)