Skip to content

Commit a62147c

Browse files
committed
Add "New Folder"/"Delete Selected" buttons to layer panel
Closes #532
1 parent 1b1a6a2 commit a62147c

File tree

8 files changed

+67
-16
lines changed

8 files changed

+67
-16
lines changed

editor/src/document/document_message_handler.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,7 @@ impl MessageHandler<DocumentMessage, &InputPreprocessorMessageHandler> for Docum
750750
CreateEmptyFolder { mut container_path } => {
751751
let id = generate_uuid();
752752
container_path.push(id);
753+
responses.push_back(DocumentMessage::DeselectAllLayers.into());
753754
responses.push_back(DocumentOperation::CreateFolder { path: container_path.clone() }.into());
754755
responses.push_back(
755756
DocumentMessage::SetLayerExpansion {
@@ -1251,6 +1252,7 @@ impl MessageHandler<DocumentMessage, &InputPreprocessorMessageHandler> for Docum
12511252
SetSnapping,
12521253
DebugPrintDocument,
12531254
ZoomCanvasToFitAll,
1255+
CreateEmptyFolder,
12541256
);
12551257

12561258
if self.layer_metadata.values().any(|data| data.selected) {

editor/src/input/input_mapper.rs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ impl Default for Mapping {
2828

2929
let mappings = mapping![
3030
// Higher priority than entries in sections below
31-
entry! {action=PortfolioMessage::Paste { clipboard: Clipboard::User }, key_down=KeyV, modifiers=[KeyControl]},
3231
entry! {action=MovementMessage::PointerMove { snap_angle: KeyControl, wait_for_snap_angle_release: true, snap_zoom: KeyControl, zoom_from_viewport: None }, message=InputMapperMessage::PointerMove},
3332
// Transform layers
3433
entry! {action=TransformLayerMessage::ApplyTransformOperation, key_down=KeyEnter},
@@ -142,27 +141,29 @@ impl Default for Mapping {
142141
// Colors
143142
entry! {action=ToolMessage::ResetColors, key_down=KeyX, modifiers=[KeyShift, KeyControl]},
144143
entry! {action=ToolMessage::SwapColors, key_down=KeyX, modifiers=[KeyShift]},
145-
// Editor Actions
144+
// Editor actions
146145
entry! {action=FrontendMessage::TriggerFileUpload, key_down=KeyO, modifiers=[KeyControl]},
147-
// Document Actions
148-
entry! {action=PortfolioMessage::Paste { clipboard: Clipboard::User }, key_down=KeyV, modifiers=[KeyControl]},
146+
// Document actions
149147
entry! {action=DocumentMessage::Redo, key_down=KeyZ, modifiers=[KeyControl, KeyShift]},
150148
entry! {action=DocumentMessage::Undo, key_down=KeyZ, modifiers=[KeyControl]},
151149
entry! {action=DocumentMessage::DeselectAllLayers, key_down=KeyA, modifiers=[KeyControl, KeyAlt]},
152150
entry! {action=DocumentMessage::SelectAllLayers, key_down=KeyA, modifiers=[KeyControl]},
153-
entry! {action=DocumentMessage::CreateEmptyFolder { container_path: vec![] }, key_down=KeyN, modifiers=[KeyControl, KeyShift]},
154151
entry! {action=DocumentMessage::DeleteSelectedLayers, key_down=KeyDelete},
155152
entry! {action=DocumentMessage::DeleteSelectedLayers, key_down=KeyBackspace},
156153
entry! {action=DocumentMessage::ExportDocument, key_down=KeyE, modifiers=[KeyControl]},
157154
entry! {action=DocumentMessage::SaveDocument, key_down=KeyS, modifiers=[KeyControl]},
158155
entry! {action=DocumentMessage::SaveDocument, key_down=KeyS, modifiers=[KeyControl, KeyShift]},
159156
entry! {action=DocumentMessage::DebugPrintDocument, key_down=Key9},
160157
entry! {action=DocumentMessage::ZoomCanvasToFitAll, key_down=Key0, modifiers=[KeyControl]},
161-
// Initiate Transform Layers
158+
entry! {action=DocumentMessage::DuplicateSelectedLayers, key_down=KeyD, modifiers=[KeyControl]},
159+
entry! {action=DocumentMessage::GroupSelectedLayers, key_down=KeyG, modifiers=[KeyControl]},
160+
entry! {action=DocumentMessage::UngroupSelectedLayers, key_down=KeyG, modifiers=[KeyControl, KeyShift]},
161+
entry! {action=DocumentMessage::CreateEmptyFolder { container_path: vec![] }, key_down=KeyN, modifiers=[KeyControl, KeyShift]},
162+
// Layer transformation
162163
entry! {action=TransformLayerMessage::BeginGrab, key_down=KeyG},
163164
entry! {action=TransformLayerMessage::BeginRotate, key_down=KeyR},
164165
entry! {action=TransformLayerMessage::BeginScale, key_down=KeyS},
165-
// Document movement
166+
// Movement actions
166167
entry! {action=MovementMessage::RotateCanvasBegin, key_down=Mmb, modifiers=[KeyControl]},
167168
entry! {action=MovementMessage::ZoomCanvasBegin, key_down=Mmb, modifiers=[KeyShift]},
168169
entry! {action=MovementMessage::TranslateCanvasBegin, key_down=Mmb},
@@ -181,17 +182,15 @@ impl Default for Mapping {
181182
entry! {action=MovementMessage::TranslateCanvasByViewportFraction { delta: DVec2::new(-1., 0.) }, key_down=KeyPageDown, modifiers=[KeyShift]},
182183
entry! {action=MovementMessage::TranslateCanvasByViewportFraction { delta: DVec2::new(0., 1.) }, key_down=KeyPageUp},
183184
entry! {action=MovementMessage::TranslateCanvasByViewportFraction { delta: DVec2::new(0., -1.) }, key_down=KeyPageDown},
184-
// Document actions
185+
// Portfolio actions
185186
entry! {action=PortfolioMessage::NewDocument, key_down=KeyN, modifiers=[KeyControl]},
186187
entry! {action=PortfolioMessage::NextDocument, key_down=KeyTab, modifiers=[KeyControl]},
187188
entry! {action=PortfolioMessage::PrevDocument, key_down=KeyTab, modifiers=[KeyControl, KeyShift]},
188189
entry! {action=PortfolioMessage::CloseAllDocumentsWithConfirmation, key_down=KeyW, modifiers=[KeyControl, KeyAlt]},
189190
entry! {action=PortfolioMessage::CloseActiveDocumentWithConfirmation, key_down=KeyW, modifiers=[KeyControl]},
190-
entry! {action=DocumentMessage::DuplicateSelectedLayers, key_down=KeyD, modifiers=[KeyControl]},
191+
entry! {action=PortfolioMessage::Paste { clipboard: Clipboard::User }, key_down=KeyV, modifiers=[KeyControl]},
191192
entry! {action=PortfolioMessage::Copy { clipboard: Clipboard::User }, key_down=KeyC, modifiers=[KeyControl]},
192193
entry! {action=PortfolioMessage::Cut { clipboard: Clipboard::User }, key_down=KeyX, modifiers=[KeyControl]},
193-
entry! {action=DocumentMessage::GroupSelectedLayers, key_down=KeyG, modifiers=[KeyControl]},
194-
entry! {action=DocumentMessage::UngroupSelectedLayers, key_down=KeyG, modifiers=[KeyControl, KeyShift]},
195194
// Nudging
196195
entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: -SHIFT_NUDGE_AMOUNT, delta_y: -SHIFT_NUDGE_AMOUNT }, key_down=KeyArrowUp, modifiers=[KeyShift, KeyArrowLeft]},
197196
entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: SHIFT_NUDGE_AMOUNT, delta_y: -SHIFT_NUDGE_AMOUNT }, key_down=KeyArrowUp, modifiers=[KeyShift, KeyArrowRight]},
@@ -218,10 +217,10 @@ impl Default for Mapping {
218217
entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: NUDGE_AMOUNT, delta_y: NUDGE_AMOUNT }, key_down=KeyArrowRight, modifiers=[KeyArrowDown]},
219218
entry! {action=DocumentMessage::NudgeSelectedLayers { delta_x: NUDGE_AMOUNT, delta_y: 0. }, key_down=KeyArrowRight},
220219
// Reorder Layers
221-
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
220+
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
222221
entry! {action=DocumentMessage::ReorderSelectedLayers { relative_index_offset: 1 }, key_down=KeyRightBracket, modifiers=[KeyControl]},
223222
entry! {action=DocumentMessage::ReorderSelectedLayers { relative_index_offset: -1 }, key_down=KeyLeftBracket, modifiers=[KeyControl]},
224-
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
223+
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
225224
// Global Actions
226225
entry! {action=GlobalMessage::LogInfo, key_down=Key1},
227226
entry! {action=GlobalMessage::LogDebug, key_down=Key2},
Lines changed: 4 additions & 0 deletions
Loading

frontend/assets/16px-solid/trash.svg

Lines changed: 7 additions & 0 deletions
Loading

frontend/src/components/panels/Document.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
<LayoutCol class="working-colors">
5454
<SwatchPairInput />
5555
<LayoutRow class="swap-and-reset">
56+
<!-- TODO: Remember to make these tooltip input hints customized to macOS also -->
5657
<IconButton :action="swapWorkingColors" :icon="'Swap'" title="Swap (Shift+X)" :size="16" />
5758
<IconButton :action="resetWorkingColors" :icon="'ResetColors'" title="Reset (Ctrl+Shift+X)" :size="16" />
5859
</LayoutRow>

frontend/src/components/panels/LayerTree.vue

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@
2828
<p>The contents of this popover menu are coming soon</p>
2929
</PopoverButton>
3030
</LayoutRow>
31+
<LayoutRow class="button-bar">
32+
<LayoutRow></LayoutRow>
33+
<LayoutRow>
34+
<!-- TODO: Remember to make these tooltip input hints customized to macOS also -->
35+
<IconButton :action="createEmptyFolder" :icon="'NewLayer'" title="New Folder (Ctrl+Shift+N)" :size="16" />
36+
<IconButton :action="deleteSelectedLayers" :icon="'Trash'" title="Delete Selected (Del)" :size="16" />
37+
</LayoutRow>
38+
</LayoutRow>
3139
<LayoutRow class="layer-tree" :scrollableY="true">
3240
<LayoutCol class="list" ref="layerTreeList" @click="() => deselectAllLayers()" @dragover="(e) => draggable && updateInsertLine(e)" @dragend="() => draggable && drop()">
3341
<LayoutRow
@@ -111,7 +119,21 @@
111119
}
112120
}
113121
122+
.button-bar {
123+
height: 24px;
124+
flex: 0 0 auto;
125+
justify-content: space-between;
126+
align-items: center;
127+
margin: 0 4px;
128+
129+
.layout-row {
130+
flex: 0 0 auto;
131+
gap: 4px;
132+
}
133+
}
134+
114135
.layer-tree {
136+
margin-top: 4px;
115137
// Crop away the 1px border below the bottom layer entry when it uses the full space of this panel
116138
margin-bottom: -1px;
117139
position: relative;
@@ -366,6 +388,12 @@ export default defineComponent({
366388
markTopOffset(height: number): string {
367389
return `${height}px`;
368390
},
391+
async createEmptyFolder() {
392+
this.editor.instance.create_empty_folder();
393+
},
394+
async deleteSelectedLayers() {
395+
this.editor.instance.delete_selected_layers();
396+
},
369397
async toggleLayerVisibility(path: BigUint64Array) {
370398
this.editor.instance.toggle_layer_visibility(path);
371399
},

frontend/src/utilities/icons.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ import File from "@/../assets/16px-solid/file.svg";
4646
import FlipHorizontal from "@/../assets/16px-solid/flip-horizontal.svg";
4747
import FlipVertical from "@/../assets/16px-solid/flip-vertical.svg";
4848
import GraphiteLogo from "@/../assets/16px-solid/graphite-logo.svg";
49+
import NewLayer from "@/../assets/16px-solid/new-layer.svg";
4950
import Paste from "@/../assets/16px-solid/paste.svg";
51+
import Trash from "@/../assets/16px-solid/trash.svg";
5052
import ViewModeNormal from "@/../assets/16px-solid/view-mode-normal.svg";
5153
import ViewModeOutline from "@/../assets/16px-solid/view-mode-outline.svg";
5254
import ViewModePixels from "@/../assets/16px-solid/view-mode-pixels.svg";
@@ -150,7 +152,9 @@ export const ICON_LIST = {
150152
FlipHorizontal: { component: FlipHorizontal, size: size16 },
151153
FlipVertical: { component: FlipVertical, size: size16 },
152154
GraphiteLogo: { component: GraphiteLogo, size: size16 },
155+
NewLayer: { component: NewLayer, size: size16 },
153156
Paste: { component: Paste, size: size16 },
157+
Trash: { component: Trash, size: size16 },
154158
ViewModeNormal: { component: ViewModeNormal, size: size16 },
155159
ViewModeOutline: { component: ViewModeOutline, size: size16 },
156160
ViewModePixels: { component: ViewModePixels, size: size16 },

frontend/wasm/src/api.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,12 @@ impl JsEditorHandle {
418418
self.dispatch(message);
419419
}
420420

421+
/// Delete all selected layers
422+
pub fn delete_selected_layers(&self) {
423+
let message = DocumentMessage::DeleteSelectedLayers;
424+
self.dispatch(message);
425+
}
426+
421427
/// Reorder selected layer
422428
pub fn reorder_selected_layers(&self, relative_index_offset: isize) {
423429
let message = DocumentMessage::ReorderSelectedLayers { relative_index_offset };
@@ -508,9 +514,9 @@ impl JsEditorHandle {
508514
self.dispatch(message);
509515
}
510516

511-
/// Requests the backend to add an empty folder inside the provided containing folder
512-
pub fn add_folder(&self, container_path: Vec<LayerId>) {
513-
let message = DocumentMessage::CreateEmptyFolder { container_path };
517+
/// Creates an empty folder at the document root
518+
pub fn create_empty_folder(&self) {
519+
let message = DocumentMessage::CreateEmptyFolder { container_path: vec![] };
514520
self.dispatch(message);
515521
}
516522

0 commit comments

Comments
 (0)