From 763a1c5a5d43a379162823898ab622029c3ff4e6 Mon Sep 17 00:00:00 2001 From: otdavies Date: Sun, 2 Jan 2022 01:50:10 -0800 Subject: [PATCH] Fixed most crashes --- editor/src/document/document_file.rs | 31 ++++++++++++++----- .../src/document/document_message_handler.rs | 17 +++++----- graphene/src/document.rs | 4 +++ graphene/src/layers/folder.rs | 5 +++ 4 files changed, 43 insertions(+), 14 deletions(-) diff --git a/editor/src/document/document_file.rs b/editor/src/document/document_file.rs index a7f994bdca..049fe78655 100644 --- a/editor/src/document/document_file.rs +++ b/editor/src/document/document_file.rs @@ -1,7 +1,6 @@ use std::collections::HashMap; use std::collections::VecDeque; -use super::document_message_handler::CopyBufferEntry; pub use super::layer_panel::*; use super::movement_handler::{MovementMessage, MovementMessageHandler}; use super::overlay_message_handler::OverlayMessageHandler; @@ -278,6 +277,21 @@ impl DocumentMessageHandler { self.layer_data.iter().filter_map(|(path, data)| data.selected.then(|| path.as_slice())) } + pub fn selected_layers_without_children(&self) -> impl Iterator { + let selected_folders: Vec<&Folder> = self + .layer_data + .iter() + .filter_map(|(path, data)| (data.selected && self.graphene_document.is_folder(path)).then(|| self.graphene_document.folder(path).unwrap())) + .collect(); + + self.selected_layers() + .filter(move |path| selected_folders.is_empty() || !selected_folders.iter().any(|folder| (*folder).folder_contains(path[path.len() - 1]))) + } + + pub fn selected_layers_contains(&self, path: &[LayerId]) -> bool { + self.layer_data.get(path).map(|layer| layer.selected).unwrap_or(false) + } + pub fn selected_visible_layers(&self) -> impl Iterator { self.selected_layers().filter(|path| match self.graphene_document.layer(path) { Ok(layer) => layer.visible, @@ -566,10 +580,14 @@ impl MessageHandler for DocumentMessageHand } GroupSelectedLayers => { let selected_layers = self.selected_layers(); + // TODO simplify and protect unwrap + let mut new_folder_path: Vec = self.graphene_document.deepest_common_folder(selected_layers).unwrap().to_vec(); + + if !new_folder_path.is_empty() && self.selected_layers_contains(&new_folder_path) { + new_folder_path.remove(new_folder_path.len() - 1); + } - let mut new_folder_path: Vec = self.graphene_document.common_path_prefix(selected_layers); new_folder_path.push(generate_uuid()); - log::debug!("new_folder_path {:?}", new_folder_path); responses.push_back(DocumentsMessage::Copy(Clipboard::System).into()); responses.push_back(DocumentMessage::DeleteSelectedLayers.into()); @@ -619,9 +637,11 @@ impl MessageHandler for DocumentMessageHand } DeleteSelectedLayers => { self.backup(responses); - for path in self.selected_layers().map(|path| path.to_vec()) { + + for path in self.selected_layers_without_children().map(|path| path.to_vec()) { responses.push_front(DocumentOperation::DeleteLayer { path }.into()); } + responses.push_front(ToolMessage::DocumentIsDirty.into()); } SetViewMode(mode) => { @@ -652,7 +672,6 @@ impl MessageHandler for DocumentMessageHand // Toggle selection when holding ctrl let layer = self.layer_data_mut(&selected); layer.selected = !layer.selected; - log::debug!("Ctrl Selection: {:?}", selected); responses.push_back(LayerChanged(selected.clone()).into()); responses.push_back(ToolMessage::DocumentIsDirty.into()); } else { @@ -677,7 +696,6 @@ impl MessageHandler for DocumentMessageHand self.layer_data.insert(path, layer_data_entry); } SetSelectedLayers(paths) => { - log::debug!("Set Selection: {:?}", paths); self.layer_data.iter_mut().filter(|(_, layer_data)| layer_data.selected).for_each(|(path, layer_data)| { layer_data.selected = false; responses.push_back(LayerChanged(path.clone()).into()) @@ -686,7 +704,6 @@ impl MessageHandler for DocumentMessageHand responses.push_front(AddSelectedLayers(paths).into()); } AddSelectedLayers(paths) => { - log::debug!("Add Selection: {:?}", paths); for path in paths { responses.extend(self.select_layer(&path)); } diff --git a/editor/src/document/document_message_handler.rs b/editor/src/document/document_message_handler.rs index 159cb06df8..8e2a1be73c 100644 --- a/editor/src/document/document_message_handler.rs +++ b/editor/src/document/document_message_handler.rs @@ -352,15 +352,18 @@ impl MessageHandler for DocumentsMessageHa responses.push_back(DocumentsMessage::SelectDocument(prev_id).into()); } Copy(clipboard) => { - let paths = self.active_document().selected_layers_sorted(); - self.copy_buffer[clipboard as usize].clear(); - for path in paths { - let document = self.active_document(); - match (document.graphene_document.layer(&path).map(|t| t.clone()), document.layer_data(&path).clone()) { + // We can't use `self.active_document()` because it counts as an immutable borrow of the entirety of `self` + let active_document = self.documents.get(&self.active_document_id).unwrap(); + + let copy_buffer = &mut self.copy_buffer; + copy_buffer[clipboard as usize].clear(); + + for layer_path in active_document.selected_layers_without_children() { + match (active_document.graphene_document.layer(layer_path).map(|t| t.clone()), *active_document.layer_data(layer_path)) { (Ok(layer), layer_data) => { - self.copy_buffer[clipboard as usize].push(CopyBufferEntry { layer, layer_data }); + copy_buffer[clipboard as usize].push(CopyBufferEntry { layer, layer_data }); } - (Err(e), _) => warn!("Could not access selected layer {:?}: {:?}", path, e), + (Err(e), _) => warn!("Could not access selected layer {:?}: {:?}", layer_path, e), } } } diff --git a/graphene/src/document.rs b/graphene/src/document.rs index 0f01705013..40a3c44c28 100644 --- a/graphene/src/document.rs +++ b/graphene/src/document.rs @@ -140,6 +140,10 @@ impl Document { path } + pub fn is_folder(&self, path: &[LayerId]) -> bool { + return self.folder(path).is_ok(); + } + // Determines which layer is closer to the root, if path_a return true, if path_b return false // Answers the question: Is A closer to the root than B? pub fn layer_closer_to_root(&self, path_a: &[u64], path_b: &[u64]) -> bool { diff --git a/graphene/src/layers/folder.rs b/graphene/src/layers/folder.rs index e48cce5031..65de0ddf36 100644 --- a/graphene/src/layers/folder.rs +++ b/graphene/src/layers/folder.rs @@ -101,6 +101,11 @@ impl Folder { Some(&mut self.layers[pos]) } + pub fn folder_contains(&self, id: LayerId) -> bool { + log::debug!("For {:?} Folder does contain {:?}", id, self.layer_ids.contains(&id)); + self.layer_ids.contains(&id) + } + pub fn position_of_layer(&self, layer_id: LayerId) -> Result { self.layer_ids.iter().position(|x| *x == layer_id).ok_or_else(|| DocumentError::LayerNotFound([layer_id].into())) }