Fixed most crashes

This commit is contained in:
otdavies
2022-01-02 01:50:10 -08:00
parent 3a74f44d86
commit 763a1c5a5d
4 changed files with 43 additions and 14 deletions
+24 -7
View File
@@ -1,7 +1,6 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::collections::VecDeque; use std::collections::VecDeque;
use super::document_message_handler::CopyBufferEntry;
pub use super::layer_panel::*; pub use super::layer_panel::*;
use super::movement_handler::{MovementMessage, MovementMessageHandler}; use super::movement_handler::{MovementMessage, MovementMessageHandler};
use super::overlay_message_handler::OverlayMessageHandler; 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())) self.layer_data.iter().filter_map(|(path, data)| data.selected.then(|| path.as_slice()))
} }
pub fn selected_layers_without_children(&self) -> impl Iterator<Item = &[LayerId]> {
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<Item = &[LayerId]> { pub fn selected_visible_layers(&self) -> impl Iterator<Item = &[LayerId]> {
self.selected_layers().filter(|path| match self.graphene_document.layer(path) { self.selected_layers().filter(|path| match self.graphene_document.layer(path) {
Ok(layer) => layer.visible, Ok(layer) => layer.visible,
@@ -566,10 +580,14 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
} }
GroupSelectedLayers => { GroupSelectedLayers => {
let selected_layers = self.selected_layers(); let selected_layers = self.selected_layers();
// TODO simplify and protect unwrap
let mut new_folder_path: Vec<u64> = 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<u64> = self.graphene_document.common_path_prefix(selected_layers);
new_folder_path.push(generate_uuid()); 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(DocumentsMessage::Copy(Clipboard::System).into());
responses.push_back(DocumentMessage::DeleteSelectedLayers.into()); responses.push_back(DocumentMessage::DeleteSelectedLayers.into());
@@ -619,9 +637,11 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
} }
DeleteSelectedLayers => { DeleteSelectedLayers => {
self.backup(responses); 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(DocumentOperation::DeleteLayer { path }.into());
} }
responses.push_front(ToolMessage::DocumentIsDirty.into()); responses.push_front(ToolMessage::DocumentIsDirty.into());
} }
SetViewMode(mode) => { SetViewMode(mode) => {
@@ -652,7 +672,6 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
// Toggle selection when holding ctrl // Toggle selection when holding ctrl
let layer = self.layer_data_mut(&selected); let layer = self.layer_data_mut(&selected);
layer.selected = !layer.selected; layer.selected = !layer.selected;
log::debug!("Ctrl Selection: {:?}", selected);
responses.push_back(LayerChanged(selected.clone()).into()); responses.push_back(LayerChanged(selected.clone()).into());
responses.push_back(ToolMessage::DocumentIsDirty.into()); responses.push_back(ToolMessage::DocumentIsDirty.into());
} else { } else {
@@ -677,7 +696,6 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
self.layer_data.insert(path, layer_data_entry); self.layer_data.insert(path, layer_data_entry);
} }
SetSelectedLayers(paths) => { SetSelectedLayers(paths) => {
log::debug!("Set Selection: {:?}", paths);
self.layer_data.iter_mut().filter(|(_, layer_data)| layer_data.selected).for_each(|(path, layer_data)| { self.layer_data.iter_mut().filter(|(_, layer_data)| layer_data.selected).for_each(|(path, layer_data)| {
layer_data.selected = false; layer_data.selected = false;
responses.push_back(LayerChanged(path.clone()).into()) responses.push_back(LayerChanged(path.clone()).into())
@@ -686,7 +704,6 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
responses.push_front(AddSelectedLayers(paths).into()); responses.push_front(AddSelectedLayers(paths).into());
} }
AddSelectedLayers(paths) => { AddSelectedLayers(paths) => {
log::debug!("Add Selection: {:?}", paths);
for path in paths { for path in paths {
responses.extend(self.select_layer(&path)); responses.extend(self.select_layer(&path));
} }
@@ -352,15 +352,18 @@ impl MessageHandler<DocumentsMessage, &InputPreprocessor> for DocumentsMessageHa
responses.push_back(DocumentsMessage::SelectDocument(prev_id).into()); responses.push_back(DocumentsMessage::SelectDocument(prev_id).into());
} }
Copy(clipboard) => { Copy(clipboard) => {
let paths = self.active_document().selected_layers_sorted(); // We can't use `self.active_document()` because it counts as an immutable borrow of the entirety of `self`
self.copy_buffer[clipboard as usize].clear(); let active_document = self.documents.get(&self.active_document_id).unwrap();
for path in paths {
let document = self.active_document(); let copy_buffer = &mut self.copy_buffer;
match (document.graphene_document.layer(&path).map(|t| t.clone()), document.layer_data(&path).clone()) { 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) => { (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),
} }
} }
} }
+4
View File
@@ -140,6 +140,10 @@ impl Document {
path 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 // 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? // 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 { pub fn layer_closer_to_root(&self, path_a: &[u64], path_b: &[u64]) -> bool {
+5
View File
@@ -101,6 +101,11 @@ impl Folder {
Some(&mut self.layers[pos]) 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<usize, DocumentError> { pub fn position_of_layer(&self, layer_id: LayerId) -> Result<usize, DocumentError> {
self.layer_ids.iter().position(|x| *x == layer_id).ok_or_else(|| DocumentError::LayerNotFound([layer_id].into())) self.layer_ids.iter().position(|x| *x == layer_id).ok_or_else(|| DocumentError::LayerNotFound([layer_id].into()))
} }