Skip to content

Commit 3652143

Browse files
committed
feat: connector customizer
1 parent 8e9c74a commit 3652143

File tree

7 files changed

+340
-167
lines changed

7 files changed

+340
-167
lines changed

lib/core/utils/enums.dart

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ enum NodeType {
1818

1919
enum ConnectionPoint { up, down, left, right }
2020

21+
// NEW: Enum for connector line types
2122
enum ConnectionType { solid, dotted, dashed }
2223

2324
// Enum to define the different shapes
@@ -34,16 +35,16 @@ enum ShapeType {
3435

3536
enum DrawMode {
3637
pointer(iconData: Icons.pan_tool_alt),
37-
hand(iconData: PhosphorIconsRegular.hand), // NEW: Add hand tool for panning
38+
hand(iconData: PhosphorIconsRegular.hand),
3839
circle(iconData: Icons.circle_outlined),
3940
rectangle(iconData: Icons.rectangle_outlined),
4041
square(iconData: Icons.square_outlined),
4142
diamond(iconData: Icons.diamond_outlined),
4243
roundedSquare(iconData: Icons.rounded_corner),
43-
parallelogram(iconData: Icons.square_foot_outlined), // Placeholder
44-
cylinder(iconData: Icons.view_in_ar_outlined), // Placeholder
44+
parallelogram(iconData: Icons.square_foot_outlined),
45+
cylinder(iconData: Icons.view_in_ar_outlined),
4546
triangle(iconData: Icons.change_history),
46-
invertedTriangle(iconData: Icons.warning_amber_rounded), // Placeholder
47+
invertedTriangle(iconData: Icons.warning_amber_rounded),
4748
textBox(iconData: PhosphorIconsRegular.textT),
4849
stickyNote(iconData: PhosphorIconsRegular.notePencil);
4950

lib/features/models/canvas_models/canvas_object.dart

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ abstract class CanvasObject extends SyncedObject {
6262
return StickyNoteObject.fromJson(json);
6363
case TextBoxObject.type:
6464
return TextBoxObject.fromJson(json);
65-
// NEW: Add case for ConnectorObject
6665
case ConnectorObject.type:
6766
return ConnectorObject.fromJson(json);
6867
default:
@@ -79,7 +78,6 @@ abstract class CanvasObject extends SyncedObject {
7978
Offset newBottomRight,
8079
);
8180

82-
// NEW: Method to get connection point coordinates
8381
Offset getConnectionPoint(Alignment alignment) {
8482
final bounds = getBounds();
8583
if (alignment == Alignment.centerLeft) return bounds.centerLeft;

lib/features/models/canvas_models/canvas_painter.dart

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'dart:ui';
12
import 'dart:convert';
23
import 'dart:math';
34
import 'package:cookethflow/core/theme/colors.dart';
@@ -139,18 +140,49 @@ class CanvasPainter extends CustomPainter {
139140
if (source != null && target != null) {
140141
final startPoint = source.getConnectionPoint(connector.sourceAlignment);
141142
final endPoint = target.getConnectionPoint(connector.targetAlignment);
142-
final paint = Paint()
143-
..color = Colors.black87
144-
..strokeWidth = 2.0
143+
144+
final connectorPaint = Paint()
145+
..color = connector.color
146+
..strokeWidth = connector.thickness
145147
..style = PaintingStyle.stroke;
146148

147-
canvas.drawLine(startPoint, endPoint, paint);
148-
_drawArrowhead(canvas, startPoint, endPoint, paint);
149+
final path = Path()..moveTo(startPoint.dx, startPoint.dy)..lineTo(endPoint.dx, endPoint.dy);
150+
151+
switch (connector.connectionType) {
152+
case ConnectionType.solid:
153+
canvas.drawPath(path, connectorPaint);
154+
break;
155+
case ConnectionType.dotted:
156+
canvas.drawPath(
157+
dashPath(path, dashArray: CircularIntervalList<double>([1.0, 3.0])),
158+
connectorPaint,
159+
);
160+
break;
161+
case ConnectionType.dashed:
162+
canvas.drawPath(
163+
dashPath(path, dashArray: CircularIntervalList<double>([10.0, 5.0])),
164+
connectorPaint,
165+
);
166+
break;
167+
}
168+
169+
_drawArrowhead(canvas, startPoint, endPoint, connectorPaint);
149170

150171
final originPaint = Paint()
151-
..color = Colors.black87
172+
..color = connector.color
152173
..style = PaintingStyle.fill;
153174
canvas.drawCircle(startPoint, 4, originPaint);
175+
176+
if (currentlySelectedObjectId == connector.id) {
177+
final selectPaint = Paint()
178+
..color = Colors.blue
179+
..strokeWidth = 2.0
180+
..style = PaintingStyle.stroke;
181+
canvas.drawPath(
182+
dashPath(path, dashArray: CircularIntervalList<double>([5.0, 3.0])),
183+
selectPaint,
184+
);
185+
}
154186
}
155187
}
156188

@@ -339,7 +371,7 @@ class CanvasPainter extends CustomPainter {
339371
...lineSpans
340372
]),
341373
textDirection: TextDirection.ltr,
342-
textAlign: TextAlign.center, // Center-align text for all objects
374+
textAlign: TextAlign.center,
343375
);
344376
final availableWidth = rect.width - (2 * textPadding) - indent;
345377
if (availableWidth > 0) {
@@ -460,6 +492,13 @@ class CanvasPainter extends CustomPainter {
460492
if (newObj.getBounds() != oldObj.getBounds()) return true;
461493
if (newObj.textDelta != oldObj.textDelta) return true;
462494
if (newObj.runtimeType != oldObj.runtimeType) return true;
495+
if (newObj is ConnectorObject && oldObj is ConnectorObject) {
496+
if (newObj.color != oldObj.color ||
497+
newObj.thickness != oldObj.thickness ||
498+
newObj.connectionType != oldObj.connectionType) {
499+
return true;
500+
}
501+
}
463502
}
464503
return false;
465504
}

lib/features/models/canvas_models/objects/connector_object.dart

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'dart:ui';
2+
import 'package:cookethflow/core/utils/enums.dart';
23
import 'package:cookethflow/features/models/canvas_models/canvas_object.dart';
34
import 'package:flutter/material.dart';
45
import 'package:uuid/uuid.dart';
@@ -10,20 +11,26 @@ class ConnectorObject extends CanvasObject {
1011
final String targetId;
1112
final Alignment sourceAlignment;
1213
final Alignment targetAlignment;
14+
final double thickness;
15+
final ConnectionType connectionType;
1316

1417
ConnectorObject({
1518
required super.id,
19+
required super.color,
1620
required this.sourceId,
1721
required this.targetId,
1822
required this.sourceAlignment,
1923
required this.targetAlignment,
20-
}) : super(color: Colors.black87, textDelta: null); // Connectors have a fixed color and no text
24+
this.thickness = 2.0,
25+
this.connectionType = ConnectionType.solid,
26+
}) : super(textDelta: null);
2127

2228
@override
2329
Map<String, dynamic> toJson() {
2430
return {
2531
'object_type': type,
2632
'id': id,
33+
'color': color.value.toRadixString(16),
2734
'source_id': sourceId,
2835
'target_id': targetId,
2936
'source_alignment': {
@@ -34,12 +41,15 @@ class ConnectorObject extends CanvasObject {
3441
'x': targetAlignment.x,
3542
'y': targetAlignment.y
3643
},
44+
'thickness': thickness,
45+
'connection_type': connectionType.name,
3746
};
3847
}
3948

4049
factory ConnectorObject.fromJson(Map<String, dynamic> json) {
4150
return ConnectorObject(
4251
id: json['id'],
52+
color: Color(int.parse(json['color'] as String, radix: 16)),
4353
sourceId: json['source_id'],
4454
targetId: json['target_id'],
4555
sourceAlignment: Alignment(
@@ -50,6 +60,11 @@ class ConnectorObject extends CanvasObject {
5060
json['target_alignment']['x'],
5161
json['target_alignment']['y'],
5262
),
63+
thickness: json['thickness'] as double? ?? 2.0,
64+
connectionType: ConnectionType.values.firstWhere(
65+
(e) => e.name == json['connection_type'],
66+
orElse: () => ConnectionType.solid,
67+
),
5368
);
5469
}
5570

@@ -58,8 +73,10 @@ class ConnectorObject extends CanvasObject {
5873
required String targetId,
5974
required Alignment sourceAlignment,
6075
required Alignment targetAlignment,
76+
Color color = Colors.black87,
77+
double thickness = 2.0,
78+
ConnectionType connectionType = ConnectionType.solid,
6179
}) {
62-
// A connector cannot connect to its own points.
6380
if (sourceId == targetId) {
6481
throw StateError('A connector cannot connect to itself.');
6582
}
@@ -70,10 +87,12 @@ class ConnectorObject extends CanvasObject {
7087
targetId: targetId,
7188
sourceAlignment: sourceAlignment,
7289
targetAlignment: targetAlignment,
90+
color: color,
91+
thickness: thickness,
92+
connectionType: connectionType,
7393
);
7494
}
7595

76-
// Connectors don't have a direct copyWith like shapes, as they are defined by their connections.
7796
@override
7897
ConnectorObject copyWith({
7998
String? textDelta,
@@ -82,34 +101,35 @@ class ConnectorObject extends CanvasObject {
82101
String? targetId,
83102
Alignment? sourceAlignment,
84103
Alignment? targetAlignment,
104+
double? thickness,
105+
ConnectionType? connectionType,
85106
}) {
86107
return ConnectorObject(
87108
id: id,
109+
color: color ?? this.color,
88110
sourceId: sourceId ?? this.sourceId,
89111
targetId: targetId ?? this.targetId,
90112
sourceAlignment: sourceAlignment ?? this.sourceAlignment,
91113
targetAlignment: targetAlignment ?? this.targetAlignment,
114+
thickness: thickness ?? this.thickness,
115+
connectionType: connectionType ?? this.connectionType,
92116
);
93117
}
94118

95-
// A connector's bounds are the line between its two points. For hit detection, this is handled differently.
96119
@override
97120
Rect getBounds() => Rect.zero;
98121

99-
// Connectors are not moved directly; they follow their connected objects.
100122
@override
101123
ConnectorObject move(Offset delta) => this;
102124

103-
// Connectors cannot be resized.
104125
@override
105126
ConnectorObject resize(Offset newTopLeft, Offset newBottomRight) => this;
106127

107-
// Hit detection for a line is more complex than for a rect.
108128
@override
109129
bool intersectsWith(Offset point) {
110-
// This requires calculating the distance from the point to the line segment.
111-
// For simplicity, we'll skip complex hit detection for now.
112-
// Interactions will be primarily through connection points on shapes.
130+
// This method is for hit detection on the connector line itself.
131+
// It requires access to the source and target objects to get the start and end points.
132+
// This logic is best handled in the WorkspaceProvider's onPanDown, where all objects are available.
113133
return false;
114134
}
115-
}
135+
}

0 commit comments

Comments
 (0)