-
Notifications
You must be signed in to change notification settings - Fork 486
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add CupertinoActionSheetButton * add CupertinoActionSheet * rename CupertinoActionSheetButton to CupertinoActionSheetAction * Converted to `StatelessWidget`s * Make CupertinoActionSheet behave like BottomSheet --------- Co-authored-by: Feodor Fitsner <[email protected]>
- Loading branch information
1 parent
60fc766
commit 366770e
Showing
7 changed files
with
490 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
118 changes: 118 additions & 0 deletions
118
packages/flet/lib/src/controls/cupertino_action_sheet.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
import 'package:flutter/cupertino.dart'; | ||
|
||
import '../flet_control_backend.dart'; | ||
import '../models/control.dart'; | ||
import 'create_control.dart'; | ||
import 'error.dart'; | ||
|
||
class CupertinoActionSheetControl extends StatefulWidget { | ||
final Control? parent; | ||
final Control control; | ||
final List<Control> children; | ||
final bool parentDisabled; | ||
final bool? parentAdaptive; | ||
final Widget? nextChild; | ||
final FletControlBackend backend; | ||
|
||
const CupertinoActionSheetControl( | ||
{super.key, | ||
this.parent, | ||
required this.control, | ||
required this.children, | ||
required this.parentDisabled, | ||
required this.parentAdaptive, | ||
required this.nextChild, | ||
required this.backend}); | ||
|
||
@override | ||
State<CupertinoActionSheetControl> createState() => | ||
_CupertinoActionSheetControlState(); | ||
} | ||
|
||
class _CupertinoActionSheetControlState | ||
extends State<CupertinoActionSheetControl> { | ||
Widget _createActionSheet() { | ||
bool disabled = widget.control.isDisabled || widget.parentDisabled; | ||
|
||
var titleCtrls = | ||
widget.children.where((c) => c.name == "title" && c.isVisible); | ||
var messageCtrls = | ||
widget.children.where((c) => c.name == "message" && c.isVisible); | ||
var cancelButtonCtrls = | ||
widget.children.where((c) => c.name == "cancel" && c.isVisible); | ||
var actionCtrls = | ||
widget.children.where((c) => c.name == "action" && c.isVisible); | ||
|
||
return CupertinoActionSheet( | ||
title: titleCtrls.isNotEmpty | ||
? createControl(widget.control, titleCtrls.first.id, disabled, | ||
parentAdaptive: widget.parentAdaptive) | ||
: null, | ||
message: messageCtrls.isNotEmpty | ||
? createControl(widget.control, messageCtrls.first.id, disabled, | ||
parentAdaptive: widget.parentAdaptive) | ||
: null, | ||
cancelButton: cancelButtonCtrls.isNotEmpty | ||
? createControl(widget.control, cancelButtonCtrls.first.id, disabled, | ||
parentAdaptive: widget.parentAdaptive) | ||
: null, | ||
actions: actionCtrls.isNotEmpty | ||
? actionCtrls | ||
.map((c) => createControl(widget.control, c.id, disabled, | ||
parentAdaptive: widget.parentAdaptive)) | ||
.toList() | ||
: null, | ||
); | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
debugPrint("CupertinoActionSheetControl build: ${widget.control.id}"); | ||
|
||
bool lastOpen = widget.control.state["open"] ?? false; | ||
|
||
var open = widget.control.attrBool("open", false)!; | ||
var modal = widget.control.attrBool("modal", false)!; | ||
|
||
debugPrint("Current open state: $lastOpen"); | ||
debugPrint("New open state: $open"); | ||
|
||
if (open && (open != lastOpen)) { | ||
var dialog = _createActionSheet(); | ||
if (dialog is ErrorControl) { | ||
return dialog; | ||
} | ||
|
||
// close previous dialog | ||
if (ModalRoute.of(context)?.isCurrent != true) { | ||
Navigator.of(context).pop(); | ||
} | ||
|
||
widget.control.state["open"] = open; | ||
|
||
WidgetsBinding.instance.addPostFrameCallback((_) { | ||
showCupertinoModalPopup( | ||
barrierDismissible: !modal, | ||
useRootNavigator: false, | ||
context: context, | ||
builder: (context) => _createActionSheet()).then((value) { | ||
lastOpen = widget.control.state["open"] ?? false; | ||
debugPrint("Action sheet should be dismissed ($hashCode): $lastOpen"); | ||
bool shouldDismiss = lastOpen; | ||
widget.control.state["open"] = false; | ||
|
||
if (shouldDismiss) { | ||
widget.backend | ||
.updateControlState(widget.control.id, {"open": "false"}); | ||
widget.backend | ||
.triggerControlEvent(widget.control.id, "dismiss", ""); | ||
} | ||
}); | ||
}); | ||
} else if (open != lastOpen && lastOpen) { | ||
Navigator.of(context).pop(); | ||
} | ||
|
||
return widget.nextChild ?? const SizedBox.shrink(); | ||
} | ||
} |
51 changes: 51 additions & 0 deletions
51
packages/flet/lib/src/controls/cupertino_action_sheet_action.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import 'package:flutter/cupertino.dart'; | ||
|
||
import '../flet_control_backend.dart'; | ||
import '../models/control.dart'; | ||
import 'create_control.dart'; | ||
import 'error.dart'; | ||
|
||
class CupertinoActionSheetActionControl extends StatelessWidget { | ||
final Control? parent; | ||
final Control control; | ||
final List<Control> children; | ||
final bool parentDisabled; | ||
final bool? parentAdaptive; | ||
final FletControlBackend backend; | ||
|
||
const CupertinoActionSheetActionControl( | ||
{super.key, | ||
this.parent, | ||
required this.control, | ||
required this.children, | ||
required this.parentDisabled, | ||
required this.parentAdaptive, | ||
required this.backend}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
debugPrint("CupertinoActionSheetActionControl build: ${control.id}"); | ||
bool disabled = control.isDisabled || parentDisabled; | ||
|
||
var contentCtrls = | ||
children.where((c) => c.name == "content" && c.isVisible); | ||
if (contentCtrls.isEmpty) { | ||
return const ErrorControl( | ||
"CupertinoActionSheetAction must have a content control!"); | ||
} | ||
|
||
return constrainedControl( | ||
context, | ||
CupertinoActionSheetAction( | ||
isDefaultAction: control.attrBool("default", false)!, | ||
isDestructiveAction: control.attrBool("destructive", false)!, | ||
onPressed: () { | ||
backend.triggerControlEvent(control.id, "click", ""); | ||
}, | ||
child: createControl(control, contentCtrls.first.id, disabled, | ||
parentAdaptive: parentAdaptive), | ||
), | ||
parent, | ||
control); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
143 changes: 143 additions & 0 deletions
143
sdk/python/packages/flet-core/src/flet_core/cupertino_action_sheet.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
from typing import Any, List, Optional, Union | ||
|
||
from flet_core.adaptive_control import AdaptiveControl | ||
from flet_core.control import Control, OptionalNumber | ||
from flet_core.ref import Ref | ||
from flet_core.types import ( | ||
AnimationValue, | ||
OffsetValue, | ||
ResponsiveNumber, | ||
RotateValue, | ||
ScaleValue, | ||
) | ||
|
||
|
||
class CupertinoActionSheet(AdaptiveControl): | ||
""" | ||
An iOS-style action sheet. | ||
----- | ||
Online docs: https://flet.dev/docs/controls/cupertinoactionsheet | ||
""" | ||
|
||
def __init__( | ||
self, | ||
title: Optional[Control] = None, | ||
message: Optional[Control] = None, | ||
actions: Optional[List[Control]] = None, | ||
cancel: Optional[Control] = None, | ||
modal: bool = False, | ||
open: bool = False, | ||
on_dismiss=None, | ||
# | ||
# ConstrainedControl and AdaptiveControl | ||
# | ||
ref: Optional[Ref] = None, | ||
visible: Optional[bool] = None, | ||
disabled: Optional[bool] = None, | ||
data: Any = None, | ||
adaptive: Optional[bool] = None, | ||
): | ||
Control.__init__( | ||
self, | ||
ref=ref, | ||
disabled=disabled, | ||
visible=visible, | ||
data=data, | ||
) | ||
|
||
AdaptiveControl.__init__(self, adaptive=adaptive) | ||
|
||
self.cancel = cancel | ||
self.title = title | ||
self.message = message | ||
self.actions = actions | ||
self.modal = modal | ||
self.open = open | ||
self.on_dismiss = on_dismiss | ||
|
||
def _get_control_name(self): | ||
return "cupertinoactionsheet" | ||
|
||
def before_update(self): | ||
super().before_update() | ||
|
||
def _get_children(self): | ||
children = [] | ||
if self.__cancel: | ||
self.__cancel._set_attr_internal("n", "cancel") | ||
children.append(self.__cancel) | ||
if self.__title: | ||
self.__title._set_attr_internal("n", "title") | ||
children.append(self.__title) | ||
if self.__message: | ||
self.__message._set_attr_internal("n", "message") | ||
children.append(self.__message) | ||
for action in self.__actions: | ||
action._set_attr_internal("n", "action") | ||
children.append(action) | ||
return children | ||
|
||
# cancel | ||
@property | ||
def cancel(self) -> Optional[Control]: | ||
return self.__cancel | ||
|
||
@cancel.setter | ||
def cancel(self, value: Optional[Control]): | ||
self.__cancel = value | ||
|
||
# title | ||
@property | ||
def title(self) -> Optional[Control]: | ||
return self.__title | ||
|
||
@title.setter | ||
def title(self, value: Optional[Control]): | ||
self.__title = value | ||
|
||
# message | ||
@property | ||
def message(self) -> Optional[Control]: | ||
return self.__message | ||
|
||
@message.setter | ||
def message(self, value: Optional[Control]): | ||
self.__message = value | ||
|
||
# actions | ||
@property | ||
def actions(self): | ||
return self.__actions | ||
|
||
@actions.setter | ||
def actions(self, value): | ||
self.__actions = value if value is not None else [] | ||
|
||
# open | ||
@property | ||
def open(self) -> Optional[bool]: | ||
return self._get_attr("open", data_type="bool", def_value=False) | ||
|
||
@open.setter | ||
def open(self, value: Optional[bool]): | ||
self._set_attr("open", value) | ||
|
||
# modal | ||
@property | ||
def modal(self) -> Optional[bool]: | ||
return self._get_attr("modal", data_type="bool", def_value=False) | ||
|
||
@modal.setter | ||
def modal(self, value: Optional[bool]): | ||
self._set_attr("modal", value) | ||
|
||
# on_dismiss | ||
@property | ||
def on_dismiss(self): | ||
return self._get_event_handler("dismiss") | ||
|
||
@on_dismiss.setter | ||
def on_dismiss(self, handler): | ||
self._add_event_handler("dismiss", handler) |
Oops, something went wrong.