Splendid keyboard detector

This commit is contained in:
mr
2024-07-17 17:45:39 +02:00
parent dce96e338c
commit bef7f65363
14 changed files with 171 additions and 114 deletions

View File

@@ -2,6 +2,7 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_flow_chart/flutter_flow_chart.dart';
import 'package:flutter_flow_chart/src/dashboard.dart';
import 'package:flutter_flow_chart/src/elements/flow_element.dart';
import 'package:flutter_flow_chart/src/flow_chart_menu.dart';
@@ -160,7 +161,7 @@ class HoverMenuController {
currentState?.hideSubMenu();
}
}
bool isPopUp = false;
class HoverMenu extends StatefulWidget {
final Widget title;
final double? width;
@@ -275,6 +276,7 @@ class HoverMenuState extends State<HoverMenu> {
}
}
var node = FocusNode();
class FlowChartState<T extends Object> extends State<FlowChart> {
List<Draggable<T>> getDraggable(List<T> items) {
List<Draggable<T>> res = [];
@@ -285,6 +287,7 @@ class FlowChartState<T extends Object> extends State<FlowChart> {
// Data is the value this Draggable stores.
data: e,
onDragStarted: () => hoverKey.currentState?.hideSubMenu(),
onDragEnd: (d) => node.requestFocus(),
childWhenDragging: Opacity(opacity: .5,
child: Padding( padding: const EdgeInsets.all(10),
child: Container( height: realSize - 20, child: widget.itemWidget(e) ))),
@@ -300,7 +303,8 @@ class FlowChartState<T extends Object> extends State<FlowChart> {
)
) )));
}
if (!widget.dashboard.isOpened && widget.onDashboardAlertOpened != null) {
if (!widget.dashboard.isOpened && widget.onDashboardAlertOpened != null && isPopUp == false) {
isPopUp = true;
widget.dashboard.isOpened = true;
Future.delayed(Duration(milliseconds: 1), () => showDialog(
barrierDismissible: false,
@@ -317,6 +321,12 @@ class FlowChartState<T extends Object> extends State<FlowChart> {
return res;
}
@override
void initState() {
node.requestFocus();
super.initState();
}
@override
Widget build(BuildContext context) {
/// get dashboard position after first frame is drawn
@@ -370,7 +380,68 @@ class FlowChartState<T extends Object> extends State<FlowChart> {
))
);
}
return ClipRect(
return KeyboardListener(
focusNode: node,
onKeyEvent: (event) {
if ((event is KeyDownEvent || event is KeyRepeatEvent) && event.logicalKey == LogicalKeyboardKey.arrowUp) {
for (var el in widget.dashboard.elements) {
if (el.isSelected) {
el.position = Offset(el.position.dx, el.position.dy - 10);
}
}
}
if ((event is KeyDownEvent || event is KeyRepeatEvent) && event.logicalKey == LogicalKeyboardKey.arrowDown) {
for (var el in widget.dashboard.elements) {
if (el.isSelected) {
el.position = Offset(el.position.dx, el.position.dy + 10);
}
}
}
if ((event is KeyDownEvent || event is KeyRepeatEvent) && event.logicalKey == LogicalKeyboardKey.arrowLeft) {
for (var el in widget.dashboard.elements) {
if (el.isSelected) {
el.position = Offset(el.position.dx - 10, el.position.dy);
}
}
}
if ((event is KeyDownEvent || event is KeyRepeatEvent) && event.logicalKey == LogicalKeyboardKey.arrowRight) {
for (var el in widget.dashboard.elements) {
if (el.isSelected) {
el.position = Offset(el.position.dx + 10, el.position.dy);
}
}
}
if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.add) {
for (var el in widget.dashboard.elementSelected) {
widget.dashboard.elements.add(FlowElement(
id: const Uuid().v4(),
position: el.position + const Offset(100, 100),
size: el.size,
text: el.text,
widget: el.widget,
kind: el.kind,
handlers: el.handlers,
handlerSize: el.handlerSize,
));
}
}
if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.delete) {
widget.dashboard.elements.removeWhere( (el) => el.isSelected );
for (var arrow in widget.dashboard.arrowsSelected) {
for (var el in widget.dashboard.elements.where((element) => element.id == arrow.fromID.split("_")[0])) {
el.next.removeAt(int.parse(arrow.fromID.split("_")[1]));
}
}
widget.dashboard.arrows.removeWhere( (el) => el.isSelected );
}
DrawingArrow.instance.notifyListeners();
widget.dashboard.chartKey.currentState?.setState(() { });
Future.delayed(Duration(milliseconds: 10), () {
node.requestFocus();
});
},
child: ClipRect(
child: Stack(
clipBehavior: Clip.none,
children: [
@@ -434,7 +505,7 @@ class FlowChartState<T extends Object> extends State<FlowChart> {
child: SingleChildScrollView( child: Column( children: menuItems ) )
)) : Container(),
])
);
));
}
}
@@ -637,6 +708,10 @@ class ChartWidgetState extends State<ChartWidget> {
final gridKey = GlobalKey();
var tapDownPos = Offset.zero;
var secondaryTapDownPos = Offset.zero;
for (int i = 0; i < widget.dashboard.elements.length; i++)
widget.dashboard.elements[i].next.removeWhere((element) =>
widget.dashboard.findElementIndexById(element.destElementId) < 0
);
return Stack( children: [
Positioned.fill(
child: GestureDetector(
@@ -650,10 +725,11 @@ class ChartWidgetState extends State<ChartWidget> {
for (var sel in widget.dashboard.elements) {
sel.isSelected = false;
}
Future.delayed(Duration(seconds: 1), () {
Future.delayed(Duration(milliseconds: 100), () {
widget.dashboard.selectedMenuKey.currentState?.setState(() {});
DrawingArrow.instance.notifyListeners();
});
}
}
if (!hoverImportant) {
@@ -792,9 +868,11 @@ class ChartWidgetState extends State<ChartWidget> {
element,
),
),
// Draw arrows
// Draw arrows
for (int i = 0; i < widget.dashboard.elements.length; i++)
for (int n = 0; n < widget.dashboard.elements[i].next.length; n++)
for (int n = 0; n < widget.dashboard.elements[i].next.length; n++)
DrawArrow(
flow: this,
key: UniqueKey(),
@@ -831,6 +909,6 @@ class ChartWidgetState extends State<ChartWidget> {
dashboard: widget.dashboard, height: MediaQuery.of(context).size.height - 100)
) : Container()
],
);
);
}
}
}

