diff --git a/editor/src/communication/dispatcher.rs b/editor/src/communication/dispatcher.rs index 1fad9df0b..3701971ee 100644 --- a/editor/src/communication/dispatcher.rs +++ b/editor/src/communication/dispatcher.rs @@ -161,10 +161,10 @@ mod test { let mut editor = create_editor_with_three_layers(); let document_before_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().graphene_document.clone(); - editor.handle_message(PortfolioMessage::Copy(Clipboard::User)); + editor.handle_message(PortfolioMessage::Copy { clipboard: Clipboard::User }); editor.handle_message(PortfolioMessage::PasteIntoFolder { clipboard: Clipboard::User, - path: vec![], + folder_path: vec![], insert_index: -1, }); let document_after_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().graphene_document.clone(); @@ -197,11 +197,13 @@ mod test { let document_before_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().graphene_document.clone(); let shape_id = document_before_copy.root.as_folder().unwrap().layer_ids[1]; - editor.handle_message(DocumentMessage::SetSelectedLayers(vec![vec![shape_id]])); - editor.handle_message(PortfolioMessage::Copy(Clipboard::User)); + editor.handle_message(DocumentMessage::SetSelectedLayers { + replacement_selected_layers: vec![vec![shape_id]], + }); + editor.handle_message(PortfolioMessage::Copy { clipboard: Clipboard::User }); editor.handle_message(PortfolioMessage::PasteIntoFolder { clipboard: Clipboard::User, - path: vec![], + folder_path: vec![], insert_index: -1, }); @@ -235,7 +237,7 @@ mod test { const LINE_INDEX: usize = 0; const PEN_INDEX: usize = 1; - editor.handle_message(DocumentMessage::CreateEmptyFolder(vec![])); + editor.handle_message(DocumentMessage::CreateEmptyFolder { container_path: vec![] }); let document_before_added_shapes = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().graphene_document.clone(); let folder_id = document_before_added_shapes.root.as_folder().unwrap().layer_ids[FOLDER_INDEX]; @@ -257,20 +259,22 @@ mod test { points: vec![(10.0, 20.0), (30.0, 40.0)], }); - editor.handle_message(DocumentMessage::SetSelectedLayers(vec![vec![folder_id]])); + editor.handle_message(DocumentMessage::SetSelectedLayers { + replacement_selected_layers: vec![vec![folder_id]], + }); let document_before_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().graphene_document.clone(); - editor.handle_message(PortfolioMessage::Copy(Clipboard::User)); + editor.handle_message(PortfolioMessage::Copy { clipboard: Clipboard::User }); editor.handle_message(DocumentMessage::DeleteSelectedLayers); editor.handle_message(PortfolioMessage::PasteIntoFolder { clipboard: Clipboard::User, - path: vec![], + folder_path: vec![], insert_index: -1, }); editor.handle_message(PortfolioMessage::PasteIntoFolder { clipboard: Clipboard::User, - path: vec![], + folder_path: vec![], insert_index: -1, }); @@ -329,18 +333,20 @@ mod test { let rect_id = document_before_copy.root.as_folder().unwrap().layer_ids[RECT_INDEX]; let ellipse_id = document_before_copy.root.as_folder().unwrap().layer_ids[ELLIPSE_INDEX]; - editor.handle_message(DocumentMessage::SetSelectedLayers(vec![vec![rect_id], vec![ellipse_id]])); - editor.handle_message(PortfolioMessage::Copy(Clipboard::User)); + editor.handle_message(DocumentMessage::SetSelectedLayers { + replacement_selected_layers: vec![vec![rect_id], vec![ellipse_id]], + }); + editor.handle_message(PortfolioMessage::Copy { clipboard: Clipboard::User }); editor.handle_message(DocumentMessage::DeleteSelectedLayers); editor.draw_rect(0., 800., 12., 200.); editor.handle_message(PortfolioMessage::PasteIntoFolder { clipboard: Clipboard::User, - path: vec![], + folder_path: vec![], insert_index: -1, }); editor.handle_message(PortfolioMessage::PasteIntoFolder { clipboard: Clipboard::User, - path: vec![], + folder_path: vec![], insert_index: -1, }); @@ -385,17 +391,19 @@ mod test { ) }; - editor.handle_message(DocumentMessage::SetSelectedLayers(sorted_layers[..2].to_vec())); + editor.handle_message(DocumentMessage::SetSelectedLayers { + replacement_selected_layers: sorted_layers[..2].to_vec(), + }); - editor.handle_message(DocumentMessage::ReorderSelectedLayers(1)); + editor.handle_message(DocumentMessage::ReorderSelectedLayers { relative_index_offset: 1 }); let (all, non_selected, selected) = verify_order(editor.dispatcher.message_handlers.portfolio_message_handler.active_document_mut()); assert_eq!(all, non_selected.into_iter().chain(selected.into_iter()).collect::>()); - editor.handle_message(DocumentMessage::ReorderSelectedLayers(-1)); + editor.handle_message(DocumentMessage::ReorderSelectedLayers { relative_index_offset: -1 }); let (all, non_selected, selected) = verify_order(editor.dispatcher.message_handlers.portfolio_message_handler.active_document_mut()); assert_eq!(all, selected.into_iter().chain(non_selected.into_iter()).collect::>()); - editor.handle_message(DocumentMessage::ReorderSelectedLayers(i32::MAX)); + editor.handle_message(DocumentMessage::ReorderSelectedLayers { relative_index_offset: isize::MAX }); let (all, non_selected, selected) = verify_order(editor.dispatcher.message_handlers.portfolio_message_handler.active_document_mut()); assert_eq!(all, non_selected.into_iter().chain(selected.into_iter()).collect::>()); } diff --git a/editor/src/document/document_message.rs b/editor/src/document/document_message.rs index d14ba0401..76c9cc054 100644 --- a/editor/src/document/document_message.rs +++ b/editor/src/document/document_message.rs @@ -14,14 +14,23 @@ use serde::{Deserialize, Serialize}; #[derive(PartialEq, Clone, Debug, Serialize, Deserialize)] pub enum DocumentMessage { AbortTransaction, - AddSelectedLayers(Vec>), - AlignSelectedLayers(AlignAxis, AlignAggregate), + AddSelectedLayers { + additional_layers: Vec>, + }, + AlignSelectedLayers { + axis: AlignAxis, + aggregate: AlignAggregate, + }, #[child] Artboard(ArtboardMessage), CommitTransaction, - CreateEmptyFolder(Vec), + CreateEmptyFolder { + container_path: Vec, + }, DebugPrintDocument, - DeleteLayer(Vec), + DeleteLayer { + layer_path: Vec, + }, DeleteSelectedLayers, DeselectAllLayers, DirtyRenderDocument, @@ -32,41 +41,78 @@ pub enum DocumentMessage { DocumentStructureChanged, DuplicateSelectedLayers, ExportDocument, - FlipSelectedLayers(FlipAxis), - FolderChanged(Vec), + FlipSelectedLayers { + flip_axis: FlipAxis, + }, + FolderChanged { + affected_folder_path: Vec, + }, GroupSelectedLayers, - LayerChanged(Vec), + LayerChanged { + affected_layer_path: Vec, + }, #[child] Movement(MovementMessage), MoveSelectedLayersTo { - path: Vec, + folder_path: Vec, insert_index: isize, }, - NudgeSelectedLayers(f64, f64), + NudgeSelectedLayers { + delta_x: f64, + delta_y: f64, + }, #[child] Overlays(OverlaysMessage), Redo, - RenameLayer(Vec, String), + RenameLayer { + layer_path: Vec, + new_name: String, + }, RenderDocument, - ReorderSelectedLayers(i32), // relative_position, + ReorderSelectedLayers { + relative_index_offset: isize, + }, RollbackTransaction, SaveDocument, SelectAllLayers, SelectionChanged, - SelectLayer(Vec, bool, bool), - SetBlendModeForSelectedLayers(BlendMode), - SetLayerExpansion(Vec, bool), - SetOpacityForSelectedLayers(f64), - SetSelectedLayers(Vec>), - SetSnapping(bool), - SetViewMode(ViewMode), + SelectLayer { + layer_path: Vec, + ctrl: bool, + shift: bool, + }, + SetBlendModeForSelectedLayers { + blend_mode: BlendMode, + }, + SetLayerExpansion { + layer_path: Vec, + set_expanded: bool, + }, + SetOpacityForSelectedLayers { + opacity: f64, + }, + SetSelectedLayers { + replacement_selected_layers: Vec>, + }, + SetSnapping { + snap: bool, + }, + SetViewMode { + view_mode: ViewMode, + }, StartTransaction, - ToggleLayerExpansion(Vec), - ToggleLayerVisibility(Vec), + ToggleLayerExpansion { + layer_path: Vec, + }, + ToggleLayerVisibility { + layer_path: Vec, + }, #[child] TransformLayers(TransformLayerMessage), Undo, - UngroupLayers(Vec), + UngroupLayers { + folder_path: Vec, + }, UngroupSelectedLayers, UpdateLayerMetadata { layer_path: Vec, diff --git a/editor/src/document/document_message_handler.rs b/editor/src/document/document_message_handler.rs index 74158765c..f1b6fbed4 100644 --- a/editor/src/document/document_message_handler.rs +++ b/editor/src/document/document_message_handler.rs @@ -340,7 +340,7 @@ impl DocumentMessageHandler { let layer_metadata = std::mem::replace(&mut self.layer_metadata, layer_metadata); self.document_redo_history.push((document, layer_metadata)); for layer in self.layer_metadata.keys() { - responses.push_back(DocumentMessage::LayerChanged(layer.clone()).into()) + responses.push_back(DocumentMessage::LayerChanged { affected_layer_path: layer.clone() }.into()) } Ok(()) } @@ -358,7 +358,7 @@ impl DocumentMessageHandler { let layer_metadata = std::mem::replace(&mut self.layer_metadata, layer_metadata); self.document_undo_history.push((document, layer_metadata)); for layer in self.layer_metadata.keys() { - responses.push_back(DocumentMessage::LayerChanged(layer.clone()).into()) + responses.push_back(DocumentMessage::LayerChanged { affected_layer_path: layer.clone() }.into()) } Ok(()) } @@ -446,15 +446,15 @@ impl MessageHandler for Docum self.undo(responses).unwrap_or_else(|e| log::warn!("{}", e)); responses.extend([RenderDocument.into(), DocumentStructureChanged.into()]); } - AddSelectedLayers(paths) => { - for path in paths { - responses.extend(self.select_layer(&path)); + AddSelectedLayers { additional_layers } => { + for layer_path in additional_layers { + responses.extend(self.select_layer(&layer_path)); } // TODO: Correctly update layer panel in clear_selection instead of here - responses.push_back(FolderChanged(Vec::new()).into()); + responses.push_back(FolderChanged { affected_folder_path: vec![] }.into()); responses.push_back(ToolMessage::DocumentIsDirty.into()); } - AlignSelectedLayers(axis, aggregate) => { + AlignSelectedLayers { axis, aggregate } => { self.backup(responses); let (paths, boxes): (Vec<_>, Vec<_>) = self .selected_layers() @@ -499,16 +499,22 @@ impl MessageHandler for Docum ); } CommitTransaction => (), - CreateEmptyFolder(mut path) => { + CreateEmptyFolder { mut container_path } => { let id = generate_uuid(); - path.push(id); - responses.push_back(DocumentOperation::CreateFolder { path: path.clone() }.into()); - responses.push_back(DocumentMessage::SetLayerExpansion(path, true).into()); + container_path.push(id); + responses.push_back(DocumentOperation::CreateFolder { path: container_path.clone() }.into()); + responses.push_back( + DocumentMessage::SetLayerExpansion { + layer_path: container_path, + set_expanded: true, + } + .into(), + ); } DebugPrintDocument => { log::debug!("{:#?}\n{:#?}", self.graphene_document, self.layer_metadata); } - DeleteLayer(path) => responses.push_front(DocumentOperation::DeleteLayer { path }.into()), + DeleteLayer { layer_path } => responses.push_front(DocumentOperation::DeleteLayer { path: layer_path }.into()), DeleteSelectedLayers => { self.backup(responses); @@ -519,7 +525,7 @@ impl MessageHandler for Docum responses.push_front(ToolMessage::DocumentIsDirty.into()); } DeselectAllLayers => { - responses.push_front(SetSelectedLayers(vec![]).into()); + responses.push_front(SetSelectedLayers { replacement_selected_layers: vec![] }.into()); self.layer_range_selection_reference.clear(); } DirtyRenderDocument => { @@ -537,20 +543,25 @@ impl MessageHandler for Docum Ok(Some(document_responses)) => { for response in document_responses { match &response { - DocumentResponse::FolderChanged { path } => responses.push_back(FolderChanged(path.clone()).into()), + DocumentResponse::FolderChanged { path } => responses.push_back(FolderChanged { affected_folder_path: path.clone() }.into()), DocumentResponse::DeletedLayer { path } => { self.layer_metadata.remove(path); } - DocumentResponse::LayerChanged { path } => responses.push_back(LayerChanged(path.clone()).into()), + DocumentResponse::LayerChanged { path } => responses.push_back(LayerChanged { affected_layer_path: path.clone() }.into()), DocumentResponse::CreatedLayer { path } => { if self.layer_metadata.contains_key(path) { log::warn!("CreatedLayer overrides existing layer metadata."); } self.layer_metadata.insert(path.clone(), LayerMetadata::new(false)); - responses.push_back(LayerChanged(path.clone()).into()); + responses.push_back(LayerChanged { affected_layer_path: path.clone() }.into()); self.layer_range_selection_reference = path.clone(); - responses.push_back(AddSelectedLayers(vec![path.clone()]).into()); + responses.push_back( + AddSelectedLayers { + additional_layers: vec![path.clone()], + } + .into(), + ); } DocumentResponse::DocumentChanged => responses.push_back(RenderDocument.into()), }; @@ -596,9 +607,9 @@ impl MessageHandler for Docum .into(), ) } - FlipSelectedLayers(axis) => { + FlipSelectedLayers { flip_axis } => { self.backup(responses); - let scale = match axis { + let scale = match flip_axis { FlipAxis::X => DVec2::new(-1., 1.), FlipAxis::Y => DVec2::new(1., -1.), }; @@ -618,9 +629,10 @@ impl MessageHandler for Docum responses.push_back(ToolMessage::DocumentIsDirty.into()); } } - FolderChanged(path) => { + FolderChanged { affected_folder_path } => { let _ = self.graphene_document.render_root(self.view_mode); - responses.extend([LayerChanged(path).into(), DocumentStructureChanged.into()]); + let affected_layer_path = affected_folder_path; + responses.extend([LayerChanged { affected_layer_path }.into(), DocumentStructureChanged.into()]); } GroupSelectedLayers => { let mut new_folder_path: Vec = self.graphene_document.shallowest_common_folder(self.selected_layers()).unwrap_or(&[]).to_vec(); @@ -632,51 +644,58 @@ impl MessageHandler for Docum new_folder_path.push(generate_uuid()); - responses.push_back(PortfolioMessage::Copy(Clipboard::System).into()); + responses.push_back(PortfolioMessage::Copy { clipboard: Clipboard::System }.into()); responses.push_back(DocumentMessage::DeleteSelectedLayers.into()); responses.push_back(DocumentOperation::CreateFolder { path: new_folder_path.clone() }.into()); - responses.push_back(DocumentMessage::ToggleLayerExpansion(new_folder_path.clone()).into()); + responses.push_back(DocumentMessage::ToggleLayerExpansion { layer_path: new_folder_path.clone() }.into()); responses.push_back( PortfolioMessage::PasteIntoFolder { clipboard: Clipboard::System, - path: new_folder_path.clone(), + folder_path: new_folder_path.clone(), insert_index: -1, } .into(), ); - responses.push_back(DocumentMessage::SetSelectedLayers(vec![new_folder_path]).into()); + responses.push_back( + DocumentMessage::SetSelectedLayers { + replacement_selected_layers: vec![new_folder_path], + } + .into(), + ); } - LayerChanged(path) => { - if let Ok(layer_entry) = self.layer_panel_entry(path) { + LayerChanged { affected_layer_path } => { + if let Ok(layer_entry) = self.layer_panel_entry(affected_layer_path) { responses.push_back(FrontendMessage::UpdateDocumentLayer { data: layer_entry }.into()); } } Movement(message) => self.movement_handler.process_action(message, (&self.graphene_document, ipp), responses), - MoveSelectedLayersTo { path, insert_index } => { - let layers = self.selected_layers().collect::>(); + MoveSelectedLayersTo { folder_path, insert_index } => { + let selected_layers = self.selected_layers().collect::>(); - // Trying to insert into self. - if layers.iter().any(|layer| path.starts_with(layer)) { + // Prevent trying to insert into self + if selected_layers.iter().any(|layer| folder_path.starts_with(layer)) { return; } - let insert_index = self.update_insert_index(&layers, &path, insert_index).unwrap(); - responses.push_back(PortfolioMessage::Copy(Clipboard::System).into()); + + let insert_index = self.update_insert_index(&selected_layers, &folder_path, insert_index).unwrap(); + + responses.push_back(PortfolioMessage::Copy { clipboard: Clipboard::System }.into()); responses.push_back(DocumentMessage::DeleteSelectedLayers.into()); responses.push_back( PortfolioMessage::PasteIntoFolder { clipboard: Clipboard::System, - path, + folder_path, insert_index, } .into(), ); } - NudgeSelectedLayers(x, y) => { + NudgeSelectedLayers { delta_x, delta_y } => { self.backup(responses); for path in self.selected_layers().map(|path| path.to_vec()) { let operation = DocumentOperation::TransformLayerInViewport { path, - transform: DAffine2::from_translation((x, y).into()).to_cols_array(), + transform: DAffine2::from_translation((delta_x, delta_y).into()).to_cols_array(), }; responses.push_back(operation.into()); } @@ -695,9 +714,9 @@ impl MessageHandler for Docum responses.push_back(DocumentHistoryForward.into()); responses.push_back(ToolMessage::DocumentIsDirty.into()); responses.push_back(RenderDocument.into()); - responses.push_back(FolderChanged(vec![]).into()); + responses.push_back(FolderChanged { affected_folder_path: vec![] }.into()); } - RenameLayer(path, name) => responses.push_back(DocumentOperation::RenameLayer { path, name }.into()), + RenameLayer { layer_path, new_name } => responses.push_back(DocumentOperation::RenameLayer { layer_path, new_name }.into()), RenderDocument => { responses.push_back( FrontendMessage::UpdateDocumentArtwork { @@ -743,32 +762,55 @@ impl MessageHandler for Docum .into(), ); } - ReorderSelectedLayers(relative_position) => { + ReorderSelectedLayers { relative_index_offset } => { self.backup(responses); + let all_layer_paths = self.all_layers_sorted(); let selected_layers = self.selected_layers_sorted(); - if let Some(pivot) = match relative_position.signum() { + + let first_or_last_selected_layer = match relative_index_offset.signum() { -1 => selected_layers.first(), 1 => selected_layers.last(), - _ => unreachable!(), - } { - let all_layer_paths: Vec<_> = all_layer_paths + _ => panic!("ReorderSelectedLayers must be given a non-zero value"), + }; + + if let Some(pivot_layer) = first_or_last_selected_layer { + let sibling_layer_paths: Vec<_> = all_layer_paths .iter() - .filter(|layer| layer.starts_with(&pivot[0..pivot.len() - 1]) && pivot.len() == layer.len()) + .filter(|layer| { + // Check if this is a sibling of the pivot layer + // TODO: Break this out into a reusable function `fn are_layers_siblings(layer_a, layer_b) -> bool` + let containing_folder_path = &pivot_layer[0..pivot_layer.len() - 1]; + layer.starts_with(containing_folder_path) && pivot_layer.len() == layer.len() + }) .collect(); - if let Some(pos) = all_layer_paths.iter().position(|path| *path == pivot) { - let max = all_layer_paths.len() as i64 - 1; - let insert_pos = (pos as i64 + relative_position as i64).clamp(0, max) as usize; - let insert = all_layer_paths.get(insert_pos); - if let Some(insert_path) = insert { - let (id, path) = insert_path.split_last().expect("Can't move the root folder"); - if let Some(folder) = self.graphene_document.layer(path).ok().and_then(|layer| layer.as_folder().ok()) { - let layer_index = folder.layer_ids.iter().position(|comparison_id| comparison_id == id).unwrap() as isize; - // If moving down, insert below this layer, if moving up, insert above this layer - let insert_index = if relative_position < 0 { layer_index } else { layer_index + 1 }; + // TODO: Break this out into a reusable function: `fn layer_index_in_containing_folder(layer_path) -> usize` + let pivot_index_among_siblings = sibling_layer_paths.iter().position(|path| *path == pivot_layer); - responses.push_back(DocumentMessage::MoveSelectedLayersTo { path: path.to_vec(), insert_index }.into()); + if let Some(pivot_index) = pivot_index_among_siblings { + let max = sibling_layer_paths.len() as i64 - 1; + let insert_index = (pivot_index as i64 + relative_index_offset as i64).clamp(0, max) as usize; + + let existing_layer_to_insert_beside = sibling_layer_paths.get(insert_index); + + // TODO: Break this block out into a call to a message called `MoveSelectedLayersNextToLayer { neighbor_path, above_or_below }` + if let Some(neighbor_path) = existing_layer_to_insert_beside { + let (neighbor_id, folder_path) = neighbor_path.split_last().expect("Can't move the root folder"); + + if let Some(folder) = self.graphene_document.layer(folder_path).ok().and_then(|layer| layer.as_folder().ok()) { + let neighbor_layer_index = folder.layer_ids.iter().position(|id| id == neighbor_id).unwrap() as isize; + + // If moving down, insert below this layer. If moving up, insert above this layer. + let insert_index = if relative_index_offset < 0 { neighbor_layer_index } else { neighbor_layer_index + 1 }; + + responses.push_back( + DocumentMessage::MoveSelectedLayersTo { + folder_path: folder_path.to_vec(), + insert_index, + } + .into(), + ); } } } @@ -797,14 +839,14 @@ impl MessageHandler for Docum ) } SelectAllLayers => { - let all_layer_paths = self.all_layers(); - responses.push_front(SetSelectedLayers(all_layer_paths.map(|path| path.to_vec()).collect()).into()); + let all = self.all_layers().map(|path| path.to_vec()).collect(); + responses.push_front(SetSelectedLayers { replacement_selected_layers: all }.into()); } SelectionChanged => { // TODO: Hoist this duplicated code into wider system responses.push_back(ToolMessage::DocumentIsDirty.into()); } - SelectLayer(selected, ctrl, shift) => { + SelectLayer { layer_path, ctrl, shift } => { let mut paths = vec![]; let last_selection_exists = !self.layer_range_selection_reference.is_empty(); @@ -813,47 +855,52 @@ impl MessageHandler for Docum // Fill the selection range self.layer_metadata .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, &layer_path, &self.layer_range_selection_reference)) .for_each(|(layer_path, _)| { paths.push(layer_path.clone()); }); } else { if ctrl { // Toggle selection when holding ctrl - let layer = self.layer_metadata_mut(&selected); + let layer = self.layer_metadata_mut(&layer_path); layer.selected = !layer.selected; - responses.push_back(LayerChanged(selected.clone()).into()); + responses.push_back( + LayerChanged { + affected_layer_path: layer_path.clone(), + } + .into(), + ); responses.push_back(ToolMessage::DocumentIsDirty.into()); } else { - paths.push(selected.clone()); + paths.push(layer_path.clone()); } // Set our last selection reference - self.layer_range_selection_reference = selected; + self.layer_range_selection_reference = layer_path; } // Don't create messages for empty operations if !paths.is_empty() { // Add or set our selected layers if ctrl { - responses.push_front(AddSelectedLayers(paths).into()); + responses.push_front(AddSelectedLayers { additional_layers: paths }.into()); } else { - responses.push_front(SetSelectedLayers(paths).into()); + responses.push_front(SetSelectedLayers { replacement_selected_layers: paths }.into()); } } } - SetBlendModeForSelectedLayers(blend_mode) => { + SetBlendModeForSelectedLayers { blend_mode } => { self.backup(responses); for path in self.layer_metadata.iter().filter_map(|(path, data)| data.selected.then(|| path.clone())) { responses.push_back(DocumentOperation::SetLayerBlendMode { path, blend_mode }.into()); } } - SetLayerExpansion(path, is_expanded) => { - self.layer_metadata_mut(&path).expanded = is_expanded; + SetLayerExpansion { layer_path, set_expanded } => { + self.layer_metadata_mut(&layer_path).expanded = set_expanded; responses.push_back(DocumentStructureChanged.into()); - responses.push_back(LayerChanged(path).into()) + responses.push_back(LayerChanged { affected_layer_path: layer_path }.into()) } - SetOpacityForSelectedLayers(opacity) => { + SetOpacityForSelectedLayers { opacity } => { self.backup(responses); let opacity = opacity.clamp(0., 1.); @@ -861,30 +908,31 @@ impl MessageHandler for Docum responses.push_back(DocumentOperation::SetLayerOpacity { path, opacity }.into()); } } - SetSelectedLayers(paths) => { + SetSelectedLayers { replacement_selected_layers } => { let selected = self.layer_metadata.iter_mut().filter(|(_, layer_metadata)| layer_metadata.selected); selected.for_each(|(path, layer_metadata)| { layer_metadata.selected = false; - responses.push_back(LayerChanged(path.clone()).into()) + responses.push_back(LayerChanged { affected_layer_path: path.clone() }.into()) }); - responses.push_front(AddSelectedLayers(paths).into()); + let additional_layers = replacement_selected_layers; + responses.push_front(AddSelectedLayers { additional_layers }.into()); } - SetSnapping(new_status) => { - self.snapping_enabled = new_status; + SetSnapping { snap } => { + self.snapping_enabled = snap; } - SetViewMode(mode) => { - self.view_mode = mode; + SetViewMode { view_mode } => { + self.view_mode = view_mode; responses.push_front(DocumentMessage::DirtyRenderDocument.into()); } StartTransaction => self.backup(responses), - ToggleLayerExpansion(path) => { - self.layer_metadata_mut(&path).expanded ^= true; + ToggleLayerExpansion { layer_path } => { + self.layer_metadata_mut(&layer_path).expanded ^= true; responses.push_back(DocumentStructureChanged.into()); - responses.push_back(LayerChanged(path).into()) + responses.push_back(LayerChanged { affected_layer_path: layer_path }.into()) } - ToggleLayerVisibility(path) => { - responses.push_back(DocumentOperation::ToggleLayerVisibility { path }.into()); + ToggleLayerVisibility { layer_path } => { + responses.push_back(DocumentOperation::ToggleLayerVisibility { path: layer_path }.into()); responses.push_back(ToolMessage::DocumentIsDirty.into()); } TransformLayers(message) => self @@ -895,24 +943,26 @@ impl MessageHandler for Docum responses.push_back(DocumentHistoryBackward.into()); responses.push_back(ToolMessage::DocumentIsDirty.into()); responses.push_back(RenderDocument.into()); - responses.push_back(FolderChanged(vec![]).into()); + responses.push_back(FolderChanged { affected_folder_path: vec![] }.into()); } - UngroupLayers(folder_path) => { + UngroupLayers { folder_path } => { // Select all the children of the folder - let to_select = self.graphene_document.folder_children_paths(&folder_path); + let select = self.graphene_document.folder_children_paths(&folder_path); + let message_buffer = [ + // Select them + DocumentMessage::SetSelectedLayers { replacement_selected_layers: select }.into(), // Copy them - DocumentMessage::SetSelectedLayers(to_select).into(), - PortfolioMessage::Copy(Clipboard::System).into(), + PortfolioMessage::Copy { clipboard: Clipboard::System }.into(), // Paste them into the folder above PortfolioMessage::PasteIntoFolder { clipboard: Clipboard::System, - path: folder_path[..folder_path.len() - 1].to_vec(), + folder_path: folder_path[..folder_path.len() - 1].to_vec(), insert_index: -1, } .into(), - // Delete parent folder - DocumentMessage::DeleteLayer(folder_path).into(), + // Delete the parent folder + DocumentMessage::DeleteLayer { layer_path: folder_path }.into(), ]; // Push these messages in reverse due to push_front @@ -924,12 +974,12 @@ impl MessageHandler for Docum responses.push_back(DocumentMessage::StartTransaction.into()); let folder_paths = self.graphene_document.sorted_folders_by_depth(self.selected_layers()); for folder_path in folder_paths { - responses.push_back(DocumentMessage::UngroupLayers(folder_path.to_vec()).into()); + responses.push_back(DocumentMessage::UngroupLayers { folder_path: folder_path.to_vec() }.into()); } responses.push_back(DocumentMessage::CommitTransaction.into()); } - UpdateLayerMetadata { layer_path: path, layer_metadata } => { - self.layer_metadata.insert(path, layer_metadata); + UpdateLayerMetadata { layer_path, layer_metadata } => { + self.layer_metadata.insert(layer_path, layer_metadata); } ZoomCanvasToFitAll => { if let Some(bounds) = self.document_bounds() { diff --git a/editor/src/document/movement_message.rs b/editor/src/document/movement_message.rs index b71a5e516..6cbf792c2 100644 --- a/editor/src/document/movement_message.rs +++ b/editor/src/document/movement_message.rs @@ -26,12 +26,20 @@ pub enum MovementMessage { zoom_from_viewport: Option, }, RotateCanvasBegin, - SetCanvasRotation(f64), - SetCanvasZoom(f64), + SetCanvasRotation { + angle_radians: f64, + }, + SetCanvasZoom { + zoom_factor: f64, + }, TransformCanvasEnd, - TranslateCanvas(DVec2), + TranslateCanvas { + delta: DVec2, + }, TranslateCanvasBegin, - TranslateCanvasByViewportFraction(DVec2), + TranslateCanvasByViewportFraction { + delta: DVec2, + }, WheelCanvasTranslate { use_y_as_x: bool, }, diff --git a/editor/src/document/movement_message_handler.rs b/editor/src/document/movement_message_handler.rs index dbb22bf96..d49e737f8 100644 --- a/editor/src/document/movement_message_handler.rs +++ b/editor/src/document/movement_message_handler.rs @@ -106,7 +106,7 @@ impl MovementMessageHandler { let mouse_fraction = mouse / viewport_bounds; let delta = delta_size * (DVec2::splat(0.5) - mouse_fraction); - MovementMessage::TranslateCanvas(delta).into() + MovementMessage::TranslateCanvas { delta }.into() } } @@ -122,7 +122,7 @@ impl MessageHandler { - self.tilt = new_radians; + SetCanvasRotation { angle_radians } => { + self.tilt = angle_radians; self.create_document_transform(&ipp.viewport_bounds, responses); responses.push_back(ToolMessage::DocumentIsDirty.into()); responses.push_back(FrontendMessage::UpdateCanvasRotation { angle_radians: self.snapped_angle() }.into()); } - SetCanvasZoom(new) => { - self.zoom = new.clamp(VIEWPORT_ZOOM_SCALE_MIN, VIEWPORT_ZOOM_SCALE_MAX); + SetCanvasZoom { zoom_factor } => { + self.zoom = zoom_factor.clamp(VIEWPORT_ZOOM_SCALE_MIN, VIEWPORT_ZOOM_SCALE_MAX); responses.push_back(FrontendMessage::UpdateCanvasZoom { factor: self.snapped_scale() }.into()); responses.push_back(ToolMessage::DocumentIsDirty.into()); responses.push_back(DocumentMessage::DirtyRenderDocumentInOutlineView.into()); @@ -246,7 +246,7 @@ impl MessageHandler { + TranslateCanvas { delta } => { let transformed_delta = document.root.transform.inverse().transform_vector2(delta); self.pan += transformed_delta; @@ -257,7 +257,7 @@ impl MessageHandler { + TranslateCanvasByViewportFraction { delta } => { let transformed_delta = document.root.transform.inverse().transform_vector2(delta * ipp.viewport_bounds.size()); self.pan += transformed_delta; @@ -269,7 +269,7 @@ impl MessageHandler -ipp.mouse.scroll_delta.as_dvec2(), true => (-ipp.mouse.scroll_delta.y as f64, 0.).into(), } * VIEWPORT_SCROLL_RATE; - responses.push_back(TranslateCanvas(delta).into()); + responses.push_back(TranslateCanvas { delta }.into()); } WheelCanvasZoom => { let scroll = ipp.mouse.scroll_delta.scroll_delta(); @@ -279,7 +279,7 @@ impl MessageHandler { self.zooming = true; diff --git a/editor/src/document/portfolio_message.rs b/editor/src/document/portfolio_message.rs index 71392e0a7..450249bfb 100644 --- a/editor/src/document/portfolio_message.rs +++ b/editor/src/document/portfolio_message.rs @@ -10,14 +10,24 @@ use serde::{Deserialize, Serialize}; #[derive(PartialEq, Clone, Debug, Serialize, Deserialize)] pub enum PortfolioMessage { AutoSaveActiveDocument, - AutoSaveDocument(u64), + AutoSaveDocument { + document_id: u64, + }, CloseActiveDocumentWithConfirmation, CloseAllDocuments, CloseAllDocumentsWithConfirmation, - CloseDocument(u64), - CloseDocumentWithConfirmation(u64), - Copy(Clipboard), - Cut(Clipboard), + CloseDocument { + document_id: u64, + }, + CloseDocumentWithConfirmation { + document_id: u64, + }, + Copy { + clipboard: Clipboard, + }, + Cut { + clipboard: Clipboard, + }, #[child] Document(DocumentMessage), NewDocument, @@ -25,19 +35,23 @@ pub enum PortfolioMessage { OpenDocument, OpenDocumentFile(String, String), OpenDocumentFileWithId { - document: String, - document_name: String, document_id: u64, + document_name: String, document_is_saved: bool, + document_serialized_content: String, + }, + Paste { + clipboard: Clipboard, }, - Paste(Clipboard), PasteIntoFolder { clipboard: Clipboard, - path: Vec, + folder_path: Vec, insert_index: isize, }, PrevDocument, RequestAboutGraphiteDialog, - SelectDocument(u64), + SelectDocument { + document_id: u64, + }, UpdateOpenDocumentsList, } diff --git a/editor/src/document/portfolio_message_handler.rs b/editor/src/document/portfolio_message_handler.rs index 2005af481..e45d91edb 100644 --- a/editor/src/document/portfolio_message_handler.rs +++ b/editor/src/document/portfolio_message_handler.rs @@ -54,7 +54,7 @@ impl PortfolioMessageHandler { fn load_document(&mut self, new_document: DocumentMessageHandler, document_id: u64, replace_first_empty: bool, responses: &mut VecDeque) { // Special case when loading a document on an empty page if replace_first_empty && self.active_document().is_unmodified_default() { - responses.push_back(PortfolioMessage::CloseDocument(self.active_document_id).into()); + responses.push_back(PortfolioMessage::CloseDocument { document_id: self.active_document_id }.into()); let active_document_index = self .document_ids @@ -92,7 +92,7 @@ impl PortfolioMessageHandler { responses.push_back(FrontendMessage::UpdateOpenDocumentsList { open_documents }.into()); - responses.push_back(PortfolioMessage::SelectDocument(document_id).into()); + responses.push_back(PortfolioMessage::SelectDocument { document_id }.into()); } /// Returns an iterator over the open documents in order. @@ -129,15 +129,15 @@ impl MessageHandler for Port use PortfolioMessage::*; #[remain::sorted] match message { - AutoSaveActiveDocument => responses.push_back(PortfolioMessage::AutoSaveDocument(self.active_document_id).into()), - AutoSaveDocument(id) => { - let document = self.documents.get(&id).unwrap(); + AutoSaveActiveDocument => responses.push_back(PortfolioMessage::AutoSaveDocument { document_id: self.active_document_id }.into()), + AutoSaveDocument { document_id } => { + let document = self.documents.get(&document_id).unwrap(); responses.push_back( FrontendMessage::TriggerIndexedDbWriteDocument { document: document.serialize_document(), details: FrontendDocumentDetails { is_saved: document.is_saved(), - id, + id: document_id, name: document.name.clone(), }, version: GRAPHITE_DOCUMENT_VERSION.to_string(), @@ -146,7 +146,7 @@ impl MessageHandler for Port ) } CloseActiveDocumentWithConfirmation => { - responses.push_back(PortfolioMessage::CloseDocumentWithConfirmation(self.active_document_id).into()); + responses.push_back(PortfolioMessage::CloseDocumentWithConfirmation { document_id: self.active_document_id }.into()); } CloseAllDocuments => { // Empty the list of internal document data @@ -159,9 +159,9 @@ impl MessageHandler for Port CloseAllDocumentsWithConfirmation => { responses.push_back(FrontendMessage::DisplayConfirmationToCloseAllDocuments.into()); } - CloseDocument(id) => { - let document_index = self.document_index(id); - self.documents.remove(&id); + CloseDocument { document_id } => { + let document_index = self.document_index(document_id); + self.documents.remove(&document_id); self.document_ids.remove(document_index); // Last tab was closed, so create a new blank tab @@ -171,7 +171,7 @@ impl MessageHandler for Port self.documents.insert(new_id, DocumentMessageHandler::default()); } - self.active_document_id = if id != self.active_document_id { + self.active_document_id = if document_id != self.active_document_id { // If we are not closing the active document, stay on it self.active_document_id } else if document_index >= self.document_ids.len() { @@ -197,24 +197,24 @@ impl MessageHandler for Port responses.push_back(FrontendMessage::UpdateOpenDocumentsList { open_documents }.into()); responses.push_back(FrontendMessage::UpdateActiveDocument { document_id: self.active_document_id }.into()); - responses.push_back(FrontendMessage::TriggerIndexedDbRemoveDocument { document_id: id }.into()); + responses.push_back(FrontendMessage::TriggerIndexedDbRemoveDocument { document_id }.into()); responses.push_back(RenderDocument.into()); responses.push_back(DocumentMessage::DocumentStructureChanged.into()); for layer in self.active_document().layer_metadata.keys() { - responses.push_back(DocumentMessage::LayerChanged(layer.clone()).into()); + responses.push_back(DocumentMessage::LayerChanged { affected_layer_path: layer.clone() }.into()); } } - CloseDocumentWithConfirmation(id) => { - let target_document = self.documents.get(&id).unwrap(); + CloseDocumentWithConfirmation { document_id } => { + let target_document = self.documents.get(&document_id).unwrap(); if target_document.is_saved() { - responses.push_back(PortfolioMessage::CloseDocument(id).into()); + responses.push_back(PortfolioMessage::CloseDocument { document_id }.into()); } else { - responses.push_back(FrontendMessage::DisplayConfirmationToCloseDocument { document_id: id }.into()); + responses.push_back(FrontendMessage::DisplayConfirmationToCloseDocument { document_id }.into()); // Select the document being closed - responses.push_back(PortfolioMessage::SelectDocument(id).into()); + responses.push_back(PortfolioMessage::SelectDocument { document_id }.into()); } } - Copy(clipboard) => { + Copy { clipboard } => { // We can't use `self.active_document()` because it counts as an immutable borrow of the entirety of `self` let active_document = self.documents.get(&self.active_document_id).unwrap(); @@ -230,8 +230,8 @@ impl MessageHandler for Port } } } - Cut(clipboard) => { - responses.push_back(Copy(clipboard).into()); + Cut { clipboard } => { + responses.push_back(Copy { clipboard }.into()); responses.push_back(DeleteSelectedLayers.into()); } Document(message) => self.active_document_mut().process_action(message, ipp, responses), @@ -246,29 +246,29 @@ impl MessageHandler for Port let current_index = self.document_index(self.active_document_id); let next_index = (current_index + 1) % self.document_ids.len(); let next_id = self.document_ids[next_index]; - responses.push_back(PortfolioMessage::SelectDocument(next_id).into()); + responses.push_back(PortfolioMessage::SelectDocument { document_id: next_id }.into()); } OpenDocument => { responses.push_back(FrontendMessage::TriggerFileUpload.into()); } - OpenDocumentFile(document_name, document) => { + OpenDocumentFile(document_name, document_serialized_content) => { responses.push_back( PortfolioMessage::OpenDocumentFileWithId { - document, - document_name, document_id: generate_uuid(), + document_name, document_is_saved: true, + document_serialized_content, } .into(), ); } OpenDocumentFileWithId { - document_name, document_id, - document, + document_name, document_is_saved, + document_serialized_content, } => { - let document = DocumentMessageHandler::with_name_and_content(document_name, document); + let document = DocumentMessageHandler::with_name_and_content(document_name, document_serialized_content); match document { Ok(mut document) => { document.set_save_state(document_is_saved); @@ -283,7 +283,7 @@ impl MessageHandler for Port ), } } - Paste(clipboard) => { + Paste { clipboard } => { let document = self.active_document(); let shallowest_common_folder = document .graphene_document @@ -294,14 +294,18 @@ impl MessageHandler for Port responses.push_back( PasteIntoFolder { clipboard, - path: shallowest_common_folder.to_vec(), + folder_path: shallowest_common_folder.to_vec(), insert_index: -1, } .into(), ); responses.push_back(CommitTransaction.into()); } - PasteIntoFolder { clipboard, path, insert_index } => { + PasteIntoFolder { + clipboard, + folder_path: path, + insert_index, + } => { let paste = |entry: &CopyBufferEntry, responses: &mut VecDeque<_>| { log::trace!("Pasting into folder {:?} as index: {}", &path, insert_index); @@ -339,22 +343,22 @@ impl MessageHandler for Port let current_index = self.document_index(self.active_document_id); let prev_index = (current_index + len - 1) % len; let prev_id = self.document_ids[prev_index]; - responses.push_back(PortfolioMessage::SelectDocument(prev_id).into()); + responses.push_back(PortfolioMessage::SelectDocument { document_id: prev_id }.into()); } RequestAboutGraphiteDialog => { responses.push_back(FrontendMessage::DisplayDialogAboutGraphite.into()); } - SelectDocument(id) => { + SelectDocument { document_id } => { let active_document = self.active_document(); if !active_document.is_saved() { - responses.push_back(PortfolioMessage::AutoSaveDocument(self.active_document_id).into()); + responses.push_back(PortfolioMessage::AutoSaveDocument { document_id: self.active_document_id }.into()); } - self.active_document_id = id; - responses.push_back(FrontendMessage::UpdateActiveDocument { document_id: id }.into()); + self.active_document_id = document_id; + responses.push_back(FrontendMessage::UpdateActiveDocument { document_id }.into()); responses.push_back(RenderDocument.into()); responses.push_back(DocumentMessage::DocumentStructureChanged.into()); for layer in self.active_document().layer_metadata.keys() { - responses.push_back(DocumentMessage::LayerChanged(layer.clone()).into()); + responses.push_back(DocumentMessage::LayerChanged { affected_layer_path: layer.clone() }.into()); } responses.push_back(ToolMessage::DocumentIsDirty.into()); } diff --git a/editor/src/document/transform_layer_message.rs b/editor/src/document/transform_layer_message.rs index 638dc7839..ab2a73c54 100644 --- a/editor/src/document/transform_layer_message.rs +++ b/editor/src/document/transform_layer_message.rs @@ -17,6 +17,6 @@ pub enum TransformLayerMessage { MouseMove { slow_key: Key, snap_key: Key }, TypeBackspace, TypeDecimalPoint, + TypeDigit { digit: u8 }, TypeNegate, - TypeNumber(u8), } diff --git a/editor/src/document/transform_layer_message_handler.rs b/editor/src/document/transform_layer_message_handler.rs index c47f7fda0..b7d0cf272 100644 --- a/editor/src/document/transform_layer_message_handler.rs +++ b/editor/src/document/transform_layer_message_handler.rs @@ -157,8 +157,8 @@ impl MessageHandler, LayerMeta } TypeBackspace => self.transform_operation.handle_typed(self.typing.type_backspace(), &mut selected, self.snap), TypeDecimalPoint => self.transform_operation.handle_typed(self.typing.type_decimal_point(), &mut selected, self.snap), + TypeDigit { digit } => self.transform_operation.handle_typed(self.typing.type_number(digit), &mut selected, self.snap), TypeNegate => self.transform_operation.handle_typed(self.typing.type_negate(), &mut selected, self.snap), - TypeNumber(number) => self.transform_operation.handle_typed(self.typing.type_number(number), &mut selected, self.snap), } } @@ -174,7 +174,7 @@ impl MessageHandler, LayerMeta MouseMove, CancelTransformOperation, ApplyTransformOperation, - TypeNumber, + TypeDigit, TypeBackspace, TypeDecimalPoint, TypeNegate, diff --git a/editor/src/input/input_mapper.rs b/editor/src/input/input_mapper.rs index 66a981e87..c66c6e265 100644 --- a/editor/src/input/input_mapper.rs +++ b/editor/src/input/input_mapper.rs @@ -27,7 +27,7 @@ impl Default for Mapping { let mappings = mapping![ // Higher priority than entries in sections below - entry! {action=PortfolioMessage::Paste(Clipboard::User), key_down=KeyV, modifiers=[KeyControl]}, + entry! {action=PortfolioMessage::Paste { clipboard: Clipboard::User }, key_down=KeyV, modifiers=[KeyControl]}, // Transform layers entry! {action=TransformLayerMessage::ApplyTransformOperation, key_down=KeyEnter}, entry! {action=TransformLayerMessage::ApplyTransformOperation, key_down=Lmb}, @@ -98,28 +98,28 @@ impl Default for Mapping { entry! {action=FillMessage::LeftMouseDown, key_down=Lmb}, entry! {action=FillMessage::RightMouseDown, key_down=Rmb}, // Tool Actions - entry! {action=ToolMessage::ActivateTool(ToolType::Select), key_down=KeyV}, - entry! {action=ToolMessage::ActivateTool(ToolType::Navigate), key_down=KeyZ}, - entry! {action=ToolMessage::ActivateTool(ToolType::Eyedropper), key_down=KeyI}, - entry! {action=ToolMessage::ActivateTool(ToolType::Fill), key_down=KeyF}, - entry! {action=ToolMessage::ActivateTool(ToolType::Path), key_down=KeyA}, - entry! {action=ToolMessage::ActivateTool(ToolType::Pen), key_down=KeyP}, - entry! {action=ToolMessage::ActivateTool(ToolType::Line), key_down=KeyL}, - entry! {action=ToolMessage::ActivateTool(ToolType::Rectangle), key_down=KeyM}, - entry! {action=ToolMessage::ActivateTool(ToolType::Ellipse), key_down=KeyE}, - entry! {action=ToolMessage::ActivateTool(ToolType::Shape), key_down=KeyY}, + entry! {action=ToolMessage::ActivateTool { tool_type: ToolType::Select }, key_down=KeyV}, + entry! {action=ToolMessage::ActivateTool { tool_type: ToolType::Navigate }, key_down=KeyZ}, + entry! {action=ToolMessage::ActivateTool { tool_type: ToolType::Eyedropper }, key_down=KeyI}, + entry! {action=ToolMessage::ActivateTool { tool_type: ToolType::Fill }, key_down=KeyF}, + entry! {action=ToolMessage::ActivateTool { tool_type: ToolType::Path }, key_down=KeyA}, + entry! {action=ToolMessage::ActivateTool { tool_type: ToolType::Pen }, key_down=KeyP}, + entry! {action=ToolMessage::ActivateTool { tool_type: ToolType::Line }, key_down=KeyL}, + entry! {action=ToolMessage::ActivateTool { tool_type: ToolType::Rectangle }, key_down=KeyM}, + entry! {action=ToolMessage::ActivateTool { tool_type: ToolType::Ellipse }, key_down=KeyE}, + entry! {action=ToolMessage::ActivateTool { tool_type: ToolType::Shape }, key_down=KeyY}, // Colors entry! {action=ToolMessage::ResetColors, key_down=KeyX, modifiers=[KeyShift, KeyControl]}, entry! {action=ToolMessage::SwapColors, key_down=KeyX, modifiers=[KeyShift]}, // Editor Actions entry! {action=FrontendMessage::TriggerFileUpload, key_down=KeyO, modifiers=[KeyControl]}, // Document Actions - entry! {action=PortfolioMessage::Paste(Clipboard::User), key_down=KeyV, modifiers=[KeyControl]}, + entry! {action=PortfolioMessage::Paste { clipboard: Clipboard::User }, key_down=KeyV, modifiers=[KeyControl]}, entry! {action=DocumentMessage::Redo, key_down=KeyZ, modifiers=[KeyControl, KeyShift]}, entry! {action=DocumentMessage::Undo, key_down=KeyZ, modifiers=[KeyControl]}, entry! {action=DocumentMessage::DeselectAllLayers, key_down=KeyA, modifiers=[KeyControl, KeyAlt]}, entry! {action=DocumentMessage::SelectAllLayers, key_down=KeyA, modifiers=[KeyControl]}, - entry! {action=DocumentMessage::CreateEmptyFolder(vec![]), key_down=KeyN, modifiers=[KeyControl, KeyShift]}, + entry! {action=DocumentMessage::CreateEmptyFolder { container_path: vec![] }, key_down=KeyN, modifiers=[KeyControl, KeyShift]}, entry! {action=DocumentMessage::DeleteSelectedLayers, key_down=KeyDelete}, entry! {action=DocumentMessage::DeleteSelectedLayers, key_down=KeyX}, entry! {action=DocumentMessage::DeleteSelectedLayers, key_down=KeyBackspace}, @@ -143,15 +143,15 @@ impl Default for Mapping { entry! {action=MovementMessage::IncreaseCanvasZoom { center_on_mouse: false }, key_down=KeyPlus, modifiers=[KeyControl]}, entry! {action=MovementMessage::IncreaseCanvasZoom { center_on_mouse: false }, key_down=KeyEquals, modifiers=[KeyControl]}, entry! {action=MovementMessage::DecreaseCanvasZoom { center_on_mouse: false }, key_down=KeyMinus, modifiers=[KeyControl]}, - entry! {action=MovementMessage::SetCanvasZoom(1.), key_down=Key1, modifiers=[KeyControl]}, - entry! {action=MovementMessage::SetCanvasZoom(2.), key_down=Key2, modifiers=[KeyControl]}, + entry! {action=MovementMessage::SetCanvasZoom { zoom_factor: 1. }, key_down=Key1, modifiers=[KeyControl]}, + entry! {action=MovementMessage::SetCanvasZoom { zoom_factor: 2. }, key_down=Key2, modifiers=[KeyControl]}, entry! {action=MovementMessage::WheelCanvasZoom, message=InputMapperMessage::MouseScroll, modifiers=[KeyControl]}, entry! {action=MovementMessage::WheelCanvasTranslate { use_y_as_x: true }, message=InputMapperMessage::MouseScroll, modifiers=[KeyShift]}, entry! {action=MovementMessage::WheelCanvasTranslate { use_y_as_x: false }, message=InputMapperMessage::MouseScroll}, - entry! {action=MovementMessage::TranslateCanvasByViewportFraction(DVec2::new(1., 0.)), key_down=KeyPageUp, modifiers=[KeyShift]}, - entry! {action=MovementMessage::TranslateCanvasByViewportFraction(DVec2::new(-1., 0.)), key_down=KeyPageDown, modifiers=[KeyShift]}, - entry! {action=MovementMessage::TranslateCanvasByViewportFraction(DVec2::new(0., 1.)), key_down=KeyPageUp}, - entry! {action=MovementMessage::TranslateCanvasByViewportFraction(DVec2::new(0., -1.)), key_down=KeyPageDown}, + entry! {action=MovementMessage::TranslateCanvasByViewportFraction { delta: DVec2::new(1., 0.) }, key_down=KeyPageUp, modifiers=[KeyShift]}, + entry! {action=MovementMessage::TranslateCanvasByViewportFraction { delta: DVec2::new(-1., 0.) }, key_down=KeyPageDown, modifiers=[KeyShift]}, + entry! {action=MovementMessage::TranslateCanvasByViewportFraction { delta: DVec2::new(0., 1.) }, key_down=KeyPageUp}, + entry! {action=MovementMessage::TranslateCanvasByViewportFraction { delta: DVec2::new(0., -1.) }, key_down=KeyPageDown}, // Document actions entry! {action=PortfolioMessage::NewDocument, key_down=KeyN, modifiers=[KeyControl]}, entry! {action=PortfolioMessage::NextDocument, key_down=KeyTab, modifiers=[KeyControl]}, @@ -159,58 +159,60 @@ impl Default for Mapping { entry! {action=PortfolioMessage::CloseAllDocumentsWithConfirmation, key_down=KeyW, modifiers=[KeyControl, KeyAlt]}, entry! {action=PortfolioMessage::CloseActiveDocumentWithConfirmation, key_down=KeyW, modifiers=[KeyControl]}, entry! {action=DocumentMessage::DuplicateSelectedLayers, key_down=KeyD, modifiers=[KeyControl]}, - entry! {action=PortfolioMessage::Copy(Clipboard::User), key_down=KeyC, modifiers=[KeyControl]}, - entry! {action=PortfolioMessage::Cut(Clipboard::User), key_down=KeyX, modifiers=[KeyControl]}, + entry! {action=PortfolioMessage::Copy { clipboard: Clipboard::User }, key_down=KeyC, modifiers=[KeyControl]}, + entry! {action=PortfolioMessage::Cut { clipboard: Clipboard::User }, key_down=KeyX, modifiers=[KeyControl]}, entry! {action=DocumentMessage::GroupSelectedLayers, key_down=KeyG, modifiers=[KeyControl]}, entry! {action=DocumentMessage::UngroupSelectedLayers, key_down=KeyG, modifiers=[KeyControl, KeyShift]}, // Nudging - entry! {action=DocumentMessage::NudgeSelectedLayers(-SHIFT_NUDGE_AMOUNT, -SHIFT_NUDGE_AMOUNT), key_down=KeyArrowUp, modifiers=[KeyShift, KeyArrowLeft]}, - entry! {action=DocumentMessage::NudgeSelectedLayers(SHIFT_NUDGE_AMOUNT, -SHIFT_NUDGE_AMOUNT), key_down=KeyArrowUp, modifiers=[KeyShift, KeyArrowRight]}, - entry! {action=DocumentMessage::NudgeSelectedLayers(0., -SHIFT_NUDGE_AMOUNT), key_down=KeyArrowUp, modifiers=[KeyShift]}, - entry! {action=DocumentMessage::NudgeSelectedLayers(-SHIFT_NUDGE_AMOUNT, SHIFT_NUDGE_AMOUNT), key_down=KeyArrowDown, modifiers=[KeyShift, KeyArrowLeft]}, - entry! {action=DocumentMessage::NudgeSelectedLayers(SHIFT_NUDGE_AMOUNT, SHIFT_NUDGE_AMOUNT), key_down=KeyArrowDown, modifiers=[KeyShift, KeyArrowRight]}, - entry! {action=DocumentMessage::NudgeSelectedLayers(0., SHIFT_NUDGE_AMOUNT), key_down=KeyArrowDown, modifiers=[KeyShift]}, - entry! {action=DocumentMessage::NudgeSelectedLayers(-SHIFT_NUDGE_AMOUNT, -SHIFT_NUDGE_AMOUNT), key_down=KeyArrowLeft, modifiers=[KeyShift, KeyArrowUp]}, - entry! {action=DocumentMessage::NudgeSelectedLayers(-SHIFT_NUDGE_AMOUNT, SHIFT_NUDGE_AMOUNT), key_down=KeyArrowLeft, modifiers=[KeyShift, KeyArrowDown]}, - entry! {action=DocumentMessage::NudgeSelectedLayers(-SHIFT_NUDGE_AMOUNT, 0.), key_down=KeyArrowLeft, modifiers=[KeyShift]}, - entry! {action=DocumentMessage::NudgeSelectedLayers(SHIFT_NUDGE_AMOUNT, -SHIFT_NUDGE_AMOUNT), key_down=KeyArrowRight, modifiers=[KeyShift, KeyArrowUp]}, - entry! {action=DocumentMessage::NudgeSelectedLayers(SHIFT_NUDGE_AMOUNT, SHIFT_NUDGE_AMOUNT), key_down=KeyArrowRight, modifiers=[KeyShift, KeyArrowDown]}, - entry! {action=DocumentMessage::NudgeSelectedLayers(SHIFT_NUDGE_AMOUNT, 0.), key_down=KeyArrowRight, modifiers=[KeyShift]}, - entry! {action=DocumentMessage::NudgeSelectedLayers(-NUDGE_AMOUNT, -NUDGE_AMOUNT), key_down=KeyArrowUp, modifiers=[KeyArrowLeft]}, - entry! {action=DocumentMessage::NudgeSelectedLayers(NUDGE_AMOUNT, -NUDGE_AMOUNT), key_down=KeyArrowUp, modifiers=[KeyArrowRight]}, - entry! {action=DocumentMessage::NudgeSelectedLayers(0., -NUDGE_AMOUNT), key_down=KeyArrowUp}, - entry! {action=DocumentMessage::NudgeSelectedLayers(-NUDGE_AMOUNT, NUDGE_AMOUNT), key_down=KeyArrowDown, modifiers=[KeyArrowLeft]}, - entry! {action=DocumentMessage::NudgeSelectedLayers(NUDGE_AMOUNT, NUDGE_AMOUNT), key_down=KeyArrowDown, modifiers=[KeyArrowRight]}, - entry! {action=DocumentMessage::NudgeSelectedLayers(0., NUDGE_AMOUNT), key_down=KeyArrowDown}, - entry! {action=DocumentMessage::NudgeSelectedLayers(-NUDGE_AMOUNT, -NUDGE_AMOUNT), key_down=KeyArrowLeft, modifiers=[KeyArrowUp]}, - entry! {action=DocumentMessage::NudgeSelectedLayers(-NUDGE_AMOUNT, NUDGE_AMOUNT), key_down=KeyArrowLeft, modifiers=[KeyArrowDown]}, - entry! {action=DocumentMessage::NudgeSelectedLayers(-NUDGE_AMOUNT, 0.), key_down=KeyArrowLeft}, - entry! {action=DocumentMessage::NudgeSelectedLayers(NUDGE_AMOUNT, -NUDGE_AMOUNT), key_down=KeyArrowRight, modifiers=[KeyArrowUp]}, - entry! {action=DocumentMessage::NudgeSelectedLayers(NUDGE_AMOUNT, NUDGE_AMOUNT), key_down=KeyArrowRight, modifiers=[KeyArrowDown]}, - entry! {action=DocumentMessage::NudgeSelectedLayers(NUDGE_AMOUNT, 0.), key_down=KeyArrowRight}, + entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: -SHIFT_NUDGE_AMOUNT, delta_y: -SHIFT_NUDGE_AMOUNT }, key_down=KeyArrowUp, modifiers=[KeyShift, KeyArrowLeft]}, + entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: SHIFT_NUDGE_AMOUNT, delta_y: -SHIFT_NUDGE_AMOUNT }, key_down=KeyArrowUp, modifiers=[KeyShift, KeyArrowRight]}, + entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: 0., delta_y: -SHIFT_NUDGE_AMOUNT }, key_down=KeyArrowUp, modifiers=[KeyShift]}, + entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: -SHIFT_NUDGE_AMOUNT, delta_y: SHIFT_NUDGE_AMOUNT }, key_down=KeyArrowDown, modifiers=[KeyShift, KeyArrowLeft]}, + entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: SHIFT_NUDGE_AMOUNT, delta_y: SHIFT_NUDGE_AMOUNT }, key_down=KeyArrowDown, modifiers=[KeyShift, KeyArrowRight]}, + entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: 0., delta_y: SHIFT_NUDGE_AMOUNT }, key_down=KeyArrowDown, modifiers=[KeyShift]}, + entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: -SHIFT_NUDGE_AMOUNT, delta_y: -SHIFT_NUDGE_AMOUNT }, key_down=KeyArrowLeft, modifiers=[KeyShift, KeyArrowUp]}, + entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: -SHIFT_NUDGE_AMOUNT, delta_y: SHIFT_NUDGE_AMOUNT }, key_down=KeyArrowLeft, modifiers=[KeyShift, KeyArrowDown]}, + entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: -SHIFT_NUDGE_AMOUNT, delta_y: 0. }, key_down=KeyArrowLeft, modifiers=[KeyShift]}, + entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: SHIFT_NUDGE_AMOUNT, delta_y: -SHIFT_NUDGE_AMOUNT }, key_down=KeyArrowRight, modifiers=[KeyShift, KeyArrowUp]}, + entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: SHIFT_NUDGE_AMOUNT, delta_y: SHIFT_NUDGE_AMOUNT }, key_down=KeyArrowRight, modifiers=[KeyShift, KeyArrowDown]}, + entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: SHIFT_NUDGE_AMOUNT, delta_y: 0. }, key_down=KeyArrowRight, modifiers=[KeyShift]}, + entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: -NUDGE_AMOUNT, delta_y: -NUDGE_AMOUNT }, key_down=KeyArrowUp, modifiers=[KeyArrowLeft]}, + entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: NUDGE_AMOUNT, delta_y: -NUDGE_AMOUNT }, key_down=KeyArrowUp, modifiers=[KeyArrowRight]}, + entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: 0., delta_y: -NUDGE_AMOUNT }, key_down=KeyArrowUp}, + entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: -NUDGE_AMOUNT, delta_y: NUDGE_AMOUNT }, key_down=KeyArrowDown, modifiers=[KeyArrowLeft]}, + entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: NUDGE_AMOUNT, delta_y: NUDGE_AMOUNT }, key_down=KeyArrowDown, modifiers=[KeyArrowRight]}, + entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: 0., delta_y: NUDGE_AMOUNT }, key_down=KeyArrowDown}, + entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: -NUDGE_AMOUNT, delta_y: -NUDGE_AMOUNT }, key_down=KeyArrowLeft, modifiers=[KeyArrowUp]}, + entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: -NUDGE_AMOUNT, delta_y: NUDGE_AMOUNT }, key_down=KeyArrowLeft, modifiers=[KeyArrowDown]}, + entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: -NUDGE_AMOUNT, delta_y: 0. }, key_down=KeyArrowLeft}, + entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: NUDGE_AMOUNT, delta_y: -NUDGE_AMOUNT }, key_down=KeyArrowRight, modifiers=[KeyArrowUp]}, + entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: NUDGE_AMOUNT, delta_y: NUDGE_AMOUNT }, key_down=KeyArrowRight, modifiers=[KeyArrowDown]}, + entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: NUDGE_AMOUNT, delta_y: 0. }, key_down=KeyArrowRight}, // Reorder Layers - entry! {action=DocumentMessage::ReorderSelectedLayers(i32::MAX), key_down=KeyRightCurlyBracket, modifiers=[KeyControl]}, // TODO: Use KeyRightBracket with ctrl+shift modifiers once input system is fixed - entry! {action=DocumentMessage::ReorderSelectedLayers(1), key_down=KeyRightBracket, modifiers=[KeyControl]}, - entry! {action=DocumentMessage::ReorderSelectedLayers(-1), key_down=KeyLeftBracket, modifiers=[KeyControl]}, - entry! {action=DocumentMessage::ReorderSelectedLayers(i32::MIN), key_down=KeyLeftCurlyBracket, modifiers=[KeyControl]}, // TODO: Use KeyLeftBracket with ctrl+shift modifiers once input system is fixed + entry! {action=DocumentMessage::ReorderSelectedLayers { relative_index_offset: isize::MAX }, key_down=KeyRightCurlyBracket, modifiers=[KeyControl]}, // TODO: Use KeyRightBracket with ctrl+shift modifiers once input system is fixed + entry! {action=DocumentMessage::ReorderSelectedLayers { relative_index_offset: 1 }, key_down=KeyRightBracket, modifiers=[KeyControl]}, + entry! {action=DocumentMessage::ReorderSelectedLayers { relative_index_offset: -1 }, key_down=KeyLeftBracket, modifiers=[KeyControl]}, + entry! {action=DocumentMessage::ReorderSelectedLayers { relative_index_offset: isize::MIN }, key_down=KeyLeftCurlyBracket, modifiers=[KeyControl]}, // TODO: Use KeyLeftBracket with ctrl+shift modifiers once input system is fixed // Global Actions entry! {action=GlobalMessage::LogInfo, key_down=Key1}, entry! {action=GlobalMessage::LogDebug, key_down=Key2}, entry! {action=GlobalMessage::LogTrace, key_down=Key3}, ]; - let (mut key_up, mut key_down, mut pointer_move, mut mouse_scroll) = mappings; + + // TODO: Hardcode these 10 lines into 10 lines of declarations, or make this use a macro to do all 10 in one line const NUMBER_KEYS: [Key; 10] = [Key0, Key1, Key2, Key3, Key4, Key5, Key6, Key7, Key8, Key9]; for (i, key) in NUMBER_KEYS.iter().enumerate() { key_down[*key as usize].0.insert( 0, MappingEntry { + action: TransformLayerMessage::TypeDigit { digit: i as u8 }.into(), trigger: InputMapperMessage::KeyDown(*key), modifiers: modifiers! {}, - action: TransformLayerMessage::TypeNumber(i as u8).into(), }, ); } + let sort = |list: &mut KeyMappingEntries| list.0.sort_by(|u, v| v.modifiers.ones().cmp(&u.modifiers.ones())); for list in [&mut key_up, &mut key_down] { for sublist in list { @@ -219,6 +221,7 @@ impl Default for Mapping { } sort(&mut pointer_move); sort(&mut mouse_scroll); + Self { key_up, key_down, diff --git a/editor/src/input/input_preprocessor.rs b/editor/src/input/input_preprocessor.rs index 24f9aefb5..2bb4ba6a3 100644 --- a/editor/src/input/input_preprocessor.rs +++ b/editor/src/input/input_preprocessor.rs @@ -23,19 +23,20 @@ bitflags! { mod test { use crate::input::input_preprocessor::ModifierKeys; use crate::input::keyboard::Key; - use crate::input::mouse::{EditorMouseState, ViewportPosition}; - use crate::input::InputPreprocessorMessageHandler; + use crate::input::mouse::EditorMouseState; + use crate::input::{InputMapperMessage, InputPreprocessorMessage, InputPreprocessorMessageHandler}; use crate::message_prelude::MessageHandler; - use crate::message_prelude::*; use std::collections::VecDeque; #[test] fn process_action_mouse_move_handle_modifier_keys() { let mut input_preprocessor = InputPreprocessorMessageHandler::default(); - let mut editor_mouse_state = EditorMouseState::new(); - editor_mouse_state.editor_position = ViewportPosition::new(4., 809.); - let message = InputPreprocessorMessage::MouseMove(editor_mouse_state, ModifierKeys::ALT); + + let editor_mouse_state = EditorMouseState::from_editor_position(4., 809.); + let modifier_keys = ModifierKeys::ALT; + let message = InputPreprocessorMessage::MouseMove { editor_mouse_state, modifier_keys }; + let mut responses = VecDeque::new(); input_preprocessor.process_action(message, (), &mut responses); @@ -47,7 +48,11 @@ mod test { #[test] fn process_action_mouse_down_handle_modifier_keys() { let mut input_preprocessor = InputPreprocessorMessageHandler::default(); - let message = InputPreprocessorMessage::MouseDown(EditorMouseState::new(), ModifierKeys::CONTROL); + + let editor_mouse_state = EditorMouseState::new(); + let modifier_keys = ModifierKeys::CONTROL; + let message = InputPreprocessorMessage::MouseDown { editor_mouse_state, modifier_keys }; + let mut responses = VecDeque::new(); input_preprocessor.process_action(message, (), &mut responses); @@ -59,7 +64,11 @@ mod test { #[test] fn process_action_mouse_up_handle_modifier_keys() { let mut input_preprocessor = InputPreprocessorMessageHandler::default(); - let message = InputPreprocessorMessage::MouseUp(EditorMouseState::new(), ModifierKeys::SHIFT); + + let editor_mouse_state = EditorMouseState::new(); + let modifier_keys = ModifierKeys::SHIFT; + let message = InputPreprocessorMessage::MouseUp { editor_mouse_state, modifier_keys }; + let mut responses = VecDeque::new(); input_preprocessor.process_action(message, (), &mut responses); @@ -72,7 +81,11 @@ mod test { fn process_action_key_down_handle_modifier_keys() { let mut input_preprocessor = InputPreprocessorMessageHandler::default(); input_preprocessor.keyboard.set(Key::KeyControl as usize); - let message = InputPreprocessorMessage::KeyDown(Key::KeyA, ModifierKeys::empty()); + + let key = Key::KeyA; + let modifier_keys = ModifierKeys::empty(); + let message = InputPreprocessorMessage::KeyDown { key, modifier_keys }; + let mut responses = VecDeque::new(); input_preprocessor.process_action(message, (), &mut responses); @@ -84,7 +97,11 @@ mod test { #[test] fn process_action_key_up_handle_modifier_keys() { let mut input_preprocessor = InputPreprocessorMessageHandler::default(); - let message = InputPreprocessorMessage::KeyUp(Key::KeyS, ModifierKeys::CONTROL | ModifierKeys::SHIFT); + + let key = Key::KeyS; + let modifier_keys = ModifierKeys::CONTROL | ModifierKeys::SHIFT; + let message = InputPreprocessorMessage::KeyUp { key, modifier_keys }; + let mut responses = VecDeque::new(); input_preprocessor.process_action(message, (), &mut responses); diff --git a/editor/src/input/input_preprocessor_message.rs b/editor/src/input/input_preprocessor_message.rs index 001431a02..04c287c81 100644 --- a/editor/src/input/input_preprocessor_message.rs +++ b/editor/src/input/input_preprocessor_message.rs @@ -12,11 +12,11 @@ use serde::{Deserialize, Serialize}; #[impl_message(Message, InputPreprocessor)] #[derive(PartialEq, Clone, Debug, Serialize, Deserialize)] pub enum InputPreprocessorMessage { - BoundsOfViewports(Vec), - KeyDown(Key, ModifierKeys), - KeyUp(Key, ModifierKeys), - MouseDown(EditorMouseState, ModifierKeys), - MouseMove(EditorMouseState, ModifierKeys), - MouseScroll(EditorMouseState, ModifierKeys), - MouseUp(EditorMouseState, ModifierKeys), + BoundsOfViewports { bounds_of_viewports: Vec }, + KeyDown { key: Key, modifier_keys: ModifierKeys }, + KeyUp { key: Key, modifier_keys: ModifierKeys }, + MouseDown { editor_mouse_state: EditorMouseState, modifier_keys: ModifierKeys }, + MouseMove { editor_mouse_state: EditorMouseState, modifier_keys: ModifierKeys }, + MouseScroll { editor_mouse_state: EditorMouseState, modifier_keys: ModifierKeys }, + MouseUp { editor_mouse_state: EditorMouseState, modifier_keys: ModifierKeys }, } diff --git a/editor/src/input/input_preprocessor_message_handler.rs b/editor/src/input/input_preprocessor_message_handler.rs index b426f26b0..536c3d5fa 100644 --- a/editor/src/input/input_preprocessor_message_handler.rs +++ b/editor/src/input/input_preprocessor_message_handler.rs @@ -18,7 +18,7 @@ impl MessageHandler for InputPreprocessorMessageHa fn process_action(&mut self, message: InputPreprocessorMessage, _data: (), responses: &mut VecDeque) { #[remain::sorted] match message { - InputPreprocessorMessage::BoundsOfViewports(bounds_of_viewports) => { + InputPreprocessorMessage::BoundsOfViewports { bounds_of_viewports } => { assert_eq!(bounds_of_viewports.len(), 1, "Only one viewport is currently supported"); for bounds in bounds_of_viewports { @@ -59,17 +59,17 @@ impl MessageHandler for InputPreprocessorMessageHa ); } } - InputPreprocessorMessage::KeyDown(key, modifier_keys) => { + InputPreprocessorMessage::KeyDown { key, modifier_keys } => { self.handle_modifier_keys(modifier_keys, responses); self.keyboard.set(key as usize); responses.push_back(InputMapperMessage::KeyDown(key).into()); } - InputPreprocessorMessage::KeyUp(key, modifier_keys) => { + InputPreprocessorMessage::KeyUp { key, modifier_keys } => { self.handle_modifier_keys(modifier_keys, responses); self.keyboard.unset(key as usize); responses.push_back(InputMapperMessage::KeyUp(key).into()); } - InputPreprocessorMessage::MouseDown(editor_mouse_state, modifier_keys) => { + InputPreprocessorMessage::MouseDown { editor_mouse_state, modifier_keys } => { self.handle_modifier_keys(modifier_keys, responses); let mouse_state = editor_mouse_state.to_mouse_state(&self.viewport_bounds); @@ -79,7 +79,7 @@ impl MessageHandler for InputPreprocessorMessageHa responses.push_back(message); } } - InputPreprocessorMessage::MouseMove(editor_mouse_state, modifier_keys) => { + InputPreprocessorMessage::MouseMove { editor_mouse_state, modifier_keys } => { self.handle_modifier_keys(modifier_keys, responses); let mouse_state = editor_mouse_state.to_mouse_state(&self.viewport_bounds); @@ -87,7 +87,7 @@ impl MessageHandler for InputPreprocessorMessageHa responses.push_back(InputMapperMessage::PointerMove.into()); } - InputPreprocessorMessage::MouseScroll(editor_mouse_state, modifier_keys) => { + InputPreprocessorMessage::MouseScroll { editor_mouse_state, modifier_keys } => { self.handle_modifier_keys(modifier_keys, responses); let mouse_state = editor_mouse_state.to_mouse_state(&self.viewport_bounds); @@ -96,7 +96,7 @@ impl MessageHandler for InputPreprocessorMessageHa responses.push_back(InputMapperMessage::MouseScroll.into()); } - InputPreprocessorMessage::MouseUp(editor_mouse_state, modifier_keys) => { + InputPreprocessorMessage::MouseUp { editor_mouse_state, modifier_keys } => { self.handle_modifier_keys(modifier_keys, responses); let mouse_state = editor_mouse_state.to_mouse_state(&self.viewport_bounds); diff --git a/editor/src/input/keyboard.rs b/editor/src/input/keyboard.rs index eee4cb908..3b35931c6 100644 --- a/editor/src/input/keyboard.rs +++ b/editor/src/input/keyboard.rs @@ -15,6 +15,7 @@ const KEY_MASK_STORAGE_LENGTH: usize = (NUMBER_OF_KEYS + STORAGE_SIZE_BITS - 1) pub type KeyStates = BitVector; +// TODO: Consider renaming to `KeyMessage` for consistency with other messages that implement `#[impl_message(..)]` #[impl_message(Message, InputMapperMessage, KeyDown)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum Key { diff --git a/editor/src/lib.rs b/editor/src/lib.rs index 26bb19cdc..1b3501b8d 100644 --- a/editor/src/lib.rs +++ b/editor/src/lib.rs @@ -80,7 +80,6 @@ pub mod message_prelude { pub use crate::viewport_tools::tools::rectangle::{RectangleMessage, RectangleMessageDiscriminant}; pub use crate::viewport_tools::tools::select::{SelectMessage, SelectMessageDiscriminant}; pub use crate::viewport_tools::tools::shape::{ShapeMessage, ShapeMessageDiscriminant}; - pub use graphite_proc_macros::*; pub use std::collections::VecDeque; diff --git a/editor/src/misc/test_utils.rs b/editor/src/misc/test_utils.rs index 83d74e2f8..17fd6e261 100644 --- a/editor/src/misc/test_utils.rs +++ b/editor/src/misc/test_utils.rs @@ -51,15 +51,18 @@ impl EditorTestUtils for Editor { fn move_mouse(&mut self, x: f64, y: f64) { let mut editor_mouse_state = EditorMouseState::new(); editor_mouse_state.editor_position = ViewportPosition::new(x, y); - self.input(InputPreprocessorMessage::MouseMove(editor_mouse_state, ModifierKeys::default())); + let modifier_keys = ModifierKeys::default(); + self.input(InputPreprocessorMessage::MouseMove { editor_mouse_state, modifier_keys }); } - fn mousedown(&mut self, state: EditorMouseState) { - self.input(InputPreprocessorMessage::MouseDown(state, ModifierKeys::default())); + fn mousedown(&mut self, editor_mouse_state: EditorMouseState) { + let modifier_keys = ModifierKeys::default(); + self.input(InputPreprocessorMessage::MouseDown { editor_mouse_state, modifier_keys }); } - fn mouseup(&mut self, state: EditorMouseState) { - self.handle_message(InputPreprocessorMessage::MouseUp(state, ModifierKeys::default())); + fn mouseup(&mut self, editor_mouse_state: EditorMouseState) { + let modifier_keys = ModifierKeys::default(); + self.handle_message(InputPreprocessorMessage::MouseUp { editor_mouse_state, modifier_keys }); } fn lmb_mousedown(&mut self, x: f64, y: f64) { @@ -74,11 +77,11 @@ impl EditorTestUtils for Editor { self.handle_message(Message::InputPreprocessor(message)); } - fn select_tool(&mut self, typ: ToolType) { - self.handle_message(Message::Tool(ToolMessage::ActivateTool(typ))); + fn select_tool(&mut self, tool_type: ToolType) { + self.handle_message(Message::Tool(ToolMessage::ActivateTool { tool_type })); } fn select_primary_color(&mut self, color: Color) { - self.handle_message(Message::Tool(ToolMessage::SelectPrimaryColor(color))); + self.handle_message(Message::Tool(ToolMessage::SelectPrimaryColor { color })); } } diff --git a/editor/src/viewport_tools/tool_message.rs b/editor/src/viewport_tools/tool_message.rs index 6b2e94fa8..2b7a8986d 100644 --- a/editor/src/viewport_tools/tool_message.rs +++ b/editor/src/viewport_tools/tool_message.rs @@ -10,7 +10,9 @@ use serde::{Deserialize, Serialize}; #[impl_message(Message, Tool)] #[derive(PartialEq, Clone, Debug, Serialize, Deserialize)] pub enum ToolMessage { - ActivateTool(ToolType), + ActivateTool { + tool_type: ToolType, + }, #[child] Crop(CropMessage), DocumentIsDirty, @@ -34,9 +36,16 @@ pub enum ToolMessage { ResetColors, #[child] Select(SelectMessage), - SelectPrimaryColor(Color), - SelectSecondaryColor(Color), - SetToolOptions(ToolType, ToolOptions), + SelectPrimaryColor { + color: Color, + }, + SelectSecondaryColor { + color: Color, + }, + SetToolOptions { + tool_type: ToolType, + tool_options: ToolOptions, + }, #[child] Shape(ShapeMessage), SwapColors, diff --git a/editor/src/viewport_tools/tool_message_handler.rs b/editor/src/viewport_tools/tool_message_handler.rs index 2ccd142cf..896318c77 100644 --- a/editor/src/viewport_tools/tool_message_handler.rs +++ b/editor/src/viewport_tools/tool_message_handler.rs @@ -20,13 +20,13 @@ impl MessageHandler { + ActivateTool { tool_type } => { let tool_data = &mut self.tool_state.tool_data; let document_data = &self.tool_state.document_tool_data; let old_tool = tool_data.active_tool_type; // Do nothing if switching to the same tool - if new_tool == old_tool { + if tool_type == old_tool { return; } @@ -41,24 +41,24 @@ impl MessageHandler { @@ -76,19 +76,19 @@ impl MessageHandler { + SelectPrimaryColor { color } => { let document_data = &mut self.tool_state.document_tool_data; document_data.primary_color = color; update_working_colors(&self.tool_state.document_tool_data, responses); } - SelectSecondaryColor(color) => { + SelectSecondaryColor { color } => { let document_data = &mut self.tool_state.document_tool_data; document_data.secondary_color = color; update_working_colors(document_data, responses); } - SetToolOptions(tool_type, tool_options) => { + SetToolOptions { tool_type, tool_options } => { let document_data = &mut self.tool_state.document_tool_data; document_data.tool_options.insert(tool_type, tool_options); diff --git a/editor/src/viewport_tools/tools/eyedropper.rs b/editor/src/viewport_tools/tools/eyedropper.rs index c1021f58e..ca0e1a02d 100644 --- a/editor/src/viewport_tools/tools/eyedropper.rs +++ b/editor/src/viewport_tools/tools/eyedropper.rs @@ -87,8 +87,8 @@ impl Fsm for EyedropperToolFsmState { if let Some(fill) = shape.style.fill() { if let Some(color) = fill.color() { match lmb_or_rmb { - EyedropperMessage::LeftMouseDown => responses.push_back(ToolMessage::SelectPrimaryColor(color).into()), - EyedropperMessage::RightMouseDown => responses.push_back(ToolMessage::SelectSecondaryColor(color).into()), + EyedropperMessage::LeftMouseDown => responses.push_back(ToolMessage::SelectPrimaryColor { color }.into()), + EyedropperMessage::RightMouseDown => responses.push_back(ToolMessage::SelectSecondaryColor { color }.into()), _ => {} } } diff --git a/editor/src/viewport_tools/tools/resize.rs b/editor/src/viewport_tools/tools/resize.rs new file mode 100644 index 000000000..abe605798 --- /dev/null +++ b/editor/src/viewport_tools/tools/resize.rs @@ -0,0 +1,57 @@ +use crate::document::DocumentMessageHandler; +use crate::input::keyboard::Key; +use crate::input::mouse::ViewportPosition; +use crate::input::InputPreprocessorMessageHandler; +use crate::message_prelude::*; +use crate::viewport_tools::snapping::SnapHandler; + +use graphene::Operation; + +use glam::{DAffine2, DVec2, Vec2Swizzles}; + +#[derive(Clone, Debug, Default)] +pub struct Resize { + pub drag_start: ViewportPosition, + pub path: Option>, + snap_handler: SnapHandler, +} +impl Resize { + /// Starts a resize, assigning the snap targets and snapping the starting position. + pub fn start(&mut self, document: &DocumentMessageHandler, mouse_position: DVec2) { + let layers = document.all_layers_sorted(); + self.snap_handler.start_snap(document, layers, &[]); + self.drag_start = self.snap_handler.snap_position(document, mouse_position); + } + + pub fn calculate_transform(&self, document: &DocumentMessageHandler, center: Key, lock_ratio: Key, ipp: &InputPreprocessorMessageHandler) -> Option { + if let Some(path) = &self.path { + let mut start = self.drag_start; + + let stop = self.snap_handler.snap_position(document, ipp.mouse.position); + + let mut size = stop - start; + if ipp.keyboard.get(lock_ratio as usize) { + size = size.abs().max(size.abs().yx()) * size.signum(); + } + if ipp.keyboard.get(center as usize) { + start -= size; + size *= 2.; + } + + Some( + Operation::SetLayerTransformInViewport { + path: path.to_vec(), + transform: DAffine2::from_scale_angle_translation(size, 0., start).to_cols_array(), + } + .into(), + ) + } else { + None + } + } + + pub fn cleanup(&mut self) { + self.snap_handler.cleanup(); + self.path = None; + } +} diff --git a/editor/src/viewport_tools/tools/select.rs b/editor/src/viewport_tools/tools/select.rs index 22fb29616..923ea05ef 100644 --- a/editor/src/viewport_tools/tools/select.rs +++ b/editor/src/viewport_tools/tools/select.rs @@ -34,7 +34,7 @@ pub enum SelectMessage { DragStop, MouseMove { snap_angle: Key }, - Align(AlignAxis, AlignAggregate), + Align { axis: AlignAxis, aggregate: AlignAggregate }, FlipHorizontal, FlipVertical, } @@ -180,7 +180,7 @@ impl Fsm for SelectToolFsmState { if let Some(intersection) = intersection.pop() { selected = vec![intersection]; - buffer.push(DocumentMessage::AddSelectedLayers(selected.clone()).into()); + buffer.push(DocumentMessage::AddSelectedLayers { additional_layers: selected.clone() }.into()); buffer.push(DocumentMessage::StartTransaction.into()); data.layers_dragging.append(&mut selected); Dragging @@ -258,7 +258,12 @@ impl Fsm for SelectToolFsmState { } (DrawingBox, DragStop) => { let quad = data.selection_quad(); - responses.push_front(DocumentMessage::AddSelectedLayers(document.graphene_document.intersects_quad_root(quad)).into()); + responses.push_front( + DocumentMessage::AddSelectedLayers { + additional_layers: document.graphene_document.intersects_quad_root(quad), + } + .into(), + ); responses.push_front( DocumentMessage::Overlays( Operation::DeleteLayer { @@ -276,18 +281,18 @@ impl Fsm for SelectToolFsmState { delete(&mut data.bounding_box_overlay_layer); Ready } - (_, Align(axis, aggregate)) => { - responses.push_back(DocumentMessage::AlignSelectedLayers(axis, aggregate).into()); + (_, Align { axis, aggregate }) => { + responses.push_back(DocumentMessage::AlignSelectedLayers { axis, aggregate }.into()); self } (_, FlipHorizontal) => { - responses.push_back(DocumentMessage::FlipSelectedLayers(FlipAxis::X).into()); + responses.push_back(DocumentMessage::FlipSelectedLayers { flip_axis: FlipAxis::X }.into()); self } (_, FlipVertical) => { - responses.push_back(DocumentMessage::FlipSelectedLayers(FlipAxis::Y).into()); + responses.push_back(DocumentMessage::FlipSelectedLayers { flip_axis: FlipAxis::Y }.into()); self } diff --git a/frontend/src/components/widgets/options/ToolOptions.vue b/frontend/src/components/widgets/options/ToolOptions.vue index e90ed3a59..f3711f090 100644 --- a/frontend/src/components/widgets/options/ToolOptions.vue +++ b/frontend/src/components/widgets/options/ToolOptions.vue @@ -95,15 +95,15 @@ export default defineComponent({ data() { const toolOptionsWidgets: Record = { Select: [ - { kind: "IconButton", message: { Align: ["X", "Min"] }, tooltip: "Align Left", props: { icon: "AlignLeft", size: 24 } }, - { kind: "IconButton", message: { Align: ["X", "Center"] }, tooltip: "Align Horizontal Center", props: { icon: "AlignHorizontalCenter", size: 24 } }, - { kind: "IconButton", message: { Align: ["X", "Max"] }, tooltip: "Align Right", props: { icon: "AlignRight", size: 24 } }, + { kind: "IconButton", message: { Align: { axis: "X", aggregate: "Min" } }, tooltip: "Align Left", props: { icon: "AlignLeft", size: 24 } }, + { kind: "IconButton", message: { Align: { axis: "X", aggregate: "Center" } }, tooltip: "Align Horizontal Center", props: { icon: "AlignHorizontalCenter", size: 24 } }, + { kind: "IconButton", message: { Align: { axis: "X", aggregate: "Max" } }, tooltip: "Align Right", props: { icon: "AlignRight", size: 24 } }, { kind: "Separator", props: { type: "Unrelated" } }, - { kind: "IconButton", message: { Align: ["Y", "Min"] }, tooltip: "Align Top", props: { icon: "AlignTop", size: 24 } }, - { kind: "IconButton", message: { Align: ["Y", "Center"] }, tooltip: "Align Vertical Center", props: { icon: "AlignVerticalCenter", size: 24 } }, - { kind: "IconButton", message: { Align: ["Y", "Max"] }, tooltip: "Align Bottom", props: { icon: "AlignBottom", size: 24 } }, + { kind: "IconButton", message: { Align: { axis: "Y", aggregate: "Min" } }, tooltip: "Align Top", props: { icon: "AlignTop", size: 24 } }, + { kind: "IconButton", message: { Align: { axis: "Y", aggregate: "Center" } }, tooltip: "Align Vertical Center", props: { icon: "AlignVerticalCenter", size: 24 } }, + { kind: "IconButton", message: { Align: { axis: "Y", aggregate: "Max" } }, tooltip: "Align Bottom", props: { icon: "AlignBottom", size: 24 } }, { kind: "Separator", props: { type: "Related" } }, diff --git a/frontend/wasm/src/api.rs b/frontend/wasm/src/api.rs index d35c44b79..0ce0bfbb9 100644 --- a/frontend/wasm/src/api.rs +++ b/frontend/wasm/src/api.rs @@ -95,8 +95,8 @@ impl JsEditorHandle { /// Modify the currently selected tool in the document state store pub fn select_tool(&self, tool: String) -> Result<(), JsValue> { match translate_tool_type(&tool) { - Some(tool) => { - let message = ToolMessage::ActivateTool(tool); + Some(tool_type) => { + let message = ToolMessage::ActivateTool { tool_type }; self.dispatch(message); Ok(()) @@ -108,9 +108,9 @@ impl JsEditorHandle { /// Update the options for a given tool pub fn set_tool_options(&self, tool: String, options: &JsValue) -> Result<(), JsValue> { match serde_wasm_bindgen::from_value::(options.clone()) { - Ok(options) => match translate_tool_type(&tool) { - Some(tool) => { - let message = ToolMessage::SetToolOptions(tool, options); + Ok(tool_options) => match translate_tool_type(&tool) { + Some(tool_type) => { + let message = ToolMessage::SetToolOptions { tool_type, tool_options }; self.dispatch(message); Ok(()) @@ -145,7 +145,7 @@ impl JsEditorHandle { } pub fn select_document(&self, document_id: u64) { - let message = PortfolioMessage::SelectDocument(document_id); + let message = PortfolioMessage::SelectDocument { document_id }; self.dispatch(message); } @@ -169,12 +169,12 @@ impl JsEditorHandle { self.dispatch(message); } - pub fn open_auto_saved_document(&self, document_id: u64, document_name: String, document_is_saved: bool, document: String) { + pub fn open_auto_saved_document(&self, document_id: u64, document_name: String, document_is_saved: bool, document_serialized_content: String) { let message = PortfolioMessage::OpenDocumentFileWithId { document_id, document_name, document_is_saved, - document, + document_serialized_content, }; self.dispatch(message); } @@ -185,12 +185,12 @@ impl JsEditorHandle { } pub fn trigger_auto_save(&self, document_id: u64) { - let message = PortfolioMessage::AutoSaveDocument(document_id); + let message = PortfolioMessage::AutoSaveDocument { document_id }; self.dispatch(message); } pub fn close_document(&self, document_id: u64) { - let message = PortfolioMessage::CloseDocument(document_id); + let message = PortfolioMessage::CloseDocument { document_id }; self.dispatch(message); } @@ -205,7 +205,7 @@ impl JsEditorHandle { } pub fn close_document_with_confirmation(&self, document_id: u64) { - let message = PortfolioMessage::CloseDocumentWithConfirmation(document_id); + let message = PortfolioMessage::CloseDocumentWithConfirmation { document_id }; self.dispatch(message); } @@ -226,7 +226,7 @@ impl JsEditorHandle { pub fn bounds_of_viewports(&self, bounds_of_viewports: &[f64]) { let chunked: Vec<_> = bounds_of_viewports.chunks(4).map(ViewportBounds::from_slice).collect(); - let message = InputPreprocessorMessage::BoundsOfViewports(chunked); + let message = InputPreprocessorMessage::BoundsOfViewports { bounds_of_viewports: chunked }; self.dispatch(message); } @@ -236,7 +236,7 @@ impl JsEditorHandle { let modifier_keys = ModifierKeys::from_bits(modifiers).expect("Invalid modifier keys"); - let message = InputPreprocessorMessage::MouseMove(editor_mouse_state, modifier_keys); + let message = InputPreprocessorMessage::MouseMove { editor_mouse_state, modifier_keys }; self.dispatch(message); } @@ -247,7 +247,7 @@ impl JsEditorHandle { let modifier_keys = ModifierKeys::from_bits(modifiers).expect("Invalid modifier keys"); - let message = InputPreprocessorMessage::MouseScroll(editor_mouse_state, modifier_keys); + let message = InputPreprocessorMessage::MouseScroll { editor_mouse_state, modifier_keys }; self.dispatch(message); } @@ -257,7 +257,7 @@ impl JsEditorHandle { let modifier_keys = ModifierKeys::from_bits(modifiers).expect("Invalid modifier keys"); - let message = InputPreprocessorMessage::MouseDown(editor_mouse_state, modifier_keys); + let message = InputPreprocessorMessage::MouseDown { editor_mouse_state, modifier_keys }; self.dispatch(message); } @@ -267,29 +267,29 @@ impl JsEditorHandle { let modifier_keys = ModifierKeys::from_bits(modifiers).expect("Invalid modifier keys"); - let message = InputPreprocessorMessage::MouseUp(editor_mouse_state, modifier_keys); + let message = InputPreprocessorMessage::MouseUp { editor_mouse_state, modifier_keys }; self.dispatch(message); } /// A keyboard button depressed within screenspace the bounds of the viewport pub fn on_key_down(&self, name: String, modifiers: u8) { let key = translate_key(&name); - let modifiers = ModifierKeys::from_bits(modifiers).expect("Invalid modifier keys"); + let modifier_keys = ModifierKeys::from_bits(modifiers).expect("Invalid modifier keys"); log::trace!("Key down {:?}, name: {}, modifiers: {:?}", key, name, modifiers); - let message = InputPreprocessorMessage::KeyDown(key, modifiers); + let message = InputPreprocessorMessage::KeyDown { key, modifier_keys }; self.dispatch(message); } /// A keyboard button released pub fn on_key_up(&self, name: String, modifiers: u8) { let key = translate_key(&name); - let modifiers = ModifierKeys::from_bits(modifiers).expect("Invalid modifier keys"); + let modifier_keys = ModifierKeys::from_bits(modifiers).expect("Invalid modifier keys"); - log::trace!("Key up {:?}, name: {}, modifiers: {:?}", key, name, modifiers); + log::trace!("Key up {:?}, name: {}, modifiers: {:?}", key, name, modifier_keys); - let message = InputPreprocessorMessage::KeyUp(key, modifiers); + let message = InputPreprocessorMessage::KeyUp { key, modifier_keys }; self.dispatch(message); } @@ -300,7 +300,7 @@ impl JsEditorHandle { None => return Err(Error::new("Invalid color").into()), }; - let message = ToolMessage::SelectPrimaryColor(primary_color); + let message = ToolMessage::SelectPrimaryColor { color: primary_color }; self.dispatch(message); Ok(()) @@ -313,7 +313,7 @@ impl JsEditorHandle { None => return Err(Error::new("Invalid color").into()), }; - let message = ToolMessage::SelectSecondaryColor(secondary_color); + let message = ToolMessage::SelectSecondaryColor { color: secondary_color }; self.dispatch(message); Ok(()) @@ -345,24 +345,24 @@ impl JsEditorHandle { /// Cut selected layers pub fn cut(&self) { - let message = PortfolioMessage::Cut(Clipboard::User); + let message = PortfolioMessage::Cut { clipboard: Clipboard::User }; self.dispatch(message); } /// Copy selected layers pub fn copy(&self) { - let message = PortfolioMessage::Copy(Clipboard::User); + let message = PortfolioMessage::Copy { clipboard: Clipboard::User }; self.dispatch(message); } /// Paste selected layers pub fn paste(&self) { - let message = PortfolioMessage::Paste(Clipboard::User); + let message = PortfolioMessage::Paste { clipboard: Clipboard::User }; self.dispatch(message); } - pub fn select_layer(&self, paths: Vec, ctrl: bool, shift: bool) { - let message = DocumentMessage::SelectLayer(paths, ctrl, shift); + pub fn select_layer(&self, layer_path: Vec, ctrl: bool, shift: bool) { + let message = DocumentMessage::SelectLayer { layer_path, ctrl, shift }; self.dispatch(message); } @@ -379,35 +379,33 @@ impl JsEditorHandle { } /// Reorder selected layer - pub fn reorder_selected_layers(&self, delta: i32) { - let message = DocumentMessage::ReorderSelectedLayers(delta); + pub fn reorder_selected_layers(&self, relative_index_offset: isize) { + let message = DocumentMessage::ReorderSelectedLayers { relative_index_offset }; self.dispatch(message); } /// Move a layer to be next to the specified neighbor - pub fn move_layer_in_tree(&self, path: Vec, insert_index: isize) { - let message = DocumentMessage::MoveSelectedLayersTo { path, insert_index }; + pub fn move_layer_in_tree(&self, folder_path: Vec, insert_index: isize) { + let message = DocumentMessage::MoveSelectedLayersTo { folder_path, insert_index }; self.dispatch(message); } /// Set the blend mode for the selected layers pub fn set_blend_mode_for_selected_layers(&self, blend_mode_svg_style_name: String) -> Result<(), JsValue> { - let blend_mode = translate_blend_mode(blend_mode_svg_style_name.as_str()); + if let Some(blend_mode) = translate_blend_mode(blend_mode_svg_style_name.as_str()) { + let message = DocumentMessage::SetBlendModeForSelectedLayers { blend_mode }; + self.dispatch(message); - match blend_mode { - Some(mode) => { - let message = DocumentMessage::SetBlendModeForSelectedLayers(mode); - self.dispatch(message); - - Ok(()) - } - None => Err(Error::new(&EditorError::Misc("UnknownBlendMode".to_string()).to_string()).into()), + Ok(()) + } else { + Err(Error::new(&EditorError::Misc("UnknownBlendMode".to_string()).to_string()).into()) } } /// Set the opacity for the selected layers pub fn set_opacity_for_selected_layers(&self, opacity_percent: f64) { - let message = DocumentMessage::SetOpacityForSelectedLayers(opacity_percent / 100.); + let opacity = opacity_percent / 100.; + let message = DocumentMessage::SetOpacityForSelectedLayers { opacity }; self.dispatch(message); } @@ -418,23 +416,24 @@ impl JsEditorHandle { } /// Set snapping disabled / enabled - pub fn set_snapping(&self, new_status: bool) { - let message = DocumentMessage::SetSnapping(new_status); + pub fn set_snapping(&self, snap: bool) { + let message = DocumentMessage::SetSnapping { snap }; self.dispatch(message); } /// Set the view mode to change the way layers are drawn in the viewport - pub fn set_view_mode(&self, new_mode: String) -> Result<(), JsValue> { - match translate_view_mode(new_mode.as_str()) { - Some(view_mode) => self.dispatch(DocumentMessage::SetViewMode(view_mode)), - None => return Err(Error::new("Invalid view mode").into()), - }; - Ok(()) + pub fn set_view_mode(&self, view_mode: String) -> Result<(), JsValue> { + if let Some(view_mode) = translate_view_mode(view_mode.as_str()) { + self.dispatch(DocumentMessage::SetViewMode { view_mode }); + Ok(()) + } else { + Err(Error::new("Invalid view mode").into()) + } } /// Sets the zoom to the value - pub fn set_canvas_zoom(&self, new_zoom: f64) { - let message = MovementMessage::SetCanvasZoom(new_zoom); + pub fn set_canvas_zoom(&self, zoom_factor: f64) { + let message = MovementMessage::SetCanvasZoom { zoom_factor }; self.dispatch(message); } @@ -451,58 +450,57 @@ impl JsEditorHandle { } /// Sets the rotation to the new value (in radians) - pub fn set_rotation(&self, new_radians: f64) { - let message = MovementMessage::SetCanvasRotation(new_radians); + pub fn set_rotation(&self, angle_radians: f64) { + let message = MovementMessage::SetCanvasRotation { angle_radians }; self.dispatch(message); } /// Translates document (in viewport coords) pub fn translate_canvas(&self, delta_x: f64, delta_y: f64) { - let message = MovementMessage::TranslateCanvas((delta_x, delta_y).into()); + let message = MovementMessage::TranslateCanvas { delta: (delta_x, delta_y).into() }; self.dispatch(message); } /// Translates document (in viewport coords) pub fn translate_canvas_by_fraction(&self, delta_x: f64, delta_y: f64) { - let message = MovementMessage::TranslateCanvasByViewportFraction((delta_x, delta_y).into()); + let message = MovementMessage::TranslateCanvasByViewportFraction { delta: (delta_x, delta_y).into() }; self.dispatch(message); } /// Update the list of selected layers. The layer paths have to be stored in one array and are separated by LayerId::MAX pub fn select_layers(&self, paths: Vec) { - let paths = paths.split(|id| *id == LayerId::MAX).map(|path| path.to_vec()).collect(); - - let message = DocumentMessage::SetSelectedLayers(paths); + let replacement_selected_layers = paths.split(|id| *id == LayerId::MAX).map(|path| path.to_vec()).collect(); + let message = DocumentMessage::SetSelectedLayers { replacement_selected_layers }; self.dispatch(message); } /// Toggle visibility of a layer from the layer list - pub fn toggle_layer_visibility(&self, path: Vec) { - let message = DocumentMessage::ToggleLayerVisibility(path); + pub fn toggle_layer_visibility(&self, layer_path: Vec) { + let message = DocumentMessage::ToggleLayerVisibility { layer_path }; self.dispatch(message); } /// Toggle expansions state of a layer from the layer list - pub fn toggle_layer_expansion(&self, path: Vec) { - let message = DocumentMessage::ToggleLayerExpansion(path); + pub fn toggle_layer_expansion(&self, layer_path: Vec) { + let message = DocumentMessage::ToggleLayerExpansion { layer_path }; self.dispatch(message); } /// Renames a layer from the layer list - pub fn rename_layer(&self, path: Vec, new_name: String) { - let message = DocumentMessage::RenameLayer(path, new_name); + pub fn rename_layer(&self, layer_path: Vec, new_name: String) { + let message = DocumentMessage::RenameLayer { layer_path, new_name }; self.dispatch(message); } /// Deletes a layer from the layer list - pub fn delete_layer(&self, path: Vec) { - let message = DocumentMessage::DeleteLayer(path); + pub fn delete_layer(&self, layer_path: Vec) { + let message = DocumentMessage::DeleteLayer { layer_path }; self.dispatch(message); } - /// Requests the backend to add a layer to the layer list - pub fn add_folder(&self, path: Vec) { - let message = DocumentMessage::CreateEmptyFolder(path); + /// Requests the backend to add an empty folder inside the provided containing folder + pub fn add_folder(&self, container_path: Vec) { + let message = DocumentMessage::CreateEmptyFolder { container_path }; self.dispatch(message); } @@ -552,13 +550,13 @@ pub fn file_save_suffix() -> String { pub fn graphite_version() -> String { GRAPHITE_DOCUMENT_VERSION.to_string() } -/// Get the constant i32::MAX +/// Get the constant `i32::MAX` #[wasm_bindgen] pub fn i32_max() -> i32 { i32::MAX } -/// Get the constant i32::MIN +/// Get the constant `i32::MIN` #[wasm_bindgen] pub fn i32_min() -> i32 { i32::MIN diff --git a/graphene/src/document.rs b/graphene/src/document.rs index 9f3581a6c..5023b6493 100644 --- a/graphene/src/document.rs +++ b/graphene/src/document.rs @@ -537,7 +537,7 @@ impl Document { return Err(DocumentError::IndexOutOfBounds); } } - Operation::RenameLayer { path, name } => { + Operation::RenameLayer { layer_path: path, new_name: name } => { self.layer_mut(path)?.name = Some(name.clone()); Some(vec![LayerChanged { path: path.clone() }]) } diff --git a/graphene/src/operation.rs b/graphene/src/operation.rs index 953c2aa84..5e07c1429 100644 --- a/graphene/src/operation.rs +++ b/graphene/src/operation.rs @@ -71,8 +71,8 @@ pub enum Operation { path: Vec, }, RenameLayer { - path: Vec, - name: String, + layer_path: Vec, + new_name: String, }, InsertLayer { layer: Layer,