mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-22 17:58:11 +08:00
Polish and add aborting to several input widgets: no Esc closing parent menus; color picker axis align; repeat on arrow buttons (#2276)
* Remove color input outline; reduce antialiasing compositing artifacts in color widgets * Rename ColorButton to ColorInput * Add features and aborting to several other widgets - Prevent Esc from closing parent floating menus when aborting - Fix missing icon regression - Gutter resizing abort - Color picker aborts, Shift axis alignment, improve click/drag behavior for gradient spectrum - Scrollbar abort, repeat when held, fix directional arrows when viewport is zoomed - Number input abort, repeat when held * Move ColorInput into the inputs folder * Fix tiny logo
This commit is contained in:
@@ -28,6 +28,8 @@
|
||||
import TextLabel from "@graphite/components/widgets/labels/TextLabel.svelte";
|
||||
import UserInputLabel from "@graphite/components/widgets/labels/UserInputLabel.svelte";
|
||||
|
||||
const BUTTON_MIDDLE = 1;
|
||||
|
||||
const editor = getContext<Editor>("editor");
|
||||
|
||||
export let tabMinWidths = false;
|
||||
@@ -100,7 +102,7 @@
|
||||
}}
|
||||
on:auxclick={(e) => {
|
||||
// Middle mouse button click
|
||||
if (e.button === 1) {
|
||||
if (e.button === BUTTON_MIDDLE) {
|
||||
e.stopPropagation();
|
||||
closeAction?.(tabIndex);
|
||||
}
|
||||
@@ -110,7 +112,7 @@
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Element/auxclick_event#browser_compatibility
|
||||
// The downside of using mouseup is that the mousedown didn't have to originate in the same element.
|
||||
// A possible future improvement could save the target element during mousedown and check if it's the same here.
|
||||
if (!isEventSupported("auxclick") && e.button === 1) {
|
||||
if (!isEventSupported("auxclick") && e.button === BUTTON_MIDDLE) {
|
||||
e.stopPropagation();
|
||||
closeAction?.(tabIndex);
|
||||
}
|
||||
|
||||
@@ -14,15 +14,17 @@
|
||||
const MIN_PANEL_SIZE = 100;
|
||||
const PANEL_SIZES = {
|
||||
/**/ root: 100,
|
||||
/* ├── */ content: 80,
|
||||
/* │ ├── */ document: 100,
|
||||
/* └── */ details: 20,
|
||||
/* ├── */ properties: 45,
|
||||
/* └── */ layers: 55,
|
||||
/* ├─ */ content: 80,
|
||||
/* │ └─ */ document: 100,
|
||||
/* └─ */ details: 20,
|
||||
/* ├─ */ properties: 45,
|
||||
/* └─ */ layers: 55,
|
||||
};
|
||||
|
||||
let panelSizes = PANEL_SIZES;
|
||||
let documentPanel: Panel | undefined;
|
||||
let gutterResizeRestore: [number, number] | undefined = undefined;
|
||||
let pointerCaptureId: number | undefined = undefined;
|
||||
|
||||
$: documentPanel?.scrollTabIntoView($portfolio.activeDocumentIndex);
|
||||
|
||||
@@ -64,32 +66,68 @@
|
||||
const proportionBeingResized = totalResizingSpaceOccupied / parentElementSize;
|
||||
|
||||
// Prevent cursor flicker as mouse temporarily leaves the gutter
|
||||
gutter.setPointerCapture(e.pointerId);
|
||||
pointerCaptureId = e.pointerId;
|
||||
gutter.setPointerCapture(pointerCaptureId);
|
||||
|
||||
const mouseStart = isHorizontal ? e.clientX : e.clientY;
|
||||
|
||||
const updatePosition = (e: PointerEvent) => {
|
||||
const abortResize = () => {
|
||||
if (pointerCaptureId) gutter.releasePointerCapture(pointerCaptureId);
|
||||
removeListeners();
|
||||
|
||||
pointerCaptureId = e.pointerId;
|
||||
gutter.setPointerCapture(pointerCaptureId);
|
||||
|
||||
if (gutterResizeRestore !== undefined) {
|
||||
panelSizes[nextSiblingName] = gutterResizeRestore[0];
|
||||
panelSizes[prevSiblingName] = gutterResizeRestore[1];
|
||||
gutterResizeRestore = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
const onPointerMove = (e: PointerEvent) => {
|
||||
const mouseCurrent = isHorizontal ? e.clientX : e.clientY;
|
||||
let mouseDelta = mouseStart - mouseCurrent;
|
||||
|
||||
mouseDelta = Math.max(nextSiblingSize + mouseDelta, MIN_PANEL_SIZE) - nextSiblingSize;
|
||||
mouseDelta = prevSiblingSize - Math.max(prevSiblingSize - mouseDelta, MIN_PANEL_SIZE);
|
||||
|
||||
if (gutterResizeRestore === undefined) gutterResizeRestore = [panelSizes[nextSiblingName], panelSizes[prevSiblingName]];
|
||||
|
||||
panelSizes[nextSiblingName] = ((nextSiblingSize + mouseDelta) / totalResizingSpaceOccupied) * proportionBeingResized * 100;
|
||||
panelSizes[prevSiblingName] = ((prevSiblingSize - mouseDelta) / totalResizingSpaceOccupied) * proportionBeingResized * 100;
|
||||
};
|
||||
|
||||
const cleanup = (e: PointerEvent) => {
|
||||
gutter.releasePointerCapture(e.pointerId);
|
||||
|
||||
document.removeEventListener("pointermove", updatePosition);
|
||||
document.removeEventListener("pointerleave", cleanup);
|
||||
document.removeEventListener("pointerup", cleanup);
|
||||
const onPointerUp = () => {
|
||||
gutterResizeRestore = undefined;
|
||||
if (pointerCaptureId) gutter.releasePointerCapture(pointerCaptureId);
|
||||
removeListeners();
|
||||
};
|
||||
|
||||
document.addEventListener("pointermove", updatePosition);
|
||||
document.addEventListener("pointerleave", cleanup);
|
||||
document.addEventListener("pointerup", cleanup);
|
||||
const onMouseDown = (e: MouseEvent) => {
|
||||
const BUTTONS_RIGHT = 0b0000_0010;
|
||||
if (e.buttons & BUTTONS_RIGHT) abortResize();
|
||||
};
|
||||
|
||||
const onKeyDown = (e: KeyboardEvent) => {
|
||||
if (e.key === "Escape") abortResize();
|
||||
};
|
||||
|
||||
const addListeners = () => {
|
||||
document.addEventListener("pointermove", onPointerMove);
|
||||
document.addEventListener("pointerup", onPointerUp);
|
||||
document.addEventListener("mousedown", onMouseDown);
|
||||
document.addEventListener("keydown", onKeyDown);
|
||||
};
|
||||
|
||||
const removeListeners = () => {
|
||||
document.removeEventListener("pointermove", onPointerMove);
|
||||
document.removeEventListener("pointerup", onPointerUp);
|
||||
document.removeEventListener("mousedown", onMouseDown);
|
||||
document.removeEventListener("keydown", onKeyDown);
|
||||
};
|
||||
|
||||
addListeners();
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user