Skip to content

Commit 399111d

Browse files
KeavonTrueDoctor
andauthored
Add a selected_layers() function and refactor code to use it (#314)
* Add a selected_layers() function * Refactor AlignSelectedLayers Co-authored-by: Dennis Kobert <[email protected]>
1 parent d3958f8 commit 399111d

File tree

1 file changed

+31
-47
lines changed

1 file changed

+31
-47
lines changed

core/editor/src/document/document_message_handler.rs

Lines changed: 31 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)