diff --git a/src/base/dom/pan-and-zoom.ts b/src/base/dom/pan-and-zoom.ts index 476110f..65ed895 100644 --- a/src/base/dom/pan-and-zoom.ts +++ b/src/base/dom/pan-and-zoom.ts @@ -5,6 +5,7 @@ */ import { BBox, Camera2, Vec2 } from "../math"; +import { Preferences } from "../../kicanvas/preferences"; const line_delta_multiplier = 8; const page_delta_multiplier = 24; @@ -12,6 +13,7 @@ const zoom_speed = 0.005; const pan_speed = 1; export type PanAndZoomCallback = () => void; +const prefs = Preferences.INSTANCE; /** * Interactive Pan and Zoom helper @@ -84,6 +86,38 @@ export class PanAndZoom { startDistance = null; startPosition = null; }); + + let dragStartPosition: Vec2 | null = null; + let dragging = false; + + this.target.addEventListener("mousedown", (e: MouseEvent) => { + if (e.button === 1 || e.button === 2) { + e.preventDefault(); + dragging = true; + dragStartPosition = new Vec2(e.clientX, e.clientY); + } + }); + + this.target.addEventListener("mousemove", (e: MouseEvent) => { + if (dragging && dragStartPosition !== null) { + const currentPosition = new Vec2(e.clientX, e.clientY); + const delta = currentPosition.sub(dragStartPosition); + this.#handle_pan(-delta.x, -delta.y); + dragStartPosition = currentPosition; + } + }); + + this.target.addEventListener("mouseup", (e: MouseEvent) => { + if (e.button === 1 || e.button === 2) { + dragging = false; + dragStartPosition = null; + } + }); + + // Prevent the browser's default context menu. + this.target.addEventListener("contextmenu", (e) => { + e.preventDefault(); + }); } #getDistanceBetweenTouches(touches: TouchList) { @@ -102,8 +136,14 @@ export class PanAndZoom { let dy = e.deltaY; // shift modifier flips the X and Y axes (horizontal scroll) - if (dx == 0 && e.shiftKey) { - [dx, dy] = [dy, dx]; + if (!prefs.alignControlsWithKiCad) { + if (dx == 0 && e.shiftKey) { + [dx, dy] = [dy, dx]; + } + } else { + if (dx == 0 && e.ctrlKey) { + [dx, dy] = [dy, dx]; + } } // work around line/page scrolling @@ -119,14 +159,25 @@ export class PanAndZoom { dx = Math.sign(dx) * Math.min(page_delta_multiplier, Math.abs(dx)); dy = Math.sign(dy) * Math.min(page_delta_multiplier, Math.abs(dy)); - // pinch zoom - if (e.ctrlKey) { - this.#rect = this.target.getBoundingClientRect(); - this.#handle_zoom(dy, this.#relative_mouse_pos(e)); - } - // pan - else { - this.#handle_pan(dx, dy); + if (!prefs.alignControlsWithKiCad) { + // pinch zoom + if (e.ctrlKey) { + this.#rect = this.target.getBoundingClientRect(); + this.#handle_zoom(dy, this.#relative_mouse_pos(e)); + } + // pan + else { + this.#handle_pan(dx, dy); + } + } else { + if (e.shiftKey || e.ctrlKey) { + this.#handle_pan(-dx, dy); + } + // pinch zoom + else { + this.#rect = this.target.getBoundingClientRect(); + this.#handle_zoom(dy, this.#relative_mouse_pos(e)); + } } this.target.dispatchEvent( diff --git a/src/kicanvas/elements/common/preferences-panel.ts b/src/kicanvas/elements/common/preferences-panel.ts index e269244..b8c28d3 100644 --- a/src/kicanvas/elements/common/preferences-panel.ts +++ b/src/kicanvas/elements/common/preferences-panel.ts @@ -63,7 +63,14 @@ export class KCPreferencesPanel extends KCUIElement { override initialContentCallback() { this.renderRoot.addEventListener("input", (e) => { - prefs.theme = themes.by_name(this.theme_control.value); + const target = e.target as HTMLInputElement; + + if (target.name === "theme") { + prefs.theme = themes.by_name(this.theme_control.value); + } + if (target.name === "align-controls-kicad") { + prefs.alignControlsWithKiCad = target.checked; + } prefs.save(); }); } @@ -89,6 +96,15 @@ export class KCPreferencesPanel extends KCUIElement { + + + `; diff --git a/src/kicanvas/preferences.ts b/src/kicanvas/preferences.ts index 5406193..d2d011d 100644 --- a/src/kicanvas/preferences.ts +++ b/src/kicanvas/preferences.ts @@ -17,9 +17,11 @@ export class Preferences extends EventTarget { private storage = new LocalStorage("kc:prefs"); public theme: Theme = themes.default; + public alignControlsWithKiCad: boolean = true; public save() { this.storage.set("theme", this.theme.name); + this.storage.set("alignControlsWithKiCad", this.alignControlsWithKiCad); this.dispatchEvent(new PreferencesChangeEvent({ preferences: this })); } @@ -27,6 +29,10 @@ export class Preferences extends EventTarget { this.theme = themes.by_name( this.storage.get("theme", themes.default.name), ); + this.alignControlsWithKiCad = this.storage.get( + "alignControlsWithKiCad", + false, + ); } }