Files
Graphite/frontend/src/components/workspace/Workspace.vue
0HyperCube 9afb9935c2 Add support for resizing workspace panels (#443)
* Resize panels

* Removing move_selection test pending #444 resolved

* Bind event listners and cursor to the document

* Fix flex grow on document being reset when drawing

* Call onresize when the boundry is dragged

* Add min panel size

* Add explicit function return types

* Dispatch resize event

* Lock pointer instead of setting cursor on document

Co-authored-by: otdavies <oliver@psyfer.io>
Co-authored-by: Keavon Chambers <keavon@keavon.com>
2022-01-08 08:02:02 -08:00

149 lines
4.7 KiB
Vue

<template>
<LayoutRow class="workspace-grid-subdivision">
<LayoutCol class="workspace-grid-subdivision">
<Panel
:panelType="'Document'"
:tabCloseButtons="true"
:tabMinWidths="true"
:tabLabels="documents.state.documents.map((doc) => doc.displayName)"
:clickAction="
(tabIndex) => {
const targetId = documents.state.documents[tabIndex].id;
editor.instance.select_document(targetId);
}
"
:closeAction="
(tabIndex) => {
const targetId = documents.state.documents[tabIndex].id;
editor.instance.close_document_with_confirmation(targetId);
}
"
:tabActiveIndex="documents.state.activeDocumentIndex"
ref="documentsPanel"
/>
</LayoutCol>
<LayoutCol class="workspace-grid-resize-gutter" @pointerdown="resizePanel($event)"></LayoutCol>
<LayoutCol class="workspace-grid-subdivision" style="flex-grow: 0.17">
<LayoutRow class="workspace-grid-subdivision" style="flex-grow: 402">
<Panel :panelType="'Properties'" :tabLabels="['Properties']" :tabActiveIndex="0" />
</LayoutRow>
<LayoutRow class="workspace-grid-resize-gutter" @pointerdown="resizePanel($event)"></LayoutRow>
<LayoutRow class="workspace-grid-subdivision" style="flex-grow: 590">
<Panel :panelType="'LayerTree'" :tabLabels="['Layer Tree']" :tabActiveIndex="0" />
</LayoutRow>
<!-- <LayoutRow class="workspace-grid-resize-gutter"></LayoutRow>
<LayoutRow class="workspace-grid-subdivision folded">
<Panel :panelType="'Minimap'" :tabLabels="['Minimap', 'Asset Manager']" :tabActiveIndex="0" />
</LayoutRow> -->
</LayoutCol>
</LayoutRow>
<DialogModal v-if="dialog.state.visible" />
</template>
<style lang="scss">
.workspace-grid-subdivision {
min-height: 28px;
flex: 1 1 0;
&.folded {
flex-grow: 0;
height: 0;
}
}
.workspace-grid-resize-gutter {
flex: 0 0 4px;
&.layout-row {
cursor: ns-resize;
}
&.layout-col {
cursor: ew-resize;
}
}
</style>
<script lang="ts">
import { defineComponent } from "vue";
import LayoutCol from "@/components/layout/LayoutCol.vue";
import LayoutRow from "@/components/layout/LayoutRow.vue";
import DialogModal from "@/components/widgets/floating-menus/DialogModal.vue";
import Panel from "@/components/workspace/Panel.vue";
const MIN_PANEL_SIZE = 100;
export default defineComponent({
inject: ["documents", "dialog", "editor"],
components: {
LayoutRow,
LayoutCol,
Panel,
DialogModal,
},
computed: {
activeDocumentIndex() {
return this.documents.state.activeDocumentIndex;
},
},
methods: {
resizePanel(event: PointerEvent) {
const gutter = event.target as HTMLElement;
const nextSibling = gutter.nextElementSibling as HTMLElement;
const previousSibling = gutter.previousElementSibling as HTMLElement;
// Are we resizing horizontally?
const horizontal = gutter.classList.contains("layout-col");
// Get the current size in px of the panels being resized
const nextSiblingSize = horizontal ? nextSibling.getBoundingClientRect().width : nextSibling.getBoundingClientRect().height;
const previousSiblingSize = horizontal ? previousSibling.getBoundingClientRect().width : previousSibling.getBoundingClientRect().height;
// Prevent cursor flicker as mouse temporarily leaves the gutter
gutter.setPointerCapture(event.pointerId);
const mouseStart = horizontal ? event.clientX : event.clientY;
function updatePosition(event: PointerEvent): void {
const mouseCurrent = horizontal ? event.clientX : event.clientY;
let mouseDelta = mouseStart - mouseCurrent;
mouseDelta = Math.max(nextSiblingSize + mouseDelta, MIN_PANEL_SIZE) - nextSiblingSize;
mouseDelta = previousSiblingSize - Math.max(previousSiblingSize - mouseDelta, MIN_PANEL_SIZE);
nextSibling.style.flexGrow = (nextSiblingSize + mouseDelta).toString();
previousSibling.style.flexGrow = (previousSiblingSize - mouseDelta).toString();
window.dispatchEvent(
new CustomEvent("resize", {
detail: {},
})
);
}
document.addEventListener("pointermove", updatePosition);
function cleanup(event: PointerEvent): void {
gutter.releasePointerCapture(event.pointerId);
document.removeEventListener("pointermove", updatePosition);
document.removeEventListener("pointerleave", cleanup);
document.removeEventListener("pointerup", cleanup);
}
document.addEventListener("pointerleave", cleanup);
document.addEventListener("pointerup", cleanup);
},
},
watch: {
activeDocumentIndex(newIndex: number) {
this.$nextTick(() => {
const documentsPanel = this.$refs.documentsPanel as typeof Panel;
const newActiveTab = documentsPanel.$el.querySelectorAll(".tab-bar .tab-group .tab")[newIndex];
newActiveTab.scrollIntoView();
});
},
},
});
</script>