From 83fda1f3645a27a17bedb2d1df8a681466d63acc Mon Sep 17 00:00:00 2001 From: r0227n Date: Sat, 30 Mar 2024 16:38:23 +0900 Subject: [PATCH] =?UTF-8?q?add:=20PopupMenu=20component=E3=81=AE=E9=9B=9B?= =?UTF-8?q?=E5=BD=A2=E4=BD=9C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/flutter_sdk_util.dart | 1 + lib/src/popup_menu_bar.dart | 85 +++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 lib/src/popup_menu_bar.dart diff --git a/lib/flutter_sdk_util.dart b/lib/flutter_sdk_util.dart index 49a4385..012c4d9 100644 --- a/lib/flutter_sdk_util.dart +++ b/lib/flutter_sdk_util.dart @@ -1,3 +1,4 @@ library flutter_sdk_util; export 'src/pinch_zoom.dart'; +export 'src/popup_menu_bar.dart'; \ No newline at end of file diff --git a/lib/src/popup_menu_bar.dart b/lib/src/popup_menu_bar.dart new file mode 100644 index 0000000..6e27297 --- /dev/null +++ b/lib/src/popup_menu_bar.dart @@ -0,0 +1,85 @@ +import 'package:flutter/material.dart'; + +class MenuEntry { + const MenuEntry({ + required this.child, + this.shortcut, + this.onPressed, + this.menuChildren, + }) : assert( + menuChildren == null || onPressed == null, + 'onPressed is ignored if menuChildren are provided', + ); + + final Widget child; + + final MenuSerializableShortcut? shortcut; + final VoidCallback? onPressed; + final List? menuChildren; + + static List build(List selections) { + Widget buildSelection(MenuEntry selection) { + if (selection.menuChildren != null) { + return SubmenuButton( + menuChildren: MenuEntry.build(selection.menuChildren!), + child: selection.child, + ); + } + + return MenuItemButton( + shortcut: selection.shortcut, + onPressed: selection.onPressed, + style: ButtonStyle( + alignment: Alignment.center, + backgroundColor: MaterialStateProperty.all(Colors.transparent), + padding: MaterialStateProperty.all(EdgeInsets.zero), + ), + child: selection.child, + ); + } + + return selections.map(buildSelection).toList(); + } + + static Map shortcuts(List selections) { + final Map result = {}; + for (final MenuEntry selection in selections) { + if (selection.menuChildren != null) { + result.addAll(MenuEntry.shortcuts(selection.menuChildren!)); + } else { + if (selection.shortcut != null && selection.onPressed != null) { + result[selection.shortcut!] = VoidCallbackIntent(selection.onPressed!); + } + } + } + return result; + } +} + +class PopupMenuBar extends StatelessWidget { + const PopupMenuBar({ + super.key, + required this.child, + required this.entries, + }); + + final Widget child; + final List entries; + + @override + Widget build(BuildContext context) { + return MenuBar( + style: MenuStyle( + backgroundColor: MaterialStateProperty.all(Colors.transparent), + shadowColor: MaterialStateProperty.all(Colors.transparent), + surfaceTintColor: MaterialStateProperty.all(Colors.transparent), + padding: MaterialStateProperty.all(EdgeInsets.zero), + ), + children: MenuEntry.build( + [ + MenuEntry(child: child, menuChildren: entries), + ], + ), + ); + } +}