mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-26 10:38:11 +08:00
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>
This commit is contained in:
co-authored by
otdavies
Keavon Chambers
parent
54e9121115
commit
a2c2f7fc9d
@@ -330,6 +330,7 @@ mod test {
|
|||||||
assert_eq!(&layers_after_copy[4], rect_before_copy);
|
assert_eq!(&layers_after_copy[4], rect_before_copy);
|
||||||
assert_eq!(&layers_after_copy[5], ellipse_before_copy);
|
assert_eq!(&layers_after_copy[5], ellipse_before_copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore] // TODO: Re-enable test, see issue #444 (https://github.com/GraphiteEditor/Graphite/pull/444)
|
#[ignore] // TODO: Re-enable test, see issue #444 (https://github.com/GraphiteEditor/Graphite/pull/444)
|
||||||
/// - create rect, shape and ellipse
|
/// - create rect, shape and ellipse
|
||||||
|
|||||||
@@ -241,7 +241,7 @@ declare module "@vue/runtime-core" {
|
|||||||
editor: EditorState;
|
editor: EditorState;
|
||||||
// This must be set to optional because there is a time in the lifecycle of the component where inputManager is undefined.
|
// This must be set to optional because there is a time in the lifecycle of the component where inputManager is undefined.
|
||||||
// That's because we initialize inputManager in `mounted()` rather than `data()` since the div hasn't been created yet.
|
// That's because we initialize inputManager in `mounted()` rather than `data()` since the div hasn't been created yet.
|
||||||
inputManger?: InputManager;
|
inputManager?: InputManager;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<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">
|
||||||
<Panel
|
<Panel
|
||||||
:panelType="'Document'"
|
:panelType="'Document'"
|
||||||
:tabCloseButtons="true"
|
:tabCloseButtons="true"
|
||||||
@@ -22,12 +22,12 @@
|
|||||||
ref="documentsPanel"
|
ref="documentsPanel"
|
||||||
/>
|
/>
|
||||||
</LayoutCol>
|
</LayoutCol>
|
||||||
<LayoutCol class="workspace-grid-resize-gutter"></LayoutCol>
|
<LayoutCol class="workspace-grid-resize-gutter" @pointerdown="resizePanel($event)"></LayoutCol>
|
||||||
<LayoutCol class="workspace-grid-subdivision" style="flex-grow: 319">
|
<LayoutCol class="workspace-grid-subdivision" style="flex-grow: 0.17">
|
||||||
<LayoutRow class="workspace-grid-subdivision" style="flex-grow: 402">
|
<LayoutRow class="workspace-grid-subdivision" style="flex-grow: 402">
|
||||||
<Panel :panelType="'Properties'" :tabLabels="['Properties']" :tabActiveIndex="0" />
|
<Panel :panelType="'Properties'" :tabLabels="['Properties']" :tabActiveIndex="0" />
|
||||||
</LayoutRow>
|
</LayoutRow>
|
||||||
<LayoutRow class="workspace-grid-resize-gutter"></LayoutRow>
|
<LayoutRow class="workspace-grid-resize-gutter" @pointerdown="resizePanel($event)"></LayoutRow>
|
||||||
<LayoutRow class="workspace-grid-subdivision" style="flex-grow: 590">
|
<LayoutRow class="workspace-grid-subdivision" style="flex-grow: 590">
|
||||||
<Panel :panelType="'LayerTree'" :tabLabels="['Layer Tree']" :tabActiveIndex="0" />
|
<Panel :panelType="'LayerTree'" :tabLabels="['Layer Tree']" :tabActiveIndex="0" />
|
||||||
</LayoutRow>
|
</LayoutRow>
|
||||||
@@ -72,6 +72,8 @@ import LayoutRow from "@/components/layout/LayoutRow.vue";
|
|||||||
import DialogModal from "@/components/widgets/floating-menus/DialogModal.vue";
|
import DialogModal from "@/components/widgets/floating-menus/DialogModal.vue";
|
||||||
import Panel from "@/components/workspace/Panel.vue";
|
import Panel from "@/components/workspace/Panel.vue";
|
||||||
|
|
||||||
|
const MIN_PANEL_SIZE = 100;
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
inject: ["documents", "dialog", "editor"],
|
inject: ["documents", "dialog", "editor"],
|
||||||
components: {
|
components: {
|
||||||
@@ -85,6 +87,54 @@ export default defineComponent({
|
|||||||
return this.documents.state.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: {
|
watch: {
|
||||||
activeDocumentIndex(newIndex: number) {
|
activeDocumentIndex(newIndex: number) {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user