Skip to content

Commit 0b388eb

Browse files
committed
feat: Add animation support for temporary connections and update connection rendering logic, Add configurable gaps, colors, and borders for connection endpoints
1 parent 645f1bf commit 0b388eb

14 files changed

+664
-247
lines changed

packages/demo/lib/examples/advanced/theming.dart

Lines changed: 148 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class _ThemingExampleState extends State<ThemingExample> {
1717
late NodeFlowTheme _theme;
1818
MarkerShape _selectedPortShape = MarkerShapes.capsuleHalf;
1919
bool _scrollToZoom = true;
20-
double _endpointSize = 5.0;
20+
Size _endpointSize = const Size.square(5.0);
2121
bool _useCustomPortBuilder = false;
2222
bool _useCustomLabelBuilder = false;
2323

@@ -377,8 +377,12 @@ class _ThemingExampleState extends State<ThemingExample> {
377377
const SizedBox(height: 24),
378378
_buildConnectionEffectSection(),
379379
const SizedBox(height: 24),
380+
_buildEndpointColorsSection(),
381+
const SizedBox(height: 24),
380382
_buildConnectionColorsSection(),
381383
const SizedBox(height: 24),
384+
_buildTemporaryConnectionSection(),
385+
const SizedBox(height: 24),
382386
_buildStrokeWidthSection(),
383387
const SizedBox(height: 24),
384388
_buildPortSizeSection(),
@@ -576,17 +580,22 @@ class _ThemingExampleState extends State<ThemingExample> {
576580
}).toList(),
577581
),
578582
const SizedBox(height: 12),
579-
_buildSlider('Endpoint Size', _endpointSize, 3.0, 15.0, (value) {
583+
_buildSlider('Endpoint Size', _endpointSize.shortestSide, 3.0, 15.0, (
584+
value,
585+
) {
586+
final newSize = Size.square(value);
580587
setState(() {
581-
_endpointSize = value;
588+
_endpointSize = newSize;
582589
});
583590
_updateTheme(
584591
_theme.copyWith(
585592
connectionTheme: _theme.connectionTheme.copyWith(
586593
startPoint: _theme.connectionTheme.startPoint.copyWith(
587-
size: value,
594+
size: newSize,
595+
),
596+
endPoint: _theme.connectionTheme.endPoint.copyWith(
597+
size: newSize,
588598
),
589-
endPoint: _theme.connectionTheme.endPoint.copyWith(size: value),
590599
),
591600
),
592601
);
@@ -635,6 +644,140 @@ class _ThemingExampleState extends State<ThemingExample> {
635644
);
636645
}
637646

647+
Widget _buildEndpointColorsSection() {
648+
return Column(
649+
crossAxisAlignment: CrossAxisAlignment.stretch,
650+
children: [
651+
const SectionTitle('Endpoint Styling'),
652+
const SizedBox(height: 12),
653+
_buildColorPicker('Fill Color', _theme.connectionTheme.endpointColor, (
654+
color,
655+
) {
656+
_updateTheme(
657+
_theme.copyWith(
658+
connectionTheme: _theme.connectionTheme.copyWith(
659+
endpointColor: color,
660+
),
661+
temporaryConnectionTheme: _theme.temporaryConnectionTheme
662+
.copyWith(endpointColor: color),
663+
),
664+
);
665+
}),
666+
const SizedBox(height: 8),
667+
_buildColorPicker(
668+
'Border Color',
669+
_theme.connectionTheme.endpointBorderColor,
670+
(color) {
671+
_updateTheme(
672+
_theme.copyWith(
673+
connectionTheme: _theme.connectionTheme.copyWith(
674+
endpointBorderColor: color,
675+
),
676+
temporaryConnectionTheme: _theme.temporaryConnectionTheme
677+
.copyWith(endpointBorderColor: color),
678+
),
679+
);
680+
},
681+
),
682+
const SizedBox(height: 8),
683+
_buildSlider(
684+
'Border Width',
685+
_theme.connectionTheme.endpointBorderWidth,
686+
0.0,
687+
3.0,
688+
(value) {
689+
_updateTheme(
690+
_theme.copyWith(
691+
connectionTheme: _theme.connectionTheme.copyWith(
692+
endpointBorderWidth: value,
693+
),
694+
temporaryConnectionTheme: _theme.temporaryConnectionTheme
695+
.copyWith(endpointBorderWidth: value),
696+
),
697+
);
698+
},
699+
),
700+
],
701+
);
702+
}
703+
704+
Widget _buildTemporaryConnectionSection() {
705+
final tempTheme = _theme.temporaryConnectionTheme;
706+
final hasDash = tempTheme.dashPattern != null;
707+
return Column(
708+
crossAxisAlignment: CrossAxisAlignment.stretch,
709+
children: [
710+
const SectionTitle('Temporary Connection'),
711+
const SizedBox(height: 12),
712+
Row(
713+
children: [
714+
const Text('Dashed Line', style: TextStyle(fontSize: 12)),
715+
const Spacer(),
716+
Switch(
717+
value: hasDash,
718+
onChanged: (value) {
719+
_updateTheme(
720+
_theme.copyWith(
721+
temporaryConnectionTheme: tempTheme.copyWith(
722+
dashPattern: value ? [6, 4] : null,
723+
),
724+
),
725+
);
726+
},
727+
),
728+
],
729+
),
730+
Text(
731+
'Show temporary connections as dashed lines',
732+
style: TextStyle(fontSize: 10, color: Colors.grey.shade600),
733+
),
734+
const SizedBox(height: 12),
735+
_buildSlider('Stroke Width', tempTheme.strokeWidth, 1.0, 5.0, (value) {
736+
_updateTheme(
737+
_theme.copyWith(
738+
temporaryConnectionTheme: tempTheme.copyWith(strokeWidth: value),
739+
),
740+
);
741+
}),
742+
const SizedBox(height: 12),
743+
const Text('End Point Shape', style: TextStyle(fontSize: 12)),
744+
const SizedBox(height: 8),
745+
Wrap(
746+
spacing: 8,
747+
runSpacing: 8,
748+
children:
749+
[
750+
('None', MarkerShapes.none),
751+
('Circle', MarkerShapes.circle),
752+
('Triangle', MarkerShapes.triangle),
753+
('Capsule', MarkerShapes.capsuleHalf),
754+
].map((entry) {
755+
final (name, shape) = entry;
756+
final isSelected = tempTheme.endPoint.shape == shape;
757+
return ChoiceChip(
758+
label: Text(name, style: const TextStyle(fontSize: 11)),
759+
selected: isSelected,
760+
onSelected: (selected) {
761+
if (selected) {
762+
_updateTheme(
763+
_theme.copyWith(
764+
temporaryConnectionTheme: tempTheme.copyWith(
765+
endPoint: ConnectionEndPoint(
766+
shape: shape,
767+
size: _endpointSize,
768+
),
769+
),
770+
),
771+
);
772+
}
773+
},
774+
);
775+
}).toList(),
776+
),
777+
],
778+
);
779+
}
780+
638781
Widget _buildColorPicker(
639782
String label,
640783
Color color,

0 commit comments

Comments
 (0)