Artboard history (#976)
* Convert DocumentSave to struct * Comit the artboard history save in some cases * Cause index out of bounds error * Use box to avoid weird wasm error * Implement the artboard history Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
parent
d2219cec36
commit
5cbe3f7573
|
|
@ -12,7 +12,7 @@ use document_legacy::Operation as DocumentOperation;
|
|||
use glam::DAffine2;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
|
||||
pub struct ArtboardMessageHandler {
|
||||
pub artboards_document: DocumentLegacy,
|
||||
pub artboard_ids: Vec<LayerId>,
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ pub enum DocumentMessage {
|
|||
},
|
||||
BackupDocument {
|
||||
document: DocumentLegacy,
|
||||
artboard: Box<ArtboardMessageHandler>,
|
||||
layer_metadata: HashMap<Vec<LayerId>, LayerMetadata>,
|
||||
},
|
||||
BooleanOperation(BooleanOperationType),
|
||||
|
|
|
|||
|
|
@ -247,7 +247,7 @@ impl MessageHandler<DocumentMessage, (u64, &InputPreprocessorMessageHandler, &Pe
|
|||
responses.push_back(BroadcastEvent::DocumentIsDirty.into());
|
||||
}
|
||||
}
|
||||
BackupDocument { document, layer_metadata } => self.backup_with_document(document, layer_metadata, responses),
|
||||
BackupDocument { document, artboard, layer_metadata } => self.backup_with_document(document, *artboard, layer_metadata, responses),
|
||||
BooleanOperation(op) => {
|
||||
// Convert Vec<&[LayerId]> to Vec<Vec<&LayerId>> because Vec<&[LayerId]> does not implement several traits (Debug, Serialize, Deserialize, ...) required by DocumentOperation enum
|
||||
responses.push_back(StartTransaction.into());
|
||||
|
|
@ -1288,9 +1288,9 @@ impl DocumentMessageHandler {
|
|||
}
|
||||
|
||||
/// Places a document into the history system
|
||||
fn backup_with_document(&mut self, document: DocumentLegacy, layer_metadata: HashMap<Vec<LayerId>, LayerMetadata>, responses: &mut VecDeque<Message>) {
|
||||
fn backup_with_document(&mut self, document: DocumentLegacy, artboard: ArtboardMessageHandler, layer_metadata: HashMap<Vec<LayerId>, LayerMetadata>, responses: &mut VecDeque<Message>) {
|
||||
self.document_redo_history.clear();
|
||||
self.document_undo_history.push_back((document, layer_metadata));
|
||||
self.document_undo_history.push_back(DocumentSave { document, artboard, layer_metadata });
|
||||
if self.document_undo_history.len() > crate::consts::MAX_UNDO_HISTORY_LEN {
|
||||
self.document_undo_history.pop_front();
|
||||
}
|
||||
|
|
@ -1301,7 +1301,7 @@ impl DocumentMessageHandler {
|
|||
|
||||
/// Copies the entire document into the history system
|
||||
pub fn backup(&mut self, responses: &mut VecDeque<Message>) {
|
||||
self.backup_with_document(self.document_legacy.clone(), self.layer_metadata.clone(), responses);
|
||||
self.backup_with_document(self.document_legacy.clone(), self.artboard_message_handler.clone(), self.layer_metadata.clone(), responses);
|
||||
}
|
||||
|
||||
/// Push a message backing up the document in its current state
|
||||
|
|
@ -1309,6 +1309,7 @@ impl DocumentMessageHandler {
|
|||
responses.push_back(
|
||||
DocumentMessage::BackupDocument {
|
||||
document: self.document_legacy.clone(),
|
||||
artboard: Box::new(self.artboard_message_handler.clone()),
|
||||
layer_metadata: self.layer_metadata.clone(),
|
||||
}
|
||||
.into(),
|
||||
|
|
@ -1321,6 +1322,23 @@ impl DocumentMessageHandler {
|
|||
// TODO: Consider if we should check if the document is saved
|
||||
}
|
||||
|
||||
/// Replace the document with a new document save, returning the document save.
|
||||
pub fn replace_document(&mut self, DocumentSave { document, artboard, layer_metadata }: DocumentSave) -> DocumentSave {
|
||||
// Keeping the root is required if the bounds of the viewport have changed during the operation
|
||||
let old_root = self.document_legacy.root.transform;
|
||||
let old_artboard_root = self.artboard_message_handler.artboards_document.root.transform;
|
||||
let document = std::mem::replace(&mut self.document_legacy, document);
|
||||
let artboard = std::mem::replace(&mut self.artboard_message_handler, artboard);
|
||||
self.document_legacy.root.transform = old_root;
|
||||
self.artboard_message_handler.artboards_document.root.transform = old_artboard_root;
|
||||
self.document_legacy.root.cache_dirty = true;
|
||||
self.artboard_message_handler.artboards_document.root.cache_dirty = true;
|
||||
|
||||
let layer_metadata = std::mem::replace(&mut self.layer_metadata, layer_metadata);
|
||||
|
||||
DocumentSave { document, artboard, layer_metadata }
|
||||
}
|
||||
|
||||
pub fn undo(&mut self, responses: &mut VecDeque<Message>) -> Result<(), EditorError> {
|
||||
// Push the UpdateOpenDocumentsList message to the bus in order to update the save status of the open documents
|
||||
responses.push_back(PortfolioMessage::UpdateOpenDocumentsList.into());
|
||||
|
|
@ -1328,7 +1346,7 @@ impl DocumentMessageHandler {
|
|||
let selected_paths: Vec<Vec<LayerId>> = self.selected_layers().map(|path| path.to_vec()).collect();
|
||||
|
||||
match self.document_undo_history.pop_back() {
|
||||
Some((document, layer_metadata)) => {
|
||||
Some(DocumentSave { document, artboard, layer_metadata }) => {
|
||||
// Update the currently displayed layer on the Properties panel if the selection changes after an undo action
|
||||
// Also appropriately update the Properties panel if an undo action results in a layer being deleted
|
||||
let prev_selected_paths: Vec<Vec<LayerId>> = layer_metadata.iter().filter_map(|(layer_id, metadata)| metadata.selected.then_some(layer_id.clone())).collect();
|
||||
|
|
@ -1337,14 +1355,9 @@ impl DocumentMessageHandler {
|
|||
responses.push_back(BroadcastEvent::SelectionChanged.into());
|
||||
}
|
||||
|
||||
// Keeping the root is required if the bounds of the viewport have changed during the operation
|
||||
let old_root = self.document_legacy.root.transform;
|
||||
let document = std::mem::replace(&mut self.document_legacy, document);
|
||||
self.document_legacy.root.transform = old_root;
|
||||
self.document_legacy.root.cache_dirty = true;
|
||||
let document_save = self.replace_document(DocumentSave { document, artboard, layer_metadata });
|
||||
|
||||
let layer_metadata = std::mem::replace(&mut self.layer_metadata, layer_metadata);
|
||||
self.document_redo_history.push_back((document, layer_metadata));
|
||||
self.document_redo_history.push_back(document_save);
|
||||
if self.document_redo_history.len() > crate::consts::MAX_UNDO_HISTORY_LEN {
|
||||
self.document_redo_history.pop_front();
|
||||
}
|
||||
|
|
@ -1368,7 +1381,7 @@ impl DocumentMessageHandler {
|
|||
let selected_paths: Vec<Vec<LayerId>> = self.selected_layers().map(|path| path.to_vec()).collect();
|
||||
|
||||
match self.document_redo_history.pop_back() {
|
||||
Some((document, layer_metadata)) => {
|
||||
Some(DocumentSave { document, artboard, layer_metadata }) => {
|
||||
// Update currently displayed layer on property panel if selection changes after redo action
|
||||
// Also appropriately update property panel if redo action results in a layer being added
|
||||
let next_selected_paths: Vec<Vec<LayerId>> = layer_metadata.iter().filter_map(|(layer_id, metadata)| metadata.selected.then_some(layer_id.clone())).collect();
|
||||
|
|
@ -1377,14 +1390,8 @@ impl DocumentMessageHandler {
|
|||
responses.push_back(BroadcastEvent::SelectionChanged.into());
|
||||
}
|
||||
|
||||
// Keeping the root is required if the bounds of the viewport have changed during the operation
|
||||
let old_root = self.document_legacy.root.transform;
|
||||
let document = std::mem::replace(&mut self.document_legacy, document);
|
||||
self.document_legacy.root.transform = old_root;
|
||||
self.document_legacy.root.cache_dirty = true;
|
||||
|
||||
let layer_metadata = std::mem::replace(&mut self.layer_metadata, layer_metadata);
|
||||
self.document_undo_history.push_back((document, layer_metadata));
|
||||
let document_save = self.replace_document(DocumentSave { document, artboard, layer_metadata });
|
||||
self.document_undo_history.push_back(document_save);
|
||||
if self.document_undo_history.len() > crate::consts::MAX_UNDO_HISTORY_LEN {
|
||||
self.document_undo_history.pop_front();
|
||||
}
|
||||
|
|
@ -1407,7 +1414,7 @@ impl DocumentMessageHandler {
|
|||
self.document_undo_history
|
||||
.iter()
|
||||
.last()
|
||||
.map(|(document_legacy, _)| document_legacy.current_state_identifier())
|
||||
.map(|DocumentSave { document, .. }| document.current_state_identifier())
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
pub use super::layer_panel::{LayerMetadata, LayerPanelEntry};
|
||||
use crate::messages::prelude::ArtboardMessageHandler;
|
||||
|
||||
use document_legacy::color::Color;
|
||||
use document_legacy::document::Document as DocumentLegacy;
|
||||
|
|
@ -8,7 +9,12 @@ use serde::{Deserialize, Serialize};
|
|||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
|
||||
pub type DocumentSave = (DocumentLegacy, HashMap<Vec<LayerId>, LayerMetadata>);
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DocumentSave {
|
||||
pub document: DocumentLegacy,
|
||||
pub artboard: ArtboardMessageHandler,
|
||||
pub layer_metadata: HashMap<Vec<LayerId>, LayerMetadata>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize, Hash)]
|
||||
pub enum FlipAxis {
|
||||
|
|
|
|||
|
|
@ -190,6 +190,8 @@ impl Fsm for ArtboardToolFsmState {
|
|||
};
|
||||
|
||||
if let Some(selected_edges) = dragging_bounds {
|
||||
responses.push_back(DocumentMessage::StartTransaction.into());
|
||||
|
||||
let snap_x = selected_edges.2 || selected_edges.3;
|
||||
let snap_y = selected_edges.0 || selected_edges.1;
|
||||
|
||||
|
|
@ -206,6 +208,7 @@ impl Fsm for ArtboardToolFsmState {
|
|||
|
||||
ArtboardToolFsmState::ResizingBounds
|
||||
} else {
|
||||
responses.push_back(DocumentMessage::StartTransaction.into());
|
||||
let tolerance = DVec2::splat(SELECTION_TOLERANCE);
|
||||
let quad = Quad::from_box([input.mouse.position - tolerance, input.mouse.position + tolerance]);
|
||||
let intersection = document.artboard_message_handler.artboards_document.intersects_quad_root(quad, font_cache);
|
||||
|
|
|
|||
Loading…
Reference in New Issue