forked from flet-dev/flet
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
…t-dev#2772) * CupertinoContextMenu: initial commit * CupertinoContextMenuAction: initial commit * Fix text color of CupertinoContextMenuAction in dark mode --------- Co-authored-by: Feodor Fitsner <[email protected]>
- Loading branch information
Showing
6 changed files
with
349 additions
and
0 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
65 changes: 65 additions & 0 deletions
65
packages/flet/lib/src/controls/cupertino_context_menu.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,65 @@ | ||
import 'package:flutter/cupertino.dart'; | ||
|
||
import '../flet_control_backend.dart'; | ||
import '../models/control.dart'; | ||
import 'create_control.dart'; | ||
import 'error.dart'; | ||
import 'flet_store_mixin.dart'; | ||
|
||
class CupertinoContextMenuControl extends StatefulWidget { | ||
final Control? parent; | ||
final Control control; | ||
final List<Control> children; | ||
final bool parentDisabled; | ||
final bool? parentAdaptive; | ||
final FletControlBackend backend; | ||
|
||
const CupertinoContextMenuControl( | ||
{super.key, | ||
this.parent, | ||
required this.control, | ||
required this.children, | ||
required this.parentDisabled, | ||
required this.parentAdaptive, | ||
required this.backend}); | ||
|
||
@override | ||
State<CupertinoContextMenuControl> createState() => | ||
_CupertinoContextMenuControlState(); | ||
} | ||
|
||
class _CupertinoContextMenuControlState | ||
extends State<CupertinoContextMenuControl> with FletStoreMixin { | ||
@override | ||
Widget build(BuildContext context) { | ||
debugPrint("CupertinoContextMenu build ($hashCode): ${widget.control.id}"); | ||
|
||
bool disabled = widget.control.isDisabled || widget.parentDisabled; | ||
bool? adaptive = | ||
widget.control.attrBool("adaptive") ?? widget.parentAdaptive; | ||
var contentCtrls = | ||
widget.children.where((c) => c.name == "content" && c.isVisible); | ||
var actionCtrls = | ||
widget.children.where((c) => c.name == "action" && c.isVisible); | ||
|
||
if (actionCtrls.isEmpty) { | ||
return const ErrorControl( | ||
"CupertinoContextMenu.actions list must have at least one action control"); | ||
} | ||
if (contentCtrls.isEmpty) { | ||
return const ErrorControl( | ||
"CupertinoContextMenu.content must be provided"); | ||
} | ||
|
||
return CupertinoContextMenu( | ||
enableHapticFeedback: | ||
widget.control.attrBool("enableHapticFeedback", false)!, | ||
actions: actionCtrls.map((c) { | ||
return createControl(widget.control, c.id, disabled, | ||
parentAdaptive: adaptive); | ||
}).toList(), | ||
child: createControl(widget.control, contentCtrls.first.id, disabled, | ||
parentAdaptive: adaptive), | ||
); | ||
} | ||
} |
66 changes: 66 additions & 0 deletions
66
packages/flet/lib/src/controls/cupertino_context_menu_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,66 @@ | ||
import 'package:flutter/cupertino.dart'; | ||
|
||
import '../flet_control_backend.dart'; | ||
import '../models/control.dart'; | ||
import '../utils/icons.dart'; | ||
import 'create_control.dart'; | ||
import 'flet_store_mixin.dart'; | ||
|
||
class CupertinoContextMenuActionControl extends StatefulWidget { | ||
final Control? parent; | ||
final Control control; | ||
final List<Control> children; | ||
final bool parentDisabled; | ||
final bool? parentAdaptive; | ||
final FletControlBackend backend; | ||
|
||
const CupertinoContextMenuActionControl( | ||
{super.key, | ||
this.parent, | ||
required this.control, | ||
required this.children, | ||
required this.parentDisabled, | ||
required this.parentAdaptive, | ||
required this.backend}); | ||
|
||
@override | ||
State<CupertinoContextMenuActionControl> createState() => | ||
_CupertinoContextMenuActionControlState(); | ||
} | ||
|
||
class _CupertinoContextMenuActionControlState | ||
extends State<CupertinoContextMenuActionControl> with FletStoreMixin { | ||
@override | ||
Widget build(BuildContext context) { | ||
debugPrint( | ||
"CupertinoContextMenuAction build ($hashCode): ${widget.control.id}"); | ||
|
||
bool disabled = widget.control.isDisabled || widget.parentDisabled; | ||
bool? adaptive = | ||
widget.control.attrBool("adaptive") ?? widget.parentAdaptive; | ||
String text = widget.control.attrString("text", "")!; | ||
var contentCtrls = | ||
widget.children.where((c) => c.name == "content" && c.isVisible); | ||
IconData? trailingIcon = | ||
parseIcon(widget.control.attrString("trailingIcon", "")!); | ||
|
||
Widget child = DefaultTextStyle( | ||
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith( | ||
color: | ||
CupertinoDynamicColor.resolve(CupertinoColors.label, context)), | ||
child: contentCtrls.isNotEmpty | ||
? createControl(widget.control, contentCtrls.first.id, disabled, | ||
parentAdaptive: adaptive) | ||
: Text(text, overflow: TextOverflow.ellipsis)); | ||
|
||
return CupertinoContextMenuAction( | ||
isDefaultAction: widget.control.attrBool("default", false)!, | ||
isDestructiveAction: widget.control.attrBool("destructive", false)!, | ||
onPressed: () { | ||
widget.backend.triggerControlEvent(widget.control.id, "click", ""); | ||
}, | ||
trailingIcon: trailingIcon, | ||
child: child, | ||
); | ||
} | ||
} |
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
89 changes: 89 additions & 0 deletions
89
sdk/python/packages/flet-core/src/flet_core/cupertino_context_menu.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,89 @@ | ||
from typing import Any, List, Optional | ||
|
||
from flet_core.adaptive_control import AdaptiveControl | ||
from flet_core.control import Control | ||
from flet_core.ref import Ref | ||
|
||
|
||
class CupertinoContextMenu(AdaptiveControl): | ||
""" | ||
A full-screen modal route that opens up when the content is long-pressed. | ||
----- | ||
Online docs: https://flet.dev/docs/controls/cupertinocontextmenu | ||
""" | ||
|
||
def __init__( | ||
self, | ||
content: Control, | ||
actions: List[Control], | ||
enable_haptic_feedback: Optional[bool] = None, | ||
# | ||
# Control | ||
# | ||
ref: Optional[Ref] = None, | ||
disabled: Optional[bool] = None, | ||
visible: Optional[bool] = None, | ||
data: Any = None, | ||
adaptive: Optional[bool] = False, | ||
): | ||
Control.__init__( | ||
self, | ||
ref=ref, | ||
disabled=disabled, | ||
visible=visible, | ||
data=data, | ||
) | ||
|
||
AdaptiveControl.__init__(self, adaptive=adaptive) | ||
|
||
self.enable_haptic_feedback = enable_haptic_feedback | ||
self.content = content | ||
self.actions = actions | ||
|
||
def _get_control_name(self): | ||
return "cupertinocontextmenu" | ||
|
||
def _before_build_command(self): | ||
super()._before_build_command() | ||
|
||
def _get_children(self): | ||
children = [] | ||
if self.__content: | ||
self.__content._set_attr_internal("n", "content") | ||
children.append(self.__content) | ||
for action in self.__actions: | ||
action._set_attr_internal("n", "action") | ||
children.append(action) | ||
return children | ||
|
||
# enable_haptic_feedback | ||
@property | ||
def enable_haptic_feedback(self) -> Optional[bool]: | ||
return self._get_attr("enableHapticFeedback", data_type="bool", def_value=False) | ||
|
||
@enable_haptic_feedback.setter | ||
def enable_haptic_feedback(self, value: Optional[bool]): | ||
self._set_attr("enableHapticFeedback", value) | ||
|
||
# content | ||
@property | ||
def content(self) -> Control: | ||
return self.__content | ||
|
||
@content.setter | ||
def content(self, value: Control): | ||
self.__content = value | ||
|
||
# actions | ||
@property | ||
def actions(self) -> List[Control]: | ||
return self.__actions | ||
|
||
@actions.setter | ||
def actions(self, value: List[Control]): | ||
assert ( | ||
isinstance(value, list) and len(value) > 0 | ||
), "CupertinoContextMenu.actions list must have at least one action control" | ||
self.__actions = value |
109 changes: 109 additions & 0 deletions
109
sdk/python/packages/flet-core/src/flet_core/cupertino_context_menu_action.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,109 @@ | ||
from typing import Any, Optional | ||
|
||
from flet_core.adaptive_control import AdaptiveControl | ||
from flet_core.control import Control | ||
from flet_core.ref import Ref | ||
|
||
|
||
class CupertinoContextMenuAction(AdaptiveControl): | ||
""" | ||
An action that can be added to a CupertinoContextMenu. | ||
----- | ||
Online docs: https://flet.dev/docs/controls/cupertinocontextmenuaction | ||
""" | ||
|
||
def __init__( | ||
self, | ||
content: Optional[Control] = None, | ||
text: Optional[str] = None, | ||
trailing_icon: Optional[str] = None, | ||
default: Optional[bool] = None, | ||
destructive: Optional[bool] = None, | ||
on_click=None, | ||
# | ||
# Control | ||
# | ||
ref: Optional[Ref] = None, | ||
disabled: Optional[bool] = None, | ||
visible: Optional[bool] = None, | ||
data: Any = None, | ||
adaptive: Optional[bool] = False, | ||
): | ||
Control.__init__( | ||
self, | ||
ref=ref, | ||
disabled=disabled, | ||
visible=visible, | ||
data=data, | ||
) | ||
|
||
AdaptiveControl.__init__(self, adaptive=adaptive) | ||
|
||
self.default = default | ||
self.destructive = destructive | ||
self.content = content | ||
self.trailing_icon = trailing_icon | ||
self.on_click = on_click | ||
self.text = text | ||
|
||
def _get_control_name(self): | ||
return "cupertinocontextmenuaction" | ||
|
||
def _get_children(self): | ||
return [self.__content] if self.__content else [] | ||
|
||
# default | ||
@property | ||
def default(self) -> Optional[bool]: | ||
return self._get_attr("default", data_type="bool", def_value=False) | ||
|
||
@default.setter | ||
def default(self, value: Optional[bool]): | ||
self._set_attr("default", value) | ||
|
||
# destructive | ||
@property | ||
def destructive(self) -> Optional[bool]: | ||
return self._get_attr("destructive", data_type="bool", def_value=False) | ||
|
||
@destructive.setter | ||
def destructive(self, value: Optional[bool]): | ||
self._set_attr("destructive", value) | ||
|
||
# trailing_icon | ||
@property | ||
def trailing_icon(self) -> Optional[str]: | ||
return self._get_attr("trailingIcon") | ||
|
||
@trailing_icon.setter | ||
def trailing_icon(self, value: Optional[str]): | ||
self._set_attr("trailingIcon", value) | ||
|
||
# text | ||
@property | ||
def text(self) -> Optional[str]: | ||
return self._get_attr("text") | ||
|
||
@text.setter | ||
def text(self, value: Optional[str]): | ||
self._set_attr("text", value) | ||
|
||
# content | ||
@property | ||
def content(self) -> Optional[Control]: | ||
return self.__content | ||
|
||
@content.setter | ||
def content(self, value: Optional[Control]): | ||
self.__content = value | ||
|
||
# on_click | ||
@property | ||
def on_click(self): | ||
return self._get_event_handler("click") | ||
|
||
@on_click.setter | ||
def on_click(self, handler): | ||
self._add_event_handler("click", handler) |