@@ -539,6 +539,7 @@ mod test_gradient {
539
539
pub use crate :: test_utils:: test_prelude:: * ;
540
540
use glam:: DAffine2 ;
541
541
use graphene_core:: vector:: fill;
542
+ use graphene_core:: vector:: style:: Gradient ;
542
543
use graphene_std:: vector:: style:: Fill ;
543
544
544
545
use super :: gradient_space_transform;
@@ -557,6 +558,30 @@ mod test_gradient {
557
558
. collect ( )
558
559
}
559
560
561
+ async fn get_gradient ( editor : & mut EditorTestUtils ) -> ( Gradient , DAffine2 ) {
562
+ let fills = get_fills ( editor) . await ;
563
+ assert_eq ! ( fills. len( ) , 1 , "Expected 1 gradient fill, found {}" , fills. len( ) ) ;
564
+
565
+ let ( fill, transform) = fills. first ( ) . unwrap ( ) ;
566
+ let gradient = fill. as_gradient ( ) . expect ( "Expected gradient fill type" ) ;
567
+
568
+ ( gradient. clone ( ) , transform. clone ( ) )
569
+ }
570
+
571
+ fn assert_stops_at_positions ( actual_positions : & [ f64 ] , expected_positions : & [ f64 ] , tolerance : f64 ) {
572
+ assert_eq ! (
573
+ actual_positions. len( ) ,
574
+ expected_positions. len( ) ,
575
+ "Expected {} stops, found {}" ,
576
+ expected_positions. len( ) ,
577
+ actual_positions. len( )
578
+ ) ;
579
+
580
+ for ( i, ( actual, expected) ) in actual_positions. iter ( ) . zip ( expected_positions. iter ( ) ) . enumerate ( ) {
581
+ assert ! ( ( actual - expected) . abs( ) < tolerance, "Stop {}: Expected position near {}, got {}" , i, expected, actual) ;
582
+ }
583
+ }
584
+
560
585
#[ tokio:: test]
561
586
async fn ignore_artboard ( ) {
562
587
let mut editor = EditorTestUtils :: create ( ) ;
@@ -583,10 +608,9 @@ mod test_gradient {
583
608
editor. select_primary_color ( Color :: GREEN ) . await ;
584
609
editor. select_secondary_color ( Color :: BLUE ) . await ;
585
610
editor. drag_tool ( ToolType :: Gradient , 2. , 3. , 24. , 4. , ModifierKeys :: empty ( ) ) . await ;
586
- let fills = get_fills ( & mut editor) . await ;
587
- assert_eq ! ( fills. len( ) , 1 ) ;
588
- let ( fill, transform) = fills. first ( ) . unwrap ( ) ;
589
- let gradient = fill. as_gradient ( ) . unwrap ( ) ;
611
+
612
+ let ( gradient, transform) = get_gradient ( & mut editor) . await ;
613
+
590
614
// Gradient goes from secondary colour to primary colour
591
615
let stops = gradient. stops . iter ( ) . map ( |stop| ( stop. 0 , stop. 1 . to_rgba8_srgb ( ) ) ) . collect :: < Vec < _ > > ( ) ;
592
616
assert_eq ! ( stops, vec![ ( 0. , Color :: BLUE . to_rgba8_srgb( ) ) , ( 1. , Color :: GREEN . to_rgba8_srgb( ) ) ] ) ;
@@ -607,9 +631,9 @@ mod test_gradient {
607
631
let end = DVec2 :: new ( 24. , 4. ) ;
608
632
editor. drag_tool ( ToolType :: Rectangle , -5. , -3. , 100. , 100. , ModifierKeys :: empty ( ) ) . await ;
609
633
editor. drag_tool ( ToolType :: Gradient , start. x , start. y , end. x , end. y , ModifierKeys :: SHIFT ) . await ;
610
- let fills = get_fills ( & mut editor ) . await ;
611
- let ( fill , transform) = fills . first ( ) . unwrap ( ) ;
612
- let gradient = fill . as_gradient ( ) . unwrap ( ) ;
634
+
635
+ let ( gradient , transform) = get_gradient ( & mut editor ) . await ;
636
+
613
637
assert ! ( transform. transform_point2( gradient. start) . abs_diff_eq( start, 1e-10 ) ) ;
614
638
615
639
// 15 degrees from horizontal
@@ -649,10 +673,9 @@ mod test_gradient {
649
673
. await ;
650
674
651
675
editor. drag_tool ( ToolType :: Gradient , 2. , 3. , 24. , 4. , ModifierKeys :: empty ( ) ) . await ;
652
- let fills = get_fills ( & mut editor) . await ;
653
- assert_eq ! ( fills. len( ) , 1 ) ;
654
- let ( fill, transform) = fills. first ( ) . unwrap ( ) ;
655
- let gradient = fill. as_gradient ( ) . unwrap ( ) ;
676
+
677
+ let ( gradient, transform) = get_gradient ( & mut editor) . await ;
678
+
656
679
assert ! ( transform. transform_point2( gradient. start) . abs_diff_eq( DVec2 :: new( 2. , 3. ) , 1e-10 ) ) ;
657
680
assert ! ( transform. transform_point2( gradient. end) . abs_diff_eq( DVec2 :: new( 24. , 4. ) , 1e-10 ) ) ;
658
681
}
@@ -663,44 +686,20 @@ mod test_gradient {
663
686
editor. new_document ( ) . await ;
664
687
665
688
editor. drag_tool ( ToolType :: Rectangle , -5. , -3. , 100. , 100. , ModifierKeys :: empty ( ) ) . await ;
666
-
667
689
editor. select_primary_color ( Color :: GREEN ) . await ;
668
690
editor. select_secondary_color ( Color :: BLUE ) . await ;
669
-
670
691
editor. drag_tool ( ToolType :: Gradient , 0. , 0. , 100. , 0. , ModifierKeys :: empty ( ) ) . await ;
671
692
672
693
// Get initial gradient state (should have 2 stops)
673
- let initial_fills = get_fills ( & mut editor) . await ;
674
- assert_eq ! ( initial_fills. len( ) , 1 ) ;
675
- let ( initial_fill, _) = initial_fills. first ( ) . unwrap ( ) ;
676
- let initial_gradient = initial_fill. as_gradient ( ) . unwrap ( ) ;
677
- assert_eq ! ( initial_gradient. stops. len( ) , 2 ) ;
694
+ let ( initial_gradient, _) = get_gradient ( & mut editor) . await ;
695
+ assert_eq ! ( initial_gradient. stops. len( ) , 2 , "Expected 2 stops, found {}" , initial_gradient. stops. len( ) ) ;
678
696
679
697
editor. select_tool ( ToolType :: Gradient ) . await ;
680
-
681
- // Simulate a double click
682
- let click_position = DVec2 :: new ( 50. , 0. ) ;
683
- let modifier_keys = ModifierKeys :: empty ( ) ;
684
-
685
- // Send the DoubleClick event
686
- editor
687
- . handle_message ( InputPreprocessorMessage :: DoubleClick {
688
- editor_mouse_state : EditorMouseState {
689
- editor_position : click_position,
690
- mouse_keys : MouseKeys :: LEFT ,
691
- scroll_delta : ScrollDelta :: default ( ) ,
692
- } ,
693
- modifier_keys,
694
- } )
695
- . await ;
698
+ editor. double_click ( DVec2 :: new ( 50. , 0. ) ) . await ;
696
699
697
700
// Check that a new stop has been added
698
- let updated_fills = get_fills ( & mut editor) . await ;
699
- assert_eq ! ( updated_fills. len( ) , 1 ) ;
700
- let ( updated_fill, _) = updated_fills. first ( ) . unwrap ( ) ;
701
- let updated_gradient = updated_fill. as_gradient ( ) . unwrap ( ) ;
702
-
703
- assert_eq ! ( updated_gradient. stops. len( ) , 3 ) ;
701
+ let ( updated_gradient, _) = get_gradient ( & mut editor) . await ;
702
+ assert_eq ! ( updated_gradient. stops. len( ) , 3 , "Expected 3 stops, found {}" , updated_gradient. stops. len( ) ) ;
704
703
705
704
let positions: Vec < f64 > = updated_gradient. stops . iter ( ) . map ( |( pos, _) | * pos) . collect ( ) ;
706
705
assert ! (
@@ -735,11 +734,9 @@ mod test_gradient {
735
734
736
735
editor. drag_tool ( ToolType :: Gradient , 0. , 0. , 100. , 0. , ModifierKeys :: empty ( ) ) . await ;
737
736
738
- // Get the initial gradient state (should have 2 stops)
739
- let initial_fills = get_fills ( & mut editor) . await ;
740
- assert_eq ! ( initial_fills. len( ) , 1 ) ;
741
- let ( initial_fill, transform) = initial_fills. first ( ) . unwrap ( ) ;
742
- let initial_gradient = initial_fill. as_gradient ( ) . unwrap ( ) ;
737
+ // Get the initial gradient state
738
+ let ( initial_gradient, transform) = get_gradient ( & mut editor) . await ;
739
+ assert_eq ! ( initial_gradient. stops. len( ) , 2 , "Expected 2 stops, found {}" , initial_gradient. stops. len( ) ) ;
743
740
744
741
// Verify initial gradient endpoints in viewport space
745
742
let initial_start = transform. transform_point2 ( initial_gradient. start ) ;
@@ -755,9 +752,7 @@ mod test_gradient {
755
752
756
753
editor. move_mouse ( start_pos. x , start_pos. y , ModifierKeys :: empty ( ) , MouseKeys :: empty ( ) ) . await ;
757
754
editor. left_mousedown ( start_pos. x , start_pos. y , ModifierKeys :: empty ( ) ) . await ;
758
-
759
755
editor. move_mouse ( end_pos. x , end_pos. y , ModifierKeys :: empty ( ) , MouseKeys :: LEFT ) . await ;
760
-
761
756
editor
762
757
. mouseup (
763
758
EditorMouseState {
@@ -770,10 +765,7 @@ mod test_gradient {
770
765
. await ;
771
766
772
767
// Check the updated gradient
773
- let updated_fills = get_fills ( & mut editor) . await ;
774
- assert_eq ! ( updated_fills. len( ) , 1 ) ;
775
- let ( updated_fill, transform) = updated_fills. first ( ) . unwrap ( ) ;
776
- let updated_gradient = updated_fill. as_gradient ( ) . unwrap ( ) ;
768
+ let ( updated_gradient, transform) = get_gradient ( & mut editor) . await ;
777
769
778
770
// Verify the start point hasn't changed
779
771
let updated_start = transform. transform_point2 ( updated_gradient. start ) ;
@@ -790,46 +782,29 @@ mod test_gradient {
790
782
editor. new_document ( ) . await ;
791
783
792
784
editor. drag_tool ( ToolType :: Rectangle , -5. , -3. , 100. , 100. , ModifierKeys :: empty ( ) ) . await ;
793
-
794
785
editor. select_primary_color ( Color :: GREEN ) . await ;
795
786
editor. select_secondary_color ( Color :: BLUE ) . await ;
796
-
797
787
editor. drag_tool ( ToolType :: Gradient , 0. , 0. , 100. , 0. , ModifierKeys :: empty ( ) ) . await ;
798
788
799
789
editor. select_tool ( ToolType :: Gradient ) . await ;
800
- let click_position = DVec2 :: new ( 50. , 0. ) ;
801
- let modifier_keys = ModifierKeys :: empty ( ) ;
802
790
803
- editor
804
- . handle_message ( InputPreprocessorMessage :: DoubleClick {
805
- editor_mouse_state : EditorMouseState {
806
- editor_position : click_position,
807
- mouse_keys : MouseKeys :: LEFT ,
808
- scroll_delta : ScrollDelta :: default ( ) ,
809
- } ,
810
- modifier_keys,
811
- } )
812
- . await ;
791
+ // Add a middle stop at 50%
792
+ editor. double_click ( DVec2 :: new ( 50. , 0. ) ) . await ;
813
793
814
- let fills = get_fills ( & mut editor) . await ;
815
- assert_eq ! ( fills. len( ) , 1 ) ;
816
- let ( initial_fill, _) = fills. first ( ) . unwrap ( ) ;
817
- let initial_gradient = initial_fill. as_gradient ( ) . unwrap ( ) ;
818
- assert_eq ! ( initial_gradient. stops. len( ) , 3 ) ;
794
+ let ( initial_gradient, _) = get_gradient ( & mut editor) . await ;
795
+ assert_eq ! ( initial_gradient. stops. len( ) , 3 , "Expected 3 stops, found {}" , initial_gradient. stops. len( ) ) ;
819
796
820
797
// Verify initial stop positions and colors
821
798
let mut stops = initial_gradient. stops . clone ( ) ;
822
799
stops. sort_by ( |a, b| a. 0 . partial_cmp ( & b. 0 ) . unwrap ( ) ) ;
823
800
824
- assert ! ( ( stops[ 0 ] . 0 - 0.0 ) . abs( ) < 0.001 ) ;
825
- assert ! ( ( stops[ 1 ] . 0 - 0.5 ) . abs( ) < 0.1 ) ;
826
- assert ! ( ( stops[ 2 ] . 0 - 1.0 ) . abs( ) < 0.001 ) ;
801
+ let positions: Vec < f64 > = stops. iter ( ) . map ( |( pos, _) | * pos) . collect ( ) ;
802
+ assert_stops_at_positions ( & positions, & [ 0.0 , 0.5 , 1.0 ] , 0.1 ) ;
827
803
828
804
let middle_color = stops[ 1 ] . 1 . to_rgba8_srgb ( ) ;
829
805
830
806
// Simulate dragging the middle stop to position 0.8
831
- editor. select_tool ( ToolType :: Gradient ) . await ;
832
-
807
+ let click_position = DVec2 :: new ( 50. , 0. ) ;
833
808
editor
834
809
. mousedown (
835
810
EditorMouseState {
@@ -855,24 +830,78 @@ mod test_gradient {
855
830
)
856
831
. await ;
857
832
858
- let fills_after_drag = get_fills ( & mut editor) . await ;
859
- assert_eq ! ( fills_after_drag. len( ) , 1 ) ;
860
- let ( updated_fill, _) = fills_after_drag. first ( ) . unwrap ( ) ;
861
- let updated_gradient = updated_fill. as_gradient ( ) . unwrap ( ) ;
862
- assert_eq ! ( updated_gradient. stops. len( ) , 3 ) ;
833
+ let ( updated_gradient, _) = get_gradient ( & mut editor) . await ;
834
+ assert_eq ! ( updated_gradient. stops. len( ) , 3 , "Expected 3 stops after dragging, found {}" , updated_gradient. stops. len( ) ) ;
863
835
864
836
// Verify updated stop positions and colors
865
837
let mut updated_stops = updated_gradient. stops . clone ( ) ;
866
838
updated_stops. sort_by ( |a, b| a. 0 . partial_cmp ( & b. 0 ) . unwrap ( ) ) ;
867
839
868
840
// Check positions are now correctly ordered
869
- assert ! ( ( updated_stops[ 0 ] . 0 - 0.0 ) . abs( ) < 0.001 ) ;
870
- assert ! ( ( updated_stops[ 1 ] . 0 - 0.8 ) . abs( ) < 0.1 ) ;
871
- assert ! ( ( updated_stops[ 2 ] . 0 - 1.0 ) . abs( ) < 0.001 ) ;
841
+ let updated_positions: Vec < f64 > = updated_stops. iter ( ) . map ( |( pos, _) | * pos) . collect ( ) ;
842
+ assert_stops_at_positions ( & updated_positions, & [ 0.0 , 0.8 , 1.0 ] , 0.1 ) ;
872
843
873
844
// Colors should maintain their associations with the stop points
874
845
assert_eq ! ( updated_stops[ 0 ] . 1 . to_rgba8_srgb( ) , Color :: BLUE . to_rgba8_srgb( ) ) ;
875
846
assert_eq ! ( updated_stops[ 1 ] . 1 . to_rgba8_srgb( ) , middle_color) ;
876
847
assert_eq ! ( updated_stops[ 2 ] . 1 . to_rgba8_srgb( ) , Color :: GREEN . to_rgba8_srgb( ) ) ;
877
848
}
849
+
850
+ #[ tokio:: test]
851
+ async fn select_and_delete_removes_stop ( ) {
852
+ let mut editor = EditorTestUtils :: create ( ) ;
853
+ editor. new_document ( ) . await ;
854
+
855
+ editor. drag_tool ( ToolType :: Rectangle , -5. , -3. , 100. , 100. , ModifierKeys :: empty ( ) ) . await ;
856
+ editor. select_primary_color ( Color :: GREEN ) . await ;
857
+ editor. select_secondary_color ( Color :: BLUE ) . await ;
858
+ editor. drag_tool ( ToolType :: Gradient , 0. , 0. , 100. , 0. , ModifierKeys :: empty ( ) ) . await ;
859
+
860
+ // Get initial gradient state (should have 2 stops)
861
+ let ( initial_gradient, _) = get_gradient ( & mut editor) . await ;
862
+ assert_eq ! ( initial_gradient. stops. len( ) , 2 , "Expected 2 stops, found {}" , initial_gradient. stops. len( ) ) ;
863
+
864
+ editor. select_tool ( ToolType :: Gradient ) . await ;
865
+
866
+ // Add two middle stops
867
+ editor. double_click ( DVec2 :: new ( 25. , 0. ) ) . await ;
868
+ editor. double_click ( DVec2 :: new ( 75. , 0. ) ) . await ;
869
+
870
+ let ( updated_gradient, _) = get_gradient ( & mut editor) . await ;
871
+ assert_eq ! ( updated_gradient. stops. len( ) , 4 , "Expected 4 stops, found {}" , updated_gradient. stops. len( ) ) ;
872
+
873
+ let positions: Vec < f64 > = updated_gradient. stops . iter ( ) . map ( |( pos, _) | * pos) . collect ( ) ;
874
+
875
+ // Use helper function to verify positions
876
+ assert_stops_at_positions ( & positions, & [ 0.0 , 0.25 , 0.75 , 1.0 ] , 0.05 ) ;
877
+
878
+ // Select the stop at position 0.75 and delete it
879
+ let position2 = DVec2 :: new ( 75. , 0. ) ;
880
+ editor. move_mouse ( position2. x , position2. y , ModifierKeys :: empty ( ) , MouseKeys :: empty ( ) ) . await ;
881
+ editor. left_mousedown ( position2. x , position2. y , ModifierKeys :: empty ( ) ) . await ;
882
+ editor
883
+ . mouseup (
884
+ EditorMouseState {
885
+ editor_position : position2,
886
+ mouse_keys : MouseKeys :: empty ( ) ,
887
+ scroll_delta : ScrollDelta :: default ( ) ,
888
+ } ,
889
+ ModifierKeys :: empty ( ) ,
890
+ )
891
+ . await ;
892
+
893
+ editor. press ( Key :: Delete , ModifierKeys :: empty ( ) ) . await ;
894
+
895
+ // Verify we now have 3 stops
896
+ let ( final_gradient, _) = get_gradient ( & mut editor) . await ;
897
+ assert_eq ! ( final_gradient. stops. len( ) , 3 , "Expected 3 stops after deletion, found {}" , final_gradient. stops. len( ) ) ;
898
+
899
+ let final_positions: Vec < f64 > = final_gradient. stops . iter ( ) . map ( |( pos, _) | * pos) . collect ( ) ;
900
+
901
+ // Verify final positions with helper function
902
+ assert_stops_at_positions ( & final_positions, & [ 0.0 , 0.25 , 1.0 ] , 0.05 ) ;
903
+
904
+ // Additional verification that 0.75 stop is gone
905
+ assert ! ( !final_positions. iter( ) . any( |pos| ( pos - 0.75 ) . abs( ) < 0.05 ) , "Stop at position 0.75 should have been deleted" ) ;
906
+ }
878
907
}
0 commit comments