www.spaceplanner.app

Web client to the spaceplanner API
git clone git://jacobedwards.org/www.spaceplanner.app
Log | Files | Refs

commit a3f7e11caf8e385e8bda0557f584e810014288cd
parent b20cceac1e920e3729aae9ad1f30beb7c49112fb
Author: Jacob R. Edwards <jacob@jacobedwards.org>
Date:   Thu, 17 Oct 2024 11:59:06 -0700

Add easier multi-selection

There is now a selectionBoxHandler which will select everything
within the box from where you press to where you release.

(This practically required the last change to function; it wouldn't
be able to co-exist with panning and zooming otherwise.)

Diffstat:
Mfiles/floorplans/floorplan/main.js | 98++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 97 insertions(+), 1 deletion(-)

diff --git a/files/floorplans/floorplan/main.js b/files/floorplans/floorplan/main.js @@ -48,7 +48,11 @@ const modes = { points: true, handlers: { contextmenu: preventDefaultHandler, - pointerdown: selectionHandler, + pointerdown: [singlePointerHandler, selectionHandler, selectionBoxHandler], + pointermove: [singlePointerHandler, selectionBoxHandler], + pointerup: [singlePointerHandler, selectionBoxHandler], + pointercancel: [singlePointerHandler, selectionBoxHandler], + keydown: keyHandler, keydown: keyHandler, select: selectHandler, reselect: selectHandler @@ -572,6 +576,90 @@ function selectionHandler(event, editor) { } } +// pointerdown, pointercancel, pointermove, pointerup +function selectionBoxHandler(ev, editor, state) { + const cleanup = function() { + if (state.rect) { + state.rect.remove() + } + for (let k in state) { + delete state[k] + } + } + const useEv = function(ev) { + if (ev.pointerType === "mouse") { + if (ev.type === "pointermove") { + return true + } + return !primaryPointer(ev) + } else { + return primaryPointer(ev) + } + } + + if (ev.type === "pointercancel") { + cleanup() + return + } + + if (ev.type === "pointerdown" && useEv(ev)) { + handled(ev) + let p = editor.draw.point(ev.clientX, ev.clientY) + if (state.rect) { + console.error("selectionBoxHandler state got messed up") + cleanup() + } + state.origin = structuredClone(p) + state.rect = editor.ui.top.rect(0, 0) + .move(p.x, p.y) + .stroke({ width: 50, dasharray: [350, 350], color: "blue" }) + .fill("rgba(0,0,1,.025)") + return + } + + if (!state.rect) { + return + } + + let p = editor.draw.point(ev.clientX, ev.clientY) + if (ev.type === "pointermove" && useEv(ev)) { + handled(ev) + let params = {} + if (state.origin.x > p.x) { + params.x = p.x + params.width = state.origin.x - p.x + } else { + params.x = state.origin.x + params.width = p.x - state.origin.x + } + if (state.origin.y > p.y) { + params.y = p.y + params.height = state.origin.y - p.y + } else { + params.y = state.origin.y + params.height = p.y - state.origin.y + } + state.rect.move(params.x, params.y).size(params.width, params.height) + } else if (ev.type === "pointerup" && useEv(ev)) { + handled(ev) + let objects = editor.draw.find("#floorplan > :not(#furniture_layouts, #door_swings) > *, #furniture_layouts > * > *") + let s = state.rect.rbox(state.rect.root()) + let selection = [] + objects.each(function() { + let b = this.rbox(this.root()) + if (((b.x >= s.x && b.x <= s.x2) || (b.x2 >= s.x && b.x2 <= s.x2)) && + ((b.y >= s.y && b.y <= s.y2) || (b.y2 >= s.y && b.y2 <= s.y2))) { + selection.push(this) + } + + }) + if (selection.length > 0) { + addSelection(editor, selection).selectList() + } + cleanup() + } +} + function keyHandler(ev, editor) { if (ev.key === "Escape") { escape() @@ -1613,6 +1701,14 @@ function escape() { }) } +function primaryPointer(ev) { + if (ev.type === "pointermove") { + return primaryMove(ev) + } else { + return truelyPrimary(ev) + } +} + function truelyPrimary(ev) { if (ev.pointerType === "mouse") { return ev.button === buttons.left