Skip to content

Commit 33951b1

Browse files
Pagelet control (#2469)
* Pagelet control initial commit * appbar property incomplete * Pagelet and AppBar * navigation_bar and bottom_appbar properties * bottom_sheet property * drawer and endDrawer started * Added drawers * drawer property - drawer is not opening * drawer, end_drawer properties work * floating_action_button, floating_action_button_location * clean up * fixed imports --------- Co-authored-by: Feodor Fitsner <[email protected]>
1 parent 7fa9de7 commit 33951b1

File tree

4 files changed

+576
-1
lines changed

4 files changed

+576
-1
lines changed

package/lib/src/controls/create_control.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ import 'navigation_bar.dart';
6767
import 'navigation_rail.dart';
6868
import 'outlined_button.dart';
6969
import 'page.dart';
70+
import 'pagelet.dart';
7071
import 'piechart.dart';
7172
import 'popup_menu_button.dart';
7273
import 'progress_bar.dart';
@@ -259,6 +260,14 @@ Widget createWidget(Key? key, ControlViewModel controlView, Control? parent,
259260
children: controlView.children,
260261
parentDisabled: parentDisabled,
261262
dispatch: controlView.dispatch);
263+
case "pagelet":
264+
return PageletControl(
265+
key: key,
266+
parent: parent,
267+
control: controlView.control,
268+
children: controlView.children,
269+
parentDisabled: parentDisabled,
270+
dispatch: controlView.dispatch);
262271
case "progressring":
263272
return ProgressRingControl(
264273
key: key, parent: parent, control: controlView.control);
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
import 'package:collection/collection.dart';
2+
import 'package:flutter/cupertino.dart';
3+
import 'package:flutter/material.dart';
4+
import 'package:flutter_redux/flutter_redux.dart';
5+
6+
import '../actions.dart';
7+
import '../flet_app_services.dart';
8+
import '../models/app_state.dart';
9+
import '../models/control.dart';
10+
import '../models/controls_view_model.dart';
11+
import '../protocol/update_control_props_payload.dart';
12+
import '../utils/colors.dart';
13+
import 'app_bar.dart';
14+
import 'create_control.dart';
15+
import 'cupertino_app_bar.dart';
16+
import 'error.dart';
17+
import 'floating_action_button.dart';
18+
import 'navigation_drawer.dart';
19+
20+
class PageletControl extends StatefulWidget {
21+
final Control? parent;
22+
final Control control;
23+
final List<Control> children;
24+
final bool parentDisabled;
25+
final dynamic dispatch;
26+
27+
const PageletControl(
28+
{super.key,
29+
this.parent,
30+
required this.control,
31+
required this.children,
32+
required this.parentDisabled,
33+
required this.dispatch});
34+
35+
@override
36+
State<PageletControl> createState() => _PageletControlState();
37+
}
38+
39+
class _PageletControlState extends State<PageletControl> {
40+
final scaffoldKey = GlobalKey<ScaffoldState>();
41+
42+
@override
43+
Widget build(BuildContext context) {
44+
debugPrint("Pagelet build: ${widget.control.id}");
45+
46+
var appBarCtrls =
47+
widget.children.where((c) => c.name == "appbar" && c.isVisible);
48+
var contentCtrls =
49+
widget.children.where((c) => c.name == "content" && c.isVisible);
50+
var navigationBarCtrls =
51+
widget.children.where((c) => c.name == "navigationbar" && c.isVisible);
52+
var bottomAppBarCtrls =
53+
widget.children.where((c) => c.name == "bottomappbar" && c.isVisible);
54+
var bottomSheetCtrls =
55+
widget.children.where((c) => c.name == "bottomsheet" && c.isVisible);
56+
var drawerCtrls =
57+
widget.children.where((c) => c.name == "drawer" && c.isVisible);
58+
var endDrawerCtrls =
59+
widget.children.where((c) => c.name == "enddrawer" && c.isVisible);
60+
var fabCtrls = widget.children
61+
.where((c) => c.name == "floatingactionbutton" && c.isVisible);
62+
63+
if (contentCtrls.isEmpty) {
64+
return const ErrorControl("Pagelet must have content specified.");
65+
}
66+
67+
bool disabled = widget.control.isDisabled || widget.parentDisabled;
68+
69+
var bgcolor = HexColor.fromString(
70+
Theme.of(context), widget.control.attrString("bgcolor", "")!);
71+
72+
List<String> childIds = [
73+
appBarCtrls.firstOrNull?.id,
74+
drawerCtrls.firstOrNull?.id,
75+
endDrawerCtrls.firstOrNull?.id
76+
].whereNotNull().toList();
77+
78+
return StoreConnector<AppState, ControlsViewModel>(
79+
distinct: true,
80+
converter: (store) => ControlsViewModel.fromStore(store, childIds),
81+
ignoreChange: (state) {
82+
//debugPrint("ignoreChange: $id");
83+
for (var id in childIds) {
84+
if (state.controls[id] == null) {
85+
return true;
86+
}
87+
}
88+
return false;
89+
},
90+
builder: (context, childrenViews) {
91+
var navBar = navigationBarCtrls.isNotEmpty
92+
? createControl(
93+
widget.control, navigationBarCtrls.first.id, disabled)
94+
: null;
95+
var bottomAppBar = bottomAppBarCtrls.isNotEmpty
96+
? createControl(
97+
widget.control, bottomAppBarCtrls.first.id, disabled)
98+
: null;
99+
var bnb = navBar ?? bottomAppBar;
100+
101+
var appBarView = childrenViews.controlViews.firstWhereOrNull(
102+
(v) => v.control.id == (appBarCtrls.firstOrNull?.id ?? ""));
103+
104+
var drawerView = childrenViews.controlViews.firstWhereOrNull(
105+
(v) => v.control.id == (drawerCtrls.firstOrNull?.id ?? ""));
106+
var endDrawerView = childrenViews.controlViews.firstWhereOrNull(
107+
(v) => v.control.id == (endDrawerCtrls.firstOrNull?.id ?? ""));
108+
109+
final bool? drawerOpened = widget.control.state["drawerOpened"];
110+
final bool? endDrawerOpened = widget.control.state["endDrawerOpened"];
111+
112+
final fabLocation = parseFloatingActionButtonLocation(
113+
widget.control,
114+
"floatingActionButtonLocation",
115+
FloatingActionButtonLocation.endFloat);
116+
117+
void dismissDrawer(String id) {
118+
List<Map<String, String>> props = [
119+
{"i": id, "open": "false"}
120+
];
121+
widget.dispatch(UpdateControlPropsAction(
122+
UpdateControlPropsPayload(props: props)));
123+
FletAppServices.of(context).server.updateControlProps(props: props);
124+
FletAppServices.of(context).server.sendPageEvent(
125+
eventTarget: id, eventName: "dismiss", eventData: "");
126+
}
127+
128+
WidgetsBinding.instance.addPostFrameCallback((_) {
129+
if (drawerView != null) {
130+
if (scaffoldKey.currentState?.isDrawerOpen == false &&
131+
drawerOpened == true) {
132+
widget.control.state["drawerOpened"] = false;
133+
dismissDrawer(drawerView.control.id);
134+
}
135+
if (drawerView.control.attrBool("open", false)! &&
136+
drawerOpened != true) {
137+
if (scaffoldKey.currentState?.isEndDrawerOpen == true) {
138+
scaffoldKey.currentState?.closeEndDrawer();
139+
}
140+
Future.delayed(const Duration(milliseconds: 1)).then((value) {
141+
scaffoldKey.currentState?.openDrawer();
142+
widget.control.state["drawerOpened"] = true;
143+
});
144+
} else if (!drawerView.control.attrBool("open", false)! &&
145+
drawerOpened == true) {
146+
scaffoldKey.currentState?.closeDrawer();
147+
widget.control.state["drawerOpened"] = false;
148+
}
149+
}
150+
if (endDrawerView != null) {
151+
if (scaffoldKey.currentState?.isEndDrawerOpen == false &&
152+
endDrawerOpened == true) {
153+
widget.control.state["endDrawerOpened"] = false;
154+
dismissDrawer(endDrawerView.control.id);
155+
}
156+
if (endDrawerView.control.attrBool("open", false)! &&
157+
endDrawerOpened != true) {
158+
if (scaffoldKey.currentState?.isDrawerOpen == true) {
159+
scaffoldKey.currentState?.closeDrawer();
160+
}
161+
Future.delayed(const Duration(milliseconds: 1)).then((value) {
162+
scaffoldKey.currentState?.openEndDrawer();
163+
widget.control.state["endDrawerOpened"] = true;
164+
});
165+
} else if (!endDrawerView.control.attrBool("open", false)! &&
166+
endDrawerOpened == true) {
167+
scaffoldKey.currentState?.closeEndDrawer();
168+
widget.control.state["endDrawerOpened"] = false;
169+
}
170+
}
171+
});
172+
173+
var bar = appBarView != null
174+
? appBarView.control.type == "appbar"
175+
? AppBarControl(
176+
parent: widget.control,
177+
control: appBarView.control,
178+
children: appBarView.children,
179+
parentDisabled: widget.control.isDisabled,
180+
height: appBarView.control
181+
.attrDouble("toolbarHeight", kToolbarHeight)!)
182+
: appBarView.control.type == "cupertinoappbar"
183+
? CupertinoAppBarControl(
184+
parent: widget.control,
185+
control: appBarView.control,
186+
children: appBarView.children,
187+
parentDisabled: widget.control.isDisabled,
188+
bgcolor: HexColor.fromString(Theme.of(context),
189+
appBarView.control.attrString("bgcolor", "")!),
190+
) as ObstructingPreferredSizeWidget
191+
: null
192+
: null;
193+
return constrainedControl(
194+
context,
195+
Scaffold(
196+
key: scaffoldKey,
197+
appBar: bar,
198+
backgroundColor: bgcolor,
199+
//backgroundColor: Colors.red,
200+
drawer: drawerView != null
201+
? NavigationDrawerControl(
202+
control: drawerView.control,
203+
children: drawerView.children,
204+
parentDisabled: widget.control.isDisabled,
205+
dispatch: widget.dispatch,
206+
)
207+
: null,
208+
onDrawerChanged: (opened) {
209+
if (drawerView != null && !opened) {
210+
widget.control.state["drawerOpened"] = false;
211+
dismissDrawer(drawerView.control.id);
212+
}
213+
},
214+
endDrawer: endDrawerView != null
215+
? NavigationDrawerControl(
216+
control: endDrawerView.control,
217+
children: endDrawerView.children,
218+
parentDisabled: widget.control.isDisabled,
219+
dispatch: widget.dispatch,
220+
)
221+
: null,
222+
onEndDrawerChanged: (opened) {
223+
if (endDrawerView != null && !opened) {
224+
widget.control.state["endDrawerOpened"] = false;
225+
dismissDrawer(endDrawerView.control.id);
226+
}
227+
},
228+
body: contentCtrls.isNotEmpty
229+
? createControl(
230+
widget.control, contentCtrls.first.id, disabled)
231+
: null,
232+
bottomNavigationBar: bnb,
233+
bottomSheet: bottomSheetCtrls.isNotEmpty
234+
? createControl(
235+
widget.control, bottomSheetCtrls.first.id, disabled)
236+
: null,
237+
floatingActionButton: fabCtrls.isNotEmpty
238+
? createControl(
239+
widget.control, fabCtrls.first.id, disabled)
240+
: null,
241+
floatingActionButtonLocation: fabLocation),
242+
widget.parent,
243+
widget.control);
244+
});
245+
}
246+
}

sdk/python/packages/flet-core/src/flet_core/__init__.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,11 @@
8181
DataTable,
8282
)
8383
from flet_core.date_picker import DatePicker, DatePickerEntryMode, DatePickerMode
84-
from flet_core.dismissible import Dismissible, DismissibleDismissEvent, DismissibleUpdateEvent
84+
from flet_core.dismissible import (
85+
Dismissible,
86+
DismissibleDismissEvent,
87+
DismissibleUpdateEvent,
88+
)
8589
from flet_core.divider import Divider
8690
from flet_core.drag_target import DragTarget, DragTargetAcceptEvent
8791
from flet_core.draggable import Draggable
@@ -154,6 +158,7 @@
154158
RouteChangeEvent,
155159
ViewPopEvent,
156160
)
161+
from flet_core.pagelet import Pagelet
157162
from flet_core.painting import (
158163
Paint,
159164
PaintingStyle,

0 commit comments

Comments
 (0)