@@ -136,6 +136,9 @@ impl DocumentMessageHandler {
136136 // TODO: Add deduplication
137137 ( !path. is_empty ( ) ) . then ( || self . handle_folder_changed ( path[ ..path. len ( ) - 1 ] . to_vec ( ) ) ) . flatten ( )
138138 }
139+ fn selected_layers ( & self ) -> impl Iterator < Item = & Vec < LayerId > > {
140+ self . active_document ( ) . layer_data . iter ( ) . filter_map ( |( path, data) | data. selected . then ( || path) )
141+ }
139142 fn layerdata ( & self , path : & [ LayerId ] ) -> & LayerData {
140143 self . active_document ( ) . layer_data . get ( path) . expect ( "Layerdata does not exist" )
141144 }
@@ -155,8 +158,7 @@ impl DocumentMessageHandler {
155158 ) ;
156159 }
157160
158- /// Returns the paths to all layers in order, optionally including only selected or non
159- /// selected layers.
161+ /// Returns the paths to all layers in order, optionally including only selected or non-selected layers.
160162 fn layers_sorted ( & self , selected : Option < bool > ) -> Vec < Vec < LayerId > > {
161163 // Compute the indices for each layer to be able to sort them
162164 let mut layers_with_indices: Vec < ( Vec < LayerId > , Vec < usize > ) > = self
@@ -366,17 +368,14 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
366368 . into ( ) ,
367369 ) ,
368370 SetBlendModeForSelectedLayers ( blend_mode) => {
369- let active_document = self . active_document ( ) ;
370-
371- for path in active_document. layer_data . iter ( ) . filter_map ( |( path, data) | data. selected . then ( || path. clone ( ) ) ) {
371+ for path in self . selected_layers ( ) . cloned ( ) {
372372 responses. push_back ( DocumentOperation :: SetLayerBlendMode { path, blend_mode } . into ( ) ) ;
373373 }
374374 }
375375 SetOpacityForSelectedLayers ( opacity) => {
376376 let opacity = opacity. clamp ( 0. , 1. ) ;
377- let active_document = self . active_document ( ) ;
378377
379- for path in active_document . layer_data . iter ( ) . filter_map ( | ( path , data ) | data . selected . then ( || path . clone ( ) ) ) {
378+ for path in self . selected_layers ( ) . cloned ( ) {
380379 responses. push_back ( DocumentOperation :: SetLayerOpacity { path, opacity } . into ( ) ) ;
381380 }
382381 }
@@ -388,8 +387,7 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
388387 responses. extend ( self . handle_folder_changed ( path) ) ;
389388 }
390389 DeleteSelectedLayers => {
391- let paths = self . selected_layers_sorted ( ) ;
392- for path in paths {
390+ for path in self . selected_layers ( ) . cloned ( ) {
393391 responses. push_back ( DocumentOperation :: DeleteLayer { path } . into ( ) )
394392 }
395393 }
@@ -608,14 +606,12 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
608606 responses. push_back ( FrontendMessage :: SetCanvasRotation { new_radians : new } . into ( ) ) ;
609607 }
610608 NudgeSelectedLayers ( x, y) => {
611- let paths = self . selected_layers_sorted ( ) ;
612-
613609 let delta = {
614610 let root_layer_rotation = self . layerdata_mut ( & [ ] ) . rotation ;
615611 let rotate_to_viewport_space = DAffine2 :: from_angle ( root_layer_rotation) . inverse ( ) ;
616612 rotate_to_viewport_space. transform_point2 ( ( x, y) . into ( ) )
617613 } ;
618- for path in paths {
614+ for path in self . selected_layers ( ) . cloned ( ) {
619615 let operation = DocumentOperation :: TransformLayer {
620616 path,
621617 transform : DAffine2 :: from_translation ( delta) . to_cols_array ( ) ,
@@ -711,13 +707,12 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
711707 }
712708 AlignSelectedLayers ( axis, aggregate) => {
713709 // TODO: Handle folder nested transforms with the transforms API
714- let selected_paths = self . selected_layers_sorted ( ) ;
715- if selected_paths. is_empty ( ) {
710+ if self . selected_layers ( ) . next ( ) . is_none ( ) {
716711 return ;
717712 }
718713
719- let selected_layers = selected_paths . iter ( ) . filter_map ( |path| {
720- let layer = self . active_document ( ) . document . layer ( path) . unwrap ( ) ;
714+ let selected_layers = self . selected_layers ( ) . cloned ( ) . filter_map ( |path| {
715+ let layer = self . active_document ( ) . document . layer ( & path) . ok ( ) ? ;
721716 let point = {
722717 let bounding_box = layer. bounding_box ( layer. transform , layer. style ) ?;
723718 match aggregate {
@@ -731,44 +726,33 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
731726 AlignAxis :: X => ( point. x , layer. transform . translation . x ) ,
732727 AlignAxis :: Y => ( point. y , layer. transform . translation . y ) ,
733728 } ;
734- Some ( ( path. clone ( ) , bounding_box_coord, translation_coord) )
729+ Some ( ( path, bounding_box_coord, translation_coord) )
735730 } ) ;
731+ let selected_layers: Vec < _ > = selected_layers. collect ( ) ;
736732
737- let bounding_box_coords = selected_layers. clone ( ) . map ( |( _, bounding_box_coord, _) | bounding_box_coord) ;
738- let aggregated_coord = match aggregate {
739- AlignAggregate :: Min => bounding_box_coords. reduce ( |a, b| a. min ( b) ) . unwrap ( ) ,
740- AlignAggregate :: Max => bounding_box_coords. reduce ( |a, b| a. max ( b) ) . unwrap ( ) ,
733+ let bounding_box_coords = selected_layers. iter ( ) . map ( |( _, bounding_box_coord, _) | bounding_box_coord) . cloned ( ) ;
734+ if let Some ( aggregated_coord) = match aggregate {
735+ AlignAggregate :: Min => bounding_box_coords. reduce ( |a, b| a. min ( b) ) ,
736+ AlignAggregate :: Max => bounding_box_coords. reduce ( |a, b| a. max ( b) ) ,
741737 AlignAggregate :: Center => {
742738 // TODO: Refactor with `reduce` and `merge_bounding_boxes` once the latter is added
743- let bounding_boxes = selected_paths. iter ( ) . filter_map ( |path| {
744- let layer = self . active_document ( ) . document . layer ( path) . unwrap ( ) ;
745- layer. bounding_box ( layer. transform , layer. style )
746- } ) ;
747- let min = bounding_boxes
748- . clone ( )
749- . map ( |bbox| match axis {
750- AlignAxis :: X => bbox[ 0 ] . x ,
751- AlignAxis :: Y => bbox[ 0 ] . y ,
752- } )
753- . reduce ( |a, b| a. min ( b) )
754- . unwrap ( ) ;
755- let max = bounding_boxes
756- . clone ( )
739+ self . selected_layers ( )
740+ . filter_map ( |path| self . active_document ( ) . document . layer ( path) . ok ( ) . map ( |layer| layer. bounding_box ( layer. transform , layer. style ) ) . flatten ( ) )
757741 . map ( |bbox| match axis {
758- AlignAxis :: X => bbox[ 1 ] . x ,
759- AlignAxis :: Y => bbox[ 1 ] . y ,
742+ AlignAxis :: X => ( bbox[ 0 ] . x , bbox [ 1 ] . x ) ,
743+ AlignAxis :: Y => ( bbox[ 0 ] . y , bbox [ 1 ] . y ) ,
760744 } )
761- . reduce ( |a, b| a. max ( b) )
762- . unwrap ( ) ;
763- ( min + max) / 2.
745+ . reduce ( |( a, b) , ( c, d) | ( a. min ( c) , b. max ( d) ) )
746+ . map ( |( min, max) | ( min + max) / 2. )
764747 }
765- AlignAggregate :: Average => bounding_box_coords. sum :: < f64 > ( ) / selected_paths. len ( ) as f64 ,
766- } ;
767- for ( path, bounding_box_coord, translation_coord) in selected_layers {
768- let new_coord = aggregated_coord - ( bounding_box_coord - translation_coord) ;
769- match axis {
770- AlignAxis :: X => responses. push_back ( DocumentMessage :: SetLayerTranslation ( path, Some ( new_coord) , None ) . into ( ) ) ,
771- AlignAxis :: Y => responses. push_back ( DocumentMessage :: SetLayerTranslation ( path, None , Some ( new_coord) ) . into ( ) ) ,
748+ AlignAggregate :: Average => Some ( bounding_box_coords. sum :: < f64 > ( ) / selected_layers. len ( ) as f64 ) ,
749+ } {
750+ for ( path, bounding_box_coord, translation_coord) in selected_layers {
751+ let new_coord = aggregated_coord - ( bounding_box_coord - translation_coord) ;
752+ match axis {
753+ AlignAxis :: X => responses. push_back ( DocumentMessage :: SetLayerTranslation ( path, Some ( new_coord) , None ) . into ( ) ) ,
754+ AlignAxis :: Y => responses. push_back ( DocumentMessage :: SetLayerTranslation ( path, None , Some ( new_coord) ) . into ( ) ) ,
755+ }
772756 }
773757 }
774758 }
0 commit comments