resize panels

This commit is contained in:
vcoppe
2024-06-25 16:06:11 +02:00
parent ad6b1900a1
commit 852f77cf7c
7 changed files with 111 additions and 39 deletions

View File

@@ -8,11 +8,12 @@
import Toolbar from '$lib/components/toolbar/Toolbar.svelte';
import StreetViewControl from '$lib/components/street-view-control/StreetViewControl.svelte';
import LayerControl from '$lib/components/layer-control/LayerControl.svelte';
import Resizer from '$lib/components/Resizer.svelte';
import { Toaster } from '$lib/components/ui/sonner';
import { settings } from '$lib/db';
const { verticalFileView, elevationProfile } = settings;
const { verticalFileView, elevationProfile, bottomPanelSize, rightPanelSize } = settings;
</script>
<div class="fixed flex flex-row w-screen h-screen">
@@ -31,7 +32,13 @@
</div>
{/if}
</div>
<div class="{$elevationProfile ? 'h-48' : 'h-10'} flex flex-row gap-2 overflow-hidden">
{#if $elevationProfile}
<Resizer orientation="row" bind:after={$bottomPanelSize} minAfter={100} maxAfter={300} />
{/if}
<div
class="{$elevationProfile ? '' : 'h-10'} flex flex-row gap-2"
style={$elevationProfile ? `height: ${$bottomPanelSize}px` : ''}
>
<GPXStatistics />
{#if $elevationProfile}
<ElevationProfile />
@@ -39,7 +46,8 @@
</div>
</div>
{#if $verticalFileView}
<FileList orientation="vertical" recursive={true} class="w-60" />
<Resizer orientation="col" bind:after={$rightPanelSize} minAfter={100} maxAfter={400} />
<FileList orientation="vertical" recursive={true} style="width: {$rightPanelSize}px" />
{/if}
</div>

View File

@@ -57,7 +57,7 @@
let marker: mapboxgl.Marker | null = null;
let dragging = false;
let { distanceUnits, velocityUnits, temperatureUnits } = settings;
let { distanceUnits, velocityUnits, temperatureUnits, bottomPanelSize } = settings;
let options = {
animation: false,
@@ -116,8 +116,8 @@
if (dragging) {
marker.remove();
} else {
marker.addTo($map);
marker.setLngLat(point.coordinates);
marker.addTo($map);
}
}
return `${$_('quantities.elevation')}: ${getElevationWithUnits(point.y, false)}`;
@@ -520,12 +520,16 @@
</script>
<div class="h-full grow min-w-0 flex flex-row gap-4 items-center py-2 pr-4">
<div class="h-full grow min-w-0">
<div class="grow h-full min-w-0">
<canvas bind:this={overlay} class="absolute pointer-events-none"></canvas>
<canvas bind:this={canvas} class="w-full h-full"></canvas>
</div>
<div class="w-fit flex flex-col border rounded">
<ToggleGroup.Root class="flex-col gap-0" type="single" bind:value={elevationFill}>
<div class="h-full flex flex-col justify-center">
<ToggleGroup.Root
class="flex-col flex-wrap gap-0 min-h-0 content-center border rounded-t"
type="single"
bind:value={elevationFill}
>
<ToggleGroup.Item class="p-0 w-6 h-6" value="slope">
<Tooltip side="left">
<TriangleRight slot="data" size="16" />
@@ -539,8 +543,11 @@
</Tooltip>
</ToggleGroup.Item>
</ToggleGroup.Root>
<Separator />
<ToggleGroup.Root class="flex-col gap-0" type="multiple" bind:value={additionalDatasets}>
<ToggleGroup.Root
class="flex-col flex-wrap gap-0 min-h-0 content-center border rounded-b -mt-[1px]"
type="multiple"
bind:value={additionalDatasets}
>
<ToggleGroup.Item class="p-0 w-6 h-6" value="speed">
<Tooltip side="left">
<Zap slot="data" size="16" />

View File

@@ -11,7 +11,7 @@
import { _ } from 'svelte-i18n';
import type { GPXStatistics } from 'gpx';
const { velocityUnits, elevationProfile } = settings;
const { velocityUnits, elevationProfile, bottomPanelSize } = settings;
let statistics: GPXStatistics;
@@ -48,29 +48,33 @@
</span>
<span slot="tooltip">{$_('quantities.elevation')}</span>
</Tooltip>
<Tooltip>
<span slot="data" class="flex flex-row items-center">
<Zap size="18" class="mr-1" />
<WithUnits value={statistics.global.speed.moving} type="speed" showUnits={false} />
<span class="mx-1">/</span>
<WithUnits value={statistics.global.speed.total} type="speed" />
</span>
<span slot="tooltip"
>{$velocityUnits === 'speed' ? $_('quantities.speed') : $_('quantities.pace')} ({$_(
'quantities.moving'
)} / {$_('quantities.total')})</span
>
</Tooltip>
<Tooltip>
<span slot="data" class="flex flex-row items-center">
<Timer size="18" class="mr-1" />
<WithUnits value={statistics.global.time.moving} type="time" />
<span class="mx-1">/</span>
<WithUnits value={statistics.global.time.total} type="time" />
</span>
<span slot="tooltip"
>{$_('quantities.time')} ({$_('quantities.moving')} / {$_('quantities.total')})</span
>
</Tooltip>
{#if $bottomPanelSize > 120 || !$elevationProfile}
<Tooltip>
<span slot="data" class="flex flex-row items-center">
<Zap size="18" class="mr-1" />
<WithUnits value={statistics.global.speed.moving} type="speed" showUnits={false} />
<span class="mx-1">/</span>
<WithUnits value={statistics.global.speed.total} type="speed" />
</span>
<span slot="tooltip"
>{$velocityUnits === 'speed' ? $_('quantities.speed') : $_('quantities.pace')} ({$_(
'quantities.moving'
)} / {$_('quantities.total')})</span
>
</Tooltip>
{/if}
{#if $bottomPanelSize > 160 || !$elevationProfile}
<Tooltip>
<span slot="data" class="flex flex-row items-center">
<Timer size="18" class="mr-1" />
<WithUnits value={statistics.global.time.moving} type="time" />
<span class="mx-1">/</span>
<WithUnits value={statistics.global.time.total} type="time" />
</span>
<span slot="tooltip"
>{$_('quantities.time')} ({$_('quantities.moving')} / {$_('quantities.total')})</span
>
</Tooltip>
{/if}
</Card.Content>
</Card.Root>

View File

@@ -21,7 +21,8 @@
easing: () => 1
};
const { distanceUnits, elevationProfile, verticalFileView } = settings;
const { distanceUnits, elevationProfile, verticalFileView, bottomPanelSize, rightPanelSize } =
settings;
let scaleControl = new mapboxgl.ScaleControl({
unit: $distanceUnits
});
@@ -117,7 +118,10 @@
scaleControl.setUnit($distanceUnits);
}
$: if ($map && (!$verticalFileView || !$elevationProfile)) {
$: if (
$map &&
(!$verticalFileView || !$elevationProfile || $bottomPanelSize || $rightPanelSize)
) {
$map.resize();
}
</script>

View File

@@ -0,0 +1,40 @@
<script lang="ts">
export let orientation: 'col' | 'row' = 'col';
export let after: number;
export let minAfter: number = 0;
export let maxAfter: number = Number.MAX_SAFE_INTEGER;
function handleMouseDown(event: MouseEvent) {
const startX = event.clientX;
const startY = event.clientY;
const startAfter = after;
const handleMouseMove = (event: MouseEvent) => {
const newAfter =
startAfter + (orientation === 'col' ? startX - event.clientX : startY - event.clientY);
if (newAfter >= minAfter && newAfter <= maxAfter) {
after = newAfter;
} else if (newAfter < minAfter && after !== minAfter) {
after = minAfter;
} else if (newAfter > maxAfter && after !== maxAfter) {
after = maxAfter;
}
};
const handleMouseUp = () => {
window.removeEventListener('mousemove', handleMouseMove);
window.removeEventListener('mouseup', handleMouseUp);
};
window.addEventListener('mousemove', handleMouseMove);
window.addEventListener('mouseup', handleMouseUp);
}
</script>
<div
class="{orientation === 'col'
? 'w-1 h-full cursor-col-resize'
: 'w-full h-1 cursor-row-resize'} {orientation}"
on:mousedown={handleMouseDown}
/>

View File

@@ -53,6 +53,7 @@
class="flex {orientation === 'vertical'
? 'flex-col py-1 pl-1 min-h-screen'
: 'flex-row'} {$$props.class ?? ''}"
{...$$restProps}
>
<FileListNode bind:node={$fileObservers} item={new ListRootItem()} />
{#if orientation === 'vertical'}

View File

@@ -47,10 +47,16 @@ function dexieSettingStore<T>(setting: string, initial: T): Writable<T> {
});
return {
subscribe: store.subscribe,
set: (value: any) => db.settings.put(value, setting),
set: (value: any) => {
if (value !== get(store)) {
db.settings.put(value, setting);
}
},
update: (callback: (value: any) => any) => {
let newValue = callback(get(store));
db.settings.put(newValue, setting);
if (newValue !== get(store)) {
db.settings.put(newValue, setting);
}
}
};
}
@@ -105,6 +111,8 @@ export const settings = {
fileOrder: dexieSettingStore<string[]>('fileOrder', []),
defaultOpacity: dexieSettingStore('defaultOpacity', 0.7),
defaultWeight: dexieSettingStore('defaultWeight', 5),
bottomPanelSize: dexieSettingStore('bottomPanelSize', 192),
rightPanelSize: dexieSettingStore('rightPanelSize', 240),
};
// Wrap Dexie live queries in a Svelte store to avoid triggering the query for every subscriber