Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
cd98c49c
Unverified
Commit
cd98c49c
authored
Aug 16, 2022
by
Greg Spencer
Committed by
GitHub
Aug 16, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Some changes needed to PlatformMenuBar before the MenuBar implementation change lands. (#109556)
parent
bacab7ee
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
120 additions
and
184 deletions
+120
-184
platform_menu_bar.0.dart
...i/lib/material/platform_menu_bar/platform_menu_bar.0.dart
+5
-5
system_channels.dart
packages/flutter/lib/src/services/system_channels.dart
+1
-1
platform_menu_bar.dart
packages/flutter/lib/src/widgets/platform_menu_bar.dart
+98
-162
platform_menu_bar_test.dart
packages/flutter/test/widgets/platform_menu_bar_test.dart
+16
-16
No files found.
examples/api/lib/material/platform_menu_bar/platform_menu_bar.0.dart
View file @
cd98c49c
...
@@ -73,12 +73,12 @@ class _MyMenuBarAppState extends State<MyMenuBarApp> {
...
@@ -73,12 +73,12 @@ class _MyMenuBarAppState extends State<MyMenuBarApp> {
// │ └ There's a million things I haven't done, but just you wait.
// │ └ There's a million things I haven't done, but just you wait.
// └ Quit
// └ Quit
return
PlatformMenuBar
(
return
PlatformMenuBar
(
menus:
<
MenuItem
>[
menus:
<
Platform
MenuItem
>[
PlatformMenu
(
PlatformMenu
(
label:
'Flutter API Sample'
,
label:
'Flutter API Sample'
,
menus:
<
MenuItem
>[
menus:
<
Platform
MenuItem
>[
PlatformMenuItemGroup
(
PlatformMenuItemGroup
(
members:
<
MenuItem
>[
members:
<
Platform
MenuItem
>[
PlatformMenuItem
(
PlatformMenuItem
(
label:
'About'
,
label:
'About'
,
onSelected:
()
{
onSelected:
()
{
...
@@ -88,7 +88,7 @@ class _MyMenuBarAppState extends State<MyMenuBarApp> {
...
@@ -88,7 +88,7 @@ class _MyMenuBarAppState extends State<MyMenuBarApp> {
],
],
),
),
PlatformMenuItemGroup
(
PlatformMenuItemGroup
(
members:
<
MenuItem
>[
members:
<
Platform
MenuItem
>[
PlatformMenuItem
(
PlatformMenuItem
(
onSelected:
()
{
onSelected:
()
{
_handleMenuSelection
(
MenuSelection
.
showMessage
);
_handleMenuSelection
(
MenuSelection
.
showMessage
);
...
@@ -98,7 +98,7 @@ class _MyMenuBarAppState extends State<MyMenuBarApp> {
...
@@ -98,7 +98,7 @@ class _MyMenuBarAppState extends State<MyMenuBarApp> {
),
),
PlatformMenu
(
PlatformMenu
(
label:
'Messages'
,
label:
'Messages'
,
menus:
<
MenuItem
>[
menus:
<
Platform
MenuItem
>[
PlatformMenuItem
(
PlatformMenuItem
(
label:
'I am not throwing away my shot.'
,
label:
'I am not throwing away my shot.'
,
shortcut:
const
SingleActivator
(
LogicalKeyboardKey
.
digit1
,
meta:
true
),
shortcut:
const
SingleActivator
(
LogicalKeyboardKey
.
digit1
,
meta:
true
),
...
...
packages/flutter/lib/src/services/system_channels.dart
View file @
cd98c49c
...
@@ -406,7 +406,7 @@ class SystemChannels {
...
@@ -406,7 +406,7 @@ class SystemChannels {
/// encoding the list of top level menu items in window "0", which each
/// encoding the list of top level menu items in window "0", which each
/// have a hierarchy of `Map<String, Object?>` containing the required
/// have a hierarchy of `Map<String, Object?>` containing the required
/// data, sent via a [StandardMessageCodec]. It is typically generated from
/// data, sent via a [StandardMessageCodec]. It is typically generated from
/// a list of [MenuItem]s, and ends up looking like this example:
/// a list of [
Platform
MenuItem]s, and ends up looking like this example:
///
///
/// ```dart
/// ```dart
/// Map<String, Object?> menu = <String, Object?>{
/// Map<String, Object?> menu = <String, Object?>{
...
...
packages/flutter/lib/src/widgets/platform_menu_bar.dart
View file @
cd98c49c
...
@@ -134,8 +134,9 @@ class ShortcutSerialization {
...
@@ -134,8 +134,9 @@ class ShortcutSerialization {
/// equivalents) being down.
/// equivalents) being down.
static
const
int
_shortcutModifierControl
=
1
<<
3
;
static
const
int
_shortcutModifierControl
=
1
<<
3
;
/// Converts the internal representation to the format needed for a [MenuItem]
/// Converts the internal representation to the format needed for a
/// to include it in its serialized form for sending to the platform.
/// [PlatformMenuItem] to include it in its serialized form for sending to the
/// platform.
Map
<
String
,
Object
?>
toChannelRepresentation
()
=>
_internal
;
Map
<
String
,
Object
?>
toChannelRepresentation
()
=>
_internal
;
}
}
...
@@ -153,112 +154,12 @@ class ShortcutSerialization {
...
@@ -153,112 +154,12 @@ class ShortcutSerialization {
///
///
/// * [SingleActivator], a [ShortcutActivator] which implements this mixin.
/// * [SingleActivator], a [ShortcutActivator] which implements this mixin.
/// * [CharacterActivator], another [ShortcutActivator] which implements this mixin.
/// * [CharacterActivator], another [ShortcutActivator] which implements this mixin.
mixin
MenuSerializableShortcut
{
mixin
MenuSerializableShortcut
implements
ShortcutActivator
{
/// Implement this in a [ShortcutActivator] subclass to allow it to be
/// Implement this in a [ShortcutActivator] subclass to allow it to be
/// serialized for use in a [PlatformMenuBar].
/// serialized for use in a [PlatformMenuBar].
ShortcutSerialization
serializeForMenu
();
ShortcutSerialization
serializeForMenu
();
}
}
/// An abstract class for describing cascading menu hierarchies that are part of
/// a [PlatformMenuBar].
///
/// This type is also used by [PlatformMenuDelegate.setMenus] to accept the menu
/// hierarchy to be sent to the platform, and by [PlatformMenuBar] to define the
/// menu hierarchy.
///
/// This class is abstract, and so can't be used directly. Typically subclasses
/// like [PlatformMenuItem] are used.
///
/// See also:
///
/// * [PlatformMenuBar], a widget that renders menu items using platform APIs
/// instead of Flutter.
abstract
class
MenuItem
with
Diagnosticable
{
/// Allows subclasses to have const constructors.
const
MenuItem
();
/// Converts the representation of this item into a map suitable for sending
/// over the default "flutter/menu" channel used by [DefaultPlatformMenuDelegate].
///
/// The `delegate` is the [PlatformMenuDelegate] that is requesting the
/// serialization. The `index` is the position of this menu item in the list
/// of [menus] of the [PlatformMenu] it belongs to, and `count` is the number
/// of [menus] in the [PlatformMenu] it belongs to.
///
/// The `getId` parameter is a [MenuItemSerializableIdGenerator] function that
/// generates a unique ID for each menu item, which is to be returned in the
/// "id" field of the menu item data.
Iterable
<
Map
<
String
,
Object
?>>
toChannelRepresentation
(
PlatformMenuDelegate
delegate
,
{
required
MenuItemSerializableIdGenerator
getId
,
});
/// The optional shortcut that selects this [MenuItem].
///
/// This shortcut is only enabled when [onSelected] is set.
MenuSerializableShortcut
?
get
shortcut
=>
null
;
/// Returns any child [MenuItem]s of this item.
///
/// Returns an empty list if this type of menu item doesn't have
/// children.
List
<
MenuItem
>
get
menus
=>
const
<
MenuItem
>[];
/// Returns all descendant [MenuItem]s of this item.
///
/// Returns an empty list if this type of menu item doesn't have
/// descendants.
List
<
MenuItem
>
get
descendants
=>
const
<
MenuItem
>[];
/// Returns a callback, if any, to be invoked if the platform menu receives a
/// "Menu.selectedCallback" method call from the platform for this item.
///
/// Only items that do not have submenus will have this callback invoked.
///
/// Only one of [onSelected] or [onSelectedIntent] may be specified.
///
/// If neither [onSelected] nor [onSelectedIntent] are specified, then this
/// menu item is considered to be disabled.
///
/// The default implementation returns null.
VoidCallback
?
get
onSelected
=>
null
;
/// Returns an intent, if any, to be invoked if the platform receives a
/// "Menu.selectedCallback" method call from the platform for this item.
///
/// Only items that do not have submenus will have this intent invoked.
///
/// Only one of [onSelected] or [onSelectedIntent] may be specified.
///
/// If neither [onSelected] nor [onSelectedIntent] are specified, then this
/// menu item is considered to be disabled.
///
/// The default implementation returns null.
Intent
?
get
onSelectedIntent
=>
null
;
/// Returns a callback, if any, to be invoked if the platform menu receives a
/// "Menu.opened" method call from the platform for this item.
///
/// Only items that have submenus will have this callback invoked.
///
/// The default implementation returns null.
VoidCallback
?
get
onOpen
=>
null
;
/// Returns a callback, if any, to be invoked if the platform menu receives a
/// "Menu.closed" method call from the platform for this item.
///
/// Only items that have submenus will have this callback invoked.
///
/// The default implementation returns null.
VoidCallback
?
get
onClose
=>
null
;
/// Returns the list of group members if this menu item is a "grouping" menu
/// item, such as [PlatformMenuItemGroup].
///
/// Defaults to an empty list.
List
<
MenuItem
>
get
members
=>
const
<
MenuItem
>[];
}
/// An abstract delegate class that can be used to set
/// An abstract delegate class that can be used to set
/// [WidgetsBinding.platformMenuDelegate] to provide for managing platform
/// [WidgetsBinding.platformMenuDelegate] to provide for managing platform
/// menus.
/// menus.
...
@@ -308,7 +209,7 @@ abstract class PlatformMenuDelegate {
...
@@ -308,7 +209,7 @@ abstract class PlatformMenuDelegate {
/// that appear in a cascading menu.
/// that appear in a cascading menu.
/// * [PlatformMenuItem], the class that describes the leaves of a menu
/// * [PlatformMenuItem], the class that describes the leaves of a menu
/// hierarchy.
/// hierarchy.
void
setMenus
(
List
<
MenuItem
>
topLevelMenus
);
void
setMenus
(
List
<
Platform
MenuItem
>
topLevelMenus
);
/// Clears any existing platform-rendered menus and leaves the application
/// Clears any existing platform-rendered menus and leaves the application
/// with no menus.
/// with no menus.
...
@@ -346,8 +247,8 @@ abstract class PlatformMenuDelegate {
...
@@ -346,8 +247,8 @@ abstract class PlatformMenuDelegate {
}
}
/// The signature for a function that generates unique menu item IDs for
/// The signature for a function that generates unique menu item IDs for
/// serialization of a [MenuItem].
/// serialization of a [
Platform
MenuItem].
typedef
MenuItemSerializableIdGenerator
=
int
Function
(
MenuItem
item
);
typedef
MenuItemSerializableIdGenerator
=
int
Function
(
Platform
MenuItem
item
);
/// The platform menu delegate that handles the built-in macOS platform menu
/// The platform menu delegate that handles the built-in macOS platform menu
/// generation using the 'flutter/menu' channel.
/// generation using the 'flutter/menu' channel.
...
@@ -370,12 +271,12 @@ class DefaultPlatformMenuDelegate extends PlatformMenuDelegate {
...
@@ -370,12 +271,12 @@ class DefaultPlatformMenuDelegate extends PlatformMenuDelegate {
/// with the platform. It defaults to [SystemChannels.menu] if not supplied.
/// with the platform. It defaults to [SystemChannels.menu] if not supplied.
DefaultPlatformMenuDelegate
({
MethodChannel
?
channel
})
DefaultPlatformMenuDelegate
({
MethodChannel
?
channel
})
:
channel
=
channel
??
SystemChannels
.
menu
,
:
channel
=
channel
??
SystemChannels
.
menu
,
_idMap
=
<
int
,
MenuItem
>{}
{
_idMap
=
<
int
,
Platform
MenuItem
>{}
{
this
.
channel
.
setMethodCallHandler
(
_methodCallHandler
);
this
.
channel
.
setMethodCallHandler
(
_methodCallHandler
);
}
}
// Map of distributed IDs to menu items.
// Map of distributed IDs to menu items.
final
Map
<
int
,
MenuItem
>
_idMap
;
final
Map
<
int
,
Platform
MenuItem
>
_idMap
;
// An ever increasing value used to dole out IDs.
// An ever increasing value used to dole out IDs.
int
_serial
=
0
;
int
_serial
=
0
;
// The context used to "lock" this delegate to a specific instance of
// The context used to "lock" this delegate to a specific instance of
...
@@ -383,14 +284,14 @@ class DefaultPlatformMenuDelegate extends PlatformMenuDelegate {
...
@@ -383,14 +284,14 @@ class DefaultPlatformMenuDelegate extends PlatformMenuDelegate {
BuildContext
?
_lockedContext
;
BuildContext
?
_lockedContext
;
@override
@override
void
clearMenus
()
=>
setMenus
(<
MenuItem
>[]);
void
clearMenus
()
=>
setMenus
(<
Platform
MenuItem
>[]);
@override
@override
void
setMenus
(
List
<
MenuItem
>
topLevelMenus
)
{
void
setMenus
(
List
<
Platform
MenuItem
>
topLevelMenus
)
{
_idMap
.
clear
();
_idMap
.
clear
();
final
List
<
Map
<
String
,
Object
?>>
representation
=
<
Map
<
String
,
Object
?>>[];
final
List
<
Map
<
String
,
Object
?>>
representation
=
<
Map
<
String
,
Object
?>>[];
if
(
topLevelMenus
.
isNotEmpty
)
{
if
(
topLevelMenus
.
isNotEmpty
)
{
for
(
final
MenuItem
childItem
in
topLevelMenus
)
{
for
(
final
Platform
MenuItem
childItem
in
topLevelMenus
)
{
representation
.
addAll
(
childItem
.
toChannelRepresentation
(
this
,
getId:
_getId
));
representation
.
addAll
(
childItem
.
toChannelRepresentation
(
this
,
getId:
_getId
));
}
}
}
}
...
@@ -412,7 +313,7 @@ class DefaultPlatformMenuDelegate extends PlatformMenuDelegate {
...
@@ -412,7 +313,7 @@ class DefaultPlatformMenuDelegate extends PlatformMenuDelegate {
///
///
/// This is called by each DefaultPlatformMenuDelegateSerializer when
/// This is called by each DefaultPlatformMenuDelegateSerializer when
/// serializing a new object so that it has a unique ID.
/// serializing a new object so that it has a unique ID.
int
_getId
(
MenuItem
item
)
{
int
_getId
(
Platform
MenuItem
item
)
{
_serial
+=
1
;
_serial
+=
1
;
_idMap
[
_serial
]
=
item
;
_idMap
[
_serial
]
=
item
;
return
_serial
;
return
_serial
;
...
@@ -457,10 +358,10 @@ class DefaultPlatformMenuDelegate extends PlatformMenuDelegate {
...
@@ -457,10 +358,10 @@ class DefaultPlatformMenuDelegate extends PlatformMenuDelegate {
if
(!
_idMap
.
containsKey
(
id
))
{
if
(!
_idMap
.
containsKey
(
id
))
{
return
;
return
;
}
}
final
MenuItem
item
=
_idMap
[
id
]!;
final
Platform
MenuItem
item
=
_idMap
[
id
]!;
if
(
call
.
method
==
_kMenuSelectedCallbackMethod
)
{
if
(
call
.
method
==
_kMenuSelectedCallbackMethod
)
{
assert
(
item
.
onSelected
==
null
||
item
.
onSelectedIntent
==
null
,
assert
(
item
.
onSelected
==
null
||
item
.
onSelectedIntent
==
null
,
'Only one of
MenuItem.onSelected or
MenuItem.onSelectedIntent may be specified'
);
'Only one of
PlatformMenuItem.onSelected or Platform
MenuItem.onSelectedIntent may be specified'
);
item
.
onSelected
?.
call
();
item
.
onSelected
?.
call
();
if
(
item
.
onSelectedIntent
!=
null
)
{
if
(
item
.
onSelectedIntent
!=
null
)
{
Actions
.
maybeInvoke
(
FocusManager
.
instance
.
primaryFocus
!.
context
!,
item
.
onSelectedIntent
!);
Actions
.
maybeInvoke
(
FocusManager
.
instance
.
primaryFocus
!.
context
!,
item
.
onSelectedIntent
!);
...
@@ -481,32 +382,40 @@ class DefaultPlatformMenuDelegate extends PlatformMenuDelegate {
...
@@ -481,32 +382,40 @@ class DefaultPlatformMenuDelegate extends PlatformMenuDelegate {
/// the box, but support for other platforms may be provided via plugins that
/// the box, but support for other platforms may be provided via plugins that
/// set [WidgetsBinding.platformMenuDelegate] in their initialization.
/// set [WidgetsBinding.platformMenuDelegate] in their initialization.
///
///
/// The [menus] member contains [MenuItem]s. They will not be part of the
/// The [menus] member contains [PlatformMenuItem]s, which configure the
/// widget tree, since they are not required to be widgets (even if they happen
/// properties of the menus on the platform menu bar.
/// to be widgets that implement [MenuItem], they still won't be part of the
/// widget tree). They are provided to configure the properties of the menus on
/// the platform menu bar.
///
///
/// As far as Flutter is concerned, this widget has no visual representation,
/// As far as Flutter is concerned, this widget has no visual representation,
/// and intercepts no events: it just returns the [child] from its build
/// and intercepts no events: it just returns the [child] from its build
/// function. This is because all of the rendering, shortcuts, and event
/// function. This is because all of the rendering, shortcuts, and event
/// handling for the menu is handled by the plugin on the host platform.
/// handling for the menu is handled by the plugin on the host platform. It is
/// only part of the widget tree to provide a convenient refresh mechanism for
/// the menu data.
///
///
/// There can only be one [PlatformMenuBar] at a time using the same
/// There can only be one [PlatformMenuBar] at a time using the same
/// [PlatformMenuDelegate]. It will assert if more than one is detected.
/// [PlatformMenuDelegate]. It will assert if more than one is detected.
///
///
/// When calling [toStringDeep] on this widget, it will give a tree of
/// When calling [toStringDeep] on this widget, it will give a tree of
/// [MenuItem]s, not a tree of widgets.
/// [
Platform
MenuItem]s, not a tree of widgets.
///
///
/// {@tool sample}
/// {@tool sample} This example shows a [PlatformMenuBar] that contains a single
/// This example shows a [PlatformMenuBar] that contains a single top level
/// top level menu, containing three items for "About", a toggleable menu item
/// menu, containing three items for "About", a toggleable menu item for showing
/// for showing a message, a cascading submenu with message choices, and "Quit".
/// a message, a cascading submenu with message choices, and "Quit".
///
///
/// **This example will only work on macOS.**
/// **This example will only work on macOS.**
///
///
/// ** See code in examples/api/lib/material/platform_menu_bar/platform_menu_bar.0.dart **
/// ** See code in examples/api/lib/material/platform_menu_bar/platform_menu_bar.0.dart **
/// {@end-tool}
/// {@end-tool}
///
/// The menus could just as effectively be managed without using the widget tree
/// by using the following code, but mixing this usage with `PlatformMenuBar` is
/// not recommended, since it will overwrite the menu configuration when it is
/// rebuilt:
///
/// ```dart
/// List<PlatformMenuItem> menus = <PlatformMenuItem>[ /* Define menus... */ ];
/// WidgetsBinding.instance.platformMenuDelegate.setMenus(menus);
/// ```
class
PlatformMenuBar
extends
StatefulWidget
with
DiagnosticableTreeMixin
{
class
PlatformMenuBar
extends
StatefulWidget
with
DiagnosticableTreeMixin
{
/// Creates a const [PlatformMenuBar].
/// Creates a const [PlatformMenuBar].
///
///
...
@@ -540,8 +449,8 @@ class PlatformMenuBar extends StatefulWidget with DiagnosticableTreeMixin {
...
@@ -540,8 +449,8 @@ class PlatformMenuBar extends StatefulWidget with DiagnosticableTreeMixin {
/// The list of menu items that are the top level children of the
/// The list of menu items that are the top level children of the
/// [PlatformMenuBar].
/// [PlatformMenuBar].
///
///
/// The `menus` member contains [
MenuItem]s. They will not be part
/// The `menus` member contains [
PlatformMenuItem]s. They will not be part of
///
of
the widget tree, since they are not widgets. They are provided to
/// the widget tree, since they are not widgets. They are provided to
/// configure the properties of the menus on the platform menu bar.
/// configure the properties of the menus on the platform menu bar.
///
///
/// Also, a Widget in Flutter is immutable, so directly modifying the
/// Also, a Widget in Flutter is immutable, so directly modifying the
...
@@ -549,19 +458,19 @@ class PlatformMenuBar extends StatefulWidget with DiagnosticableTreeMixin {
...
@@ -549,19 +458,19 @@ class PlatformMenuBar extends StatefulWidget with DiagnosticableTreeMixin {
/// `somePlatformMenuBarWidget.menus.add(...)` will result in incorrect
/// `somePlatformMenuBarWidget.menus.add(...)` will result in incorrect
/// behaviors. Whenever the menus list is modified, a new list object
/// behaviors. Whenever the menus list is modified, a new list object
/// should be provided.
/// should be provided.
final
List
<
MenuItem
>
menus
;
final
List
<
Platform
MenuItem
>
menus
;
@override
@override
State
<
PlatformMenuBar
>
createState
()
=>
_PlatformMenuBarState
();
State
<
PlatformMenuBar
>
createState
()
=>
_PlatformMenuBarState
();
@override
@override
List
<
DiagnosticsNode
>
debugDescribeChildren
()
{
List
<
DiagnosticsNode
>
debugDescribeChildren
()
{
return
menus
.
map
<
DiagnosticsNode
>((
MenuItem
child
)
=>
child
.
toDiagnosticsNode
()).
toList
();
return
menus
.
map
<
DiagnosticsNode
>((
Platform
MenuItem
child
)
=>
child
.
toDiagnosticsNode
()).
toList
();
}
}
}
}
class
_PlatformMenuBarState
extends
State
<
PlatformMenuBar
>
{
class
_PlatformMenuBarState
extends
State
<
PlatformMenuBar
>
{
List
<
MenuItem
>
descendants
=
<
MenuItem
>[];
List
<
PlatformMenuItem
>
descendants
=
<
Platform
MenuItem
>[];
@override
@override
void
initState
()
{
void
initState
()
{
...
@@ -585,8 +494,8 @@ class _PlatformMenuBarState extends State<PlatformMenuBar> {
...
@@ -585,8 +494,8 @@ class _PlatformMenuBarState extends State<PlatformMenuBar> {
@override
@override
void
didUpdateWidget
(
PlatformMenuBar
oldWidget
)
{
void
didUpdateWidget
(
PlatformMenuBar
oldWidget
)
{
super
.
didUpdateWidget
(
oldWidget
);
super
.
didUpdateWidget
(
oldWidget
);
final
List
<
MenuItem
>
newDescendants
=
<
MenuItem
>[
final
List
<
PlatformMenuItem
>
newDescendants
=
<
Platform
MenuItem
>[
for
(
final
MenuItem
item
in
widget
.
menus
)
...<
MenuItem
>[
for
(
final
PlatformMenuItem
item
in
widget
.
menus
)
...<
Platform
MenuItem
>[
item
,
item
,
...
item
.
descendants
,
...
item
.
descendants
,
],
],
...
@@ -617,45 +526,39 @@ class _PlatformMenuBarState extends State<PlatformMenuBar> {
...
@@ -617,45 +526,39 @@ class _PlatformMenuBarState extends State<PlatformMenuBar> {
///
///
/// * [PlatformMenuItem], a class representing a leaf menu item in a
/// * [PlatformMenuItem], a class representing a leaf menu item in a
/// [PlatformMenuBar].
/// [PlatformMenuBar].
class
PlatformMenu
extends
MenuItem
with
DiagnosticableTreeMixin
{
class
PlatformMenu
extends
Platform
MenuItem
with
DiagnosticableTreeMixin
{
/// Creates a const [PlatformMenu].
/// Creates a const [PlatformMenu].
///
///
/// The [label] and [menus] fields are required.
/// The [label] and [menus] fields are required.
const
PlatformMenu
({
const
PlatformMenu
({
required
this
.
label
,
required
super
.
label
,
this
.
onOpen
,
this
.
onOpen
,
this
.
onClose
,
this
.
onClose
,
required
this
.
menus
,
required
this
.
menus
,
});
});
/// The label that will appear on the menu.
final
String
label
;
/// The callback that is called when this menu is opened.
@override
@override
final
VoidCallback
?
onOpen
;
final
VoidCallback
?
onOpen
;
/// The callback that is called when this menu is closed.
@override
@override
final
VoidCallback
?
onClose
;
final
VoidCallback
?
onClose
;
/// The menu items in the submenu opened by this menu item.
/// The menu items in the submenu opened by this menu item.
///
///
/// If this is an empty list, this [PlatformMenu] will be disabled.
/// If this is an empty list, this [PlatformMenu] will be disabled.
@override
final
List
<
PlatformMenuItem
>
menus
;
final
List
<
MenuItem
>
menus
;
/// Returns all descendant [MenuItem]s of this item.
/// Returns all descendant [
Platform
MenuItem]s of this item.
@override
@override
List
<
MenuItem
>
get
descendants
=>
getDescendants
(
this
);
List
<
Platform
MenuItem
>
get
descendants
=>
getDescendants
(
this
);
/// Returns all descendants of the given item.
/// Returns all descendants of the given item.
///
///
/// This API is supplied so that implementers of [PlatformMenu] can share
/// This API is supplied so that implementers of [PlatformMenu] can share
/// this implementation.
/// this implementation.
static
List
<
MenuItem
>
getDescendants
(
PlatformMenu
item
)
{
static
List
<
Platform
MenuItem
>
getDescendants
(
PlatformMenu
item
)
{
return
<
MenuItem
>[
return
<
Platform
MenuItem
>[
for
(
final
MenuItem
child
in
item
.
menus
)
...<
MenuItem
>[
for
(
final
PlatformMenuItem
child
in
item
.
menus
)
...<
Platform
MenuItem
>[
child
,
child
,
...
child
.
descendants
,
...
child
.
descendants
,
],
],
...
@@ -681,7 +584,7 @@ class PlatformMenu extends MenuItem with DiagnosticableTreeMixin {
...
@@ -681,7 +584,7 @@ class PlatformMenu extends MenuItem with DiagnosticableTreeMixin {
MenuItemSerializableIdGenerator
getId
,
MenuItemSerializableIdGenerator
getId
,
)
{
)
{
final
List
<
Map
<
String
,
Object
?>>
result
=
<
Map
<
String
,
Object
?>>[];
final
List
<
Map
<
String
,
Object
?>>
result
=
<
Map
<
String
,
Object
?>>[];
for
(
final
MenuItem
childItem
in
item
.
menus
)
{
for
(
final
Platform
MenuItem
childItem
in
item
.
menus
)
{
result
.
addAll
(
childItem
.
toChannelRepresentation
(
result
.
addAll
(
childItem
.
toChannelRepresentation
(
delegate
,
delegate
,
getId:
getId
,
getId:
getId
,
...
@@ -717,7 +620,7 @@ class PlatformMenu extends MenuItem with DiagnosticableTreeMixin {
...
@@ -717,7 +620,7 @@ class PlatformMenu extends MenuItem with DiagnosticableTreeMixin {
@override
@override
List
<
DiagnosticsNode
>
debugDescribeChildren
()
{
List
<
DiagnosticsNode
>
debugDescribeChildren
()
{
return
menus
.
map
<
DiagnosticsNode
>((
MenuItem
child
)
=>
child
.
toDiagnosticsNode
()).
toList
();
return
menus
.
map
<
DiagnosticsNode
>((
Platform
MenuItem
child
)
=>
child
.
toDiagnosticsNode
()).
toList
();
}
}
@override
@override
...
@@ -733,17 +636,17 @@ class PlatformMenu extends MenuItem with DiagnosticableTreeMixin {
...
@@ -733,17 +636,17 @@ class PlatformMenu extends MenuItem with DiagnosticableTreeMixin {
/// Visual dividers will be added before and after this group if other menu
/// Visual dividers will be added before and after this group if other menu
/// items appear in the [PlatformMenu], and the leading one omitted if it is
/// items appear in the [PlatformMenu], and the leading one omitted if it is
/// first and the trailing one omitted if it is last in the menu.
/// first and the trailing one omitted if it is last in the menu.
class
PlatformMenuItemGroup
extends
MenuItem
{
class
PlatformMenuItemGroup
extends
Platform
MenuItem
{
/// Creates a const [PlatformMenuItemGroup].
/// Creates a const [PlatformMenuItemGroup].
///
///
/// The [members] field is required.
/// The [members] field is required.
const
PlatformMenuItemGroup
({
required
this
.
members
});
const
PlatformMenuItemGroup
({
required
this
.
members
})
:
super
(
label:
''
)
;
/// The [MenuItem]s that are members of this menu item group.
/// The [
Platform
MenuItem]s that are members of this menu item group.
///
///
/// An assertion will be thrown if there isn't at least one member of the group.
/// An assertion will be thrown if there isn't at least one member of the group.
@override
@override
final
List
<
MenuItem
>
members
;
final
List
<
Platform
MenuItem
>
members
;
@override
@override
Iterable
<
Map
<
String
,
Object
?>>
toChannelRepresentation
(
Iterable
<
Map
<
String
,
Object
?>>
toChannelRepresentation
(
...
@@ -760,7 +663,7 @@ class PlatformMenuItemGroup extends MenuItem {
...
@@ -760,7 +663,7 @@ class PlatformMenuItemGroup extends MenuItem {
/// This API is supplied so that implementers of [PlatformMenuItemGroup] can share
/// This API is supplied so that implementers of [PlatformMenuItemGroup] can share
/// this implementation.
/// this implementation.
static
Iterable
<
Map
<
String
,
Object
?>>
serialize
(
static
Iterable
<
Map
<
String
,
Object
?>>
serialize
(
MenuItem
group
,
Platform
MenuItem
group
,
PlatformMenuDelegate
delegate
,
{
PlatformMenuDelegate
delegate
,
{
required
MenuItemSerializableIdGenerator
getId
,
required
MenuItemSerializableIdGenerator
getId
,
})
{
})
{
...
@@ -769,7 +672,7 @@ class PlatformMenuItemGroup extends MenuItem {
...
@@ -769,7 +672,7 @@ class PlatformMenuItemGroup extends MenuItem {
_kIdKey:
getId
(
group
),
_kIdKey:
getId
(
group
),
_kIsDividerKey:
true
,
_kIsDividerKey:
true
,
});
});
for
(
final
MenuItem
item
in
group
.
members
)
{
for
(
final
Platform
MenuItem
item
in
group
.
members
)
{
result
.
addAll
(
item
.
toChannelRepresentation
(
result
.
addAll
(
item
.
toChannelRepresentation
(
delegate
,
delegate
,
getId:
getId
,
getId:
getId
,
...
@@ -785,21 +688,21 @@ class PlatformMenuItemGroup extends MenuItem {
...
@@ -785,21 +688,21 @@ class PlatformMenuItemGroup extends MenuItem {
@override
@override
void
debugFillProperties
(
DiagnosticPropertiesBuilder
properties
)
{
void
debugFillProperties
(
DiagnosticPropertiesBuilder
properties
)
{
super
.
debugFillProperties
(
properties
);
super
.
debugFillProperties
(
properties
);
properties
.
add
(
IterableProperty
<
MenuItem
>(
'members'
,
members
));
properties
.
add
(
IterableProperty
<
Platform
MenuItem
>(
'members'
,
members
));
}
}
}
}
/// A class for [MenuItem]s that do not have submenus (as a [PlatformMenu]
/// A class for [
Platform
MenuItem]s that do not have submenus (as a [PlatformMenu]
/// would), but can be selected.
/// would), but can be selected.
///
///
/// These [MenuItem]s are the leaves of the menu item tree, and [onSelected]
/// These [
Platform
MenuItem]s are the leaves of the menu item tree, and [onSelected]
/// will be called when they are selected by clicking on them, or via an
/// will be called when they are selected by clicking on them, or via an
/// optional keyboard [shortcut].
/// optional keyboard [shortcut].
///
///
/// See also:
/// See also:
///
///
/// * [PlatformMenu], a menu item that opens a submenu.
/// * [PlatformMenu], a menu item that opens a submenu.
class
PlatformMenuItem
extends
MenuItem
{
class
PlatformMenuItem
with
Diagnosticable
{
/// Creates a const [PlatformMenuItem].
/// Creates a const [PlatformMenuItem].
///
///
/// The [label] attribute is required.
/// The [label] attribute is required.
...
@@ -816,24 +719,57 @@ class PlatformMenuItem extends MenuItem {
...
@@ -816,24 +719,57 @@ class PlatformMenuItem extends MenuItem {
/// The optional shortcut that selects this [PlatformMenuItem].
/// The optional shortcut that selects this [PlatformMenuItem].
///
///
/// This shortcut is only enabled when [onSelected] is set.
/// This shortcut is only enabled when [onSelected] is set.
@override
final
MenuSerializableShortcut
?
shortcut
;
final
MenuSerializableShortcut
?
shortcut
;
/// An optional callback that is called when this [PlatformMenuItem] is
/// An optional callback that is called when this [PlatformMenuItem] is
/// selected.
/// selected.
///
///
/// If unset, this menu item will be disabled.
/// If unset, this menu item will be disabled.
@override
final
VoidCallback
?
onSelected
;
final
VoidCallback
?
onSelected
;
/// Returns a callback, if any, to be invoked if the platform menu receives a
/// "Menu.opened" method call from the platform for this item.
///
/// Only items that have submenus will have this callback invoked.
///
/// The default implementation returns null.
VoidCallback
?
get
onOpen
=>
null
;
/// Returns a callback, if any, to be invoked if the platform menu receives a
/// "Menu.closed" method call from the platform for this item.
///
/// Only items that have submenus will have this callback invoked.
///
/// The default implementation returns null.
VoidCallback
?
get
onClose
=>
null
;
/// An optional intent that is invoked when this [PlatformMenuItem] is
/// An optional intent that is invoked when this [PlatformMenuItem] is
/// selected.
/// selected.
///
///
/// If unset, this menu item will be disabled.
/// If unset, this menu item will be disabled.
@override
final
Intent
?
onSelectedIntent
;
final
Intent
?
onSelectedIntent
;
@override
/// Returns all descendant [PlatformMenuItem]s of this item.
///
/// Returns an empty list if this type of menu item doesn't have
/// descendants.
List
<
PlatformMenuItem
>
get
descendants
=>
const
<
PlatformMenuItem
>[];
/// Returns the list of group members if this menu item is a "grouping" menu
/// item, such as [PlatformMenuItemGroup].
///
/// Defaults to an empty list.
List
<
PlatformMenuItem
>
get
members
=>
const
<
PlatformMenuItem
>[];
/// Converts the representation of this item into a map suitable for sending
/// over the default "flutter/menu" channel used by [DefaultPlatformMenuDelegate].
///
/// The `delegate` is the [PlatformMenuDelegate] that is requesting the
/// serialization.
///
/// The `getId` parameter is a [MenuItemSerializableIdGenerator] function that
/// generates a unique ID for each menu item, which is to be returned in the
/// "id" field of the menu item data.
Iterable
<
Map
<
String
,
Object
?>>
toChannelRepresentation
(
Iterable
<
Map
<
String
,
Object
?>>
toChannelRepresentation
(
PlatformMenuDelegate
delegate
,
{
PlatformMenuDelegate
delegate
,
{
required
MenuItemSerializableIdGenerator
getId
,
required
MenuItemSerializableIdGenerator
getId
,
...
...
packages/flutter/test/widgets/platform_menu_bar_test.dart
View file @
cd98c49c
...
@@ -163,9 +163,9 @@ void main() {
...
@@ -163,9 +163,9 @@ void main() {
const
MaterialApp
(
const
MaterialApp
(
home:
Material
(
home:
Material
(
child:
PlatformMenuBar
(
child:
PlatformMenuBar
(
menus:
<
MenuItem
>[],
menus:
<
Platform
MenuItem
>[],
child:
PlatformMenuBar
(
child:
PlatformMenuBar
(
menus:
<
MenuItem
>[],
menus:
<
Platform
MenuItem
>[],
child:
SizedBox
(),
child:
SizedBox
(),
),
),
),
),
...
@@ -180,7 +180,7 @@ void main() {
...
@@ -180,7 +180,7 @@ void main() {
shortcut:
SingleActivator
(
LogicalKeyboardKey
.
keyA
),
shortcut:
SingleActivator
(
LogicalKeyboardKey
.
keyA
),
);
);
const
PlatformMenuBar
menuBar
=
PlatformMenuBar
(
const
PlatformMenuBar
menuBar
=
PlatformMenuBar
(
menus:
<
MenuItem
>[
item
],
menus:
<
Platform
MenuItem
>[
item
],
child:
SizedBox
(),
child:
SizedBox
(),
);
);
...
@@ -205,14 +205,14 @@ void main() {
...
@@ -205,14 +205,14 @@ void main() {
);
);
});
});
});
});
group
(
'
Platform
MenuBarItem'
,
()
{
group
(
'MenuBarItem'
,
()
{
testWidgets
(
'diagnostics'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'diagnostics'
,
(
WidgetTester
tester
)
async
{
const
PlatformMenuItem
childItem
=
PlatformMenuItem
(
const
PlatformMenuItem
childItem
=
PlatformMenuItem
(
label:
'label'
,
label:
'label'
,
);
);
const
PlatformMenu
item
=
PlatformMenu
(
const
PlatformMenu
item
=
PlatformMenu
(
label:
'label'
,
label:
'label'
,
menus:
<
MenuItem
>[
childItem
],
menus:
<
Platform
MenuItem
>[
childItem
],
);
);
final
DiagnosticPropertiesBuilder
builder
=
DiagnosticPropertiesBuilder
();
final
DiagnosticPropertiesBuilder
builder
=
DiagnosticPropertiesBuilder
();
...
@@ -258,19 +258,19 @@ const List<String> subMenu2 = <String>[
...
@@ -258,19 +258,19 @@ const List<String> subMenu2 = <String>[
'Sub Menu 20'
,
'Sub Menu 20'
,
];
];
List
<
MenuItem
>
createTestMenus
({
List
<
Platform
MenuItem
>
createTestMenus
({
void
Function
(
String
)?
onActivate
,
void
Function
(
String
)?
onActivate
,
void
Function
(
String
)?
onOpen
,
void
Function
(
String
)?
onOpen
,
void
Function
(
String
)?
onClose
,
void
Function
(
String
)?
onClose
,
Map
<
String
,
MenuSerializableShortcut
>
shortcuts
=
const
<
String
,
MenuSerializableShortcut
>{},
Map
<
String
,
MenuSerializableShortcut
>
shortcuts
=
const
<
String
,
MenuSerializableShortcut
>{},
bool
includeStandard
=
false
,
bool
includeStandard
=
false
,
})
{
})
{
final
List
<
MenuItem
>
result
=
<
MenuItem
>[
final
List
<
PlatformMenuItem
>
result
=
<
Platform
MenuItem
>[
PlatformMenu
(
PlatformMenu
(
label:
mainMenu
[
0
],
label:
mainMenu
[
0
],
onOpen:
onOpen
!=
null
?
()
=>
onOpen
(
mainMenu
[
0
])
:
null
,
onOpen:
onOpen
!=
null
?
()
=>
onOpen
(
mainMenu
[
0
])
:
null
,
onClose:
onClose
!=
null
?
()
=>
onClose
(
mainMenu
[
0
])
:
null
,
onClose:
onClose
!=
null
?
()
=>
onClose
(
mainMenu
[
0
])
:
null
,
menus:
<
MenuItem
>[
menus:
<
Platform
MenuItem
>[
PlatformMenuItem
(
PlatformMenuItem
(
label:
subMenu0
[
0
],
label:
subMenu0
[
0
],
onSelected:
onActivate
!=
null
?
()
=>
onActivate
(
subMenu0
[
0
])
:
null
,
onSelected:
onActivate
!=
null
?
()
=>
onActivate
(
subMenu0
[
0
])
:
null
,
...
@@ -282,9 +282,9 @@ List<MenuItem> createTestMenus({
...
@@ -282,9 +282,9 @@ List<MenuItem> createTestMenus({
label:
mainMenu
[
1
],
label:
mainMenu
[
1
],
onOpen:
onOpen
!=
null
?
()
=>
onOpen
(
mainMenu
[
1
])
:
null
,
onOpen:
onOpen
!=
null
?
()
=>
onOpen
(
mainMenu
[
1
])
:
null
,
onClose:
onClose
!=
null
?
()
=>
onClose
(
mainMenu
[
1
])
:
null
,
onClose:
onClose
!=
null
?
()
=>
onClose
(
mainMenu
[
1
])
:
null
,
menus:
<
MenuItem
>[
menus:
<
Platform
MenuItem
>[
PlatformMenuItemGroup
(
PlatformMenuItemGroup
(
members:
<
MenuItem
>[
members:
<
Platform
MenuItem
>[
PlatformMenuItem
(
PlatformMenuItem
(
label:
subMenu1
[
0
],
label:
subMenu1
[
0
],
onSelected:
onActivate
!=
null
?
()
=>
onActivate
(
subMenu1
[
0
])
:
null
,
onSelected:
onActivate
!=
null
?
()
=>
onActivate
(
subMenu1
[
0
])
:
null
,
...
@@ -296,9 +296,9 @@ List<MenuItem> createTestMenus({
...
@@ -296,9 +296,9 @@ List<MenuItem> createTestMenus({
label:
subMenu1
[
1
],
label:
subMenu1
[
1
],
onOpen:
onOpen
!=
null
?
()
=>
onOpen
(
subMenu1
[
1
])
:
null
,
onOpen:
onOpen
!=
null
?
()
=>
onOpen
(
subMenu1
[
1
])
:
null
,
onClose:
onClose
!=
null
?
()
=>
onClose
(
subMenu1
[
1
])
:
null
,
onClose:
onClose
!=
null
?
()
=>
onClose
(
subMenu1
[
1
])
:
null
,
menus:
<
MenuItem
>[
menus:
<
Platform
MenuItem
>[
PlatformMenuItemGroup
(
PlatformMenuItemGroup
(
members:
<
MenuItem
>[
members:
<
Platform
MenuItem
>[
PlatformMenuItem
(
PlatformMenuItem
(
label:
subSubMenu10
[
0
],
label:
subSubMenu10
[
0
],
onSelected:
onActivate
!=
null
?
()
=>
onActivate
(
subSubMenu10
[
0
])
:
null
,
onSelected:
onActivate
!=
null
?
()
=>
onActivate
(
subSubMenu10
[
0
])
:
null
,
...
@@ -307,7 +307,7 @@ List<MenuItem> createTestMenus({
...
@@ -307,7 +307,7 @@ List<MenuItem> createTestMenus({
],
],
),
),
PlatformMenuItemGroup
(
PlatformMenuItemGroup
(
members:
<
MenuItem
>[
members:
<
Platform
MenuItem
>[
PlatformMenuItem
(
PlatformMenuItem
(
label:
subSubMenu10
[
1
],
label:
subSubMenu10
[
1
],
onSelected:
onActivate
!=
null
?
()
=>
onActivate
(
subSubMenu10
[
1
])
:
null
,
onSelected:
onActivate
!=
null
?
()
=>
onActivate
(
subSubMenu10
[
1
])
:
null
,
...
@@ -321,7 +321,7 @@ List<MenuItem> createTestMenus({
...
@@ -321,7 +321,7 @@ List<MenuItem> createTestMenus({
shortcut:
shortcuts
[
subSubMenu10
[
2
]],
shortcut:
shortcuts
[
subSubMenu10
[
2
]],
),
),
PlatformMenuItemGroup
(
PlatformMenuItemGroup
(
members:
<
MenuItem
>[
members:
<
Platform
MenuItem
>[
PlatformMenuItem
(
PlatformMenuItem
(
label:
subSubMenu10
[
3
],
label:
subSubMenu10
[
3
],
onSelected:
onActivate
!=
null
?
()
=>
onActivate
(
subSubMenu10
[
3
])
:
null
,
onSelected:
onActivate
!=
null
?
()
=>
onActivate
(
subSubMenu10
[
3
])
:
null
,
...
@@ -342,7 +342,7 @@ List<MenuItem> createTestMenus({
...
@@ -342,7 +342,7 @@ List<MenuItem> createTestMenus({
label:
mainMenu
[
2
],
label:
mainMenu
[
2
],
onOpen:
onOpen
!=
null
?
()
=>
onOpen
(
mainMenu
[
2
])
:
null
,
onOpen:
onOpen
!=
null
?
()
=>
onOpen
(
mainMenu
[
2
])
:
null
,
onClose:
onClose
!=
null
?
()
=>
onClose
(
mainMenu
[
2
])
:
null
,
onClose:
onClose
!=
null
?
()
=>
onClose
(
mainMenu
[
2
])
:
null
,
menus:
<
MenuItem
>[
menus:
<
Platform
MenuItem
>[
PlatformMenuItem
(
PlatformMenuItem
(
// Always disabled.
// Always disabled.
label:
subMenu2
[
0
],
label:
subMenu2
[
0
],
...
@@ -355,7 +355,7 @@ List<MenuItem> createTestMenus({
...
@@ -355,7 +355,7 @@ List<MenuItem> createTestMenus({
label:
mainMenu
[
3
],
label:
mainMenu
[
3
],
onOpen:
onOpen
!=
null
?
()
=>
onOpen
(
mainMenu
[
2
])
:
null
,
onOpen:
onOpen
!=
null
?
()
=>
onOpen
(
mainMenu
[
2
])
:
null
,
onClose:
onClose
!=
null
?
()
=>
onClose
(
mainMenu
[
2
])
:
null
,
onClose:
onClose
!=
null
?
()
=>
onClose
(
mainMenu
[
2
])
:
null
,
menus:
<
MenuItem
>[],
menus:
<
Platform
MenuItem
>[],
),
),
];
];
return
result
;
return
result
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment