@@ -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