mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-21 04:18:12 +08:00
Implement backend part of the layer selection (#172)
* Implement backend part of the layer selection
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
use crate::{
|
||||
layers::{self, Folder, Layer, LayerData, LayerDataTypes, Line, PolyLine, Rect, Shape},
|
||||
response::LayerPanelEntry,
|
||||
DocumentError, DocumentResponse, LayerId, Operation,
|
||||
};
|
||||
|
||||
@@ -168,19 +167,6 @@ impl Document {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns a list of `LayerPanelEntry`s intended for display purposes. These don't contain
|
||||
/// any actual data, but rather metadata such as visibility and names of the layers.
|
||||
pub fn layer_panel(&self, path: &[LayerId]) -> Result<Vec<LayerPanelEntry>, DocumentError> {
|
||||
let folder = self.document_folder(path)?;
|
||||
let entries = folder
|
||||
.layers()
|
||||
.iter()
|
||||
.zip(folder.layer_ids.iter())
|
||||
.map(|(layer, id)| LayerPanelEntry::from_layer(layer, [path, &[*id]].concat()))
|
||||
.collect();
|
||||
Ok(entries)
|
||||
}
|
||||
|
||||
/// Mutate the document by applying the `operation` to it. If the operation necessitates a
|
||||
/// reaction from the frontend, responses may be returned.
|
||||
pub fn handle_operation(&mut self, operation: Operation) -> Result<Option<Vec<DocumentResponse>>, DocumentError> {
|
||||
@@ -255,14 +241,12 @@ impl Document {
|
||||
self.delete(&path)?;
|
||||
|
||||
let (path, _) = split_path(path.as_slice()).unwrap_or_else(|_| (&[], 0));
|
||||
let children = self.layer_panel(path)?;
|
||||
Some(vec![DocumentResponse::DocumentChanged, DocumentResponse::ExpandFolder { path: path.to_vec(), children }])
|
||||
Some(vec![DocumentResponse::DocumentChanged, DocumentResponse::FolderChanged { path: path.to_vec() }])
|
||||
}
|
||||
Operation::AddFolder { path } => {
|
||||
self.set_layer(&path, Layer::new(LayerDataTypes::Folder(Folder::default())))?;
|
||||
|
||||
let children = self.layer_panel(path.as_slice())?;
|
||||
Some(vec![DocumentResponse::DocumentChanged, DocumentResponse::ExpandFolder { path: path.clone(), children }])
|
||||
Some(vec![DocumentResponse::DocumentChanged, DocumentResponse::FolderChanged { path: path.clone() }])
|
||||
}
|
||||
Operation::MountWorkingFolder { path } => {
|
||||
self.work_mount_path = path.clone();
|
||||
@@ -298,17 +282,15 @@ impl Document {
|
||||
}
|
||||
}
|
||||
|
||||
let children = self.layer_panel(path.as_slice())?;
|
||||
// TODO: Return `responses` and add deduplication in the future
|
||||
Some(vec![DocumentResponse::DocumentChanged, DocumentResponse::ExpandFolder { path, children }])
|
||||
Some(vec![DocumentResponse::DocumentChanged, DocumentResponse::FolderChanged { path }])
|
||||
}
|
||||
Operation::ToggleVisibility { path } => {
|
||||
let _ = self.layer_mut(&path).map(|layer| {
|
||||
layer.visible = !layer.visible;
|
||||
layer.cache_dirty = true;
|
||||
});
|
||||
let children = self.layer_panel(&path.as_slice()[..path.len() - 1])?;
|
||||
Some(vec![DocumentResponse::DocumentChanged, DocumentResponse::ExpandFolder { path: vec![], children }])
|
||||
let path = path.as_slice()[..path.len() - 1].to_vec();
|
||||
Some(vec![DocumentResponse::DocumentChanged, DocumentResponse::FolderChanged { path }])
|
||||
}
|
||||
};
|
||||
if !matches!(
|
||||
|
||||
@@ -9,7 +9,6 @@ pub struct Folder {
|
||||
next_assignment_id: LayerId,
|
||||
pub layer_ids: Vec<LayerId>,
|
||||
layers: Vec<Layer>,
|
||||
pub collapsed: bool,
|
||||
}
|
||||
|
||||
impl LayerData for Folder {
|
||||
@@ -88,7 +87,6 @@ impl Default for Folder {
|
||||
layer_ids: vec![],
|
||||
layers: vec![],
|
||||
next_assignment_id: 0,
|
||||
collapsed: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,91 +1,19 @@
|
||||
use crate::{
|
||||
layers::{Layer, LayerDataTypes},
|
||||
LayerId,
|
||||
};
|
||||
use crate::LayerId;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
||||
pub struct LayerPanelEntry {
|
||||
pub name: String,
|
||||
pub visible: bool,
|
||||
pub layer_type: LayerType,
|
||||
pub collapsed: bool,
|
||||
pub path: Vec<LayerId>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
||||
pub enum LayerType {
|
||||
Folder,
|
||||
Shape,
|
||||
Circle,
|
||||
Rect,
|
||||
Line,
|
||||
PolyLine,
|
||||
Ellipse,
|
||||
}
|
||||
|
||||
impl fmt::Display for LayerType {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
let name = match self {
|
||||
LayerType::Folder => "Folder",
|
||||
LayerType::Shape => "Shape",
|
||||
LayerType::Rect => "Rectangle",
|
||||
LayerType::Line => "Line",
|
||||
LayerType::Circle => "Circle",
|
||||
LayerType::PolyLine => "Polyline",
|
||||
LayerType::Ellipse => "Ellipse",
|
||||
};
|
||||
|
||||
formatter.write_str(name)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&LayerDataTypes> for LayerType {
|
||||
fn from(data: &LayerDataTypes) -> Self {
|
||||
use LayerDataTypes::*;
|
||||
match data {
|
||||
Folder(_) => LayerType::Folder,
|
||||
Shape(_) => LayerType::Shape,
|
||||
Circle(_) => LayerType::Circle,
|
||||
Rect(_) => LayerType::Rect,
|
||||
Line(_) => LayerType::Line,
|
||||
PolyLine(_) => LayerType::PolyLine,
|
||||
Ellipse(_) => LayerType::Ellipse,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LayerPanelEntry {
|
||||
pub fn from_layer(layer: &Layer, path: Vec<LayerId>) -> Self {
|
||||
let layer_type: LayerType = (&layer.data).into();
|
||||
let name = layer.name.clone().unwrap_or_else(|| format!("Unnamed {}", layer_type));
|
||||
let collapsed = if let LayerDataTypes::Folder(f) = &layer.data { f.collapsed } else { true };
|
||||
Self {
|
||||
name,
|
||||
visible: layer.visible,
|
||||
layer_type,
|
||||
collapsed,
|
||||
path,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
||||
#[repr(C)]
|
||||
// TODO - Make Copy when possible
|
||||
pub enum DocumentResponse {
|
||||
DocumentChanged,
|
||||
CollapseFolder { path: Vec<LayerId> },
|
||||
ExpandFolder { path: Vec<LayerId>, children: Vec<LayerPanelEntry> },
|
||||
FolderChanged { path: Vec<LayerId> },
|
||||
}
|
||||
|
||||
impl fmt::Display for DocumentResponse {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
let name = match self {
|
||||
DocumentResponse::DocumentChanged { .. } => "DocumentChanged",
|
||||
DocumentResponse::CollapseFolder { .. } => "CollapseFolder",
|
||||
DocumentResponse::ExpandFolder { .. } => "ExpandFolder",
|
||||
DocumentResponse::FolderChanged { .. } => "FolderChanged",
|
||||
};
|
||||
|
||||
formatter.write_str(name)
|
||||
|
||||
Reference in New Issue
Block a user