v7
This commit is contained in:
@@ -2,32 +2,47 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
class HoverIconButton extends StatefulWidget {
|
||||
final VoidCallback onPressed;
|
||||
final IconData icon;
|
||||
final double size;
|
||||
final Color? hoverColor;
|
||||
final Color? defaultColor;
|
||||
const HoverIconButton({super.key,required this.onPressed ,required this.icon,this.hoverColor,this.size=24,this.defaultColor});
|
||||
final VoidCallback? onPressed;
|
||||
final IconData icon;
|
||||
final double size;
|
||||
final Color? hoverColor;
|
||||
final Color? defaultColor;
|
||||
final MouseCursor cursor;
|
||||
|
||||
const HoverIconButton({
|
||||
super.key,
|
||||
required this.onPressed,
|
||||
required this.icon,
|
||||
this.hoverColor,
|
||||
this.size = 24,
|
||||
this.defaultColor,
|
||||
this.cursor = SystemMouseCursors.cell,
|
||||
});
|
||||
|
||||
@override
|
||||
State<HoverIconButton> createState() => _HoverIconButtonState();
|
||||
}
|
||||
|
||||
class _HoverIconButtonState extends State<HoverIconButton> {
|
||||
|
||||
bool _hover = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Color? color = (_hover)?widget.hoverColor??Theme.of(context).primaryColor:(widget.defaultColor??null);
|
||||
Color? color = (_hover)
|
||||
? widget.hoverColor ?? Theme.of(context).primaryColor
|
||||
: (widget.defaultColor ?? null);
|
||||
|
||||
return MouseRegion(
|
||||
cursor: SystemMouseCursors.click,
|
||||
cursor: widget.cursor,
|
||||
onEnter: _onEnter,
|
||||
onExit: _onExit,
|
||||
child: GestureDetector(
|
||||
onTap: widget.onPressed,
|
||||
child: Icon(widget.icon,size: widget.size,color: color,)),
|
||||
child: Icon(
|
||||
widget.icon,
|
||||
size: widget.size,
|
||||
color: color,
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -42,4 +57,4 @@ class _HoverIconButtonState extends State<HoverIconButton> {
|
||||
_hover = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
117
lib/components/toly_ui/popable/pop_menu.dart
Normal file
117
lib/components/toly_ui/popable/pop_menu.dart
Normal file
@@ -0,0 +1,117 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'toly_pop_menu.dart';
|
||||
|
||||
class PopPanel<T> extends StatefulWidget {
|
||||
final Widget child;
|
||||
final Size size;
|
||||
final Offset offset;
|
||||
|
||||
/// Builds the context menu.
|
||||
final Widget panel;
|
||||
|
||||
const PopPanel({
|
||||
super.key,
|
||||
required this.child,
|
||||
required this.panel,
|
||||
this.offset = Offset.zero,
|
||||
this.size = const Size(250, 0),
|
||||
});
|
||||
|
||||
@override
|
||||
State<PopPanel> createState() => _PopPanelState();
|
||||
}
|
||||
|
||||
class _PopPanelState<T> extends State<PopPanel<T>> {
|
||||
final ContextMenuController _contextMenuController = ContextMenuController();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: _onTap,
|
||||
child: widget.child,
|
||||
);
|
||||
}
|
||||
|
||||
void _show() {
|
||||
TolyPopupMenuEntry<T> item = CustomTolyMenuItem(
|
||||
widget.panel,
|
||||
size: widget.size,
|
||||
);
|
||||
|
||||
final RenderBox button = context.findRenderObject()! as RenderBox;
|
||||
final RenderBox overlay =
|
||||
Navigator.of(context).overlay!.context.findRenderObject()! as RenderBox;
|
||||
final Offset offset = Offset(button.size.width / 2, button.size.height)+widget.offset;
|
||||
final RelativeRect position = RelativeRect.fromRect(
|
||||
Rect.fromPoints(
|
||||
button.localToGlobal(offset, ancestor: overlay),
|
||||
button.localToGlobal(button.size.bottomRight(Offset.zero) + offset,
|
||||
ancestor: overlay),
|
||||
),
|
||||
Offset.zero & overlay.size,
|
||||
);
|
||||
showTolyMenu<T?>(
|
||||
elevation: 0,
|
||||
color: Colors.transparent,
|
||||
context: context,
|
||||
items: [item],
|
||||
position: position,
|
||||
).then<void>((T? newValue) {
|
||||
if (!mounted) {
|
||||
return null;
|
||||
}
|
||||
if (newValue == null) {
|
||||
// widget.onCanceled?.call();
|
||||
return null;
|
||||
}
|
||||
// widget.onSelected?.call(newValue);
|
||||
});
|
||||
}
|
||||
|
||||
void _onTap() {
|
||||
_show();
|
||||
}
|
||||
}
|
||||
|
||||
class CustomTolyMenuItem<T> extends TolyPopupMenuEntry<T> {
|
||||
final Size size;
|
||||
final Widget content;
|
||||
|
||||
const CustomTolyMenuItem(this.content, {super.key, required this.size});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _CustomTolyMenuItemState();
|
||||
|
||||
@override
|
||||
// TODO: implement height
|
||||
double get height => kMinInteractiveDimension;
|
||||
|
||||
@override
|
||||
bool represents(value) => true;
|
||||
}
|
||||
|
||||
class _CustomTolyMenuItemState<T> extends State<CustomTolyMenuItem> {
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant CustomTolyMenuItem oldWidget) {
|
||||
print('============_CustomTolyMenuItemState#didUpdateWidget');
|
||||
super.didUpdateWidget(oldWidget);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: widget.size.width,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
boxShadow: [
|
||||
BoxShadow(color: Colors.black.withOpacity(0.1), blurRadius: 6)
|
||||
]),
|
||||
// padding: EdgeInsets.symmetric(horizontal: 12, vertical: 16),
|
||||
child: widget.content,
|
||||
// color: Colors.lightBlueAccent,
|
||||
);
|
||||
}
|
||||
}
|
||||
52
lib/components/toly_ui/popable/popover.dart
Normal file
52
lib/components/toly_ui/popable/popover.dart
Normal file
@@ -0,0 +1,52 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// A builder that includes an Offset to draw the context menu at.
|
||||
typedef ContextMenuBuilder = Widget Function(BuildContext context, Offset offset);
|
||||
|
||||
|
||||
class Popover extends StatefulWidget {
|
||||
final Widget child;
|
||||
/// Builds the context menu.
|
||||
final ContextMenuBuilder contextMenuBuilder;
|
||||
|
||||
const Popover({
|
||||
super.key,
|
||||
required this.child,
|
||||
required this.contextMenuBuilder,
|
||||
});
|
||||
|
||||
@override
|
||||
State<Popover> createState() => _PopoverState();
|
||||
}
|
||||
|
||||
class _PopoverState extends State<Popover> {
|
||||
|
||||
final ContextMenuController _contextMenuController = ContextMenuController();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: _onTap,
|
||||
child: widget.child,
|
||||
);
|
||||
}
|
||||
|
||||
void _show(Offset position) {
|
||||
_contextMenuController.show(
|
||||
context: context,
|
||||
contextMenuBuilder: (BuildContext context) {
|
||||
return widget.contextMenuBuilder(context, position);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
final double width = 200;
|
||||
|
||||
void _onTap() {
|
||||
final RenderBox button = context.findRenderObject()! as RenderBox;
|
||||
final RenderBox overlay = Navigator.of(context).overlay!.context.findRenderObject()! as RenderBox;
|
||||
final Offset offset = Offset(button.size.width / 2, button.size.height);
|
||||
Offset boxOffset = button.localToGlobal(offset, ancestor: overlay);
|
||||
_show(boxOffset.translate(-width, 0));
|
||||
}
|
||||
}
|
||||
1433
lib/components/toly_ui/popable/toly_pop_menu.dart
Normal file
1433
lib/components/toly_ui/popable/toly_pop_menu.dart
Normal file
File diff suppressed because it is too large
Load Diff
@@ -2,4 +2,6 @@
|
||||
export 'navigation/menu_meta.dart';
|
||||
export 'navigation/toly_breadcrumb.dart';
|
||||
export 'navigation/toly_navigation_rail.dart';
|
||||
export 'popable/drop_selectable_widget.dart';
|
||||
export 'popable/drop_selectable_widget.dart';
|
||||
export 'popable/popover.dart';
|
||||
export 'popable/pop_menu.dart';
|
||||
Reference in New Issue
Block a user