From ff232bd722f1443d7791b41dbe2ab120c712995e Mon Sep 17 00:00:00 2001 From: Till Arnold Date: Wed, 16 Jun 2021 11:15:02 +0200 Subject: [PATCH] Add keyboard shortcut to duplicate layers (#214) * Add keyboard shortcut to duplicate layers * Avoid heap allocation in DuplicateSelectedLayers --- client/web/src/components/panels/Document.vue | 2 ++ core/document/src/document.rs | 7 +++++++ core/document/src/operation.rs | 3 +++ core/editor/src/document/document_message_handler.rs | 8 +++++++- core/editor/src/input/input_mapper.rs | 1 + 5 files changed, 20 insertions(+), 1 deletion(-) diff --git a/client/web/src/components/panels/Document.vue b/client/web/src/components/panels/Document.vue index 5db2e273..6e73fe60 100644 --- a/client/web/src/components/panels/Document.vue +++ b/client/web/src/components/panels/Document.vue @@ -202,10 +202,12 @@ export default defineComponent({ on_mouse_move(e.offsetX, e.offsetY); }, async keyDown(e: KeyboardEvent) { + e.preventDefault(); const { on_key_down } = await wasm; on_key_down(e.key); }, async keyUp(e: KeyboardEvent) { + e.preventDefault(); const { on_key_up } = await wasm; on_key_up(e.key); }, diff --git a/core/document/src/document.rs b/core/document/src/document.rs index 63e9e097..7dc43e48 100644 --- a/core/document/src/document.rs +++ b/core/document/src/document.rs @@ -248,6 +248,13 @@ impl Document { let (path, _) = split_path(path.as_slice()).unwrap_or_else(|_| (&[], 0)); Some(vec![DocumentResponse::DocumentChanged, DocumentResponse::FolderChanged { path: path.to_vec() }]) } + Operation::DuplicateLayer { path } => { + let layer = self.layer(&path)?.clone(); + let (folder_path, _) = split_path(path.as_slice()).unwrap_or_else(|_| (&[], 0)); + let folder = self.folder_mut(folder_path)?; + folder.add_layer(layer, -1).ok_or(DocumentError::IndexOutOfBounds)?; + Some(vec![DocumentResponse::DocumentChanged, DocumentResponse::FolderChanged { path: folder_path.to_vec() }]) + } Operation::AddFolder { path } => { self.set_layer(&path, Layer::new(LayerDataTypes::Folder(Folder::default())))?; diff --git a/core/document/src/operation.rs b/core/document/src/operation.rs index dcdeea49..e63ada01 100644 --- a/core/document/src/operation.rs +++ b/core/document/src/operation.rs @@ -60,6 +60,9 @@ pub enum Operation { DeleteLayer { path: Vec, }, + DuplicateLayer { + path: Vec, + }, AddFolder { path: Vec, }, diff --git a/core/editor/src/document/document_message_handler.rs b/core/editor/src/document/document_message_handler.rs index 0dcc23bb..269a1f9e 100644 --- a/core/editor/src/document/document_message_handler.rs +++ b/core/editor/src/document/document_message_handler.rs @@ -11,6 +11,7 @@ pub enum DocumentMessage { SelectLayers(Vec>), DeleteLayer(Vec), DeleteSelectedLayers, + DuplicateSelectedLayers, AddFolder(Vec), RenameLayer(Vec, String), ToggleLayerVisibility(Vec), @@ -160,6 +161,11 @@ impl MessageHandler for DocumentMessageHandler { responses.push_back(DocumentOperation::DeleteLayer { path }.into()) } } + DuplicateSelectedLayers => { + for path in self.active_document().layer_data.iter().filter_map(|(path, data)| data.selected.then(|| path.clone())) { + responses.push_back(DocumentOperation::DuplicateLayer { path }.into()) + } + } SelectLayers(paths) => { self.clear_selection(); for path in paths { @@ -208,7 +214,7 @@ impl MessageHandler for DocumentMessageHandler { } fn actions(&self) -> ActionList { if self.active_document().layer_data.values().any(|data| data.selected) { - actions!(DocumentMessageDiscriminant; Undo, DeleteSelectedLayers, RenderDocument, ExportDocument, NewDocument, NextDocument, PrevDocument) + actions!(DocumentMessageDiscriminant; Undo, DeleteSelectedLayers, DuplicateSelectedLayers, RenderDocument, ExportDocument, NewDocument, NextDocument, PrevDocument) } else { actions!(DocumentMessageDiscriminant; Undo, RenderDocument, ExportDocument, NewDocument, NextDocument, PrevDocument) } diff --git a/core/editor/src/input/input_mapper.rs b/core/editor/src/input/input_mapper.rs index 5806110f..5c2144cd 100644 --- a/core/editor/src/input/input_mapper.rs +++ b/core/editor/src/input/input_mapper.rs @@ -167,6 +167,7 @@ impl Default for Mapping { entry! {action=GlobalMessage::LogInfo, key_down=Key1}, entry! {action=GlobalMessage::LogDebug, key_down=Key2}, entry! {action=GlobalMessage::LogTrace, key_down=Key3}, + entry! {action=DocumentMessage::DuplicateSelectedLayers, key_down=KeyD, modifiers=[KeyControl]}, ]; Self { up, down, pointer_move } }