Populate layer entry cache (#437)
* Populate layer entry cache * Serialize the DocumentMessageHandler * Fix restoring of collapsed/expanded state, add iter impl for Layer, and clean up layer_data() functions * Fixed bug with CreateEmptyLayer revealed by test Co-authored-by: Keavon Chambers <keavon@keavon.com> Co-authored-by: otdavies <oliver@psyfer.io>
This commit is contained in:
parent
3eb915eaee
commit
fd1ddfc41e
|
|
@ -101,6 +101,7 @@ dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"rand_chacha",
|
"rand_chacha",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"spin",
|
"spin",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
@ -113,7 +114,6 @@ dependencies = [
|
||||||
"kurbo",
|
"kurbo",
|
||||||
"log",
|
"log",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -157,9 +157,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "0.4.8"
|
version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
|
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
|
|
@ -274,9 +274,9 @@ checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.5"
|
version = "1.0.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scoped-tls"
|
name = "scoped-tls"
|
||||||
|
|
@ -324,9 +324,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.68"
|
version = "1.0.73"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8"
|
checksum = "bcbd0344bc6533bc7ec56df11d42fb70f1b912351c0825ccb7211b59d8af7cf5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ log = "0.4"
|
||||||
bitflags = "1.2.1"
|
bitflags = "1.2.1"
|
||||||
thiserror = "1.0.24"
|
thiserror = "1.0.24"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
serde_json = { version = "1.0" }
|
||||||
graphite-proc-macros = { path = "../proc-macros" }
|
graphite-proc-macros = { path = "../proc-macros" }
|
||||||
glam = { version="0.17", features = ["serde"] }
|
glam = { version="0.17", features = ["serde"] }
|
||||||
rand_chacha = "0.3.1"
|
rand_chacha = "0.3.1"
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ use std::collections::VecDeque;
|
||||||
pub use super::layer_panel::*;
|
pub use super::layer_panel::*;
|
||||||
use super::movement_handler::{MovementMessage, MovementMessageHandler};
|
use super::movement_handler::{MovementMessage, MovementMessageHandler};
|
||||||
use super::transform_layer_handler::{TransformLayerMessage, TransformLayerMessageHandler};
|
use super::transform_layer_handler::{TransformLayerMessage, TransformLayerMessageHandler};
|
||||||
|
use super::vectorize_layerdata;
|
||||||
|
|
||||||
use crate::consts::DEFAULT_DOCUMENT_NAME;
|
use crate::consts::DEFAULT_DOCUMENT_NAME;
|
||||||
use crate::consts::{ASYMPTOTIC_EFFECT, FILE_EXPORT_SUFFIX, FILE_SAVE_SUFFIX, SCALE_EFFECT, SCROLLBAR_SPACING};
|
use crate::consts::{ASYMPTOTIC_EFFECT, FILE_EXPORT_SUFFIX, FILE_SAVE_SUFFIX, SCALE_EFFECT, SCROLLBAR_SPACING};
|
||||||
|
|
@ -58,16 +59,21 @@ pub struct VectorManipulatorShape {
|
||||||
pub transform: DAffine2,
|
pub transform: DAffine2,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct DocumentMessageHandler {
|
pub struct DocumentMessageHandler {
|
||||||
pub graphene_document: GrapheneDocument,
|
pub graphene_document: GrapheneDocument,
|
||||||
|
#[serde(skip)]
|
||||||
pub document_undo_history: Vec<DocumentSave>,
|
pub document_undo_history: Vec<DocumentSave>,
|
||||||
|
#[serde(skip)]
|
||||||
pub document_redo_history: Vec<DocumentSave>,
|
pub document_redo_history: Vec<DocumentSave>,
|
||||||
pub saved_document_identifier: u64,
|
pub saved_document_identifier: u64,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
#[serde(with = "vectorize_layerdata")]
|
||||||
pub layer_data: HashMap<Vec<LayerId>, LayerData>,
|
pub layer_data: HashMap<Vec<LayerId>, LayerData>,
|
||||||
layer_range_selection_reference: Vec<LayerId>,
|
layer_range_selection_reference: Vec<LayerId>,
|
||||||
|
#[serde(skip)]
|
||||||
movement_handler: MovementMessageHandler,
|
movement_handler: MovementMessageHandler,
|
||||||
|
#[serde(skip)]
|
||||||
transform_layer_handler: TransformLayerMessageHandler,
|
transform_layer_handler: TransformLayerMessageHandler,
|
||||||
pub snapping_enabled: bool,
|
pub snapping_enabled: bool,
|
||||||
pub view_mode: ViewMode,
|
pub view_mode: ViewMode,
|
||||||
|
|
@ -115,6 +121,7 @@ pub enum DocumentMessage {
|
||||||
ToggleLayerVisibility(Vec<LayerId>),
|
ToggleLayerVisibility(Vec<LayerId>),
|
||||||
FlipSelectedLayers(FlipAxis),
|
FlipSelectedLayers(FlipAxis),
|
||||||
ToggleLayerExpansion(Vec<LayerId>),
|
ToggleLayerExpansion(Vec<LayerId>),
|
||||||
|
SetLayerExpansion(Vec<LayerId>, bool),
|
||||||
FolderChanged(Vec<LayerId>),
|
FolderChanged(Vec<LayerId>),
|
||||||
LayerChanged(Vec<LayerId>),
|
LayerChanged(Vec<LayerId>),
|
||||||
DocumentStructureChanged,
|
DocumentStructureChanged,
|
||||||
|
|
@ -157,30 +164,27 @@ impl From<DocumentOperation> for Message {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DocumentMessageHandler {
|
impl DocumentMessageHandler {
|
||||||
|
pub fn serialize_document(&self) -> String {
|
||||||
|
let val = serde_json::to_string(self);
|
||||||
|
// We fully expect the serialization to succeed
|
||||||
|
val.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deserialize_document(serialized_content: &str) -> Result<Self, DocumentError> {
|
||||||
|
log::info!("Deserialising: {:?}", serialized_content);
|
||||||
|
serde_json::from_str(serialized_content).map_err(|e| DocumentError::InvalidFile(e.to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn with_name(name: String, ipp: &InputPreprocessor) -> Self {
|
pub fn with_name(name: String, ipp: &InputPreprocessor) -> Self {
|
||||||
let mut document = Self {
|
let mut document = Self { name, ..Self::default() };
|
||||||
graphene_document: GrapheneDocument::default(),
|
document.graphene_document.root.transform = document.layer_data(&[]).calculate_offset_transform(ipp.viewport_bounds.size() / 2., 0.);
|
||||||
document_undo_history: Vec::new(),
|
|
||||||
document_redo_history: Vec::new(),
|
|
||||||
saved_document_identifier: 0,
|
|
||||||
name,
|
|
||||||
layer_data: vec![(vec![], LayerData::new(true))].into_iter().collect(),
|
|
||||||
layer_range_selection_reference: Vec::new(),
|
|
||||||
movement_handler: MovementMessageHandler::default(),
|
|
||||||
transform_layer_handler: TransformLayerMessageHandler::default(),
|
|
||||||
snapping_enabled: true,
|
|
||||||
view_mode: ViewMode::default(),
|
|
||||||
};
|
|
||||||
document.graphene_document.root.transform = document.layerdata(&[]).calculate_offset_transform(ipp.viewport_bounds.size() / 2., 0.);
|
|
||||||
document
|
document
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_name_and_content(name: String, serialized_content: String, ipp: &InputPreprocessor) -> Result<Self, EditorError> {
|
pub fn with_name_and_content(name: String, serialized_content: String) -> Result<Self, EditorError> {
|
||||||
let mut document = Self::with_name(name, ipp);
|
match Self::deserialize_document(&serialized_content) {
|
||||||
let internal_document = GrapheneDocument::with_content(&serialized_content);
|
Ok(mut document) => {
|
||||||
match internal_document {
|
document.name = name;
|
||||||
Ok(handle) => {
|
|
||||||
document.graphene_document = handle;
|
|
||||||
Ok(document)
|
Ok(document)
|
||||||
}
|
}
|
||||||
Err(DocumentError::InvalidFile(msg)) => Err(EditorError::Document(msg)),
|
Err(DocumentError::InvalidFile(msg)) => Err(EditorError::Document(msg)),
|
||||||
|
|
@ -199,7 +203,7 @@ impl DocumentMessageHandler {
|
||||||
if self.graphene_document.layer(path).ok()?.overlay {
|
if self.graphene_document.layer(path).ok()?.overlay {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
self.layer_data(path).selected = true;
|
self.layer_data_mut(path).selected = true;
|
||||||
let data = self.layer_panel_entry(path.to_vec()).ok()?;
|
let data = self.layer_panel_entry(path.to_vec()).ok()?;
|
||||||
(!path.is_empty()).then(|| FrontendMessage::UpdateLayer { data }.into())
|
(!path.is_empty()).then(|| FrontendMessage::UpdateLayer { data }.into())
|
||||||
}
|
}
|
||||||
|
|
@ -244,12 +248,8 @@ impl DocumentMessageHandler {
|
||||||
shapes.collect::<Vec<VectorManipulatorShape>>()
|
shapes.collect::<Vec<VectorManipulatorShape>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn layerdata(&self, path: &[LayerId]) -> &LayerData {
|
pub fn create_layer_data(&mut self, path: &[LayerId]) {
|
||||||
self.layer_data.get(path).expect("Layerdata does not exist")
|
self.layer_data.insert(path.to_vec(), LayerData::new(true));
|
||||||
}
|
|
||||||
|
|
||||||
pub fn layerdata_mut(&mut self, path: &[LayerId]) -> &mut LayerData {
|
|
||||||
self.layer_data.entry(path.to_vec()).or_insert_with(|| LayerData::new(true))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn selected_layers(&self) -> impl Iterator<Item = &[LayerId]> {
|
pub fn selected_layers(&self) -> impl Iterator<Item = &[LayerId]> {
|
||||||
|
|
@ -265,7 +265,7 @@ impl DocumentMessageHandler {
|
||||||
LayerDataType::Shape(_) => (),
|
LayerDataType::Shape(_) => (),
|
||||||
LayerDataType::Folder(ref folder) => {
|
LayerDataType::Folder(ref folder) => {
|
||||||
path.push(*id);
|
path.push(*id);
|
||||||
if self.layerdata(path).expanded {
|
if self.layer_data(path).expanded {
|
||||||
structure.push(space);
|
structure.push(space);
|
||||||
self.serialize_structure(folder, structure, data, path);
|
self.serialize_structure(folder, structure, data, path);
|
||||||
space = 0;
|
space = 0;
|
||||||
|
|
@ -352,8 +352,18 @@ impl DocumentMessageHandler {
|
||||||
self.layers_sorted(Some(false))
|
self.layers_sorted(Some(false))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn layer_data(&mut self, path: &[LayerId]) -> &mut LayerData {
|
pub fn layer_data(&self, path: &[LayerId]) -> &LayerData {
|
||||||
layer_data(&mut self.layer_data, path)
|
self.layer_data.get(path).expect("Layerdata does not exist")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn layer_data_mut(&mut self, path: &[LayerId]) -> &mut LayerData {
|
||||||
|
Self::layer_data_mut_no_borrow_self(&mut self.layer_data, path)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn layer_data_mut_no_borrow_self<'a>(layer_data: &'a mut HashMap<Vec<LayerId>, LayerData>, path: &[LayerId]) -> &'a mut LayerData {
|
||||||
|
layer_data
|
||||||
|
.get_mut(path)
|
||||||
|
.unwrap_or_else(|| panic!("Layer data cannot be found because the path {:?} does not exist", path))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn backup(&mut self, responses: &mut VecDeque<Message>) {
|
pub fn backup(&mut self, responses: &mut VecDeque<Message>) {
|
||||||
|
|
@ -431,7 +441,7 @@ impl DocumentMessageHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn layer_panel_entry(&mut self, path: Vec<LayerId>) -> Result<LayerPanelEntry, EditorError> {
|
pub fn layer_panel_entry(&mut self, path: Vec<LayerId>) -> Result<LayerPanelEntry, EditorError> {
|
||||||
let data: LayerData = *layer_data(&mut self.layer_data, &path);
|
let data: LayerData = *self.layer_data_mut(&path);
|
||||||
let layer = self.graphene_document.layer(&path)?;
|
let layer = self.graphene_document.layer(&path)?;
|
||||||
let entry = layer_panel_entry(&data, self.graphene_document.multiply_transforms(&path)?, layer, path);
|
let entry = layer_panel_entry(&data, self.graphene_document.multiply_transforms(&path)?, layer, path);
|
||||||
Ok(entry)
|
Ok(entry)
|
||||||
|
|
@ -442,27 +452,23 @@ impl DocumentMessageHandler {
|
||||||
pub fn layer_panel(&mut self, path: &[LayerId]) -> Result<Vec<LayerPanelEntry>, EditorError> {
|
pub fn layer_panel(&mut self, path: &[LayerId]) -> Result<Vec<LayerPanelEntry>, EditorError> {
|
||||||
let folder = self.graphene_document.folder(path)?;
|
let folder = self.graphene_document.folder(path)?;
|
||||||
let paths: Vec<Vec<LayerId>> = folder.layer_ids.iter().map(|id| [path, &[*id]].concat()).collect();
|
let paths: Vec<Vec<LayerId>> = folder.layer_ids.iter().map(|id| [path, &[*id]].concat()).collect();
|
||||||
let data: Vec<LayerData> = paths.iter().map(|path| *layer_data(&mut self.layer_data, path)).collect();
|
let entries = paths.iter().rev().filter_map(|path| self.layer_panel_entry_from_path(path)).collect();
|
||||||
let folder = self.graphene_document.folder(path)?;
|
|
||||||
let entries = folder
|
|
||||||
.layers()
|
|
||||||
.iter()
|
|
||||||
.zip(paths.iter().zip(data))
|
|
||||||
.rev()
|
|
||||||
.filter(|(layer, _)| !layer.overlay)
|
|
||||||
.map(|(layer, (path, data))| {
|
|
||||||
layer_panel_entry(
|
|
||||||
&data,
|
|
||||||
self.graphene_document
|
|
||||||
.generate_transform_across_scope(path, Some(self.graphene_document.root.transform.inverse()))
|
|
||||||
.unwrap(),
|
|
||||||
layer,
|
|
||||||
path.to_vec(),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
Ok(entries)
|
Ok(entries)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn layer_panel_entry_from_path(&self, path: &[LayerId]) -> Option<LayerPanelEntry> {
|
||||||
|
let layer_data = self.layer_data(path);
|
||||||
|
let transform = self
|
||||||
|
.graphene_document
|
||||||
|
.generate_transform_across_scope(path, Some(self.graphene_document.root.transform.inverse()))
|
||||||
|
.ok()?;
|
||||||
|
let layer = self.graphene_document.layer(path).ok()?;
|
||||||
|
|
||||||
|
match layer.overlay {
|
||||||
|
true => None,
|
||||||
|
false => Some(layer_panel_entry(layer_data, transform, layer, path.to_vec())),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHandler {
|
impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHandler {
|
||||||
|
|
@ -471,7 +477,7 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
|
||||||
match message {
|
match message {
|
||||||
Movement(message) => self
|
Movement(message) => self
|
||||||
.movement_handler
|
.movement_handler
|
||||||
.process_action(message, (layer_data(&mut self.layer_data, &[]), &self.graphene_document, ipp), responses),
|
.process_action(message, (Self::layer_data_mut_no_borrow_self(&mut self.layer_data, &[]), &self.graphene_document, ipp), responses),
|
||||||
TransformLayers(message) => self
|
TransformLayers(message) => self
|
||||||
.transform_layer_handler
|
.transform_layer_handler
|
||||||
.process_action(message, (&mut self.layer_data, &mut self.graphene_document, ipp), responses),
|
.process_action(message, (&mut self.layer_data, &mut self.graphene_document, ipp), responses),
|
||||||
|
|
@ -521,7 +527,7 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
|
||||||
};
|
};
|
||||||
responses.push_back(
|
responses.push_back(
|
||||||
FrontendMessage::SaveDocument {
|
FrontendMessage::SaveDocument {
|
||||||
document: self.graphene_document.serialize_document(),
|
document: self.serialize_document(),
|
||||||
name,
|
name,
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
|
|
@ -530,8 +536,8 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
|
||||||
CreateEmptyFolder(mut path) => {
|
CreateEmptyFolder(mut path) => {
|
||||||
let id = generate_uuid();
|
let id = generate_uuid();
|
||||||
path.push(id);
|
path.push(id);
|
||||||
self.layerdata_mut(&path).expanded = true;
|
responses.push_back(DocumentOperation::CreateFolder { path: path.clone() }.into());
|
||||||
responses.push_back(DocumentOperation::CreateFolder { path }.into())
|
responses.push_back(DocumentMessage::SetLayerExpansion(path, true).into());
|
||||||
}
|
}
|
||||||
GroupSelectedLayers => {
|
GroupSelectedLayers => {
|
||||||
let selected_layers = self.selected_layers();
|
let selected_layers = self.selected_layers();
|
||||||
|
|
@ -574,7 +580,12 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
|
||||||
responses.push_back(DocumentOperation::ToggleLayerVisibility { path }.into());
|
responses.push_back(DocumentOperation::ToggleLayerVisibility { path }.into());
|
||||||
}
|
}
|
||||||
ToggleLayerExpansion(path) => {
|
ToggleLayerExpansion(path) => {
|
||||||
self.layer_data(&path).expanded ^= true;
|
self.layer_data_mut(&path).expanded ^= true;
|
||||||
|
responses.push_back(DocumentStructureChanged.into());
|
||||||
|
responses.push_back(LayerChanged(path).into())
|
||||||
|
}
|
||||||
|
SetLayerExpansion(path, is_expanded) => {
|
||||||
|
self.layer_data_mut(&path).expanded = is_expanded;
|
||||||
responses.push_back(DocumentStructureChanged.into());
|
responses.push_back(DocumentStructureChanged.into());
|
||||||
responses.push_back(LayerChanged(path).into())
|
responses.push_back(LayerChanged(path).into())
|
||||||
}
|
}
|
||||||
|
|
@ -621,7 +632,7 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
|
||||||
} else {
|
} else {
|
||||||
if ctrl {
|
if ctrl {
|
||||||
// Toggle selection when holding ctrl
|
// Toggle selection when holding ctrl
|
||||||
let layer = self.layerdata_mut(&selected);
|
let layer = self.layer_data_mut(&selected);
|
||||||
layer.selected = !layer.selected;
|
layer.selected = !layer.selected;
|
||||||
responses.push_back(LayerChanged(selected.clone()).into());
|
responses.push_back(LayerChanged(selected.clone()).into());
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -734,7 +745,7 @@ impl MessageHandler<DocumentMessage, &InputPreprocessor> for DocumentMessageHand
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
let root_layerdata = self.layerdata(&[]);
|
let root_layerdata = self.layer_data(&[]);
|
||||||
|
|
||||||
let scale = 0.5 + ASYMPTOTIC_EFFECT + root_layerdata.scale * SCALE_EFFECT;
|
let scale = 0.5 + ASYMPTOTIC_EFFECT + root_layerdata.scale * SCALE_EFFECT;
|
||||||
let viewport_size = ipp.viewport_bounds.size();
|
let viewport_size = ipp.viewport_bounds.size();
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ impl DocumentsMessageHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Fix how this doesn't preserve tab order upon loading new document from file>load
|
// TODO Fix how this doesn't preserve tab order upon loading new document from file>load
|
||||||
fn load_document(&mut self, new_document: DocumentMessageHandler, document_id: u64, replace_first_empty: bool, responses: &mut VecDeque<Message>) {
|
fn load_document(&mut self, mut new_document: DocumentMessageHandler, document_id: u64, replace_first_empty: bool, responses: &mut VecDeque<Message>) {
|
||||||
// Special case when loading a document on an empty page
|
// Special case when loading a document on an empty page
|
||||||
if replace_first_empty && self.active_document().is_unmodified_default() {
|
if replace_first_empty && self.active_document().is_unmodified_default() {
|
||||||
responses.push_back(DocumentsMessage::CloseDocument(self.active_document_id).into());
|
responses.push_back(DocumentsMessage::CloseDocument(self.active_document_id).into());
|
||||||
|
|
@ -110,6 +110,15 @@ impl DocumentsMessageHandler {
|
||||||
self.document_ids.push(document_id);
|
self.document_ids.push(document_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
responses.extend(
|
||||||
|
new_document
|
||||||
|
.layer_data
|
||||||
|
.keys()
|
||||||
|
.filter_map(|path| new_document.layer_panel_entry_from_path(path))
|
||||||
|
.map(|entry| FrontendMessage::UpdateLayer { data: entry }.into())
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
);
|
||||||
|
|
||||||
self.documents.insert(document_id, new_document);
|
self.documents.insert(document_id, new_document);
|
||||||
|
|
||||||
// Send the new list of document tab names
|
// Send the new list of document tab names
|
||||||
|
|
@ -273,7 +282,7 @@ impl MessageHandler<DocumentsMessage, &InputPreprocessor> for DocumentsMessageHa
|
||||||
document,
|
document,
|
||||||
document_is_saved,
|
document_is_saved,
|
||||||
} => {
|
} => {
|
||||||
let document = DocumentMessageHandler::with_name_and_content(document_name, document, ipp);
|
let document = DocumentMessageHandler::with_name_and_content(document_name, document);
|
||||||
match document {
|
match document {
|
||||||
Ok(mut document) => {
|
Ok(mut document) => {
|
||||||
document.set_save_state(document_is_saved);
|
document.set_save_state(document_is_saved);
|
||||||
|
|
@ -307,7 +316,7 @@ impl MessageHandler<DocumentsMessage, &InputPreprocessor> for DocumentsMessageHa
|
||||||
let document = self.documents.get(&id).unwrap();
|
let document = self.documents.get(&id).unwrap();
|
||||||
responses.push_back(
|
responses.push_back(
|
||||||
FrontendMessage::AutoSaveDocument {
|
FrontendMessage::AutoSaveDocument {
|
||||||
document: document.graphene_document.serialize_document(),
|
document: document.serialize_document(),
|
||||||
details: FrontendDocumentDetails {
|
details: FrontendDocumentDetails {
|
||||||
is_saved: document.is_saved(),
|
is_saved: document.is_saved(),
|
||||||
id,
|
id,
|
||||||
|
|
|
||||||
|
|
@ -35,10 +35,6 @@ impl LayerData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn layer_data<'a>(layer_data: &'a mut HashMap<Vec<LayerId>, LayerData>, path: &[LayerId]) -> &'a mut LayerData {
|
|
||||||
layer_data.get_mut(path).expect(&format!("Layer data cannot be found because the path {:?} does not exist", path))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn layer_panel_entry(layer_data: &LayerData, transform: DAffine2, layer: &Layer, path: Vec<LayerId>) -> LayerPanelEntry {
|
pub fn layer_panel_entry(layer_data: &LayerData, transform: DAffine2, layer: &Layer, path: Vec<LayerId>) -> LayerPanelEntry {
|
||||||
let layer_type: LayerType = (&layer.data).into();
|
let layer_type: LayerType = (&layer.data).into();
|
||||||
let name = layer.name.clone().unwrap_or_else(|| format!("Unnamed {}", layer_type));
|
let name = layer.name.clone().unwrap_or_else(|| format!("Unnamed {}", layer_type));
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ mod document_message_handler;
|
||||||
pub mod layer_panel;
|
pub mod layer_panel;
|
||||||
mod movement_handler;
|
mod movement_handler;
|
||||||
mod transform_layer_handler;
|
mod transform_layer_handler;
|
||||||
|
mod vectorize_layerdata;
|
||||||
|
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use document_file::LayerData;
|
pub use document_file::LayerData;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
/// Necessary because serde can't serialize hashmaps when the keys don't implement display.
|
||||||
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
|
use std::iter::FromIterator;
|
||||||
|
|
||||||
|
pub fn serialize<'a, T, K, V, S>(target: T, ser: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
T: IntoIterator<Item = (&'a K, &'a V)>,
|
||||||
|
K: Serialize + 'a,
|
||||||
|
V: Serialize + 'a,
|
||||||
|
{
|
||||||
|
let container: Vec<_> = target.into_iter().collect();
|
||||||
|
serde::Serialize::serialize(&container, ser)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deserialize<'de, T, K, V, D>(des: D) -> Result<T, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
T: FromIterator<(K, V)>,
|
||||||
|
K: Deserialize<'de>,
|
||||||
|
V: Deserialize<'de>,
|
||||||
|
{
|
||||||
|
let container: Vec<_> = serde::Deserialize::deserialize(des)?;
|
||||||
|
Ok(T::from_iter(container.into_iter()))
|
||||||
|
}
|
||||||
|
|
@ -17,5 +17,4 @@ kurbo = { git = "https://github.com/linebender/kurbo.git", features = [
|
||||||
"serde",
|
"serde",
|
||||||
] }
|
] }
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = { version = "1.0" }
|
|
||||||
glam = { version = "0.17", features = ["serde"] }
|
glam = { version = "0.17", features = ["serde"] }
|
||||||
|
|
|
||||||
|
|
@ -34,10 +34,6 @@ impl Default for Document {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Document {
|
impl Document {
|
||||||
pub fn with_content(serialized_content: &str) -> Result<Self, DocumentError> {
|
|
||||||
serde_json::from_str(serialized_content).map_err(|e| DocumentError::InvalidFile(e.to_string()))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Wrapper around render, that returns the whole document as a Response.
|
/// Wrapper around render, that returns the whole document as a Response.
|
||||||
pub fn render_root(&mut self, mode: ViewMode) -> String {
|
pub fn render_root(&mut self, mode: ViewMode) -> String {
|
||||||
self.root.render(&mut vec![], mode);
|
self.root.render(&mut vec![], mode);
|
||||||
|
|
@ -48,12 +44,6 @@ impl Document {
|
||||||
self.state_identifier.finish()
|
self.state_identifier.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn serialize_document(&self) -> String {
|
|
||||||
let val = serde_json::to_string(self);
|
|
||||||
// We fully expect the serialization to succeed
|
|
||||||
val.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks whether each layer under `path` intersects with the provided `quad` and adds all intersection layers as paths to `intersections`.
|
/// Checks whether each layer under `path` intersects with the provided `quad` and adds all intersection layers as paths to `intersections`.
|
||||||
pub fn intersects_quad(&self, quad: Quad, path: &mut Vec<LayerId>, intersections: &mut Vec<Vec<LayerId>>) {
|
pub fn intersects_quad(&self, quad: Quad, path: &mut Vec<LayerId>, intersections: &mut Vec<Vec<LayerId>>) {
|
||||||
self.layer(path).unwrap().intersects_quad(quad, path, intersections);
|
self.layer(path).unwrap().intersects_quad(quad, path, intersections);
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,10 @@ impl Layer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn iter(&self) -> LayerIter<'_> {
|
||||||
|
LayerIter { stack: vec![self] }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn render(&mut self, transforms: &mut Vec<DAffine2>, view_mode: ViewMode) -> &str {
|
pub fn render(&mut self, transforms: &mut Vec<DAffine2>, view_mode: ViewMode) -> &str {
|
||||||
if !self.visible {
|
if !self.visible {
|
||||||
return "";
|
return "";
|
||||||
|
|
@ -179,3 +183,40 @@ impl Clone for Layer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoIterator for &'a Layer {
|
||||||
|
type Item = &'a Layer;
|
||||||
|
type IntoIter = LayerIter<'a>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
self.iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct LayerIter<'a> {
|
||||||
|
pub stack: Vec<&'a Layer>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for LayerIter<'_> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self { stack: vec![] }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for LayerIter<'a> {
|
||||||
|
type Item = &'a Layer;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
match self.stack.pop() {
|
||||||
|
Some(layer) => {
|
||||||
|
if let LayerDataType::Folder(folder) = &layer.data {
|
||||||
|
let layers = folder.layers();
|
||||||
|
self.stack.extend(layers);
|
||||||
|
};
|
||||||
|
Some(layer)
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue