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

View File

@@ -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<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]> {
self.selected_layers().filter(|path| match self.graphene_document.layer(path) {
Ok(layer) => layer.visible,
@@ -566,10 +580,14 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
}
GroupSelectedLayers => {
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());
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<DocumentMessage, &InputPreprocessor> 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<DocumentMessage, &InputPreprocessor> 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<DocumentMessage, &InputPreprocessor> 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<DocumentMessage, &InputPreprocessor> 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));
}

View File

@@ -352,15 +352,18 @@ impl MessageHandler<DocumentsMessage, &InputPreprocessor> 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),
}
}
}

View File

@@ -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 {

View File

@@ -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<usize, DocumentError> {
self.layer_ids.iter().position(|x| *x == layer_id).ok_or_else(|| DocumentError::LayerNotFound([layer_id].into()))
}