mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-17 23:38:06 +08:00
Fixed most crashes
This commit is contained in:
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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()))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user