From 07491b9741e2b0ca13bbd95cff9f899d4f22a89a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thea=20Sch=C3=B6bl?= Date: Tue, 31 Mar 2026 19:40:01 +0200 Subject: [PATCH] feat: device flip --- .../components/layout/GenericLayout.svelte | 194 +++++++++++------- src/lib/components/layout/KeyboardKey.svelte | 12 +- 2 files changed, 128 insertions(+), 78 deletions(-) diff --git a/src/lib/components/layout/GenericLayout.svelte b/src/lib/components/layout/GenericLayout.svelte index f4424e53..6369594b 100644 --- a/src/lib/components/layout/GenericLayout.svelte +++ b/src/lib/components/layout/GenericLayout.svelte @@ -14,7 +14,6 @@ CompiledLayout, CompiledLayoutKey, } from "$lib/assets/layouts/layout.d.ts"; - import { setting } from "$lib/setting.js"; const { scale, margin, strokeWidth, fontSize, iconFontSize } = getContext("visual-layout-config"); @@ -120,9 +119,13 @@ } function edit(index: number) { - const keyInfo = layoutInfo.keys[index]; + const keyInfo = + layoutInfo.keys.find(({ id }) => id === index) ?? + layoutInfo.fixedKeys.find(({ id }) => id === index); if (!keyInfo) return; - const clickedGroup = groupParent.children.item(index) as SVGGElement; + const clickedGroup = groupParent.querySelector( + `g[data-id="${index}"]`, + ) as SVGGElement; const nextAction = get(layout)[get(activeProfile)]![get(activeLayer)]?.[keyInfo.id]; const currentAction = @@ -190,7 +193,8 @@ } let focusKey: CompiledLayoutKey; - let groupParent: SVGElement; + let groupParent: SVGGElement; + let rotationTarget: SVGCircleElement; let rotationSetting = $derived( $deviceMeta?.settings .find((it) => it.name === "misc") @@ -201,26 +205,43 @@ ? ($settings[$activeProfile]?.[rotationSetting.id]?.value ?? 90) : 90, ); + + let flippedSetting = $derived( + $deviceMeta?.settings + .find((it) => it.name === "misc") + ?.items.find((it) => it.name === "device orientation"), + ); + let flipped = $derived( + flippedSetting + ? $settings[$activeProfile]?.[flippedSetting.id]?.value !== 0 + : false, + ); + let draggingRotation = $state(90); let isDragging = $state(false); let rotation = $derived(isDragging ? draggingRotation : settingRotation); let dragOffset = 0; function calcDragOffset(event: MouseEvent) { - const offset = groupParent.getBoundingClientRect(); - const centerX = - offset.x + - (layoutInfo.rotationAnchor?.[0] ?? 0) * - scale * - (offset.width / (layoutInfo.size[0] * scale)); - const centerY = - offset.y + - (layoutInfo.rotationAnchor?.[1] ?? 0) * - scale * - (offset.height / (layoutInfo.size[1] * scale)); - return ( - Math.atan2(event.x - centerX, event.y - centerY) * (180 / Math.PI) + 90 - ); + const offset = rotationTarget.getBoundingClientRect(); + const cx = offset.x + offset.width / 2; + const cy = offset.y + offset.height / 2; + const a = Math.atan2(event.x - cx, event.y - cy) * (180 / Math.PI) + 90; + return flipped ? (a + 180) % 360 : a; + } + + function toggleFlip() { + changes.update((changes) => { + changes.push([ + { + type: ChangeType.Setting, + id: flippedSetting!.id, + setting: flipped ? 0 : 1, + profile: get(activeProfile), + }, + ]); + return changes; + }); } function dragRotation(event: MouseEvent) { @@ -261,73 +282,96 @@ - {#each layoutInfo.keys as key, i} - (focusKey = key)} - onclick={() => edit(i)} - onkeypress={({ key }) => { - if (key === "Enter") { - edit(i); - } - }} - /> - {/each} - {#if rotationSetting} - - {#if isDragging} - + {#each layoutInfo.keys as key} + (focusKey = key)} + onclick={() => edit(key.id)} + onkeypress={(event) => { + if (event.key === "Enter") { + edit(key.id); + } + }} + /> + {/each} + {#if rotationSetting} + {rotation - 90}° + stroke="currentColor" + stroke-width={strokeWidth} + /> + {#if isDragging} + {@const x = (layoutInfo.size[0] * scale) / 2} + {@const y = layoutInfo.size[1] * scale + margin * (flipped ? 2 : 3)} + {rotation - 90}° + {/if} {/if} - {/if} - - - {#each layoutInfo.fixedKeys as key, i} - (focusKey = key)} - onclick={() => edit(i)} - onkeypress={({ key }) => { - if (key === "Enter") { - edit(i); - } - }} + + - {/each} + + + {#each layoutInfo.fixedKeys as key} + (focusKey = key)} + onclick={() => edit(key.id)} + onkeypress={(event) => { + if (event.key === "Enter") { + edit(key.id); + } + }} + /> + {/each} + +