Refactor document tab management from Panel.vue into utilities/documents.ts
This commit is contained in:
parent
7cc3a44527
commit
4d90d70220
|
|
@ -217,7 +217,7 @@ img {
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
import dialog from "@/utilities/dialog";
|
import dialog from "@/utilities/dialog";
|
||||||
import document from "@/utilities/document";
|
import documents from "@/utilities/documents";
|
||||||
import fullscreen from "@/utilities/fullscreen";
|
import fullscreen from "@/utilities/fullscreen";
|
||||||
import MainWindow from "@/components/window/MainWindow.vue";
|
import MainWindow from "@/components/window/MainWindow.vue";
|
||||||
import LayoutRow from "@/components/layout/LayoutRow.vue";
|
import LayoutRow from "@/components/layout/LayoutRow.vue";
|
||||||
|
|
@ -225,7 +225,7 @@ import LayoutRow from "@/components/layout/LayoutRow.vue";
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
provide: {
|
provide: {
|
||||||
dialog,
|
dialog,
|
||||||
document,
|
documents,
|
||||||
fullscreen,
|
fullscreen,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
<MenuBarInput v-if="platform !== ApplicationPlatform.Mac" />
|
<MenuBarInput v-if="platform !== ApplicationPlatform.Mac" />
|
||||||
</div>
|
</div>
|
||||||
<div class="header-third">
|
<div class="header-third">
|
||||||
<WindowTitle :title="`${document.title}${document.unsaved ? '*' : ''} - Graphite`" />
|
<WindowTitle :title="`${documents.title}${documents.unsaved ? '*' : ''} - Graphite`" />
|
||||||
</div>
|
</div>
|
||||||
<div class="header-third">
|
<div class="header-third">
|
||||||
<WindowButtonsWindows :maximized="maximized" v-if="platform === ApplicationPlatform.Windows || platform === ApplicationPlatform.Linux" />
|
<WindowButtonsWindows :maximized="maximized" v-if="platform === ApplicationPlatform.Windows || platform === ApplicationPlatform.Linux" />
|
||||||
|
|
@ -41,7 +41,7 @@ import MenuBarInput from "@/components/widgets/inputs/MenuBarInput.vue";
|
||||||
import { ApplicationPlatform } from "@/components/window/MainWindow.vue";
|
import { ApplicationPlatform } from "@/components/window/MainWindow.vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
inject: ["document"],
|
inject: ["documents"],
|
||||||
props: {
|
props: {
|
||||||
platform: { type: String, required: true },
|
platform: { type: String, required: true },
|
||||||
maximized: { type: Boolean, required: true },
|
maximized: { type: Boolean, required: true },
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,11 @@
|
||||||
:class="{ active: tabIndex === tabActiveIndex }"
|
:class="{ active: tabIndex === tabActiveIndex }"
|
||||||
v-for="(tabLabel, tabIndex) in tabLabels"
|
v-for="(tabLabel, tabIndex) in tabLabels"
|
||||||
:key="tabIndex"
|
:key="tabIndex"
|
||||||
@click.middle="handleTabClose(tabIndex)"
|
@click.middle="closeDocumentWithConfirmation(tabIndex)"
|
||||||
@click="handleTabClick(tabIndex)"
|
@click="selectDocument(tabIndex)"
|
||||||
>
|
>
|
||||||
<span>{{ tabLabel }}</span>
|
<span>{{ tabLabel }}</span>
|
||||||
<IconButton :action="() => handleTabClose(tabIndex)" :icon="'CloseX'" :size="16" v-if="tabCloseButtons" />
|
<IconButton :action="() => closeDocumentWithConfirmation(tabIndex)" :icon="'CloseX'" :size="16" v-if="tabCloseButtons" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<PopoverButton :icon="PopoverButtonIcon.VerticalEllipsis">
|
<PopoverButton :icon="PopoverButtonIcon.VerticalEllipsis">
|
||||||
|
|
@ -144,7 +144,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, PropType } from "vue";
|
import { defineComponent, PropType } from "vue";
|
||||||
|
|
||||||
import { createDialog, dismissDialog } from "@/utilities/dialog";
|
import { selectDocument, closeDocumentWithConfirmation } from "@/utilities/documents";
|
||||||
|
|
||||||
import Document from "@/components/panels/Document.vue";
|
import Document from "@/components/panels/Document.vue";
|
||||||
import Properties from "@/components/panels/Properties.vue";
|
import Properties from "@/components/panels/Properties.vue";
|
||||||
|
|
@ -153,12 +153,8 @@ import Minimap from "@/components/panels/Minimap.vue";
|
||||||
import IconButton from "@/components/widgets/buttons/IconButton.vue";
|
import IconButton from "@/components/widgets/buttons/IconButton.vue";
|
||||||
import PopoverButton, { PopoverButtonIcon } from "@/components/widgets/buttons/PopoverButton.vue";
|
import PopoverButton, { PopoverButtonIcon } from "@/components/widgets/buttons/PopoverButton.vue";
|
||||||
import { MenuDirection } from "@/components/widgets/floating-menus/FloatingMenu.vue";
|
import { MenuDirection } from "@/components/widgets/floating-menus/FloatingMenu.vue";
|
||||||
import { ResponseType, registerResponseHandler, Response, DisplayConfirmationToCloseDocument } from "@/utilities/response-handler";
|
|
||||||
|
|
||||||
const wasm = import("@/../wasm/pkg");
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
inject: ["dialog"],
|
|
||||||
components: {
|
components: {
|
||||||
Document,
|
Document,
|
||||||
Properties,
|
Properties,
|
||||||
|
|
@ -167,78 +163,6 @@ export default defineComponent({
|
||||||
IconButton,
|
IconButton,
|
||||||
PopoverButton,
|
PopoverButton,
|
||||||
},
|
},
|
||||||
methods: {
|
|
||||||
handleTabClick(tabIndex: number) {
|
|
||||||
if (this.panelType === "Document") this.selectDocument(tabIndex);
|
|
||||||
},
|
|
||||||
handleTabClose(tabIndex: number) {
|
|
||||||
if (this.panelType === "Document") this.closeDocumentWithConfirmation(tabIndex);
|
|
||||||
},
|
|
||||||
async selectDocument(tabIndex: number) {
|
|
||||||
const { select_document } = await wasm;
|
|
||||||
select_document(tabIndex);
|
|
||||||
},
|
|
||||||
async closeDocumentWithConfirmation(tabIndex: number) {
|
|
||||||
this.selectDocument(tabIndex);
|
|
||||||
const tabLabel = this.tabLabels[tabIndex];
|
|
||||||
|
|
||||||
// TODO: Rename to "Save changes before closing?" when we can actually save documents somewhere, not just export SVGs
|
|
||||||
createDialog("File", "Close without exporting SVG?", tabLabel, [
|
|
||||||
{
|
|
||||||
kind: "TextButton",
|
|
||||||
callback: async () => {
|
|
||||||
(await wasm).export_document();
|
|
||||||
dismissDialog();
|
|
||||||
},
|
|
||||||
props: { label: "Export", emphasized: true, minWidth: 96 },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: "TextButton",
|
|
||||||
callback: async () => {
|
|
||||||
(await wasm).close_document(tabIndex);
|
|
||||||
dismissDialog();
|
|
||||||
},
|
|
||||||
props: { label: "Discard", minWidth: 96 },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: "TextButton",
|
|
||||||
callback: async () => {
|
|
||||||
dismissDialog();
|
|
||||||
},
|
|
||||||
props: { label: "Cancel", minWidth: 96 },
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
async closeAllDocumentsWithConfirmation() {
|
|
||||||
createDialog("Copy", "Close all documents?", "Unsaved work will be lost!", [
|
|
||||||
{
|
|
||||||
kind: "TextButton",
|
|
||||||
callback: async () => {
|
|
||||||
(await wasm).close_all_documents();
|
|
||||||
dismissDialog();
|
|
||||||
},
|
|
||||||
props: { label: "Discard All", minWidth: 96 },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
kind: "TextButton",
|
|
||||||
callback: async () => {
|
|
||||||
dismissDialog();
|
|
||||||
},
|
|
||||||
props: { label: "Cancel", minWidth: 96 },
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
// TODO: Move these somewhere more appropriate to act upon all panels
|
|
||||||
registerResponseHandler(ResponseType.DisplayConfirmationToCloseDocument, (responseData: Response) => {
|
|
||||||
const data = responseData as DisplayConfirmationToCloseDocument;
|
|
||||||
this.closeDocumentWithConfirmation(data.document_index);
|
|
||||||
});
|
|
||||||
registerResponseHandler(ResponseType.DisplayConfirmationToCloseAllDocuments, (_responseData: Response) => {
|
|
||||||
this.closeAllDocumentsWithConfirmation();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
props: {
|
props: {
|
||||||
tabMinWidths: { type: Boolean, default: false },
|
tabMinWidths: { type: Boolean, default: false },
|
||||||
tabCloseButtons: { type: Boolean, default: false },
|
tabCloseButtons: { type: Boolean, default: false },
|
||||||
|
|
@ -248,6 +172,8 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
selectDocument,
|
||||||
|
closeDocumentWithConfirmation,
|
||||||
PopoverButtonIcon,
|
PopoverButtonIcon,
|
||||||
MenuDirection,
|
MenuDirection,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<LayoutRow class="workspace-grid-subdivision">
|
<LayoutRow class="workspace-grid-subdivision">
|
||||||
<LayoutCol class="workspace-grid-subdivision" style="flex-grow: 1597">
|
<LayoutCol class="workspace-grid-subdivision" style="flex-grow: 1597">
|
||||||
<Panel :panelType="'Document'" :tabCloseButtons="true" :tabMinWidths="true" :tabLabels="documents" :tabActiveIndex="activeDocument" />
|
<Panel :panelType="'Document'" :tabCloseButtons="true" :tabMinWidths="true" :tabLabels="documents.documents" :tabActiveIndex="documents.activeDocumentIndex" />
|
||||||
</LayoutCol>
|
</LayoutCol>
|
||||||
<LayoutCol class="workspace-grid-resize-gutter"></LayoutCol>
|
<LayoutCol class="workspace-grid-resize-gutter"></LayoutCol>
|
||||||
<LayoutCol class="workspace-grid-subdivision" style="flex-grow: 319">
|
<LayoutCol class="workspace-grid-subdivision" style="flex-grow: 319">
|
||||||
|
|
@ -48,47 +48,21 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
|
|
||||||
import { setDocumentTitle } from "@/utilities/document";
|
|
||||||
|
|
||||||
import Panel from "@/components/workspace/Panel.vue";
|
import Panel from "@/components/workspace/Panel.vue";
|
||||||
import { ResponseType, registerResponseHandler, Response, SetActiveDocument, UpdateOpenDocumentsList } from "@/utilities/response-handler";
|
|
||||||
import LayoutRow from "@/components/layout/LayoutRow.vue";
|
import LayoutRow from "@/components/layout/LayoutRow.vue";
|
||||||
import LayoutCol from "@/components/layout/LayoutCol.vue";
|
import LayoutCol from "@/components/layout/LayoutCol.vue";
|
||||||
import DialogModal from "@/components/widgets/floating-menus/DialogModal.vue";
|
import DialogModal from "@/components/widgets/floating-menus/DialogModal.vue";
|
||||||
|
|
||||||
const wasm = import("@/../wasm/pkg");
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
inject: ["dialog"],
|
inject: ["documents", "dialog"],
|
||||||
components: {
|
components: {
|
||||||
LayoutRow,
|
LayoutRow,
|
||||||
LayoutCol,
|
LayoutCol,
|
||||||
Panel,
|
Panel,
|
||||||
DialogModal,
|
DialogModal,
|
||||||
},
|
},
|
||||||
mounted() {
|
|
||||||
registerResponseHandler(ResponseType.UpdateOpenDocumentsList, (responseData: Response) => {
|
|
||||||
const documentListData = responseData as UpdateOpenDocumentsList;
|
|
||||||
if (documentListData) {
|
|
||||||
this.documents = documentListData.open_documents;
|
|
||||||
setDocumentTitle(this.documents[this.activeDocument]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
registerResponseHandler(ResponseType.SetActiveDocument, (responseData: Response) => {
|
|
||||||
const documentData = responseData as SetActiveDocument;
|
|
||||||
if (documentData) {
|
|
||||||
this.activeDocument = documentData.document_index;
|
|
||||||
setDocumentTitle(this.documents[this.activeDocument]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
(async () => (await wasm).get_open_documents_list())();
|
|
||||||
},
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {};
|
||||||
activeDocument: 0,
|
|
||||||
documents: [] as Array<string>,
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
import { reactive, readonly } from "vue";
|
|
||||||
|
|
||||||
const state = reactive({
|
|
||||||
title: "",
|
|
||||||
unsaved: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
export function setDocumentTitle(title: string) {
|
|
||||||
state.title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setUnsavedState(isUnsaved: boolean) {
|
|
||||||
state.unsaved = isUnsaved;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function documentTitle(): string {
|
|
||||||
return state.title;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function documentIsUnsaved(): boolean {
|
|
||||||
return state.unsaved;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default readonly(state);
|
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
import { reactive, readonly } from "vue";
|
||||||
|
|
||||||
|
import { createDialog, dismissDialog } from "@/utilities/dialog";
|
||||||
|
import { ResponseType, registerResponseHandler, Response, SetActiveDocument, UpdateOpenDocumentsList, DisplayConfirmationToCloseDocument } from "@/utilities/response-handler";
|
||||||
|
|
||||||
|
const wasm = import("@/../wasm/pkg");
|
||||||
|
|
||||||
|
const state = reactive({
|
||||||
|
title: "",
|
||||||
|
unsaved: false,
|
||||||
|
documents: [] as Array<string>,
|
||||||
|
activeDocumentIndex: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
export async function selectDocument(tabIndex: number) {
|
||||||
|
const { select_document } = await wasm;
|
||||||
|
select_document(tabIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function closeDocumentWithConfirmation(tabIndex: number) {
|
||||||
|
selectDocument(tabIndex);
|
||||||
|
|
||||||
|
const tabLabel = state.documents[tabIndex];
|
||||||
|
|
||||||
|
// TODO: Rename to "Save changes before closing?" when we can actually save documents somewhere, not just export SVGs
|
||||||
|
createDialog("File", "Close without exporting SVG?", tabLabel, [
|
||||||
|
{
|
||||||
|
kind: "TextButton",
|
||||||
|
callback: async () => {
|
||||||
|
(await wasm).export_document();
|
||||||
|
dismissDialog();
|
||||||
|
},
|
||||||
|
props: { label: "Export", emphasized: true, minWidth: 96 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kind: "TextButton",
|
||||||
|
callback: async () => {
|
||||||
|
(await wasm).close_document(tabIndex);
|
||||||
|
dismissDialog();
|
||||||
|
},
|
||||||
|
props: { label: "Discard", minWidth: 96 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kind: "TextButton",
|
||||||
|
callback: async () => {
|
||||||
|
dismissDialog();
|
||||||
|
},
|
||||||
|
props: { label: "Cancel", minWidth: 96 },
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function closeAllDocumentsWithConfirmation() {
|
||||||
|
createDialog("Copy", "Close all documents?", "Unsaved work will be lost!", [
|
||||||
|
{
|
||||||
|
kind: "TextButton",
|
||||||
|
callback: async () => {
|
||||||
|
(await wasm).close_all_documents();
|
||||||
|
dismissDialog();
|
||||||
|
},
|
||||||
|
props: { label: "Discard All", minWidth: 96 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
kind: "TextButton",
|
||||||
|
callback: async () => {
|
||||||
|
dismissDialog();
|
||||||
|
},
|
||||||
|
props: { label: "Cancel", minWidth: 96 },
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default readonly(state);
|
||||||
|
|
||||||
|
registerResponseHandler(ResponseType.UpdateOpenDocumentsList, (responseData: Response) => {
|
||||||
|
const documentListData = responseData as UpdateOpenDocumentsList;
|
||||||
|
if (documentListData) {
|
||||||
|
state.documents = documentListData.open_documents;
|
||||||
|
state.title = state.documents[state.activeDocumentIndex];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
registerResponseHandler(ResponseType.SetActiveDocument, (responseData: Response) => {
|
||||||
|
const documentData = responseData as SetActiveDocument;
|
||||||
|
if (documentData) {
|
||||||
|
state.activeDocumentIndex = documentData.document_index;
|
||||||
|
state.title = state.documents[state.activeDocumentIndex];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
registerResponseHandler(ResponseType.DisplayConfirmationToCloseDocument, (responseData: Response) => {
|
||||||
|
const data = responseData as DisplayConfirmationToCloseDocument;
|
||||||
|
closeDocumentWithConfirmation(data.document_index);
|
||||||
|
});
|
||||||
|
registerResponseHandler(ResponseType.DisplayConfirmationToCloseAllDocuments, (_responseData: Response) => {
|
||||||
|
closeAllDocumentsWithConfirmation();
|
||||||
|
});
|
||||||
|
|
||||||
|
(async () => (await wasm).get_open_documents_list())();
|
||||||
Loading…
Reference in New Issue