mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00

I previously made a PR (#136140) that used `switch` expressions to make some parts of the Flutter codebase easier to understand. It was assigned to the framework team, and @christopherfujino let me know that it was too large to effectively review and recommended breaking it up into smaller pull requests. Here's a PR that only targets files in the `dev/` directory. Hopefully this will be easier to work with! (solves issue https://github.com/flutter/flutter/issues/136139)
789 lines
25 KiB
Dart
789 lines
25 KiB
Dart
// Copyright 2014 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
|
|
void main() {
|
|
runApp(
|
|
const MaterialApp(
|
|
title: 'Menu Tester',
|
|
home: Material(
|
|
child: Home(),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
class Home extends StatefulWidget {
|
|
const Home({super.key});
|
|
|
|
@override
|
|
State<Home> createState() => _HomeState();
|
|
}
|
|
|
|
class _HomeState extends State<Home> {
|
|
final MenuController _controller = MenuController();
|
|
VisualDensity _density = VisualDensity.standard;
|
|
TextDirection _textDirection = TextDirection.ltr;
|
|
double _extraPadding = 0;
|
|
bool _addItem = false;
|
|
bool _accelerators = true;
|
|
bool _transparent = false;
|
|
bool _funkyTheme = false;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final ThemeData theme = Theme.of(context);
|
|
MenuThemeData menuTheme = MenuTheme.of(context);
|
|
MenuBarThemeData menuBarTheme = MenuBarTheme.of(context);
|
|
MenuButtonThemeData menuButtonTheme = MenuButtonTheme.of(context);
|
|
if (_funkyTheme) {
|
|
menuTheme = const MenuThemeData(
|
|
style: MenuStyle(
|
|
shape: MaterialStatePropertyAll<OutlinedBorder>(
|
|
RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.all(
|
|
Radius.circular(10),
|
|
),
|
|
),
|
|
),
|
|
backgroundColor: MaterialStatePropertyAll<Color?>(Colors.blue),
|
|
elevation: MaterialStatePropertyAll<double?>(10),
|
|
padding: MaterialStatePropertyAll<EdgeInsetsDirectional>(
|
|
EdgeInsetsDirectional.all(20),
|
|
),
|
|
),
|
|
);
|
|
menuButtonTheme = const MenuButtonThemeData(
|
|
style: ButtonStyle(
|
|
shape: MaterialStatePropertyAll<OutlinedBorder>(StadiumBorder()),
|
|
backgroundColor: MaterialStatePropertyAll<Color?>(Colors.green),
|
|
foregroundColor: MaterialStatePropertyAll<Color?>(Colors.white),
|
|
),
|
|
);
|
|
menuBarTheme = const MenuBarThemeData(
|
|
style: MenuStyle(
|
|
shape: MaterialStatePropertyAll<OutlinedBorder>(RoundedRectangleBorder()),
|
|
backgroundColor: MaterialStatePropertyAll<Color?>(Colors.blue),
|
|
elevation: MaterialStatePropertyAll<double?>(10),
|
|
padding: MaterialStatePropertyAll<EdgeInsetsDirectional>(
|
|
EdgeInsetsDirectional.all(20),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
return SafeArea(
|
|
child: Padding(
|
|
padding: EdgeInsets.all(_extraPadding),
|
|
child: Directionality(
|
|
textDirection: _textDirection,
|
|
child: Theme(
|
|
data: theme.copyWith(
|
|
visualDensity: _density,
|
|
menuTheme: _transparent
|
|
? MenuThemeData(
|
|
style: MenuStyle(
|
|
backgroundColor: MaterialStatePropertyAll<Color>(
|
|
Colors.blue.withOpacity(0.12),
|
|
),
|
|
elevation: const MaterialStatePropertyAll<double>(0),
|
|
),
|
|
)
|
|
: menuTheme,
|
|
menuBarTheme: menuBarTheme,
|
|
menuButtonTheme: menuButtonTheme,
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: <Widget>[
|
|
_TestMenus(
|
|
menuController: _controller,
|
|
accelerators: _accelerators,
|
|
addItem: _addItem,
|
|
),
|
|
Expanded(
|
|
child: SingleChildScrollView(
|
|
child: _Controls(
|
|
menuController: _controller,
|
|
density: _density,
|
|
addItem: _addItem,
|
|
accelerators: _accelerators,
|
|
transparent: _transparent,
|
|
funkyTheme: _funkyTheme,
|
|
extraPadding: _extraPadding,
|
|
textDirection: _textDirection,
|
|
onDensityChanged: (VisualDensity value) {
|
|
setState(() {
|
|
_density = value;
|
|
});
|
|
},
|
|
onTextDirectionChanged: (TextDirection value) {
|
|
setState(() {
|
|
_textDirection = value;
|
|
});
|
|
},
|
|
onExtraPaddingChanged: (double value) {
|
|
setState(() {
|
|
_extraPadding = value;
|
|
});
|
|
},
|
|
onAddItemChanged: (bool value) {
|
|
setState(() {
|
|
_addItem = value;
|
|
});
|
|
},
|
|
onAcceleratorsChanged: (bool value) {
|
|
setState(() {
|
|
_accelerators = value;
|
|
});
|
|
},
|
|
onTransparentChanged: (bool value) {
|
|
setState(() {
|
|
_transparent = value;
|
|
});
|
|
},
|
|
onFunkyThemeChanged: (bool value) {
|
|
setState(() {
|
|
_funkyTheme = value;
|
|
});
|
|
},
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _Controls extends StatefulWidget {
|
|
const _Controls({
|
|
required this.density,
|
|
required this.textDirection,
|
|
required this.extraPadding,
|
|
this.addItem = false,
|
|
this.accelerators = true,
|
|
this.transparent = false,
|
|
this.funkyTheme = false,
|
|
required this.onDensityChanged,
|
|
required this.onTextDirectionChanged,
|
|
required this.onExtraPaddingChanged,
|
|
required this.onAddItemChanged,
|
|
required this.onAcceleratorsChanged,
|
|
required this.onTransparentChanged,
|
|
required this.onFunkyThemeChanged,
|
|
required this.menuController,
|
|
});
|
|
|
|
final VisualDensity density;
|
|
final TextDirection textDirection;
|
|
final double extraPadding;
|
|
final bool addItem;
|
|
final bool accelerators;
|
|
final bool transparent;
|
|
final bool funkyTheme;
|
|
final ValueChanged<VisualDensity> onDensityChanged;
|
|
final ValueChanged<TextDirection> onTextDirectionChanged;
|
|
final ValueChanged<double> onExtraPaddingChanged;
|
|
final ValueChanged<bool> onAddItemChanged;
|
|
final ValueChanged<bool> onAcceleratorsChanged;
|
|
final ValueChanged<bool> onTransparentChanged;
|
|
final ValueChanged<bool> onFunkyThemeChanged;
|
|
final MenuController menuController;
|
|
|
|
@override
|
|
State<_Controls> createState() => _ControlsState();
|
|
}
|
|
|
|
class _ControlsState extends State<_Controls> {
|
|
final FocusNode _focusNode = FocusNode(debugLabel: 'Floating');
|
|
|
|
@override
|
|
void dispose() {
|
|
_focusNode.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Center(
|
|
child: SingleChildScrollView(
|
|
child: Column(
|
|
children: <Widget>[
|
|
MenuAnchor(
|
|
childFocusNode: _focusNode,
|
|
style: const MenuStyle(alignment: AlignmentDirectional.topEnd),
|
|
alignmentOffset: const Offset(100, -8),
|
|
menuChildren: <Widget>[
|
|
MenuItemButton(
|
|
shortcut: TestMenu.standaloneMenu1.shortcut,
|
|
onPressed: () {
|
|
_itemSelected(TestMenu.standaloneMenu1);
|
|
},
|
|
child: MenuAcceleratorLabel(TestMenu.standaloneMenu1.label),
|
|
),
|
|
MenuItemButton(
|
|
leadingIcon: const Icon(Icons.send),
|
|
trailingIcon: const Icon(Icons.mail),
|
|
onPressed: () {
|
|
_itemSelected(TestMenu.standaloneMenu2);
|
|
},
|
|
child: MenuAcceleratorLabel(TestMenu.standaloneMenu2.label),
|
|
),
|
|
],
|
|
builder: (BuildContext context, MenuController controller, Widget? child) {
|
|
return TextButton(
|
|
focusNode: _focusNode,
|
|
onPressed: () {
|
|
if (controller.isOpen) {
|
|
controller.close();
|
|
} else {
|
|
controller.open();
|
|
}
|
|
},
|
|
child: child!,
|
|
);
|
|
},
|
|
child: const MenuAcceleratorLabel('Open Menu'),
|
|
),
|
|
ConstrainedBox(
|
|
constraints: const BoxConstraints(maxWidth: 400),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
children: <Widget>[
|
|
_ControlSlider(
|
|
label: 'Extra Padding: ${widget.extraPadding.toStringAsFixed(1)}',
|
|
value: widget.extraPadding,
|
|
max: 40,
|
|
divisions: 20,
|
|
onChanged: (double value) {
|
|
widget.onExtraPaddingChanged(value);
|
|
},
|
|
),
|
|
_ControlSlider(
|
|
label: 'Horizontal Density: ${widget.density.horizontal.toStringAsFixed(1)}',
|
|
value: widget.density.horizontal,
|
|
max: 4,
|
|
min: -4,
|
|
divisions: 12,
|
|
onChanged: (double value) {
|
|
widget.onDensityChanged(
|
|
VisualDensity(
|
|
horizontal: value,
|
|
vertical: widget.density.vertical,
|
|
),
|
|
);
|
|
},
|
|
),
|
|
_ControlSlider(
|
|
label: 'Vertical Density: ${widget.density.vertical.toStringAsFixed(1)}',
|
|
value: widget.density.vertical,
|
|
max: 4,
|
|
min: -4,
|
|
divisions: 12,
|
|
onChanged: (double value) {
|
|
widget.onDensityChanged(
|
|
VisualDensity(
|
|
horizontal: widget.density.horizontal,
|
|
vertical: value,
|
|
),
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: <Widget>[
|
|
Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: <Widget>[
|
|
Checkbox(
|
|
value: widget.textDirection == TextDirection.rtl,
|
|
onChanged: (bool? value) {
|
|
if (value ?? false) {
|
|
widget.onTextDirectionChanged(TextDirection.rtl);
|
|
} else {
|
|
widget.onTextDirectionChanged(TextDirection.ltr);
|
|
}
|
|
},
|
|
),
|
|
const Text('RTL Text')
|
|
],
|
|
),
|
|
Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: <Widget>[
|
|
Checkbox(
|
|
value: widget.addItem,
|
|
onChanged: (bool? value) {
|
|
if (value ?? false) {
|
|
widget.onAddItemChanged(true);
|
|
} else {
|
|
widget.onAddItemChanged(false);
|
|
}
|
|
},
|
|
),
|
|
const Text('Add Item')
|
|
],
|
|
),
|
|
Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: <Widget>[
|
|
Checkbox(
|
|
value: widget.accelerators,
|
|
onChanged: (bool? value) {
|
|
if (value ?? false) {
|
|
widget.onAcceleratorsChanged(true);
|
|
} else {
|
|
widget.onAcceleratorsChanged(false);
|
|
}
|
|
},
|
|
),
|
|
const Text('Enable Accelerators')
|
|
],
|
|
),
|
|
Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: <Widget>[
|
|
Checkbox(
|
|
value: widget.transparent,
|
|
onChanged: (bool? value) {
|
|
if (value ?? false) {
|
|
widget.onTransparentChanged(true);
|
|
} else {
|
|
widget.onTransparentChanged(false);
|
|
}
|
|
},
|
|
),
|
|
const Text('Transparent')
|
|
],
|
|
),
|
|
Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: <Widget>[
|
|
Checkbox(
|
|
value: widget.funkyTheme,
|
|
onChanged: (bool? value) {
|
|
if (value ?? false) {
|
|
widget.onFunkyThemeChanged(true);
|
|
} else {
|
|
widget.onFunkyThemeChanged(false);
|
|
}
|
|
},
|
|
),
|
|
const Text('Funky Theme')
|
|
],
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
void _itemSelected(TestMenu item) {
|
|
debugPrint('App: Selected item ${item.label}');
|
|
}
|
|
}
|
|
|
|
class _ControlSlider extends StatelessWidget {
|
|
const _ControlSlider({
|
|
required this.label,
|
|
required this.value,
|
|
required this.onChanged,
|
|
this.min = 0,
|
|
this.max = 1,
|
|
this.divisions,
|
|
});
|
|
|
|
final String label;
|
|
final double value;
|
|
final ValueChanged<double> onChanged;
|
|
final double min;
|
|
final double max;
|
|
final int? divisions;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Row(
|
|
mainAxisAlignment: MainAxisAlignment.end,
|
|
children: <Widget>[
|
|
Container(
|
|
alignment: AlignmentDirectional.centerEnd,
|
|
constraints: const BoxConstraints(minWidth: 150),
|
|
child: Text(label),
|
|
),
|
|
Expanded(
|
|
child: Slider(
|
|
value: value,
|
|
min: min,
|
|
max: max,
|
|
divisions: divisions,
|
|
onChanged: onChanged,
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|
|
|
|
class _TestMenus extends StatefulWidget {
|
|
const _TestMenus({
|
|
required this.menuController,
|
|
this.addItem = false,
|
|
this.accelerators = false,
|
|
});
|
|
|
|
final MenuController menuController;
|
|
final bool addItem;
|
|
final bool accelerators;
|
|
|
|
@override
|
|
State<_TestMenus> createState() => _TestMenusState();
|
|
}
|
|
|
|
class _TestMenusState extends State<_TestMenus> {
|
|
final TextEditingController textController = TextEditingController();
|
|
bool? checkboxState = false;
|
|
TestMenu? radioValue;
|
|
ShortcutRegistryEntry? _shortcutsEntry;
|
|
|
|
void _itemSelected(TestMenu item) {
|
|
debugPrint('App: Selected item ${item.label}');
|
|
}
|
|
|
|
void _openItem(TestMenu item) {
|
|
debugPrint('App: Opened item ${item.label}');
|
|
}
|
|
|
|
void _closeItem(TestMenu item) {
|
|
debugPrint('App: Closed item ${item.label}');
|
|
}
|
|
|
|
void _setRadio(TestMenu? item) {
|
|
debugPrint('App: Set Radio item ${item?.label}');
|
|
setState(() {
|
|
radioValue = item;
|
|
});
|
|
}
|
|
|
|
void _setCheck(TestMenu item) {
|
|
debugPrint('App: Set Checkbox item ${item.label}');
|
|
setState(() {
|
|
checkboxState = switch (checkboxState) {
|
|
false => true,
|
|
true => null,
|
|
null => false,
|
|
};
|
|
});
|
|
}
|
|
|
|
@override
|
|
void didChangeDependencies() {
|
|
super.didChangeDependencies();
|
|
_shortcutsEntry?.dispose();
|
|
final Map<ShortcutActivator, Intent> shortcuts = <ShortcutActivator, Intent>{};
|
|
for (final TestMenu item in TestMenu.values) {
|
|
if (item.shortcut == null) {
|
|
continue;
|
|
}
|
|
switch (item) {
|
|
case TestMenu.radioMenu1:
|
|
case TestMenu.radioMenu2:
|
|
case TestMenu.radioMenu3:
|
|
shortcuts[item.shortcut!] = VoidCallbackIntent(() => _setRadio(item));
|
|
case TestMenu.subMenu1:
|
|
shortcuts[item.shortcut!] = VoidCallbackIntent(() => _setCheck(item));
|
|
case TestMenu.mainMenu1:
|
|
case TestMenu.mainMenu2:
|
|
case TestMenu.mainMenu3:
|
|
case TestMenu.mainMenu4:
|
|
case TestMenu.subMenu2:
|
|
case TestMenu.subMenu3:
|
|
case TestMenu.subMenu4:
|
|
case TestMenu.subMenu5:
|
|
case TestMenu.subMenu6:
|
|
case TestMenu.subMenu7:
|
|
case TestMenu.subMenu8:
|
|
case TestMenu.subSubMenu1:
|
|
case TestMenu.subSubMenu2:
|
|
case TestMenu.subSubMenu3:
|
|
case TestMenu.subSubSubMenu1:
|
|
case TestMenu.testButton:
|
|
case TestMenu.standaloneMenu1:
|
|
case TestMenu.standaloneMenu2:
|
|
shortcuts[item.shortcut!] = VoidCallbackIntent(() => _itemSelected(item));
|
|
}
|
|
}
|
|
_shortcutsEntry = ShortcutRegistry.of(context).addAll(shortcuts);
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_shortcutsEntry?.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Row(
|
|
children: <Widget>[
|
|
Expanded(
|
|
child: MenuBar(
|
|
controller: widget.menuController,
|
|
children: createTestMenus(
|
|
onPressed: _itemSelected,
|
|
onOpen: _openItem,
|
|
onClose: _closeItem,
|
|
onCheckboxChanged: (TestMenu menu, bool? value) {
|
|
_setCheck(menu);
|
|
},
|
|
onRadioChanged: _setRadio,
|
|
checkboxValue: checkboxState,
|
|
radioValue: radioValue,
|
|
menuController: widget.menuController,
|
|
textEditingController: textController,
|
|
includeExtraGroups: widget.addItem,
|
|
accelerators: widget.accelerators,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|
|
|
|
List<Widget> createTestMenus({
|
|
void Function(TestMenu)? onPressed,
|
|
void Function(TestMenu, bool?)? onCheckboxChanged,
|
|
void Function(TestMenu?)? onRadioChanged,
|
|
void Function(TestMenu)? onOpen,
|
|
void Function(TestMenu)? onClose,
|
|
Map<TestMenu, MenuSerializableShortcut> shortcuts = const <TestMenu, MenuSerializableShortcut>{},
|
|
bool? checkboxValue,
|
|
TestMenu? radioValue,
|
|
MenuController? menuController,
|
|
TextEditingController? textEditingController,
|
|
bool includeExtraGroups = false,
|
|
bool accelerators = false,
|
|
}) {
|
|
Widget submenuButton(
|
|
TestMenu menu, {
|
|
required List<Widget> menuChildren,
|
|
}) {
|
|
return SubmenuButton(
|
|
onOpen: onOpen != null ? () => onOpen(menu) : null,
|
|
onClose: onClose != null ? () => onClose(menu) : null,
|
|
menuChildren: menuChildren,
|
|
child: accelerators ? MenuAcceleratorLabel(menu.acceleratorLabel) : Text(menu.label),
|
|
);
|
|
}
|
|
|
|
Widget menuItemButton(
|
|
TestMenu menu, {
|
|
bool enabled = true,
|
|
Widget? leadingIcon,
|
|
Widget? trailingIcon,
|
|
Key? key,
|
|
}) {
|
|
return MenuItemButton(
|
|
key: key,
|
|
onPressed: enabled && onPressed != null ? () => onPressed(menu) : null,
|
|
shortcut: shortcuts[menu],
|
|
leadingIcon: leadingIcon,
|
|
trailingIcon: trailingIcon,
|
|
child: accelerators ? MenuAcceleratorLabel(menu.acceleratorLabel) : Text(menu.label),
|
|
);
|
|
}
|
|
|
|
Widget checkboxMenuButton(
|
|
TestMenu menu, {
|
|
bool enabled = true,
|
|
bool tristate = false,
|
|
Widget? leadingIcon,
|
|
Widget? trailingIcon,
|
|
Key? key,
|
|
}) {
|
|
return CheckboxMenuButton(
|
|
key: key,
|
|
value: checkboxValue,
|
|
tristate: tristate,
|
|
onChanged: enabled && onCheckboxChanged != null ? (bool? value) => onCheckboxChanged(menu, value) : null,
|
|
shortcut: menu.shortcut,
|
|
trailingIcon: trailingIcon,
|
|
child: accelerators ? MenuAcceleratorLabel(menu.acceleratorLabel) : Text(menu.label),
|
|
);
|
|
}
|
|
|
|
Widget radioMenuButton(
|
|
TestMenu menu, {
|
|
bool enabled = true,
|
|
bool toggleable = false,
|
|
Widget? leadingIcon,
|
|
Widget? trailingIcon,
|
|
Key? key,
|
|
}) {
|
|
return RadioMenuButton<TestMenu>(
|
|
key: key,
|
|
groupValue: radioValue,
|
|
value: menu,
|
|
toggleable: toggleable,
|
|
onChanged: enabled && onRadioChanged != null ? onRadioChanged : null,
|
|
shortcut: menu.shortcut,
|
|
trailingIcon: trailingIcon,
|
|
child: accelerators ? MenuAcceleratorLabel(menu.acceleratorLabel) : Text(menu.label),
|
|
);
|
|
}
|
|
|
|
final List<Widget> result = <Widget>[
|
|
submenuButton(
|
|
TestMenu.mainMenu1,
|
|
menuChildren: <Widget>[
|
|
checkboxMenuButton(
|
|
TestMenu.subMenu1,
|
|
tristate: true,
|
|
trailingIcon: const Icon(Icons.assessment),
|
|
),
|
|
radioMenuButton(
|
|
TestMenu.radioMenu1,
|
|
toggleable: true,
|
|
trailingIcon: const Icon(Icons.assessment),
|
|
),
|
|
radioMenuButton(
|
|
TestMenu.radioMenu2,
|
|
toggleable: true,
|
|
trailingIcon: const Icon(Icons.assessment),
|
|
),
|
|
radioMenuButton(
|
|
TestMenu.radioMenu3,
|
|
toggleable: true,
|
|
trailingIcon: const Icon(Icons.assessment),
|
|
),
|
|
menuItemButton(
|
|
TestMenu.subMenu2,
|
|
leadingIcon: const Icon(Icons.send),
|
|
trailingIcon: const Icon(Icons.mail),
|
|
),
|
|
],
|
|
),
|
|
submenuButton(
|
|
TestMenu.mainMenu2,
|
|
menuChildren: <Widget>[
|
|
MenuAcceleratorCallbackBinding(
|
|
onInvoke: onPressed != null
|
|
? () {
|
|
onPressed.call(TestMenu.testButton);
|
|
menuController?.close();
|
|
}
|
|
: null,
|
|
child: TextButton(
|
|
onPressed: onPressed != null
|
|
? () {
|
|
onPressed.call(TestMenu.testButton);
|
|
menuController?.close();
|
|
}
|
|
: null,
|
|
child: accelerators
|
|
? MenuAcceleratorLabel(TestMenu.testButton.acceleratorLabel)
|
|
: Text(TestMenu.testButton.label),
|
|
),
|
|
),
|
|
menuItemButton(TestMenu.subMenu3),
|
|
],
|
|
),
|
|
submenuButton(
|
|
TestMenu.mainMenu3,
|
|
menuChildren: <Widget>[
|
|
menuItemButton(TestMenu.subMenu8),
|
|
MenuItemButton(
|
|
onPressed: () {
|
|
debugPrint('Focused Item: $primaryFocus');
|
|
},
|
|
child: const Text('Print Focused Item'),
|
|
)
|
|
],
|
|
),
|
|
submenuButton(
|
|
TestMenu.mainMenu4,
|
|
menuChildren: <Widget>[
|
|
MenuItemButton(
|
|
onPressed: () {
|
|
debugPrint('Activated text input item with ${textEditingController?.text} as a value.');
|
|
},
|
|
child: SizedBox(
|
|
width: 200,
|
|
child: TextField(
|
|
controller: textEditingController,
|
|
onSubmitted: (String value) {
|
|
debugPrint('String $value submitted.');
|
|
},
|
|
),
|
|
),
|
|
),
|
|
submenuButton(
|
|
TestMenu.subMenu5,
|
|
menuChildren: <Widget>[
|
|
menuItemButton(TestMenu.subSubMenu1),
|
|
menuItemButton(TestMenu.subSubMenu2),
|
|
if (includeExtraGroups)
|
|
submenuButton(
|
|
TestMenu.subSubMenu3,
|
|
menuChildren: <Widget>[
|
|
for (int i=0; i < 100; ++i)
|
|
MenuItemButton(
|
|
onPressed: () {},
|
|
child: Text('Menu Item $i'),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
menuItemButton(TestMenu.subMenu6, enabled: false),
|
|
menuItemButton(TestMenu.subMenu7),
|
|
menuItemButton(TestMenu.subMenu7),
|
|
menuItemButton(TestMenu.subMenu8),
|
|
],
|
|
),
|
|
];
|
|
return result;
|
|
}
|
|
|
|
enum TestMenu {
|
|
mainMenu1('Menu 1'),
|
|
mainMenu2('M&enu &2'),
|
|
mainMenu3('Me&nu &3'),
|
|
mainMenu4('Men&u &4'),
|
|
radioMenu1('Radio Menu One', SingleActivator(LogicalKeyboardKey.digit1, control: true)),
|
|
radioMenu2('Radio Menu Two', SingleActivator(LogicalKeyboardKey.digit2, control: true)),
|
|
radioMenu3('Radio Menu Three', SingleActivator(LogicalKeyboardKey.digit3, control: true)),
|
|
subMenu1('Sub Menu &1', SingleActivator(LogicalKeyboardKey.keyB, control: true)),
|
|
subMenu2('Sub Menu &2'),
|
|
subMenu3('Sub Menu &3', SingleActivator(LogicalKeyboardKey.enter, control: true)),
|
|
subMenu4('Sub Menu &4'),
|
|
subMenu5('Sub Menu &5'),
|
|
subMenu6('Sub Menu &6', SingleActivator(LogicalKeyboardKey.tab, control: true)),
|
|
subMenu7('Sub Menu &7'),
|
|
subMenu8('Sub Menu &8'),
|
|
subSubMenu1('Sub Sub Menu &1', SingleActivator(LogicalKeyboardKey.f10, control: true)),
|
|
subSubMenu2('Sub Sub Menu &2'),
|
|
subSubMenu3('Sub Sub Menu &3'),
|
|
subSubSubMenu1('Sub Sub Sub Menu &1', SingleActivator(LogicalKeyboardKey.f11, control: true)),
|
|
testButton('&TEST && &&& Button &'),
|
|
standaloneMenu1('Standalone Menu &1', SingleActivator(LogicalKeyboardKey.keyC, control: true)),
|
|
standaloneMenu2('Standalone Menu &2');
|
|
|
|
const TestMenu(this.acceleratorLabel, [this.shortcut]);
|
|
final MenuSerializableShortcut? shortcut;
|
|
final String acceleratorLabel;
|
|
// Strip the accelerator markers.
|
|
String get label => MenuAcceleratorLabel.stripAcceleratorMarkers(acceleratorLabel);
|
|
}
|