flutter_desktop: remote menubar remove submenu

Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
fufesou 2022-08-30 17:20:25 +08:00
parent f42c6ffeaf
commit 4d914e9a01
3 changed files with 219 additions and 118 deletions

View File

@ -97,15 +97,18 @@ class MenuConfig {
} }
abstract class MenuEntryBase<T> { abstract class MenuEntryBase<T> {
mod_menu.PopupMenuEntry<T> build(BuildContext context, MenuConfig conf); List<mod_menu.PopupMenuEntry<T>> build(BuildContext context, MenuConfig conf);
} }
class MenuEntryDivider<T> extends MenuEntryBase<T> { class MenuEntryDivider<T> extends MenuEntryBase<T> {
@override @override
mod_menu.PopupMenuEntry<T> build(BuildContext context, MenuConfig conf) { List<mod_menu.PopupMenuEntry<T>> build(
return mod_menu.PopupMenuDivider( BuildContext context, MenuConfig conf) {
return [
mod_menu.PopupMenuDivider(
height: conf.dividerHeight, height: conf.dividerHeight,
); )
];
} }
} }
@ -113,6 +116,85 @@ typedef RadioOptionsGetter = List<Tuple2<String, String>> Function();
typedef RadioCurOptionGetter = Future<String> Function(); typedef RadioCurOptionGetter = Future<String> Function();
typedef RadioOptionSetter = Future<void> Function(String); typedef RadioOptionSetter = Future<void> Function(String);
class MenuEntryRadioUtils<T> {}
class MenuEntryRadios<T> extends MenuEntryBase<T> {
final String text;
final RadioOptionsGetter optionsGetter;
final RadioCurOptionGetter curOptionGetter;
final RadioOptionSetter optionSetter;
final RxString _curOption = "".obs;
MenuEntryRadios(
{required this.text,
required this.optionsGetter,
required this.curOptionGetter,
required this.optionSetter}) {
() async {
_curOption.value = await curOptionGetter();
}();
}
List<Tuple2<String, String>> get options => optionsGetter();
RxString get curOption => _curOption;
setOption(String option) async {
await optionSetter(option);
final opt = await curOptionGetter();
if (_curOption.value != opt) {
_curOption.value = opt;
}
}
mod_menu.PopupMenuEntry<T> _buildMenuItem(
BuildContext context, MenuConfig conf, Tuple2<String, String> opt) {
return mod_menu.PopupMenuItem(
padding: EdgeInsets.zero,
height: conf.height,
child: TextButton(
child: Container(
alignment: AlignmentDirectional.centerStart,
constraints: BoxConstraints(minHeight: conf.height),
child: Row(
children: [
Text(
opt.item1,
style: const TextStyle(
color: Colors.black,
fontSize: MenuConfig.fontSize,
fontWeight: FontWeight.normal),
),
Expanded(
child: Align(
alignment: Alignment.centerRight,
child: SizedBox(
width: 20.0,
height: 20.0,
child: Obx(() => opt.item2 == curOption.value
? Icon(
Icons.check,
color: conf.commonColor,
)
: const SizedBox.shrink())),
)),
],
),
),
onPressed: () {
if (opt.item2 != curOption.value) {
setOption(opt.item2);
}
},
),
);
}
@override
List<mod_menu.PopupMenuEntry<T>> build(
BuildContext context, MenuConfig conf) {
return options.map((opt) => _buildMenuItem(context, conf, opt)).toList();
}
}
class MenuEntrySubRadios<T> extends MenuEntryBase<T> { class MenuEntrySubRadios<T> extends MenuEntryBase<T> {
final String text; final String text;
final RadioOptionsGetter optionsGetter; final RadioOptionsGetter optionsGetter;
@ -151,7 +233,17 @@ class MenuEntrySubRadios<T> extends MenuEntryBase<T> {
constraints: BoxConstraints(minHeight: conf.height), constraints: BoxConstraints(minHeight: conf.height),
child: Row( child: Row(
children: [ children: [
SizedBox( Text(
opt.item1,
style: const TextStyle(
color: Colors.black,
fontSize: MenuConfig.fontSize,
fontWeight: FontWeight.normal),
),
Expanded(
child: Align(
alignment: Alignment.centerRight,
child: SizedBox(
width: 20.0, width: 20.0,
height: 20.0, height: 20.0,
child: Obx(() => opt.item2 == curOption.value child: Obx(() => opt.item2 == curOption.value
@ -160,14 +252,7 @@ class MenuEntrySubRadios<T> extends MenuEntryBase<T> {
color: conf.commonColor, color: conf.commonColor,
) )
: const SizedBox.shrink())), : const SizedBox.shrink())),
const SizedBox(width: MenuConfig.midPadding), )),
Text(
opt.item1,
style: const TextStyle(
color: Colors.black,
fontSize: MenuConfig.fontSize,
fontWeight: FontWeight.normal),
)
], ],
), ),
), ),
@ -181,8 +266,10 @@ class MenuEntrySubRadios<T> extends MenuEntryBase<T> {
} }
@override @override
mod_menu.PopupMenuEntry<T> build(BuildContext context, MenuConfig conf) { List<mod_menu.PopupMenuEntry<T>> build(
return PopupMenuChildrenItem( BuildContext context, MenuConfig conf) {
return [
PopupMenuChildrenItem(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
height: conf.height, height: conf.height,
itemBuilder: (BuildContext context) => itemBuilder: (BuildContext context) =>
@ -205,7 +292,8 @@ class MenuEntrySubRadios<T> extends MenuEntryBase<T> {
), ),
)) ))
]), ]),
); )
];
} }
} }
@ -221,8 +309,10 @@ abstract class MenuEntrySwitchBase<T> extends MenuEntryBase<T> {
Future<void> setOption(bool option); Future<void> setOption(bool option);
@override @override
mod_menu.PopupMenuEntry<T> build(BuildContext context, MenuConfig conf) { List<mod_menu.PopupMenuEntry<T>> build(
return mod_menu.PopupMenuItem( BuildContext context, MenuConfig conf) {
return [
mod_menu.PopupMenuItem(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
height: conf.height, height: conf.height,
child: Obx( child: Obx(
@ -249,7 +339,8 @@ abstract class MenuEntrySwitchBase<T> extends MenuEntryBase<T> {
contentPadding: const EdgeInsets.only(left: 8.0), contentPadding: const EdgeInsets.only(left: 8.0),
), ),
), ),
); )
];
} }
} }
@ -307,13 +398,17 @@ class MenuEntrySubMenu<T> extends MenuEntryBase<T> {
}); });
@override @override
mod_menu.PopupMenuEntry<T> build(BuildContext context, MenuConfig conf) { List<mod_menu.PopupMenuEntry<T>> build(
return PopupMenuChildrenItem( BuildContext context, MenuConfig conf) {
return [
PopupMenuChildrenItem(
height: conf.height, height: conf.height,
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
position: mod_menu.PopupMenuPosition.overSide, position: mod_menu.PopupMenuPosition.overSide,
itemBuilder: (BuildContext context) => itemBuilder: (BuildContext context) => entries
entries.map((entry) => entry.build(context, conf)).toList(), .map((entry) => entry.build(context, conf))
.expand((i) => i)
.toList(),
child: Row(children: [ child: Row(children: [
const SizedBox(width: MenuConfig.midPadding), const SizedBox(width: MenuConfig.midPadding),
Text( Text(
@ -332,7 +427,8 @@ class MenuEntrySubMenu<T> extends MenuEntryBase<T> {
), ),
)) ))
]), ]),
); )
];
} }
} }
@ -346,8 +442,10 @@ class MenuEntryButton<T> extends MenuEntryBase<T> {
}); });
@override @override
mod_menu.PopupMenuEntry<T> build(BuildContext context, MenuConfig conf) { List<mod_menu.PopupMenuEntry<T>> build(
return mod_menu.PopupMenuItem( BuildContext context, MenuConfig conf) {
return [
mod_menu.PopupMenuItem(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
height: conf.height, height: conf.height,
child: TextButton( child: TextButton(
@ -364,6 +462,7 @@ class MenuEntryButton<T> extends MenuEntryBase<T> {
proc(); proc();
}, },
), ),
); )
];
} }
} }