View File

@@ -17,6 +17,7 @@ class FlowChartMenu extends StatefulWidget {
}
class FlowChartMenuState extends State<FlowChartMenu> {
@override Widget build(BuildContext context) {
bool isLow = MediaQuery.of(context).size.width < 600;
GlobalKey<FormFieldState> zoomKey = GlobalKey<FormFieldState>();
return Container( // SHORTCUT
width: widget.width,
@@ -33,6 +34,7 @@ class FlowChartMenuState extends State<FlowChartMenu> {
Padding( padding: EdgeInsets.only(right: 15),
child: InkWell( mouseCursor: SystemMouseCursors.click,
onTap: () {
widget.dashboard.defaultName = "graph_${DateTime.now().toString().replaceAll(" ", "_").substring(0, DateTime.now().toString().length - 7)}";
showDialog(
barrierDismissible: false,
context: context, builder: (context) {
@@ -189,7 +191,7 @@ class FlowChartMenuState extends State<FlowChartMenu> {
],
)
),)),
Container(
isLow ? Container() : Container(
decoration: BoxDecoration(
border: Border(right: BorderSide(color: Colors.white, width: 1))
),
@@ -232,9 +234,10 @@ class FlowChartMenuState extends State<FlowChartMenu> {
color: !widget.dashboard.canForward() ? Colors.grey.shade300 : Colors.white))),
])),
Padding( child: Text("file opened : ${widget.dashboard.name}", overflow: TextOverflow.ellipsis,
style: TextStyle(color: Colors.white, fontSize: 14), textAlign: TextAlign.center),
padding: EdgeInsets.symmetric(horizontal: 20)),
Expanded(
child: Padding( child: Text("file opened : ${widget.dashboard.name}", overflow: TextOverflow.ellipsis,
style: TextStyle(color: Colors.white, fontSize: 14), textAlign: TextAlign.start),
padding: EdgeInsets.symmetric(horizontal: 20))),
])),
])
);