Skip to content

Commit aa97700

Browse files
TrueDoctorotdavies
authored andcommitted
Tidy up path handling in document_file (#464)
* Tidy up path handling in document_file + Improve #455 * Cargo Clippy lints * Rename to_vec to map_to_vec Co-authored-by: Oliver Davies <[email protected]>
1 parent 8b3edb0 commit aa97700

File tree

6 files changed

+38
-63
lines changed

6 files changed

+38
-63
lines changed

editor/src/communication/dispatcher.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -339,10 +339,19 @@ mod test {
339339
init_logger();
340340
let mut editor = create_editor_with_three_layers();
341341

342-
let sorted_layers = editor.dispatcher.documents_message_handler.active_document().all_layers_sorted();
342+
fn map_to_vec<'a>(paths: Vec<&'a [LayerId]>) -> Vec<Vec<LayerId>> {
343+
paths.iter().map(|layer| layer.to_vec()).collect::<Vec<_>>()
344+
}
345+
let sorted_layers = map_to_vec(editor.dispatcher.documents_message_handler.active_document().all_layers_sorted());
343346
println!("Sorted layers: {:?}", sorted_layers);
344347

345-
let verify_order = |handler: &mut DocumentMessageHandler| (handler.all_layers_sorted(), handler.non_selected_layers_sorted(), handler.selected_layers_sorted());
348+
let verify_order = |handler: &mut DocumentMessageHandler| {
349+
(
350+
map_to_vec(handler.all_layers_sorted()),
351+
map_to_vec(handler.non_selected_layers_sorted()),
352+
map_to_vec(handler.selected_layers_sorted()),
353+
)
354+
};
346355

347356
editor.handle_message(DocumentMessage::SetSelectedLayers(sorted_layers[..2].to_vec()));
348357

editor/src/document/document_file.rs

Lines changed: 22 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -273,31 +273,14 @@ impl DocumentMessageHandler {
273273
self.layer_metadata.iter().filter_map(|(path, data)| data.selected.then(|| path.as_slice()))
274274
}
275275

276-
pub fn selected_layers_without_children(&self) -> Vec<Vec<LayerId>> {
277-
// TODO optimize this after MVP. Look at commit 1aaf5c0d7dbe67cd9f4ba8b536a4771a2cef6439, optimization was started
278-
// Traversing the layer tree recursively was chosen for readability, but should be replaced with an optimized approach later
279-
fn recurse_layer_tree(ctx: &DocumentMessageHandler, mut path: Vec<u64>, without_children: &mut Vec<Vec<LayerId>>, selected: bool) {
280-
if let Ok(folder) = ctx.graphene_document.folder(&path) {
281-
for child in folder.list_layers() {
282-
path.push(*child);
283-
let selected_or_parent_selected = selected || ctx.selected_layers_contains(&path);
284-
let selected_without_any_parent_selected = !selected && ctx.selected_layers_contains(&path);
285-
if ctx.graphene_document.is_folder(&path) {
286-
if selected_without_any_parent_selected {
287-
without_children.push(path.clone());
288-
}
289-
recurse_layer_tree(ctx, path.clone(), without_children, selected_or_parent_selected);
290-
} else if selected_without_any_parent_selected {
291-
without_children.push(path.clone());
292-
}
293-
path.pop();
294-
}
295-
}
296-
}
276+
pub fn selected_layers_without_children(&self) -> Vec<&[LayerId]> {
277+
let mut sorted_layers = self.selected_layers().collect::<Vec<_>>();
278+
// Sorting here creates groups of similar UUID paths
279+
sorted_layers.sort();
280+
sorted_layers.dedup_by(|a, b| a.starts_with(b));
297281

298-
let mut without_children: Vec<Vec<LayerId>> = vec![];
299-
recurse_layer_tree(self, vec![], &mut without_children, false);
300-
without_children
282+
// We need to maintain layer ordering
283+
self.sort_layers(sorted_layers.iter().copied())
301284
}
302285

303286
pub fn selected_layers_contains(&self, path: &[LayerId]) -> bool {
@@ -365,23 +348,19 @@ impl DocumentMessageHandler {
365348
}
366349

367350
/// Returns an unsorted list of all layer paths including folders at all levels, except the document's top-level root folder itself
368-
pub fn all_layers(&self) -> Vec<Vec<LayerId>> {
369-
self.layer_metadata.keys().filter(|path| !path.is_empty()).cloned().collect()
351+
pub fn all_layers(&self) -> impl Iterator<Item = &[LayerId]> {
352+
self.layer_metadata.keys().filter_map(|path| (!path.is_empty()).then(|| path.as_slice()))
370353
}
371354

372355
/// Returns the paths to all layers in order, optionally including only selected or non-selected layers.
373-
fn layers_sorted(&self, selected: Option<bool>) -> Vec<Vec<LayerId>> {
356+
fn sort_layers<'a>(&self, paths: impl Iterator<Item = &'a [LayerId]>) -> Vec<&'a [LayerId]> {
374357
// Compute the indices for each layer to be able to sort them
375-
let mut layers_with_indices: Vec<(Vec<LayerId>, Vec<usize>)> = self
376-
377-
.layer_metadata
378-
.iter()
358+
let mut layers_with_indices: Vec<(&[LayerId], Vec<usize>)> = paths
379359
// 'path.len() > 0' filters out root layer since it has no indices
380-
.filter_map(|(path, data)| (!path.is_empty() && (data.selected == selected.unwrap_or(data.selected))).then(|| path.clone()))
360+
.filter_map(|path| (!path.is_empty()).then(|| path))
381361
.filter_map(|path| {
382-
// TODO: Currently it is possible that `layer_metadata` contains layers that are don't actually exist (has been partially fixed in #281) and thus
383362
// TODO: `indices_for_path` can return an error. We currently skip these layers and log a warning. Once this problem is solved this code can be simplified.
384-
match self.graphene_document.indices_for_path(&path) {
363+
match self.graphene_document.indices_for_path(path) {
385364
Err(err) => {
386365
warn!("layers_sorted: Could not get indices for the layer {:?}: {:?}", path, err);
387366
None
@@ -396,19 +375,19 @@ impl DocumentMessageHandler {
396375
}
397376

398377
/// Returns the paths to all layers in order
399-
pub fn all_layers_sorted(&self) -> Vec<Vec<LayerId>> {
400-
self.layers_sorted(None)
378+
pub fn all_layers_sorted(&self) -> Vec<&[LayerId]> {
379+
self.sort_layers(self.all_layers())
401380
}
402381

403382
/// Returns the paths to all selected layers in order
404-
pub fn selected_layers_sorted(&self) -> Vec<Vec<LayerId>> {
405-
self.layers_sorted(Some(true))
383+
pub fn selected_layers_sorted(&self) -> Vec<&[LayerId]> {
384+
self.sort_layers(self.selected_layers())
406385
}
407386

408387
/// Returns the paths to all non_selected layers in order
409388
#[allow(dead_code)] // used for test cases
410-
pub fn non_selected_layers_sorted(&self) -> Vec<Vec<LayerId>> {
411-
self.layers_sorted(Some(false))
389+
pub fn non_selected_layers_sorted(&self) -> Vec<&[LayerId]> {
390+
self.sort_layers(self.all_layers().filter(|layer| !self.selected_layers().any(|path| &path == layer)))
412391
}
413392

414393
pub fn layer_metadata(&self, path: &[LayerId]) -> &LayerMetadata {
@@ -652,7 +631,7 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
652631
self.backup(responses);
653632

654633
for path in self.selected_layers_without_children() {
655-
responses.push_front(DocumentOperation::DeleteLayer { path }.into());
634+
responses.push_front(DocumentOperation::DeleteLayer { path: path.to_vec() }.into());
656635
}
657636

658637
responses.push_front(ToolMessage::DocumentIsDirty.into());
@@ -664,7 +643,7 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
664643
DuplicateSelectedLayers => {
665644
self.backup(responses);
666645
for path in self.selected_layers_sorted() {
667-
responses.push_back(DocumentOperation::DuplicateLayer { path }.into());
646+
responses.push_back(DocumentOperation::DuplicateLayer { path: path.to_vec() }.into());
668647
}
669648
}
670649
SelectLayer(selected, ctrl, shift) => {
@@ -730,7 +709,7 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
730709
}
731710
SelectAllLayers => {
732711
let all_layer_paths = self.all_layers();
733-
responses.push_front(SetSelectedLayers(all_layer_paths).into());
712+
responses.push_front(SetSelectedLayers(all_layer_paths.map(|path| path.to_vec()).collect()).into());
734713
}
735714
DeselectAllLayers => {
736715
responses.push_front(SetSelectedLayers(vec![]).into());

editor/src/document/document_message_handler.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ impl MessageHandler<DocumentsMessage, &InputPreprocessor> for DocumentsMessageHa
359359
copy_buffer[clipboard as usize].clear();
360360

361361
for layer_path in active_document.selected_layers_without_children() {
362-
match (active_document.graphene_document.layer(&layer_path).map(|t| t.clone()), *active_document.layer_metadata(&layer_path)) {
362+
match (active_document.graphene_document.layer(layer_path).map(|t| t.clone()), *active_document.layer_metadata(layer_path)) {
363363
(Ok(layer), layer_metadata) => {
364364
copy_buffer[clipboard as usize].push(CopyBufferEntry { layer, layer_metadata });
365365
}

editor/src/document/overlay_message_handler.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use graphene::Operation as DocumentOperation;
88
use graphene::document::Document as GrapheneDocument;
99
use graphene::layers::style::ViewMode;
1010
use serde::{Deserialize, Serialize};
11-
use std::collections::{HashMap, VecDeque};
1211

1312
#[impl_message(Message, DocumentMessage, Overlay)]
1413
#[derive(PartialEq, Clone, Debug, Serialize, Deserialize)]
@@ -26,7 +25,6 @@ impl From<DocumentOperation> for OverlayMessage {
2625
#[derive(Debug, Clone, Default)]
2726
pub struct OverlayMessageHandler {
2827
pub overlays_graphene_document: GrapheneDocument,
29-
overlay_path_mapping: HashMap<Vec<LayerId>, Vec<LayerId>>,
3028
}
3129

3230
impl MessageHandler<OverlayMessage, (&mut LayerMetadata, &Document, &InputPreprocessor)> for OverlayMessageHandler {

editor/src/tool/snapping.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,21 @@ use crate::consts::SNAP_TOLERANCE;
55

66
use super::DocumentMessageHandler;
77

8-
#[derive(Debug, Clone)]
8+
#[derive(Debug, Clone, Default)]
99
pub struct SnapHandler {
1010
snap_targets: Option<(Vec<f64>, Vec<f64>)>,
1111
}
12-
impl Default for SnapHandler {
13-
fn default() -> Self {
14-
Self { snap_targets: None }
15-
}
16-
}
1712

1813
impl SnapHandler {
1914
/// Gets a list of snap targets for the X and Y axes in Viewport coords for the target layers (usually all layers or all non-selected layers.)
2015
/// This should be called at the start of a drag.
21-
pub fn start_snap(&mut self, document_message_handler: &DocumentMessageHandler, target_layers: Vec<Vec<LayerId>>, ignore_layers: &[Vec<LayerId>]) {
16+
pub fn start_snap(&mut self, document_message_handler: &DocumentMessageHandler, target_layers: Vec<&[LayerId]>, ignore_layers: &[Vec<LayerId>]) {
2217
if document_message_handler.snapping_enabled {
2318
// Could be made into sorted Vec or a HashSet for more performant lookups.
2419
self.snap_targets = Some(
2520
target_layers
2621
.iter()
27-
.filter(|path| !ignore_layers.contains(path))
22+
.filter(|path| !ignore_layers.iter().any(|layer| layer.as_slice() == **path))
2823
.filter_map(|path| document_message_handler.graphene_document.viewport_bounding_box(path).ok()?)
2924
.flat_map(|[bound1, bound2]| [bound1, bound2, ((bound1 + bound2) / 2.)])
3025
.map(|vec| vec.into())

graphene/src/layers/mod.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -189,17 +189,11 @@ impl<'a> IntoIterator for &'a Layer {
189189
}
190190
}
191191

192-
#[derive(Debug)]
192+
#[derive(Debug, Default)]
193193
pub struct LayerIter<'a> {
194194
pub stack: Vec<&'a Layer>,
195195
}
196196

197-
impl Default for LayerIter<'_> {
198-
fn default() -> Self {
199-
Self { stack: vec![] }
200-
}
201-
}
202-
203197
impl<'a> Iterator for LayerIter<'a> {
204198
type Item = &'a Layer;
205199

0 commit comments

Comments
 (0)