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 a context menu in webmap #33

Open
wants to merge 27 commits into
base: v3
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
af631b9
Add a context menu in webmap
jedrek0429 Mar 29, 2024
3d07eca
Merge branch 'v3' into feat/hijack-context-menu
granny Mar 30, 2024
0077e66
whitespace
granny Mar 30, 2024
7abf48e
Merge branch 'granny:v3' into feat/hijack-context-menu
jedrek0429 Mar 30, 2024
94fa8ce
Add more configurability and custom html for the context menus
jedrek0429 Mar 31, 2024
a85b820
Apply suggestions from code review
jedrek0429 Apr 2, 2024
fb379ea
Merge branch 'v3' into feat/hijack-context-menu
granny Apr 4, 2024
9af1026
make the context menu items a button
granny Apr 4, 2024
a8dc6a6
make contextmenu a flexbox
granny Apr 4, 2024
693aa6f
make each coordinate a variable
granny Apr 4, 2024
ce169e1
take inspiration from LiveAtlas' contextmenu
granny Apr 4, 2024
3b859f5
remove custom html
granny Apr 4, 2024
1378fef
remove unused onRemove parameter
granny Apr 4, 2024
6d2c66c
remove unused import
granny Apr 4, 2024
3b0cf8b
Merge branch 'v3' into feat/hijack-context-menu
granny Apr 4, 2024
adb03e1
update copy-coords value in lang file
granny Apr 4, 2024
c6b7bba
update copy-coords value in lang file x2
granny Apr 4, 2024
5649794
Merge branch 'v3' into feat/hijack-context-menu
granny Apr 5, 2024
b2e3077
move display flex into leaflet-control-contextmenu class
granny Apr 5, 2024
d8aa273
use String constructor
granny Apr 5, 2024
26450a2
remove unused import
granny Apr 5, 2024
c6bdd76
remove dash from id
granny Apr 5, 2024
eff01b7
content -> context
granny Apr 5, 2024
ac770d0
bleugh
granny Apr 5, 2024
78ef803
Merge branch 'v3' into feat/hijack-context-menu
granny Apr 12, 2024
cdd801c
replace the switch case with a map that "gets" the item if set in config
granny Apr 12, 2024
c1ba1fb
whitespace
granny Apr 12, 2024
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
8 changes: 8 additions & 0 deletions core/src/main/java/net/pl3x/map/core/configuration/Lang.java
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,14 @@ public final class Lang extends AbstractConfig {
public static String UI_BLOCKINFO_UNKNOWN_BLOCK = "Unknown block";
@Key("ui.blockinfo.unknown.biome")
public static String UI_BLOCKINFO_UNKNOWN_BIOME = "Unknown biome";
@Key("ui.contextmenu.label")
public static String UI_CONTEXTMENU_LABEL = "ContextMenu";
@Key("ui.contextmenu.copy-coords")
public static String UI_CONTEXTMENU_COPY_COORDS = "Copy coordinates";
@Key("ui.contextmenu.copy-link")
public static String UI_CONTEXTMENU_COPY_LINK = "Copy link to here";
@Key("ui.contextmenu.center-map")
public static String UI_CONTEXTMENU_CENTER_MAP = "Center map here";
@Key("ui.coords.label")
public static String UI_COORDS_LABEL = "Coordinates";
@Key("ui.coords.value")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,37 @@ public final class WorldConfig extends AbstractConfig {
@Comment("""
The display position for the link box""")
public String UI_LINK = "bottomright";

@Key("ui.context-menu.enabled")
@Comment("""
Enable the context menu.""")
public boolean UI_CONTEXT_MENU_ENABLED = true;

@Key("ui.context-menu.items")
@Comment("""
Items to show in the context menu. Leave empty for custom html.
Available items are:
copy-coords, copy-link, center-map""")
public List<@NotNull String> UI_CONTEXT_MENU_ITEMS = new ArrayList<>() {{
add("copy-coords");
add("copy-link");
add("center-map");
}};

@Key("ui.context-menu.custom-html.enabled")
@Comment("""
Use custom html for the context menu.""")
public boolean UI_CONTEXT_MENU_CUSTOM_HTML_ENABLED = false;

@Key("ui.context-menu.custom-html.html")
@Comment("""
Custom html for the context menu.""")
public String UI_CONTEXT_MENU_CUSTOM_HTML_HTML = "";

@Key("ui.context-menu.custom-html.css")
@Comment("""
Custom css for the context menu.""")
public String UI_CONTEXT_MENU_CUSTOM_HTML_CSS = "";

@Key("center.x")
@Comment("""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,15 @@ public void run() {
ui.put("coords", config.UI_COORDS);
ui.put("blockinfo", config.UI_BLOCKINFO);
ui.put("attribution", config.UI_ATTRIBUTION);
ui.put("contextMenu", Map.of(
"enabled", config.UI_CONTEXT_MENU_ENABLED,
"items", config.UI_CONTEXT_MENU_ITEMS,
"customHtml", Map.of(
"enabled", config.UI_CONTEXT_MENU_CUSTOM_HTML_ENABLED,
"html", config.UI_CONTEXT_MENU_CUSTOM_HTML_HTML,
"css", config.UI_CONTEXT_MENU_CUSTOM_HTML_CSS
)
));

Map<String, Object> settings = new LinkedHashMap<>();
settings.put("name", world.getName().replace(":", "-"));
Expand Down Expand Up @@ -161,10 +170,16 @@ private void parseSettings() {
lang.put("title", Lang.UI_TITLE);
lang.put("langFile", Lang.UI_BLOCK_AND_BIOME_LANG_FILE);
lang.put("blockInfo", Map.of(
"label", Lang.UI_BLOCKINFO_LABEL,
"value", Lang.UI_BLOCKINFO_VALUE,
"label", Lang.UI_BLOCKINFO_LABEL,
"value", Lang.UI_BLOCKINFO_VALUE,
"unknown", Map.of("block", Lang.UI_BLOCKINFO_UNKNOWN_BLOCK, "biome", Lang.UI_BLOCKINFO_UNKNOWN_BIOME))
);
lang.put("contextMenu", Map.of(
"label", Lang.UI_CONTEXTMENU_LABEL,
"copyCoords", Lang.UI_CONTEXTMENU_COPY_COORDS,
"copyLink", Lang.UI_CONTEXTMENU_COPY_LINK,
"centerMap", Lang.UI_CONTEXTMENU_CENTER_MAP
));
lang.put("coords", Map.of("label", Lang.UI_COORDS_LABEL, "value", Lang.UI_COORDS_VALUE));
lang.put("layers", Map.of("label", Lang.UI_LAYERS_LABEL, "value", Lang.UI_LAYERS_VALUE));
lang.put("link", Map.of("label", Lang.UI_LINK_LABEL, "value", Lang.UI_LINK_VALUE));
Expand Down
5 changes: 5 additions & 0 deletions core/src/main/resources/locale/lang-pl.yml
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ ui:
unknown:
block: Nieznany blok
biome: Nieznany biom
contextmenu:
label: ContextMenu
copy-coords: Skopiuj współrzędne
copy-link: Skopiuj link do tego miejsca
center-map: Wyśrodkuj mapę w tym miejscu
coords:
label: Współrzędne
value: <x>, <y>, <z>
Expand Down
1 change: 1 addition & 0 deletions webmap/src/Pl3xMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {ControlManager} from "./control/ControlManager";
import {PlayerManager} from "./player/PlayerManager";
import {WorldManager} from "./world/WorldManager";
import {getJSON} from "./util/Util";
import ContextMenuControl from "./control/ContextMenuControl";
import SidebarControl from "./control/SidebarControl";
import Pl3xMapLeafletMap from "./map/Pl3xMapLeafletMap";
import "./scss/styles.scss";
Expand Down
101 changes: 101 additions & 0 deletions webmap/src/control/ContextMenuControl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import * as L from "leaflet";
import {Pl3xMap} from "../Pl3xMap";
import {ContextMenuCustomHtml, ContextMenuItemType} from "../settings/WorldSettings";

export default class ContextMenuControl extends L.Control {
private readonly _pl3xmap: Pl3xMap;
private _dom: HTMLDivElement = L.DomUtil.create('div');
private _customHtml: ContextMenuCustomHtml;


constructor(pl3xmap: Pl3xMap) {
super();
this._pl3xmap = pl3xmap;
this._customHtml = pl3xmap.worldManager.currentWorld?.settings.ui.contextMenu.customHtml ?? new ContextMenuCustomHtml();
if (this._pl3xmap.worldManager.currentWorld?.settings.ui.contextMenu.enabled) {
this._init();
}
}

private _init(): void {
this._pl3xmap.map.on('contextmenu', this._show, this);
this._pl3xmap.map.on('click', this._hide, this);
if (this._customHtml.enabled) {
const style = L.DomUtil.create('style', 'leaflet-control-contextmenu-custom-style', document.head);
style.innerHTML = this._customHtml.css;
}
}

onAdd(): HTMLDivElement {
this._dom = L.DomUtil.create('div', 'leaflet-control leaflet-control-contextmenu');
this._dom.dataset.label = this._pl3xmap.settings!.lang.contextMenu.label;
if (this._customHtml.enabled) {
this._dom.innerHTML = this._customHtml.html;
}
return this._dom;
}

private _show(event: L.LeafletMouseEvent): void {
L.DomEvent.stopPropagation(event);
if (!this._customHtml.enabled) {
this._dom.innerHTML = '';
this._getItems(event).forEach((item) => {
const menuItem = L.DomUtil.create('div', 'leaflet-control-contextmenu-item', this._dom);
menuItem.innerHTML = item.label;
L.DomEvent.on(menuItem, 'click', (e) => {
L.DomEvent.stopPropagation(e);
item.callback();
this._hide();
});
});
}
jedrek0429 marked this conversation as resolved.
Show resolved Hide resolved
this._dom.style.display = 'block';
this._dom.style.left = event.containerPoint.x + 'px';
this._dom.style.top = event.containerPoint.y + 'px';
}

private _hide(): void {
this._dom.style.display = 'none';
}

private _getItems(e: L.LeafletMouseEvent): Map<string, { label: string, callback: () => void }> {
const {x, y, z} = this._pl3xmap.controlManager.coordsControl ?? {x: 0, y: 0, z: 0};
const coords = `(${x}, ${y ?? '???'}, ${z})`;
const world = this._pl3xmap.worldManager.currentWorld;
const settings = world?.settings.ui.contextMenu;
const items: Map<string, { label: string, callback: () => void }> = new Map();

settings?.items.forEach((item) => {
switch (item) {
case ContextMenuItemType.copyCoords:
items.set('copyCoords', {
label: `${this._pl3xmap.settings!.lang.contextMenu.copyCoords} ${coords}`,
callback: () => navigator.clipboard.writeText(coords),
});
break;
case ContextMenuItemType.copyLink:
items.set('copyLink', {
label: this._pl3xmap.settings!.lang.contextMenu.copyLink,
callback: () => navigator.clipboard.writeText(
window.location.href +
this._pl3xmap.controlManager.linkControl?.getUrlFromCoords(
x,
z,
this._pl3xmap.map.getCurrentZoom(),
world
)
),
});
break;
case ContextMenuItemType.centerMap:
items.set('centerMap', {
label: this._pl3xmap.settings!.lang.contextMenu.centerMap,
callback: () => this._pl3xmap.map.panTo(e.latlng),
});
break;
}
});

return items;
}
}
jedrek0429 marked this conversation as resolved.
Show resolved Hide resolved
12 changes: 12 additions & 0 deletions webmap/src/control/ControlManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import {Pl3xMap} from "../Pl3xMap";
import {BlockInfoControl} from "./BlockInfoControl";
import {CoordsControl} from "./CoordsControl";
import {LinkControl} from "./LinkControl";
import ContextMenuControl from "./ContextMenuControl";
import SidebarControl from "./SidebarControl";

export class ControlManager {
private readonly _pl3xmap: Pl3xMap;

private _contextMenuControl?: ContextMenuControl;
private _sidebarControl?: SidebarControl
private _blockInfoControl?: BlockInfoControl;
private _coordsControl?: CoordsControl;
Expand All @@ -16,6 +18,16 @@ export class ControlManager {
this._pl3xmap = pl3xmap;
}

get contextMenuControl(): ContextMenuControl | undefined {
return this._contextMenuControl;
}

set contextMenuControl(menu: ContextMenuControl | undefined) {
this._contextMenuControl?.remove();
this._contextMenuControl = menu;
this._contextMenuControl?.addTo(this._pl3xmap.map);
}

get sidebarControl(): SidebarControl | undefined {
return this._sidebarControl;
}
Expand Down
4 changes: 4 additions & 0 deletions webmap/src/control/LinkControl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ export class LinkControl extends ControlBox {
const zoom: number = this._pl3xmap.map.getCurrentZoom();
const x: number = Math.floor(center[0]);
const z: number = Math.floor(center[1]);
return this.getUrlFromCoords(x, z, zoom, world);
}

public getUrlFromCoords(x: number, z: number, zoom: number, world?: World): string {
let url: string = `?`;
if (world !== undefined) {
url += `world=${world.name}&renderer=${world.currentRenderer?.label ?? 'basic'}`;
Expand Down
23 changes: 23 additions & 0 deletions webmap/src/scss/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -229,3 +229,26 @@ img.leaflet-tile {
}
}
}

.leaflet-control-contextmenu {
display: none;
position: absolute;
background-color: var(--ui-background);
border: var(--ui-border);
border-radius: var(--ui-border-radius);
overflow: hidden;
z-index: 10000; /* Ensure the menu appears over other map controls */
}

.leaflet-control-contextmenu-item {
padding: 5px;
font-size: 12px;
color: var(--ui-text);
cursor: pointer;
transition: background-color 0.3s ease-in-out;

&:hover {
background-color: var(--ui-background-hover);
color: var(--ui-text-hover);
}
}
50 changes: 43 additions & 7 deletions webmap/src/settings/Lang.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
export class Lang {
private readonly _title: string;
private readonly _langFile: string;
private readonly _contextMenu: ContextMenu;
private readonly _coords: Label;
private readonly _blockInfo: BlockInfo;
private readonly _layers: Label;
Expand All @@ -12,9 +13,10 @@ export class Lang {
private readonly _players: Label;
private readonly _worlds: Label;

constructor(title: string, langFile: string, coords: Label, blockInfo: BlockInfo, layers: Label, link: Label, markers: Label, players: Label, worlds: Label) {
constructor(title: string, langFile: string, contextMenu: ContextMenu, coords: Label, blockInfo: BlockInfo, layers: Label, link: Label, markers: Label, players: Label, worlds: Label) {
this._title = title;
this._langFile = langFile;
this._contextMenu = contextMenu;
this._coords = coords;
this._blockInfo = blockInfo;
this._layers = layers;
Expand All @@ -32,6 +34,10 @@ export class Lang {
return this._langFile;
}

get contextMenu(): ContextMenu {
return this._contextMenu;
}

get coords(): Label {
return this._coords;
}
Expand Down Expand Up @@ -88,13 +94,13 @@ export class Label {
export class BlockInfoUnknown {
private readonly _block: string;
private readonly _biome: string;


constructor(block: string, biome: string) {
this._block = block;
this._biome = biome;
}

get block(): string {
return this._block;
}
Expand All @@ -110,14 +116,44 @@ export class BlockInfoUnknown {
*/
export class BlockInfo extends Label {
private readonly _unknown: BlockInfoUnknown;


jedrek0429 marked this conversation as resolved.
Show resolved Hide resolved
constructor(label: string, value: string, unknown: BlockInfoUnknown) {
super(label, value);
this._unknown = unknown;
}

get unknown(): BlockInfoUnknown {
return this._unknown;
}
}

export class ContextMenu {
private readonly _label: string;
private readonly _copyCoords: string;
private readonly _copyLink: string;
private readonly _centerMap: string;

constructor(label: string, copyCoords: string, copyLink: string, centerMap: string) {
this._label = label;
this._copyCoords = copyCoords;
this._copyLink = copyLink;
this._centerMap = centerMap;
}

get label(): string {
return this._label;
}

get copyCoords(): string {
return this._copyCoords;
}

get copyLink(): string {
return this._copyLink;
}

get centerMap(): string {
return this._centerMap;
}
}
Loading
Loading