marco.pms.mobile/lib/widgets/custom_pop_menu.dart
Vaibhav Surve 99902e743c Flutter application
- Created generated_plugin_registrant.cc and generated_plugin_registrant.h to manage plugin registration.
- Added generated_plugins.cmake for plugin configuration in CMake.
- Implemented CMakeLists.txt for the Windows runner, defining build settings and dependencies.
- Created Runner.rc for application resources including versioning and icons.
- Developed flutter_window.cpp and flutter_window.h to manage the Flutter window lifecycle.
- Implemented main.cpp as the entry point for the Windows application.
- Added resource.h for resource definitions.
- Included app icon in resources.
- Created runner.exe.manifest for application settings.
- Developed utils.cpp and utils.h for console management and command line argument handling.
- Implemented win32_window.cpp and win32_window.h for high DPI-aware window management.
2025-04-17 12:30:38 +05:30

140 lines
3.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:marco/helpers/utils/mixins/ui_mixin.dart';
enum CustomPopupMenuPlacement { left, right, top, bottom }
typedef HideFn = void Function(Function hideFn);
class CustomPopupMenu extends StatefulWidget {
final Widget menu;
final ValueChanged<bool> onChange;
final WidgetBuilder menuBuilder;
final int selectedIndex;
final CustomPopupMenuPlacement placement;
final double offsetX, offsetY;
final bool backdrop;
final bool show;
final HideFn? hideFn;
const CustomPopupMenu(
{super.key,
required this.menu,
required this.onChange,
required this.menuBuilder,
this.selectedIndex = 0,
this.backdrop = false,
this.show = true,
this.placement = CustomPopupMenuPlacement.bottom,
this.offsetX = 0,
this.hideFn,
this.offsetY = 0});
@override
_CustomPopupMenuState createState() => _CustomPopupMenuState();
}
class _CustomPopupMenuState extends State<CustomPopupMenu>
with SingleTickerProviderStateMixin, UIMixin {
late GlobalKey _key;
bool isMenuOpen = false;
late Offset buttonPosition;
late Size buttonSize;
OverlayEntry? _overlayEntry;
OverlayEntry? _overlayEntry1;
@override
void initState() {
_key = LabeledGlobalKey("popup-button");
super.initState();
if (widget.hideFn != null) {
widget.hideFn!(closeMenu);
}
}
findButton() {
RenderBox? renderBox =
_key.currentContext!.findRenderObject() as RenderBox?;
buttonSize = renderBox!.size;
buttonPosition = renderBox.localToGlobal(Offset.zero);
}
closeMenu() {
_overlayEntry?.remove();
_overlayEntry1?.remove();
// if(_animationController.)
// _animationController.reverse();
isMenuOpen = false;
}
openMenu() {
findButton();
_overlayEntry = _overlayEntryBuilder();
_overlayEntry1 = _overlayEntryBuilder1();
Overlay.of(context).insert(_overlayEntry1!);
Overlay.of(context).insert(
_overlayEntry!,
);
isMenuOpen = true;
}
@override
Widget build(BuildContext context) {
return Container(
key: _key,
child: MouseRegion(
cursor: SystemMouseCursors.click,
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
if (isMenuOpen) {
closeMenu();
widget.onChange(false);
} else {
openMenu();
widget.onChange(true);
}
},
child: widget.menu),
),
);
}
OverlayEntry _overlayEntryBuilder() {
double left = 0, top = 0;
if (widget.placement == CustomPopupMenuPlacement.bottom) {
top = buttonPosition.dy + buttonSize.height + widget.offsetY;
left = buttonPosition.dx + widget.offsetX;
} else if (widget.placement == CustomPopupMenuPlacement.right) {
top = buttonPosition.dy + widget.offsetY;
left = buttonPosition.dx + buttonSize.width + widget.offsetX;
}
return OverlayEntry(
builder: (context) {
return Positioned(
top: top,
left: left,
child: widget.menuBuilder(context),
);
},
);
}
OverlayEntry _overlayEntryBuilder1() {
return OverlayEntry(
builder: (context) {
return GestureDetector(
onTap: () => {closeMenu()},
child: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
color: widget.backdrop
? colorScheme.onSurface.withAlpha(12)
: Colors.transparent,
),
);
},
);
}
}