View File

@ -236,6 +236,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
height: _MenubarTheme.height, height: _MenubarTheme.height,
dividerHeight: _MenubarTheme.dividerHeight, dividerHeight: _MenubarTheme.dividerHeight,
))) )))
.expand((i) => i)
.toList(), .toList(),
); );
} }
@ -258,6 +259,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
height: _MenubarTheme.height, height: _MenubarTheme.height,
dividerHeight: _MenubarTheme.dividerHeight, dividerHeight: _MenubarTheme.dividerHeight,
))) )))
.expand((i) => i)
.toList(), .toList(),
); );
} }
@ -401,7 +403,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
List<MenuEntryBase<String>> _getDisplayMenu() { List<MenuEntryBase<String>> _getDisplayMenu() {
final displayMenu = [ final displayMenu = [
MenuEntrySubRadios<String>( MenuEntryRadios<String>(
text: translate('Ratio'), text: translate('Ratio'),
optionsGetter: () => [ optionsGetter: () => [
Tuple2<String, String>(translate('Original'), 'original'), Tuple2<String, String>(translate('Original'), 'original'),
@ -418,7 +420,8 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
id: widget.id, name: "view-style", value: v); id: widget.id, name: "view-style", value: v);
widget.ffi.canvasModel.updateViewStyle(); widget.ffi.canvasModel.updateViewStyle();
}), }),
MenuEntrySubRadios<String>( MenuEntryDivider<String>(),
MenuEntryRadios<String>(
text: translate('Scroll Style'), text: translate('Scroll Style'),
optionsGetter: () => [ optionsGetter: () => [
Tuple2<String, String>(translate('ScrollAuto'), 'scrollauto'), Tuple2<String, String>(translate('ScrollAuto'), 'scrollauto'),
@ -434,7 +437,8 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
id: widget.id, name: "scroll-style", value: v); id: widget.id, name: "scroll-style", value: v);
widget.ffi.canvasModel.updateScrollStyle(); widget.ffi.canvasModel.updateScrollStyle();
}), }),
MenuEntrySubRadios<String>( MenuEntryDivider<String>(),
MenuEntryRadios<String>(
text: translate('Image Quality'), text: translate('Image Quality'),
optionsGetter: () => [ optionsGetter: () => [
Tuple2<String, String>(translate('Good image quality'), 'best'), Tuple2<String, String>(translate('Good image quality'), 'best'),
@ -451,6 +455,7 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
optionSetter: (String v) async { optionSetter: (String v) async {
await bind.sessionSetImageQuality(id: widget.id, value: v); await bind.sessionSetImageQuality(id: widget.id, value: v);
}), }),
MenuEntryDivider<String>(),
MenuEntrySwitch<String>( MenuEntrySwitch<String>(
text: translate('Show remote cursor'), text: translate('Show remote cursor'),
getter: () async { getter: () async {

View File

@ -40,10 +40,7 @@ dependencies:
url_launcher: ^6.0.9 url_launcher: ^6.0.9
shared_preferences: ^2.0.6 shared_preferences: ^2.0.6
toggle_switch: ^1.4.0 toggle_switch: ^1.4.0
dash_chat_2: dash_chat_2: ^0.0.14
git:
url: https://github.com/fufesou/Dash-Chat-2
ref: feat_maxWidth
draggable_float_widget: ^0.0.2 draggable_float_widget: ^0.0.2
settings_ui: ^2.0.2 settings_ui: ^2.0.2
flutter_breadcrumb: ^1.0.1 flutter_breadcrumb: ^1.0.1