mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-16 23:08:05 +08:00
Add responses in document for layer system (#91)
This commit is contained in:
committed by
Keavon Chambers
parent
b27eaf3fae
commit
f05cb30acb
@@ -2,7 +2,8 @@ use layers::PolyLine;
|
||||
|
||||
use crate::{
|
||||
layers::{self, Folder, Layer, LayerData, LayerDataTypes, Line, Rect, Shape},
|
||||
DocumentError, LayerId, Operation,
|
||||
response::{LayerPanelEntry, LayerType},
|
||||
DocumentError, DocumentResponse, LayerId, Operation,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
@@ -57,6 +58,11 @@ impl Document {
|
||||
out
|
||||
}
|
||||
|
||||
/// Wrapper around render, that returns the whole document as a Response
|
||||
pub fn render_root(&self) -> DocumentResponse {
|
||||
DocumentResponse::UpdateCanvas { document: self.render(&mut vec![]) }
|
||||
}
|
||||
|
||||
fn is_mounted(&self, mount_path: &[LayerId], path: &[LayerId]) -> bool {
|
||||
path.starts_with(mount_path) && self.work_mounted
|
||||
}
|
||||
@@ -138,13 +144,28 @@ impl Document {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn handle_operation<F: Fn(String)>(&mut self, operation: Operation, update_frontend: &F) -> Result<(), DocumentError> {
|
||||
pub fn layer_panel(&self, path: &[LayerId]) -> Result<Vec<LayerPanelEntry>, DocumentError> {
|
||||
let folder = self.document_folder(path)?;
|
||||
let l_type = |layer: &LayerDataTypes| match layer {
|
||||
LayerDataTypes::Folder(_) => LayerType::Folder,
|
||||
_ => LayerType::Shape,
|
||||
};
|
||||
let translate = |layer: &Layer| LayerPanelEntry {
|
||||
name: layer.name.clone().unwrap_or_else(|| String::from("UnnamedFolder")),
|
||||
visible: layer.visible,
|
||||
layer_type: l_type(&layer.data),
|
||||
};
|
||||
let entries = folder.layers().iter().map(|layer| translate(layer)).collect();
|
||||
Ok(entries)
|
||||
}
|
||||
|
||||
pub fn handle_operation<F: Fn(Vec<DocumentResponse>)>(&mut self, operation: Operation, send_response: &F) -> Result<(), DocumentError> {
|
||||
self.work_operations.push(operation.clone());
|
||||
match operation {
|
||||
Operation::AddCircle { path, insert_index, cx, cy, r, style } => {
|
||||
self.add_layer(&path, Layer::new(LayerDataTypes::Circle(layers::Circle::new(kurbo::Point::new(cx, cy), r, style))), insert_index)?;
|
||||
|
||||
update_frontend(self.render(&mut vec![]));
|
||||
send_response(vec![self.render_root()]);
|
||||
}
|
||||
Operation::AddRect {
|
||||
path,
|
||||
@@ -161,7 +182,7 @@ impl Document {
|
||||
insert_index,
|
||||
)?;
|
||||
|
||||
update_frontend(self.render(&mut vec![]));
|
||||
send_response(vec![self.render_root()]);
|
||||
}
|
||||
Operation::AddLine {
|
||||
path,
|
||||
@@ -178,13 +199,13 @@ impl Document {
|
||||
insert_index,
|
||||
)?;
|
||||
|
||||
update_frontend(self.render(&mut vec![]));
|
||||
send_response(vec![self.render_root()]);
|
||||
}
|
||||
Operation::AddPen { path, insert_index, points, style } => {
|
||||
let points: Vec<kurbo::Point> = points.into_iter().map(|it| it.into()).collect();
|
||||
let polyline = PolyLine::new(points, style);
|
||||
self.add_layer(&path, Layer::new(LayerDataTypes::PolyLine(polyline)), insert_index)?;
|
||||
update_frontend(self.render(&mut vec![]));
|
||||
send_response(vec![self.render_root()]);
|
||||
}
|
||||
Operation::AddShape {
|
||||
path,
|
||||
@@ -199,12 +220,12 @@ impl Document {
|
||||
let s = Shape::new(kurbo::Point::new(x0, y0), kurbo::Vec2 { x: x0 - x1, y: y0 - y1 }, sides, style);
|
||||
self.add_layer(&path, Layer::new(LayerDataTypes::Shape(s)), insert_index)?;
|
||||
|
||||
update_frontend(self.render(&mut vec![]));
|
||||
send_response(vec![self.render_root()]);
|
||||
}
|
||||
Operation::DeleteLayer { path } => {
|
||||
self.delete(&path)?;
|
||||
|
||||
update_frontend(self.render(&mut vec![]));
|
||||
send_response(vec![self.render_root()]);
|
||||
}
|
||||
Operation::AddFolder { path } => self.set_layer(&path, Layer::new(LayerDataTypes::Folder(Folder::default())))?,
|
||||
Operation::MountWorkingFolder { path } => {
|
||||
@@ -225,16 +246,19 @@ impl Document {
|
||||
}
|
||||
Operation::CommitTransaction => {
|
||||
let mut ops = Vec::new();
|
||||
let mut path: Vec<LayerId> = vec![];
|
||||
std::mem::swap(&mut path, &mut self.work_mount_path);
|
||||
std::mem::swap(&mut ops, &mut self.work_operations);
|
||||
let len = ops.len() - 1;
|
||||
self.work_mounted = false;
|
||||
self.work_mount_path = vec![];
|
||||
self.work = Folder::default();
|
||||
for operation in ops.into_iter().take(len) {
|
||||
self.handle_operation(operation, update_frontend)?
|
||||
self.handle_operation(operation, send_response)?
|
||||
}
|
||||
|
||||
update_frontend(self.render(&mut vec![]));
|
||||
let children = self.layer_panel(path.as_slice())?;
|
||||
send_response(vec![self.render_root(), DocumentResponse::ExpandFolder { path, children }]);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
||||
@@ -47,6 +47,10 @@ impl Folder {
|
||||
self.layer_ids.as_slice()
|
||||
}
|
||||
|
||||
pub fn layers(&self) -> &[Layer] {
|
||||
self.layers.as_slice()
|
||||
}
|
||||
|
||||
pub fn layer(&self, id: LayerId) -> Option<&Layer> {
|
||||
let pos = self.layer_ids.iter().position(|x| *x == id)?;
|
||||
Some(&self.layers[pos])
|
||||
|
||||
@@ -2,11 +2,13 @@ pub mod color;
|
||||
pub mod document;
|
||||
pub mod layers;
|
||||
pub mod operation;
|
||||
pub mod response;
|
||||
mod shape_points;
|
||||
|
||||
pub use operation::Operation;
|
||||
pub use response::DocumentResponse;
|
||||
|
||||
type LayerId = u64;
|
||||
pub type LayerId = u64;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum DocumentError {
|
||||
|
||||
47
core/document/src/response.rs
Normal file
47
core/document/src/response.rs
Normal file
@@ -0,0 +1,47 @@
|
||||
use crate::LayerId;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LayerPanelEntry {
|
||||
pub name: String,
|
||||
pub visible: bool,
|
||||
pub layer_type: LayerType,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum LayerType {
|
||||
Folder,
|
||||
Shape,
|
||||
}
|
||||
|
||||
impl fmt::Display for LayerType {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
let name = match self {
|
||||
LayerType::Folder => "folder",
|
||||
LayerType::Shape => "shape",
|
||||
};
|
||||
|
||||
formatter.write_str(name)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[repr(C)]
|
||||
// TODO - Make Copy when possible
|
||||
pub enum DocumentResponse {
|
||||
UpdateCanvas { document: String },
|
||||
CollapseFolder { path: Vec<LayerId> },
|
||||
ExpandFolder { path: Vec<LayerId>, children: Vec<LayerPanelEntry> },
|
||||
}
|
||||
|
||||
impl fmt::Display for DocumentResponse {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
let name = match self {
|
||||
DocumentResponse::UpdateCanvas { .. } => "UpdateCanvas",
|
||||
DocumentResponse::CollapseFolder { .. } => "CollapseFolder",
|
||||
DocumentResponse::ExpandFolder { .. } => "ExpandFolder",
|
||||
};
|
||||
|
||||
formatter.write_str(name)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user