This commit is contained in:
mr
2025-06-13 13:33:24 +02:00
parent c4ea1541c4
commit ab593a45b9
26 changed files with 219 additions and 221 deletions

View File

@@ -371,7 +371,7 @@ class Dashboard extends ChangeNotifier {
bool noHistory = false;
void addToHistory() {
if (noHistory) {
Future.delayed(Duration(seconds: 2), () {
Future.delayed(const Duration(seconds: 2), () {
noHistory = false;
});
return;
@@ -379,7 +379,7 @@ class Dashboard extends ChangeNotifier {
if (tempHistory.length >= 50) { tempHistory.removeAt(0); }
tempHistory.add(toMap());
history = tempHistory.map((e) => e).toList();
Future.delayed(Duration(seconds: 1), () {
Future.delayed(const Duration(seconds: 1), () {
chartMenuKey.currentState?.setState(() { });
});
}

View File

@@ -26,6 +26,7 @@ abstract class FlowData {
FlowData deserialize(Map<String, dynamic> data);
}
// ignore: must_be_immutable
class FlowChart<T extends FlowData> extends StatefulWidget {
FlowChart({
required this.dashboard,
@@ -60,7 +61,7 @@ class FlowChart<T extends FlowData> extends StatefulWidget {
this.menuExtension,
this.itemLeftBottomBadges,
this.itemrightTopBadges,
}) {}
});
final String? current;
final List<String> categories;
final double width;
@@ -170,7 +171,7 @@ class FlowChart<T extends FlowData> extends StatefulWidget {
/// Trigger for the scale change
final void Function(double scale)? onScaleUpdate;
bool dashboardSelected = true;
@override
State<FlowChart> createState() => FlowChartState<T>();
}
@@ -182,6 +183,7 @@ class HoverMenuController {
currentState?.hideSubMenu();
}
}
// ignore: must_be_immutable
class HoverMenu extends StatefulWidget {
final Widget title;
final double? width;
@@ -191,12 +193,12 @@ class HoverMenu extends StatefulWidget {
HoverMenu({
Key? key,
super.key,
required this.title,
this.items = const [],
this.width,
this.controller,
}) : super(key: key);
});
@override
HoverMenuState createState() => HoverMenuState();
@@ -324,6 +326,7 @@ class FlowChartState<T extends FlowData> extends State<FlowChart> {
widget.dashboard.inDialog = true;
showDialog(
barrierDismissible: false,
// ignore: use_build_context_synchronously
context: context, builder: (context) {
return AlertDialog(
titlePadding: EdgeInsets.zero,
@@ -364,63 +367,63 @@ class FlowChartState<T extends FlowData> extends State<FlowChart> {
autofocus: true,
onKeyEvent: (event) {
bool change = false;
if (event.logicalKey == LogicalKeyboardKey.controlLeft && event is KeyDownEvent) {
print("CTRL true");
isCtrl = true;
}
if (event.logicalKey == LogicalKeyboardKey.controlLeft && event is KeyUpEvent) {
print("CTRL false");
isCtrl = false;
}
if ((event is KeyDownEvent || event.logicalKey == LogicalKeyboardKey.keyZ) && isCtrl) {
widget.dashboard.back();
}
if ((event is KeyDownEvent || event.logicalKey == LogicalKeyboardKey.keyY) && isCtrl) {
widget.dashboard.forward();
}
if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.add) {
change = true;
for (var el in widget.dashboard.elementSelected) {
widget.dashboard.addElement(FlowElement<T>(
element: el.element as T,
dashboard: widget.dashboard,
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,
), context);
}
}
if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.delete) {
change = true;
widget.dashboard.removeElements((element) {
if (element.isSelected) {
widget.dashboard.arrows.removeWhere( (e) => e.toID.contains(element.id) || e.fromID.contains(element.id));
}
return element.isSelected;
}, context);
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]));
if (widget.dashboardSelected) {
if (event.logicalKey == LogicalKeyboardKey.controlLeft && event is KeyDownEvent) {
isCtrl = true;
}
if (event.logicalKey == LogicalKeyboardKey.controlLeft && event is KeyUpEvent) {
isCtrl = false;
}
if ((event is KeyDownEvent || event.logicalKey == LogicalKeyboardKey.keyZ) && isCtrl) {
widget.dashboard.back();
}
if ((event is KeyDownEvent || event.logicalKey == LogicalKeyboardKey.keyY) && isCtrl) {
widget.dashboard.forward();
}
if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.add) {
change = true;
for (var el in widget.dashboard.elementSelected) {
widget.dashboard.addElement(FlowElement<T>(
element: el.element as T,
dashboard: widget.dashboard,
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,
), context);
}
}
widget.dashboard.removeArrows( (el) => el.isSelected, context );
}
if (change) {
DrawingArrow.instance.notifyListeners();
widget.dashboard.chartKey.currentState?.setState(() { });
node.requestFocus();
if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.delete) {
change = true;
widget.dashboard.removeElements((element) {
if (element.isSelected) {
widget.dashboard.arrows.removeWhere( (e) => e.toID.contains(element.id) || e.fromID.contains(element.id));
}
return element.isSelected;
}, context);
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.removeArrows( (el) => el.isSelected, context );
}
if (change) {
DrawingArrow.instance.notifyListeners();
widget.dashboard.chartKey.currentState?.setState(() { });
node.requestFocus();
}
}
},
child: ClipRect(
child: Stack(
clipBehavior: Clip.none,
children: [
Stack(children: [
Stack(children: [
// Draw the grid
DragTarget<T>(
builder: (
@@ -428,7 +431,15 @@ class FlowChartState<T extends FlowData> extends State<FlowChart> {
List<dynamic> accepted,
List<dynamic> rejected,
) {
return SizedBox(
return MouseRegion(
onEnter: (ev) {
print("sqfdsfd");
widget.dashboardSelected = true;
},
onExit: (ev) {
widget.dashboardSelected = false;
},
child: SizedBox(
width: widget.width,
height: widget.height,
child: ChartWidget<T>(
@@ -449,7 +460,7 @@ class FlowChartState<T extends FlowData> extends State<FlowChart> {
onHandlerPressed: widget.onHandlerLongPressed,
onHandlerLongPressed: widget.onHandlerLongPressed,
onPivotSecondaryPressed: widget.onPivotSecondaryPressed,
));
)));
},
onAcceptWithDetails: (DragTargetDetails<T> details) {
var e = details.data;
@@ -479,24 +490,24 @@ class FlowChartState<T extends FlowData> extends State<FlowChart> {
);
widget.dashboard.addElement(el, context);
},
)]
)]
),
widget.dashboard.isMenu ? Positioned(top: 50, child: FlowChartSelectedMenu(
key: widget.dashboard.selectedMenuKey,
dashboard: widget.dashboard,
height: widget.height - 50) ) : Container(),
height: widget.height - 50)) : Container(),
widget.dashboard.isInfo ? Positioned(top: 50, right: 0, child:
FlowChartLeftMenu<T>(
key: widget.dashboard.selectedLeftMenuKey,
dashboard: widget.dashboard,
menuExtension: widget.menuExtension,
categories: widget.categories,
height: widget.height,
innerMenuWidth: widget.innerMenuWidth,
itemWidth: widget.itemWidth,
draggableItemBuilder: widget.draggableItemBuilder as List<T> Function(String cat),
getDraggable: getDraggable,
)) : Container()
key: widget.dashboard.selectedLeftMenuKey,
dashboard: widget.dashboard,
menuExtension: widget.menuExtension,
categories: widget.categories,
height: widget.height,
innerMenuWidth: widget.innerMenuWidth,
itemWidth: widget.itemWidth,
draggableItemBuilder: widget.draggableItemBuilder as List<T> Function(String cat),
getDraggable: getDraggable,
)) : Container()
])
));
}
@@ -576,8 +587,9 @@ class _DrawingArrowWidgetState extends State<DrawingArrowWidget> {
}
}
// ignore: must_be_immutable
class ChartWidget<T extends FlowData> extends StatefulWidget {
ChartWidget ({ Key? key,
ChartWidget ({ super.key,
required this.flowChart,
this.onElementPressed,
this.onElementSecondaryTapped,
@@ -597,7 +609,7 @@ class ChartWidget<T extends FlowData> extends StatefulWidget {
required this.dashboard,
this.onNewConnection,
this.menuWidget,
}) : super(key: key);
});
FlowChartState flowChart;
@@ -764,7 +776,7 @@ class ChartWidgetState<T extends FlowData> extends State<ChartWidget> {
if (!hoverImportant) {
for (var sel in widget.dashboard.elements) { sel.isSelected = false; }
for (var sel in widget.dashboard.arrows) { sel.isSelected = false; }
Future.delayed(Duration(milliseconds: 100), () {
Future.delayed(const Duration(milliseconds: 100), () {
widget.dashboard.selectedMenuKey.currentState?.setState(() {});
DrawingArrow.instance.notifyListeners();
});

View File

@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_flow_chart/flutter_flow_chart.dart';
// ignore: must_be_immutable
class FlowChartLeftMenu<T extends FlowData> extends StatefulWidget {
Dashboard dashboard;
List<String> categories;
@@ -39,10 +40,10 @@ class FlowChartLeftMenuState<T extends FlowData> extends State<FlowChartLeftMenu
: Theme(
data: Theme.of(context).copyWith(dividerColor: widget.dashboard.midDashColor),
child: ExpansionTile(
collapsedShape: RoundedRectangleBorder(
collapsedShape: const RoundedRectangleBorder(
side: BorderSide.none,
),
shape: RoundedRectangleBorder(
shape: const RoundedRectangleBorder(
side: BorderSide.none,
),
initiallyExpanded: true,
@@ -70,16 +71,16 @@ class FlowChartLeftMenuState<T extends FlowData> extends State<FlowChartLeftMenu
);
}
return Container(
height: widget.height,
color: widget.dashboard.midDashColor,
child: Stack( children: [
Container(
height: widget.height,
color: widget.dashboard.midDashColor,
child: Stack( children: [
Container(
width: widget.innerMenuWidth,
height: 50,
decoration: BoxDecoration(border: Border(
bottom: BorderSide(color: Colors.grey.shade400),
right: BorderSide(color: widget.dashboard.midDashColor),
left: BorderSide(color: Colors.white))),
left: const BorderSide(color: Colors.white))),
child: TextFormField(
style: const TextStyle(color: Colors.black, fontSize: 15),
cursorColor: widget.dashboard.dashColor,
@@ -91,7 +92,7 @@ class FlowChartLeftMenuState<T extends FlowData> extends State<FlowChartLeftMenu
fillColor: widget.dashboard.midDashColor,
filled: true,
contentPadding: const EdgeInsets.only(left: 50, right: 50, top: 15, bottom: 15),
hintStyle: TextStyle(
hintStyle: const TextStyle(
color: Colors.grey,
fontSize: 15,
fontWeight: FontWeight.w400
@@ -101,7 +102,7 @@ class FlowChartLeftMenuState<T extends FlowData> extends State<FlowChartLeftMenu
)
),
Container(
margin: EdgeInsets.only(top: 50),
margin: const EdgeInsets.only(top: 50),
height: widget.height - 100,
constraints: BoxConstraints(minWidth: widget.itemWidth),
width: widget.dashboard.isMenu ? widget.innerMenuWidth : 0,

View File

@@ -6,6 +6,7 @@ import 'package:flutter_colorpicker/flutter_colorpicker.dart';
import 'package:number_text_input_formatter/number_text_input_formatter.dart';
import 'package:uuid/uuid.dart';
// ignore: must_be_immutable
class FlowChartSelectedMenu extends StatefulWidget {
Dashboard dashboard;
double height = 100;
@@ -21,12 +22,13 @@ class FlowChartSelectedMenuState extends State<FlowChartSelectedMenu> {
width: 200,
height: widget.height,
color: widget.dashboard.midDashColor,
child: SingleChildScrollView( child: Column( children: [ ...widget.dashboard.infoItemWidget != null ?
child: SingleChildScrollView( child: Column( children: [
...widget.dashboard.infoItemWidget != null ?
widget.dashboard.infoItemWidget!(widget.dashboard.elementSelected.first.element, widget.dashboard.elementSelected.first.id) : [],
widget.dashboard.arrowsSelected.isNotEmpty || widget.dashboard.elementSelected.isNotEmpty ? Container(
width: 200,
margin: EdgeInsets.only(top: 15),
decoration: BoxDecoration(border: Border(
margin: const EdgeInsets.only(top: 15),
decoration: const BoxDecoration(border: Border(
top: BorderSide(color: Colors.grey, width: 1))),
child: Column(crossAxisAlignment: CrossAxisAlignment.center, children: [
Tooltip( message: "remove",
@@ -38,13 +40,13 @@ class FlowChartSelectedMenuState extends State<FlowChartSelectedMenu> {
}
return element.isSelected;
}, context);
Future.delayed(Duration(milliseconds: 100), () {
Future.delayed( const Duration(milliseconds: 100), () {
widget.dashboard.flutterChartKey.currentState?.setState(() { });
});
}, child: Container( margin: EdgeInsets.all(10),
}, child: Container( margin: const EdgeInsets.all(10),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: Colors.black, width: 1)),
width: 200, height: 30,
child: Icon(Icons.delete_outline, color: Colors.black),
child: const Icon(Icons.delete_outline, color: Colors.black),
))
),
Tooltip( message: "copy",
@@ -52,17 +54,17 @@ class FlowChartSelectedMenuState extends State<FlowChartSelectedMenu> {
onTap: () {
for (var sel in widget.dashboard.elementSelected) {
var el =FlowElement.fromMap(widget.dashboard, sel.toMap());
el.id = Uuid().v8();
el.id = const Uuid().v8();
widget.dashboard.addElement(FlowElement.fromMap(widget.dashboard, sel.toMap()), context);
widget.dashboard.elements.last.position += Offset(50, 50);
widget.dashboard.elements.last.position += const Offset(50, 50);
}
Future.delayed(Duration(milliseconds: 100), () {
Future.delayed( const Duration(milliseconds: 100), () {
widget.dashboard.chartKey.currentState?.setState(() { });
});
}, child: Container( margin: EdgeInsets.only(left: 10, right: 10, bottom: 10),
}, child: Container( margin: const EdgeInsets.only(left: 10, right: 10, bottom: 10),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), border: Border.all(color: Colors.black, width: 1)),
width: 200, height: 30,
child: Icon(Icons.copy, color: Colors.black),
child: const Icon(Icons.copy, color: Colors.black),
))
),
])
@@ -120,11 +122,14 @@ class FlowChartSelectedMenuState extends State<FlowChartSelectedMenu> {
Container( padding: const EdgeInsets.all(10), width: 200, height: 60,
decoration: const BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey, width: 1))),
child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [
Text("STYLE ${widget.dashboard.elementSelected.isNotEmpty ? "ELEMENT" : "ARROW"}", style: TextStyle(fontSize: 15, fontWeight: FontWeight.bold), textAlign: TextAlign.center),
Text("<${widget.dashboard.arrowsSelected.isEmpty && widget.dashboard.elementSelected.isEmpty ? "general" : "selected"}>", style: TextStyle(fontSize: 12), textAlign: TextAlign.center),
Text("STYLE ${widget.dashboard.elementSelected.isNotEmpty ? "ELEMENT" : "ARROW"}",
style: const TextStyle(fontSize: 15, fontWeight: FontWeight.bold), textAlign: TextAlign.center),
Text("<${widget.dashboard.arrowsSelected.isEmpty && widget.dashboard.elementSelected.isEmpty ? "general" : "selected"}>",
style: const TextStyle(fontSize: 12), textAlign: TextAlign.center),
])),
SizedBox( width: 200, height: widget.height - 60, child: SingleChildScrollView( child: Column( children: [
widget.dashboard.elementSelected.isNotEmpty ? Container() : Container( padding: EdgeInsets.symmetric(horizontal: 10, vertical: 20),
widget.dashboard.elementSelected.isNotEmpty ? Container() : Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 20),
decoration: const BoxDecoration(border: Border(bottom: BorderSide(color: Colors.grey, width: 1))),
child: Column( children: [
Row( children: [
@@ -617,7 +622,9 @@ class FlowChartSelectedMenuState extends State<FlowChartSelectedMenu> {
]
)
),
widget.dashboard.error != null ? Container( width: 200, color: Colors.red, padding: EdgeInsets.all(10),
widget.dashboard.error != null ? Container( width: 200,
color: Colors.red,
padding: const EdgeInsets.all(10),
child: Center( child: Text(widget.dashboard.error!,
style: const TextStyle(color: Colors.white, fontSize: 15), textAlign: TextAlign.center))) : Container(),
w

View File

@@ -177,7 +177,7 @@ class ElementWidgetState<T extends FlowData> extends State<ElementWidget> {
childWhenDragging: const SizedBox.shrink(),
feedback: Material(
color: Colors.transparent,
child: Padding( padding: EdgeInsets.all(6),
child: Padding( padding: const EdgeInsets.all(6),
child: Container(
decoration: BoxDecoration(border: Border.all( color: Colors.red, width: 2)),
width: widget.element.size.width - 12,
@@ -262,7 +262,7 @@ class ElementWidgetState<T extends FlowData> extends State<ElementWidget> {
children: (!widget.isHovered ? [] : [
IconButton(tooltip: "remove element", onPressed: () {
widget.dashboard.removeElement(widget.element, context);
}, icon: Icon(Icons.delete_outline)),
}, icon: const Icon(Icons.delete_outline)),
IconButton(tooltip: "copy element", onPressed: () {
FlowElement<T> newElement = FlowElement<T>(
element: widget.element.element as T?,
@@ -273,7 +273,7 @@ class ElementWidgetState<T extends FlowData> extends State<ElementWidget> {
widget: widget.element.widget,
);
widget.dashboard.addElement(newElement, context);
}, icon: Icon(Icons.copy, size: 20)),
}, icon: const Icon(Icons.copy, size: 20)),
]))
),
])

View File

@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
/// The arrow tip.
// ignore: must_be_immutable
class HandlerWidget extends StatelessWidget {
///
HandlerWidget({

View File

@@ -4,6 +4,7 @@ import 'package:flutter_flow_chart/src/ui/element_widget.dart';
import 'package:flutter_flow_chart/src/ui/handler_widget.dart';
/// The widget to press and drag to resize the element
// ignore: must_be_immutable
class ResizeWidget extends StatefulWidget {
Widget? bottomLeftBadge;
Widget? bottomRightBadge;
@@ -23,7 +24,7 @@ class ResizeWidget extends StatefulWidget {
super.key,
});
Color handlerColor = Color.fromRGBO(38, 166, 154, 1);
Color handlerColor = const Color.fromRGBO(38, 166, 154, 1);
final ElementWidgetState comp;
///
final Dashboard dashboard;