Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add mouse drag panning support and align wheel behavior with KiCad #85

Merged
merged 2 commits into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 61 additions & 10 deletions src/base/dom/pan-and-zoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
*/

import { BBox, Camera2, Vec2 } from "../math";
import { Preferences } from "../../kicanvas/preferences";

const line_delta_multiplier = 8;
const page_delta_multiplier = 24;
const zoom_speed = 0.005;
const pan_speed = 1;

export type PanAndZoomCallback = () => void;
const prefs = Preferences.INSTANCE;

/**
* Interactive Pan and Zoom helper
Expand Down Expand Up @@ -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) {
Expand All @@ -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
Expand All @@ -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(
Expand Down
18 changes: 17 additions & 1 deletion src/kicanvas/elements/common/preferences-panel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});
}
Expand All @@ -89,6 +96,15 @@ export class KCPreferencesPanel extends KCUIElement {
</select>
</kc-ui-control>
</kc-ui-control-list>
<kc-ui-control>
<label>
<input
type="checkbox"
name="align-controls-kicad"
checked="${prefs.alignControlsWithKiCad}" />
Align controls with KiCad
</label>
</kc-ui-control>
</kc-ui-panel-body>
</kc-ui-panel>
`;
Expand Down
6 changes: 6 additions & 0 deletions src/kicanvas/preferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,22 @@ 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 }));
}

public load() {
this.theme = themes.by_name(
this.storage.get("theme", themes.default.name),
);
this.alignControlsWithKiCad = this.storage.get(
"alignControlsWithKiCad",
false,
);
}
}

Expand Down
Loading