Menu bar definition in backend (#681)

* initial menu layout working

* removed api.rs functions

* no action shortcut for no-op

* code review

* nitpicks
This commit is contained in:
mfish33
2022-06-18 18:46:23 -06:00
committed by Keavon Chambers
parent 9bd27ec3f8
commit 5d6d2b22bc
35 changed files with 781 additions and 475 deletions

View File

@@ -72,151 +72,42 @@
<script lang="ts">
import { defineComponent } from "vue";
import { Editor } from "@/wasm-communication/editor";
import { MenuEntry, UpdateMenuBarLayout } from "@/wasm-communication/messages";
import MenuList, { MenuListEntry, MenuListEntries } from "@/components/floating-menus/MenuList.vue";
import MenuList, { MenuListEntry } from "@/components/floating-menus/MenuList.vue";
import IconLabel from "@/components/widgets/labels/IconLabel.vue";
function makeEntries(editor: Editor): MenuListEntries {
return [
{
label: "File",
ref: undefined,
children: [
[
{ label: "New…", icon: "File", shortcut: ["KeyControl", "KeyN"], shortcutRequiresLock: true, action: (): void => editor.instance.request_new_document_dialog() },
{ label: "Open…", shortcut: ["KeyControl", "KeyO"], action: (): void => editor.instance.open_document() },
{
label: "Open Recent",
shortcut: ["KeyControl", "KeyShift", "KeyO"],
action: (): void => undefined,
children: [
[{ label: "Reopen Last Closed", shortcut: ["KeyControl", "KeyShift", "KeyT"], shortcutRequiresLock: true }, { label: "Clear Recently Opened" }],
[
{ label: "Some Recent File.gdd" },
{ label: "Another Recent File.gdd" },
{ label: "An Older File.gdd" },
{ label: "Some Other Older File.gdd" },
{ label: "Yet Another Older File.gdd" },
],
],
},
],
[
{ label: "Close", shortcut: ["KeyControl", "KeyW"], shortcutRequiresLock: true, action: async (): Promise<void> => editor.instance.close_active_document_with_confirmation() },
{ label: "Close All", shortcut: ["KeyControl", "KeyAlt", "KeyW"], action: async (): Promise<void> => editor.instance.close_all_documents_with_confirmation() },
],
[
{ label: "Save", shortcut: ["KeyControl", "KeyS"], action: async (): Promise<void> => editor.instance.save_document() },
{ label: "Save As…", shortcut: ["KeyControl", "KeyShift", "KeyS"], action: async (): Promise<void> => editor.instance.save_document() },
{ label: "Save All", shortcut: ["KeyControl", "KeyAlt", "KeyS"] },
{ label: "Auto-Save", icon: "CheckboxChecked" },
],
[
{ label: "Import…", shortcut: ["KeyControl", "KeyI"] },
{ label: "Export…", shortcut: ["KeyControl", "KeyE"], action: async (): Promise<void> => editor.instance.export_document() },
],
[{ label: "Quit", shortcut: ["KeyControl", "KeyQ"] }],
],
},
{
label: "Edit",
ref: undefined,
children: [
[
{ label: "Undo", shortcut: ["KeyControl", "KeyZ"], action: async (): Promise<void> => editor.instance.undo() },
{ label: "Redo", shortcut: ["KeyControl", "KeyShift", "KeyZ"], action: async (): Promise<void> => editor.instance.redo() },
],
[
{ label: "Cut", shortcut: ["KeyControl", "KeyX"], action: async (): Promise<void> => editor.instance.cut() },
{ label: "Copy", icon: "Copy", shortcut: ["KeyControl", "KeyC"], action: async (): Promise<void> => editor.instance.copy() },
// TODO: Fix this
// { label: "Paste", icon: "Paste", shortcut: ["KeyControl", "KeyV"], action: async (): Promise<void> => editor.instance.paste() },
],
],
},
{
label: "Layer",
ref: undefined,
children: [
[
{ label: "Select All", shortcut: ["KeyControl", "KeyA"], action: async (): Promise<void> => editor.instance.select_all_layers() },
{ label: "Deselect All", shortcut: ["KeyControl", "KeyAlt", "KeyA"], action: async (): Promise<void> => editor.instance.deselect_all_layers() },
{
label: "Order",
action: (): void => undefined,
children: [
[
{
label: "Raise To Front",
shortcut: ["KeyControl", "KeyShift", "KeyLeftBracket"],
action: async (): Promise<void> => editor.instance.reorder_selected_layers(editor.instance.i32_max()),
},
{ label: "Raise", shortcut: ["KeyControl", "KeyRightBracket"], action: async (): Promise<void> => editor.instance.reorder_selected_layers(1) },
{ label: "Lower", shortcut: ["KeyControl", "KeyLeftBracket"], action: async (): Promise<void> => editor.instance.reorder_selected_layers(-1) },
{
label: "Lower to Back",
shortcut: ["KeyControl", "KeyShift", "KeyRightBracket"],
action: async (): Promise<void> => editor.instance.reorder_selected_layers(editor.instance.i32_min()),
},
],
],
},
],
],
},
{
label: "Document",
ref: undefined,
children: [[{ label: "Menu entries coming soon" }]],
},
{
label: "View",
ref: undefined,
children: [
[
{
label: "Show/Hide Node Graph (In Development)",
action: async (): Promise<void> => editor.instance.toggle_node_graph_visibility(),
},
],
],
},
{
label: "Help",
ref: undefined,
children: [
[
{
label: "About Graphite",
action: async (): Promise<void> => editor.instance.request_about_graphite_dialog(),
},
],
[
{ label: "Report a Bug", action: (): unknown => window.open("https://github.com/GraphiteEditor/Graphite/issues/new", "_blank") },
{ label: "Visit on GitHub", action: (): unknown => window.open("https://github.com/GraphiteEditor/Graphite", "_blank") },
],
[
{
label: "Debug: Set Log Level",
action: (): void => undefined,
children: [
[
{ label: "Log Level Info", action: async (): Promise<void> => editor.instance.log_level_info(), shortcut: ["Key1"] },
{ label: "Log Level Debug", action: async (): Promise<void> => editor.instance.log_level_debug(), shortcut: ["Key2"] },
{ label: "Log Level Trace", action: async (): Promise<void> => editor.instance.log_level_trace(), shortcut: ["Key3"] },
],
],
},
{ label: "Debug: Panic (DANGER)", action: async (): Promise<void> => editor.instance.intentional_panic() },
],
],
},
];
}
const LOCK_REQUIRING_SHORTCUTS = [
["KeyControl", "KeyN"],
["KeyControl", "KeyShift", "KeyT"],
["KeyControl", "KeyW"],
];
type FrontendMenuColumn = {
label: string;
children: FrontendMenuEntry[][];
};
type FrontendMenuEntry = Omit<MenuEntry, "action" | "children"> & { shortcutRequiresLock: boolean | undefined; action: () => void; children: FrontendMenuEntry[][] | undefined };
export default defineComponent({
inject: ["editor"],
mounted() {
this.editor.subscriptions.subscribeJsMessage(UpdateMenuBarLayout, (updateMenuBarLayout) => {
const shortcutRequiresLock = (shortcut: string[]): boolean => LOCK_REQUIRING_SHORTCUTS.some((lockKeyCombo) => shortcut.every((shortcutKey, index) => shortcutKey === lockKeyCombo[index]));
const menuEntryToFrontendMenuEntry = (subLayout: MenuEntry[][]): FrontendMenuEntry[][] =>
subLayout.map((group) =>
group.map((entry) => ({
...entry,
children: entry.children ? menuEntryToFrontendMenuEntry(entry.children) : undefined,
action: (): void => this.editor.instance.update_layout(updateMenuBarLayout.layout_target, entry.action.widget_id, undefined),
shortcutRequiresLock: entry.shortcut ? shortcutRequiresLock(entry.shortcut) : undefined,
}))
);
this.entries = updateMenuBarLayout.layout.map((column) => ({ ...column, children: menuEntryToFrontendMenuEntry(column.children) }));
});
},
methods: {
onClick(menuEntry: MenuListEntry, target: EventTarget | null) {
// Focus the target so that keyboard inputs are sent to the dropdown
@@ -236,7 +127,7 @@ export default defineComponent({
},
data() {
return {
entries: makeEntries(this.editor),
entries: [] as FrontendMenuColumn[],
open: false,
};
},