WIP fix of folder crash / indent

This commit is contained in:
otdavies
2021-12-31 02:39:59 -08:00
parent 401bba878a
commit 3a74f44d86
4 changed files with 95 additions and 25 deletions

View File

@@ -567,11 +567,9 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
GroupSelectedLayers => {
let selected_layers = self.selected_layers();
let common_prefix = self.graphene_document.common_layer_path_prefix(selected_layers);
let (_id, common_prefix) = common_prefix.split_last().unwrap_or((&0, &[]));
let mut new_folder_path = common_prefix.to_vec();
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());
@@ -621,10 +619,10 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
}
DeleteSelectedLayers => {
self.backup(responses);
responses.push_front(ToolMessage::DocumentIsDirty.into());
for path in self.selected_layers().map(|path| path.to_vec()) {
responses.push_front(DocumentOperation::DeleteLayer { path }.into());
}
responses.push_front(ToolMessage::DocumentIsDirty.into());
}
SetViewMode(mode) => {
self.view_mode = mode;
@@ -645,7 +643,7 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
// Fill the selection range
self.layer_data
.iter()
.filter(|(target, _)| self.graphene_document.layer_is_between(&target, &selected, &self.layer_range_selection_reference))
.filter(|(target, _)| self.graphene_document.layer_is_between(target, &selected, &self.layer_range_selection_reference))
.for_each(|(layer_path, _)| {
paths.push(layer_path.clone());
});
@@ -654,7 +652,9 @@ 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 {
paths.push(selected.clone());
}
@@ -664,7 +664,7 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
}
// Don't create messages for empty operations
if paths.len() > 0 {
if !paths.is_empty() {
// Add or set our selected layers
if ctrl {
responses.push_front(AddSelectedLayers(paths).into());
@@ -677,6 +677,7 @@ 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())
@@ -685,6 +686,7 @@ 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

@@ -61,7 +61,7 @@ impl Document {
pub fn folder(&self, path: &[LayerId]) -> Result<&Folder, DocumentError> {
let mut root = &self.root;
for id in path {
root = root.as_folder()?.layer(*id).ok_or(DocumentError::LayerNotFound)?;
root = root.as_folder()?.layer(*id).ok_or_else(|| DocumentError::LayerNotFound(path.into()))?;
}
root.as_folder()
}
@@ -72,7 +72,7 @@ impl Document {
fn folder_mut(&mut self, path: &[LayerId]) -> Result<&mut Folder, DocumentError> {
let mut root = &mut self.root;
for id in path {
root = root.as_folder_mut()?.layer_mut(*id).ok_or(DocumentError::LayerNotFound)?;
root = root.as_folder_mut()?.layer_mut(*id).ok_or_else(|| DocumentError::LayerNotFound(path.into()))?;
}
root.as_folder_mut()
}
@@ -83,7 +83,7 @@ impl Document {
return Ok(&self.root);
}
let (path, id) = split_path(path)?;
self.folder(path)?.layer(id).ok_or(DocumentError::LayerNotFound)
self.folder(path)?.layer(id).ok_or_else(|| DocumentError::LayerNotFound(path.into()))
}
/// Returns a mutable reference to the layer or folder at the path.
@@ -92,7 +92,7 @@ impl Document {
return Ok(&mut self.root);
}
let (path, id) = split_path(path)?;
self.folder_mut(path)?.layer_mut(id).ok_or(DocumentError::LayerNotFound)
self.folder_mut(path)?.layer_mut(id).ok_or_else(|| DocumentError::LayerNotFound(path.into()))
}
pub fn deepest_common_folder<'a>(&self, layers: impl Iterator<Item = &'a [LayerId]>) -> Result<&'a [LayerId], DocumentError> {
@@ -113,9 +113,36 @@ impl Document {
.unwrap_or_default()
}
pub fn common_path_prefix<'a>(&self, layers: impl Iterator<Item = &'a [LayerId]>) -> Vec<u64> {
let mut path_len: usize = usize::MAX;
let mut path: Vec<u64> = vec![];
layers.for_each(|layer| {
for i in 0..std::cmp::min(layer.len(), path_len) {
let a = *layer.get(i).unwrap();
let l = layer.len();
if i >= path.len() {
path.insert(i, a);
if l < path_len {
path_len = l;
}
}
let b = *path.get(i).unwrap();
if a != b {
path_len = i;
path.drain(path_len..path.len());
}
}
});
path
}
// 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: &Vec<u64>, path_b: &Vec<u64>) -> bool {
pub fn layer_closer_to_root(&self, path_a: &[u64], path_b: &[u64]) -> bool {
// Convert UUIDs to indices
let indices_for_path_a = self.indices_for_path(path_a).unwrap();
let indices_for_path_b = self.indices_for_path(path_b).unwrap();
@@ -137,13 +164,13 @@ impl Document {
return index_a < index_b;
}
return false;
false
}
// Is the target layer between a <-> b layers, inclusive
pub fn layer_is_between(&self, target: &Vec<u64>, path_a: &Vec<u64>, path_b: &Vec<u64>) -> bool {
// If the target is a nonsense path, it isn't between
if target.len() < 1 {
pub fn layer_is_between(&self, target: &[u64], path_a: &[u64], path_b: &[u64]) -> bool {
// If the target is the root, it isn't between
if target.is_empty() {
return false;
}
@@ -157,7 +184,7 @@ impl Document {
let layer_vs_b = self.layer_closer_to_root(target, path_b);
// To be inbetween you need to be above A and below B or vice versa
return layer_vs_a != layer_vs_b;
layer_vs_a != layer_vs_b
}
/// Given a path to a layer, returns a vector of the indices in the layer tree
@@ -169,12 +196,12 @@ impl Document {
// TODO: appears to be n^2? should we maintain a lookup table?
for id in path {
let pos = root.layer_ids.iter().position(|x| *x == *id).ok_or(DocumentError::LayerNotFound)?;
let pos = root.layer_ids.iter().position(|x| *x == *id).ok_or_else(|| DocumentError::LayerNotFound(path.into()))?;
indices.push(pos);
root = root.folder(*id).ok_or(DocumentError::LayerNotFound)?;
root = root.folder(*id).ok_or(DocumentError::LayerNotFound(path.into()))?;
}
indices.push(root.layer_ids.iter().position(|x| *x == layer_id).ok_or(DocumentError::LayerNotFound)?);
indices.push(root.layer_ids.iter().position(|x| *x == layer_id).ok_or_else(|| DocumentError::LayerNotFound(path.into()))?);
Ok(indices)
}
@@ -268,7 +295,7 @@ impl Document {
let mut root = &mut self.root;
root.cache_dirty = true;
for id in path {
root = root.as_folder_mut()?.layer_mut(*id).ok_or(DocumentError::LayerNotFound)?;
root = root.as_folder_mut()?.layer_mut(*id).ok_or_else(|| DocumentError::LayerNotFound(path.into()))?;
root.cache_dirty = true;
}
Ok(())
@@ -301,7 +328,7 @@ impl Document {
let mut transforms = vec![self.root.transform];
for id in path {
if let Ok(folder) = root.as_folder() {
root = folder.layer(*id).ok_or(DocumentError::LayerNotFound)?;
root = folder.layer(*id).ok_or_else(|| DocumentError::LayerNotFound(path.into()))?;
}
transforms.push(root.transform);
}
@@ -313,7 +340,7 @@ impl Document {
let mut trans = self.root.transform;
for id in path {
if let Ok(folder) = root.as_folder() {
root = folder.layer(*id).ok_or(DocumentError::LayerNotFound)?;
root = folder.layer(*id).ok_or_else(|| DocumentError::LayerNotFound(path.into()))?;
}
trans = trans * root.transform;
}
@@ -515,6 +542,7 @@ impl Document {
Some(vec![LayerChanged { path: path.clone() }])
}
Operation::CreateFolder { path } => {
log::debug!("Creating a folder with path {:?}", path);
self.set_layer(path, Layer::new(LayerDataType::Folder(Folder::default()), DAffine2::IDENTITY.to_cols_array()), -1)?;
self.mark_as_dirty(path)?;
@@ -633,3 +661,43 @@ fn update_thumbnails_upstream(path: &[LayerId]) -> Vec<DocumentResponse> {
}
responses
}
#[test]
fn common_layer_path_prefix_test() {
let mut fake_layers: Vec<Vec<u64>> = vec![vec![]];
fake_layers.push(vec![1, 2]);
// fake_layers.push(vec![1, 2]);
// fake_layers.push(vec![1, 2]);
// fake_layers.push(vec![1, 2, 0]);
let layers = fake_layers.iter().map(|layer| layer.as_slice());
let result = common_path_prefix(layers);
println!("Layers {:?}", result);
}
pub fn common_path_prefix<'a>(layers: impl Iterator<Item = &'a [LayerId]>) -> Vec<u64> {
let mut path_len: usize = usize::MAX;
let mut path: Vec<u64> = vec![];
layers.for_each(|layer| {
for i in 0..std::cmp::min(layer.len(), path_len) {
let a = *layer.get(i).unwrap();
let l = layer.len();
if i >= path.len() {
path.insert(i, a);
if l < path_len {
path_len = l;
}
}
let b = *path.get(i).unwrap();
if a != b {
path_len = i;
path.drain(path_len..path.len());
}
}
});
path
}

View File

@@ -102,7 +102,7 @@ impl Folder {
}
pub fn position_of_layer(&self, layer_id: LayerId) -> Result<usize, DocumentError> {
self.layer_ids.iter().position(|x| *x == layer_id).ok_or(DocumentError::LayerNotFound)
self.layer_ids.iter().position(|x| *x == layer_id).ok_or_else(|| DocumentError::LayerNotFound([layer_id].into()))
}
pub fn folder(&self, id: LayerId) -> Option<&Folder> {

View File

@@ -14,7 +14,7 @@ pub type LayerId = u64;
#[derive(Debug, Clone, PartialEq)]
pub enum DocumentError {
LayerNotFound,
LayerNotFound(Vec<LayerId>),
InvalidPath,
IndexOutOfBounds,
NotAFolder,