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) {
height: conf.dividerHeight, return [
); mod_menu.PopupMenuDivider(
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,23 +233,26 @@ class MenuEntrySubRadios<T> extends MenuEntryBase<T> {
constraints: BoxConstraints(minHeight: conf.height), constraints: BoxConstraints(minHeight: conf.height),
child: Row( child: Row(
children: [ children: [
SizedBox(
width: 20.0,
height: 20.0,
child: Obx(() => opt.item2 == curOption.value
? Icon(
Icons.check,
color: conf.commonColor,
)
: const SizedBox.shrink())),
const SizedBox(width: MenuConfig.midPadding),
Text( Text(
opt.item1, opt.item1,
style: const TextStyle( style: const TextStyle(
color: Colors.black, color: Colors.black,
fontSize: MenuConfig.fontSize, fontSize: MenuConfig.fontSize,
fontWeight: FontWeight.normal), 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())),
)),
], ],
), ),
), ),
@ -181,31 +266,34 @@ 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) {
padding: EdgeInsets.zero, return [
height: conf.height, PopupMenuChildrenItem(
itemBuilder: (BuildContext context) => padding: EdgeInsets.zero,
options.map((opt) => _buildSecondMenu(context, conf, opt)).toList(), height: conf.height,
child: Row(children: [ itemBuilder: (BuildContext context) =>
const SizedBox(width: MenuConfig.midPadding), options.map((opt) => _buildSecondMenu(context, conf, opt)).toList(),
Text( child: Row(children: [
text, const SizedBox(width: MenuConfig.midPadding),
style: const TextStyle( Text(
color: Colors.black, text,
fontSize: MenuConfig.fontSize, style: const TextStyle(
fontWeight: FontWeight.normal), color: Colors.black,
), fontSize: MenuConfig.fontSize,
Expanded( fontWeight: FontWeight.normal),
child: Align(
alignment: Alignment.centerRight,
child: Icon(
Icons.keyboard_arrow_right,
color: conf.commonColor,
), ),
)) Expanded(
]), child: Align(
); alignment: Alignment.centerRight,
child: Icon(
Icons.keyboard_arrow_right,
color: conf.commonColor,
),
))
]),
)
];
} }
} }
@ -221,35 +309,38 @@ 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) {
padding: EdgeInsets.zero, return [
height: conf.height, mod_menu.PopupMenuItem(
child: Obx( padding: EdgeInsets.zero,
() => SwitchListTile( height: conf.height,
value: curOption.value, child: Obx(
onChanged: (v) { () => SwitchListTile(
setOption(v); value: curOption.value,
}, onChanged: (v) {
title: Container( setOption(v);
alignment: AlignmentDirectional.centerStart, },
constraints: BoxConstraints(minHeight: conf.height), title: Container(
child: Text( alignment: AlignmentDirectional.centerStart,
text, constraints: BoxConstraints(minHeight: conf.height),
style: const TextStyle( child: Text(
color: Colors.black, text,
fontSize: MenuConfig.fontSize, style: const TextStyle(
fontWeight: FontWeight.normal), color: Colors.black,
)), fontSize: MenuConfig.fontSize,
dense: true, fontWeight: FontWeight.normal),
visualDensity: const VisualDensity( )),
horizontal: VisualDensity.minimumDensity, dense: true,
vertical: VisualDensity.minimumDensity, visualDensity: const VisualDensity(
horizontal: VisualDensity.minimumDensity,
vertical: VisualDensity.minimumDensity,
),
contentPadding: const EdgeInsets.only(left: 8.0),
), ),
contentPadding: const EdgeInsets.only(left: 8.0),
), ),
), )
); ];
} }
} }
@ -307,32 +398,37 @@ 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) {
height: conf.height, return [
padding: EdgeInsets.zero, PopupMenuChildrenItem(
position: mod_menu.PopupMenuPosition.overSide, height: conf.height,
itemBuilder: (BuildContext context) => padding: EdgeInsets.zero,
entries.map((entry) => entry.build(context, conf)).toList(), position: mod_menu.PopupMenuPosition.overSide,
child: Row(children: [ itemBuilder: (BuildContext context) => entries
const SizedBox(width: MenuConfig.midPadding), .map((entry) => entry.build(context, conf))
Text( .expand((i) => i)
text, .toList(),
style: const TextStyle( child: Row(children: [
color: Colors.black, const SizedBox(width: MenuConfig.midPadding),
fontSize: MenuConfig.fontSize, Text(
fontWeight: FontWeight.normal), text,
), style: const TextStyle(
Expanded( color: Colors.black,
child: Align( fontSize: MenuConfig.fontSize,
alignment: Alignment.centerRight, fontWeight: FontWeight.normal),
child: Icon(
Icons.keyboard_arrow_right,
color: conf.commonColor,
), ),
)) Expanded(
]), child: Align(
); alignment: Alignment.centerRight,
child: Icon(
Icons.keyboard_arrow_right,
color: conf.commonColor,
),
))
]),
)
];
} }
} }
@ -346,24 +442,27 @@ 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) {
padding: EdgeInsets.zero, return [
height: conf.height, mod_menu.PopupMenuItem(
child: TextButton( padding: EdgeInsets.zero,
child: Container( height: conf.height,
alignment: AlignmentDirectional.centerStart, child: TextButton(
constraints: BoxConstraints(minHeight: conf.height), child: Container(
child: childBuilder( alignment: AlignmentDirectional.centerStart,
const TextStyle( constraints: BoxConstraints(minHeight: conf.height),
color: Colors.black, child: childBuilder(
fontSize: MenuConfig.fontSize, const TextStyle(
fontWeight: FontWeight.normal), color: Colors.black,
)), fontSize: MenuConfig.fontSize,
onPressed: () { fontWeight: FontWeight.normal),
proc(); )),
}, onPressed: () {
), 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