mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2025-08-31 23:53:25 +00:00
delete waypoint
This commit is contained in:
@@ -2,7 +2,7 @@ import { currentTool, Tool } from "$lib/stores";
|
|||||||
import { settings, type GPXFileWithStatistics, dbUtils } from "$lib/db";
|
import { settings, type GPXFileWithStatistics, dbUtils } from "$lib/db";
|
||||||
import { get, type Readable } from "svelte/store";
|
import { get, type Readable } from "svelte/store";
|
||||||
import mapboxgl from "mapbox-gl";
|
import mapboxgl from "mapbox-gl";
|
||||||
import { currentPopupWaypoint, waypointPopup } from "./WaypointPopup";
|
import { currentPopupWaypoint, deleteWaypoint, waypointPopup } from "./WaypointPopup";
|
||||||
import { addSelectItem, selectItem, selection } from "$lib/components/file-list/Selection";
|
import { addSelectItem, selectItem, selection } from "$lib/components/file-list/Selection";
|
||||||
import { ListTrackSegmentItem, ListWaypointItem, ListWaypointsItem, ListTrackItem, ListFileItem, ListRootItem } from "$lib/components/file-list/FileList";
|
import { ListTrackSegmentItem, ListWaypointItem, ListWaypointsItem, ListTrackItem, ListFileItem, ListRootItem } from "$lib/components/file-list/FileList";
|
||||||
import type { Waypoint } from "gpx";
|
import type { Waypoint } from "gpx";
|
||||||
@@ -57,9 +57,10 @@ export class GPXLayer {
|
|||||||
unsubscribe: Function[] = [];
|
unsubscribe: Function[] = [];
|
||||||
|
|
||||||
updateBinded: () => void = this.update.bind(this);
|
updateBinded: () => void = this.update.bind(this);
|
||||||
layerOnMouseEnterBinded: () => void = this.layerOnMouseEnter.bind(this);
|
layerOnMouseEnterBinded: (e: any) => void = this.layerOnMouseEnter.bind(this);
|
||||||
layerOnMouseLeaveBinded: () => void = this.layerOnMouseLeave.bind(this);
|
layerOnMouseLeaveBinded: () => void = this.layerOnMouseLeave.bind(this);
|
||||||
layerOnClickBinded: (e: any) => void = this.layerOnClick.bind(this);
|
layerOnClickBinded: (e: any) => void = this.layerOnClick.bind(this);
|
||||||
|
maybeHideWaypointPopupBinded: (e: any) => void = this.maybeHideWaypointPopup.bind(this);
|
||||||
|
|
||||||
constructor(map: mapboxgl.Map, fileId: string, file: Readable<GPXFileWithStatistics | undefined>) {
|
constructor(map: mapboxgl.Map, fileId: string, file: Readable<GPXFileWithStatistics | undefined>) {
|
||||||
this.map = map;
|
this.map = map;
|
||||||
@@ -183,16 +184,19 @@ export class GPXLayer {
|
|||||||
this.showWaypointPopup(marker._waypoint);
|
this.showWaypointPopup(marker._waypoint);
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
});
|
});
|
||||||
marker.getElement().addEventListener('mouseout', () => {
|
|
||||||
this.hideWaypointPopup();
|
|
||||||
});
|
|
||||||
marker.getElement().addEventListener('click', (e) => {
|
marker.getElement().addEventListener('click', (e) => {
|
||||||
if (dragEndTimestamp && Date.now() - dragEndTimestamp < 1000) {
|
if (dragEndTimestamp && Date.now() - dragEndTimestamp < 1000) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (get(currentTool) === Tool.WAYPOINT && e.shiftKey) {
|
||||||
|
deleteWaypoint(this.fileId, marker._waypoint._data.index);
|
||||||
|
e.stopPropagation();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (get(verticalFileView)) {
|
if (get(verticalFileView)) {
|
||||||
if ((e.shiftKey || e.ctrlKey || e.metaKey) && get(selection).hasAnyChildren(new ListWaypointsItem(this.fileId), false)) {
|
if ((e.ctrlKey || e.metaKey) && get(selection).hasAnyChildren(new ListWaypointsItem(this.fileId), false)) {
|
||||||
addSelectItem(new ListWaypointItem(this.fileId, marker._waypoint._data.index));
|
addSelectItem(new ListWaypointItem(this.fileId, marker._waypoint._data.index));
|
||||||
} else {
|
} else {
|
||||||
selectItem(new ListWaypointItem(this.fileId, marker._waypoint._data.index));
|
selectItem(new ListWaypointItem(this.fileId, marker._waypoint._data.index));
|
||||||
@@ -310,7 +314,7 @@ export class GPXLayer {
|
|||||||
item = new ListFileItem(this.fileId);
|
item = new ListFileItem(this.fileId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.originalEvent.shiftKey || e.originalEvent.ctrlKey || e.originalEvent.metaKey) {
|
if (e.originalEvent.ctrlKey || e.originalEvent.metaKey) {
|
||||||
addSelectItem(item);
|
addSelectItem(item);
|
||||||
} else {
|
} else {
|
||||||
selectItem(item);
|
selectItem(item);
|
||||||
@@ -318,19 +322,35 @@ export class GPXLayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
showWaypointPopup(waypoint: Waypoint) {
|
showWaypointPopup(waypoint: Waypoint) {
|
||||||
|
if (get(currentPopupWaypoint) !== null) {
|
||||||
|
this.hideWaypointPopup();
|
||||||
|
}
|
||||||
let marker = this.markers[waypoint._data.index];
|
let marker = this.markers[waypoint._data.index];
|
||||||
if (marker) {
|
if (marker) {
|
||||||
currentPopupWaypoint.set(waypoint);
|
currentPopupWaypoint.set([waypoint, this.fileId]);
|
||||||
marker.setPopup(waypointPopup);
|
marker.setPopup(waypointPopup);
|
||||||
marker.togglePopup();
|
marker.togglePopup();
|
||||||
|
this.map.on('mousemove', this.maybeHideWaypointPopupBinded);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
maybeHideWaypointPopup(e: any) {
|
||||||
|
let waypoint = get(currentPopupWaypoint)?.[0];
|
||||||
|
if (waypoint) {
|
||||||
|
let marker = this.markers[waypoint._data.index];
|
||||||
|
if (this.map.project(marker.getLngLat()).dist(this.map.project(e.lngLat)) > 100) {
|
||||||
|
this.hideWaypointPopup();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hideWaypointPopup() {
|
hideWaypointPopup() {
|
||||||
let waypoint = get(currentPopupWaypoint);
|
let waypoint = get(currentPopupWaypoint)?.[0];
|
||||||
if (waypoint) {
|
if (waypoint) {
|
||||||
let marker = this.markers[waypoint._data.index];
|
let marker = this.markers[waypoint._data.index];
|
||||||
marker?.getPopup()?.remove();
|
marker?.getPopup()?.remove();
|
||||||
|
currentPopupWaypoint.set(null);
|
||||||
|
this.map.off('mousemove', this.maybeHideWaypointPopupBinded);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,10 +1,12 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import * as Card from '$lib/components/ui/card';
|
import * as Card from '$lib/components/ui/card';
|
||||||
import { waypointPopup, currentPopupWaypoint } from './WaypointPopup';
|
import { Button } from '$lib/components/ui/button';
|
||||||
|
import Shortcut from '$lib/components/Shortcut.svelte';
|
||||||
|
import { waypointPopup, currentPopupWaypoint, deleteWaypoint } from './WaypointPopup';
|
||||||
import WithUnits from '$lib/components/WithUnits.svelte';
|
import WithUnits from '$lib/components/WithUnits.svelte';
|
||||||
import { Dot } from 'lucide-svelte';
|
import { Dot, Trash2 } from 'lucide-svelte';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
|
import { Tool, currentTool } from '$lib/stores';
|
||||||
import { _ } from 'svelte-i18n';
|
import { _ } from 'svelte-i18n';
|
||||||
|
|
||||||
let popupElement: HTMLDivElement;
|
let popupElement: HTMLDivElement;
|
||||||
@@ -17,25 +19,39 @@
|
|||||||
|
|
||||||
<div bind:this={popupElement} class="hidden">
|
<div bind:this={popupElement} class="hidden">
|
||||||
{#if $currentPopupWaypoint}
|
{#if $currentPopupWaypoint}
|
||||||
<Card.Root class="border-none shadow-md text-base max-w-72 p-2">
|
<Card.Root class="border-none shadow-md text-base max-w-80 p-2">
|
||||||
<Card.Header class="p-0">
|
<Card.Header class="p-0">
|
||||||
<Card.Title class="text-md">{$currentPopupWaypoint.name}</Card.Title>
|
<Card.Title class="text-md">{$currentPopupWaypoint[0].name}</Card.Title>
|
||||||
</Card.Header>
|
</Card.Header>
|
||||||
<Card.Content class="flex flex-col p-0 text-sm">
|
<Card.Content class="flex flex-col p-0 text-sm">
|
||||||
<div class="flex flex-row items-center text-muted-foreground">
|
<div class="flex flex-row items-center text-muted-foreground">
|
||||||
{$currentPopupWaypoint.getLatitude().toFixed(6)}° {$currentPopupWaypoint
|
{$currentPopupWaypoint[0].getLatitude().toFixed(6)}° {$currentPopupWaypoint[0]
|
||||||
.getLongitude()
|
.getLongitude()
|
||||||
.toFixed(6)}°
|
.toFixed(6)}°
|
||||||
{#if $currentPopupWaypoint.ele !== undefined}
|
{#if $currentPopupWaypoint[0].ele !== undefined}
|
||||||
<Dot size="16" />
|
<Dot size="16" />
|
||||||
<WithUnits value={$currentPopupWaypoint.ele} type="elevation" />
|
<WithUnits value={$currentPopupWaypoint[0].ele} type="elevation" />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{#if $currentPopupWaypoint.desc}
|
{#if $currentPopupWaypoint[0].desc}
|
||||||
<span>{$currentPopupWaypoint.desc}</span>
|
<span>{$currentPopupWaypoint[0].desc}</span>
|
||||||
{/if}
|
{/if}
|
||||||
{#if $currentPopupWaypoint.cmt}
|
{#if $currentPopupWaypoint[0].cmt}
|
||||||
<span>{$currentPopupWaypoint.cmt}</span>
|
<span>{$currentPopupWaypoint[0].cmt}</span>
|
||||||
|
{/if}
|
||||||
|
{#if $currentTool === Tool.WAYPOINT}
|
||||||
|
<div class="mt-2">
|
||||||
|
<Button
|
||||||
|
class="w-full px-2 py-1 h-6 justify-start"
|
||||||
|
variant="ghost"
|
||||||
|
on:click={() =>
|
||||||
|
deleteWaypoint($currentPopupWaypoint[1], $currentPopupWaypoint[0]._data.index)}
|
||||||
|
>
|
||||||
|
<Trash2 size="16" class="mr-1" />
|
||||||
|
{$_('menu.delete')}
|
||||||
|
<Shortcut key="" shift={true} click={true} />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
</Card.Root>
|
</Card.Root>
|
||||||
|
@@ -1,10 +1,15 @@
|
|||||||
|
import { dbUtils } from "$lib/db";
|
||||||
import type { Waypoint } from "gpx";
|
import type { Waypoint } from "gpx";
|
||||||
import mapboxgl from "mapbox-gl";
|
import mapboxgl from "mapbox-gl";
|
||||||
import { writable } from "svelte/store";
|
import { writable } from "svelte/store";
|
||||||
|
|
||||||
export const currentPopupWaypoint = writable<Waypoint | null>(null);
|
export const currentPopupWaypoint = writable<[Waypoint, string] | null>(null);
|
||||||
|
|
||||||
export const waypointPopup = new mapboxgl.Popup({
|
export const waypointPopup = new mapboxgl.Popup({
|
||||||
closeButton: false,
|
closeButton: false,
|
||||||
maxWidth: undefined
|
maxWidth: undefined
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export function deleteWaypoint(fileId: string, waypointIndex: number) {
|
||||||
|
dbUtils.applyToFile(fileId, (file) => file.replaceWaypoints(waypointIndex, waypointIndex, [])[0]);
|
||||||
|
}
|
@@ -19,7 +19,7 @@
|
|||||||
import { onDestroy, onMount } from 'svelte';
|
import { onDestroy, onMount } from 'svelte';
|
||||||
import { map } from '$lib/stores';
|
import { map } from '$lib/stores';
|
||||||
import { resetCursor, setCrosshairCursor } from '$lib/utils';
|
import { resetCursor, setCrosshairCursor } from '$lib/utils';
|
||||||
import { CircleX } from 'lucide-svelte';
|
import { CirclePlus, CircleX, RefreshCw } from 'lucide-svelte';
|
||||||
|
|
||||||
let name: string;
|
let name: string;
|
||||||
let description: string;
|
let description: string;
|
||||||
@@ -164,7 +164,7 @@
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex flex-col gap-3 w-80">
|
<div class="flex flex-col gap-3 w-96">
|
||||||
<fieldset class="flex flex-col gap-2">
|
<fieldset class="flex flex-col gap-2">
|
||||||
<Label for="name">{$_('toolbar.waypoint.name')}</Label>
|
<Label for="name">{$_('toolbar.waypoint.name')}</Label>
|
||||||
<Input bind:value={name} id="name" class="font-semibold h-8" />
|
<Input bind:value={name} id="name" class="font-semibold h-8" />
|
||||||
@@ -207,8 +207,10 @@
|
|||||||
on:click={createOrUpdateWaypoint}
|
on:click={createOrUpdateWaypoint}
|
||||||
>
|
>
|
||||||
{#if $selectedWaypoint}
|
{#if $selectedWaypoint}
|
||||||
|
<RefreshCw size="16" class="mr-1" />
|
||||||
{$_('toolbar.waypoint.update')}
|
{$_('toolbar.waypoint.update')}
|
||||||
{:else}
|
{:else}
|
||||||
|
<CirclePlus size="16" class="mr-1" />
|
||||||
{$_('toolbar.waypoint.create')}
|
{$_('toolbar.waypoint.create')}
|
||||||
{/if}
|
{/if}
|
||||||
</Button>
|
</Button>
|
||||||
|
Reference in New Issue
Block a user