Skip to content

Commit a2c2f7f

Browse files
0HyperCubeotdaviesKeavon
authored
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 <[email protected]> Co-authored-by: Keavon Chambers <[email protected]>
1 parent 54e9121 commit a2c2f7f

File tree

3 files changed

+56
-5
lines changed

3 files changed

+56
-5
lines changed

editor/src/communication/dispatcher.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@ mod test {
330330
assert_eq!(&layers_after_copy[4], rect_before_copy);
331331
assert_eq!(&layers_after_copy[5], ellipse_before_copy);
332332
}
333+
333334
#[test]
334335
#[ignore] // TODO: Re-enable test, see issue #444 (https://github.com/GraphiteEditor/Graphite/pull/444)
335336
/// - create rect, shape and ellipse

frontend/src/App.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ declare module "@vue/runtime-core" {
241241
editor: EditorState;
242242
// This must be set to optional because there is a time in the lifecycle of the component where inputManager is undefined.
243243
// That's because we initialize inputManager in `mounted()` rather than `data()` since the div hasn't been created yet.
244-
inputManger?: InputManager;
244+
inputManager?: InputManager;
245245
}
246246
}
247247

frontend/src/components/workspace/Workspace.vue

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
22
<LayoutRow class="workspace-grid-subdivision">
3-
<LayoutCol class="workspace-grid-subdivision" style="flex-grow: 1597">
3+
<LayoutCol class="workspace-grid-subdivision">
44
<Panel
55
:panelType="'Document'"
66
:tabCloseButtons="true"
@@ -22,12 +22,12 @@
2222
ref="documentsPanel"
2323
/>
2424
</LayoutCol>
25-
<LayoutCol class="workspace-grid-resize-gutter"></LayoutCol>
26-
<LayoutCol class="workspace-grid-subdivision" style="flex-grow: 319">
25+
<LayoutCol class="workspace-grid-resize-gutter" @pointerdown="resizePanel($event)"></LayoutCol>
26+
<LayoutCol class="workspace-grid-subdivision" style="flex-grow: 0.17">
2727
<LayoutRow class="workspace-grid-subdivision" style="flex-grow: 402">
2828
<Panel :panelType="'Properties'" :tabLabels="['Properties']" :tabActiveIndex="0" />
2929
</LayoutRow>
30-
<LayoutRow class="workspace-grid-resize-gutter"></LayoutRow>
30+
<LayoutRow class="workspace-grid-resize-gutter" @pointerdown="resizePanel($event)"></LayoutRow>
3131
<LayoutRow class="workspace-grid-subdivision" style="flex-grow: 590">
3232
<Panel :panelType="'LayerTree'" :tabLabels="['Layer Tree']" :tabActiveIndex="0" />
3333
</LayoutRow>
@@ -72,6 +72,8 @@ import LayoutRow from "@/components/layout/LayoutRow.vue";
7272
import DialogModal from "@/components/widgets/floating-menus/DialogModal.vue";
7373
import Panel from "@/components/workspace/Panel.vue";
7474
75+
const MIN_PANEL_SIZE = 100;
76+
7577
export default defineComponent({
7678
inject: ["documents", "dialog", "editor"],
7779
components: {
@@ -85,6 +87,54 @@ export default defineComponent({
8587
return this.documents.state.activeDocumentIndex;
8688
},
8789
},
90+
methods: {
91+
resizePanel(event: PointerEvent) {
92+
const gutter = event.target as HTMLElement;
93+
const nextSibling = gutter.nextElementSibling as HTMLElement;
94+
const previousSibling = gutter.previousElementSibling as HTMLElement;
95+
96+
// Are we resizing horizontally?
97+
const horizontal = gutter.classList.contains("layout-col");
98+
99+
// Get the current size in px of the panels being resized
100+
const nextSiblingSize = horizontal ? nextSibling.getBoundingClientRect().width : nextSibling.getBoundingClientRect().height;
101+
const previousSiblingSize = horizontal ? previousSibling.getBoundingClientRect().width : previousSibling.getBoundingClientRect().height;
102+
103+
// Prevent cursor flicker as mouse temporarily leaves the gutter
104+
gutter.setPointerCapture(event.pointerId);
105+
106+
const mouseStart = horizontal ? event.clientX : event.clientY;
107+
108+
function updatePosition(event: PointerEvent): void {
109+
const mouseCurrent = horizontal ? event.clientX : event.clientY;
110+
let mouseDelta = mouseStart - mouseCurrent;
111+
112+
mouseDelta = Math.max(nextSiblingSize + mouseDelta, MIN_PANEL_SIZE) - nextSiblingSize;
113+
mouseDelta = previousSiblingSize - Math.max(previousSiblingSize - mouseDelta, MIN_PANEL_SIZE);
114+
115+
nextSibling.style.flexGrow = (nextSiblingSize + mouseDelta).toString();
116+
previousSibling.style.flexGrow = (previousSiblingSize - mouseDelta).toString();
117+
118+
window.dispatchEvent(
119+
new CustomEvent("resize", {
120+
detail: {},
121+
})
122+
);
123+
}
124+
125+
document.addEventListener("pointermove", updatePosition);
126+
127+
function cleanup(event: PointerEvent): void {
128+
gutter.releasePointerCapture(event.pointerId);
129+
document.removeEventListener("pointermove", updatePosition);
130+
document.removeEventListener("pointerleave", cleanup);
131+
document.removeEventListener("pointerup", cleanup);
132+
}
133+
134+
document.addEventListener("pointerleave", cleanup);
135+
document.addEventListener("pointerup", cleanup);
136+
},
137+
},
88138
watch: {
89139
activeDocumentIndex(newIndex: number) {
90140
this.$nextTick(() => {

0 commit comments

Comments
 (0)