@@ -65,19 +65,79 @@ impl Folder {
6565 Ok ( ( ) )
6666 }
6767
68- pub fn reorder_layer ( & mut self , source_id : LayerId , target_id : LayerId ) -> Result < ( ) , DocumentError > {
69- let source_pos = self . layer_ids . iter ( ) . position ( |x| * x == source_id) . ok_or ( DocumentError :: LayerNotFound ) ?;
68+ pub fn reorder_layers ( & mut self , source_ids : Vec < LayerId > , target_id : LayerId ) -> Result < ( ) , DocumentError > {
69+ let source_pos = self . layer_ids . iter ( ) . position ( |x| * x == source_ids[ 0 ] ) . ok_or ( DocumentError :: LayerNotFound ) ?;
70+ let source_pos_end = source_pos + source_ids. len ( ) - 1 ;
7071 let target_pos = self . layer_ids . iter ( ) . position ( |x| * x == target_id) . ok_or ( DocumentError :: LayerNotFound ) ?;
7172
72- let layer_to_move = self . layers . remove ( source_pos) ;
73- self . layers . insert ( target_pos, layer_to_move) ;
74- let layer_id_to_move = self . layer_ids . remove ( source_pos) ;
75- self . layer_ids . insert ( target_pos, layer_id_to_move) ;
73+ let mut last_pos = source_pos;
74+ for layer_id in & source_ids[ 1 ..source_ids. len ( ) ] {
75+ let layer_pos = self . layer_ids . iter ( ) . position ( |x| * x == * layer_id) . ok_or ( DocumentError :: LayerNotFound ) ?;
76+ if ( layer_pos as i32 - last_pos as i32 ) . abs ( ) > 1 {
77+ // Selection is not contiguous
78+ return Err ( DocumentError :: InvalidPath ) ;
79+ }
80+ last_pos = layer_pos;
81+ }
82+
83+ if source_pos < target_pos {
84+ // Dragging up
85+
86+ // Prevent shifting past end
87+ if source_pos_end + 1 >= self . layers . len ( ) {
88+ return Err ( DocumentError :: InvalidPath ) ;
89+ }
7690
77- let min_index = source_pos. min ( target_pos) ;
78- let max_index = source_pos. max ( target_pos) ;
79- for layer_index in min_index..max_index {
80- self . layers [ layer_index] . cache_dirty = true ;
91+ fn rearrange < T > ( arr : & mut Vec < T > , source_pos : usize , source_pos_end : usize , target_pos : usize )
92+ where
93+ T : Clone ,
94+ {
95+ * arr = [
96+ & arr[ 0 ..source_pos] , // Elements before selection
97+ & arr[ source_pos_end + 1 ..=target_pos] , // Elements between selection end and target
98+ & arr[ source_pos..=source_pos_end] , // Selection itself
99+ & arr[ target_pos + 1 ..] , // Elements before target
100+ ]
101+ . concat ( ) ;
102+ }
103+
104+ rearrange ( & mut self . layers , source_pos, source_pos_end, target_pos) ;
105+ rearrange ( & mut self . layer_ids , source_pos, source_pos_end, target_pos) ;
106+
107+ let min_index = source_pos_end. min ( target_pos) ;
108+ let max_index = source_pos_end. max ( target_pos) ;
109+ for layer_index in min_index..max_index {
110+ self . layers [ layer_index] . cache_dirty = true ;
111+ }
112+ } else {
113+ // Dragging down
114+
115+ // Prevent shifting past end
116+ if source_pos == 0 {
117+ return Err ( DocumentError :: InvalidPath ) ;
118+ }
119+
120+ fn rearrange < T > ( arr : & mut Vec < T > , source_pos : usize , source_pos_end : usize , target_pos : usize )
121+ where
122+ T : Clone ,
123+ {
124+ * arr = [
125+ & arr[ 0 ..target_pos] , // Elements before target
126+ & arr[ source_pos..=source_pos_end] , // Selection itself
127+ & arr[ target_pos..source_pos] , // Elements between selection and target
128+ & arr[ source_pos_end + 1 ..] , // Elements before selection
129+ ]
130+ . concat ( ) ;
131+ }
132+
133+ rearrange ( & mut self . layers , source_pos, source_pos_end, target_pos) ;
134+ rearrange ( & mut self . layer_ids , source_pos, source_pos_end, target_pos) ;
135+
136+ let min_index = source_pos. min ( target_pos) ;
137+ let max_index = source_pos. max ( target_pos) ;
138+ for layer_index in min_index..max_index {
139+ self . layers [ layer_index] . cache_dirty = true ;
140+ }
81141 }
82142
83143 Ok ( ( ) )
0 commit comments