import React, { useEffect, useRef, useState } from "react"; import { Unit } from "../../unit/unit"; import { ContextAction } from "../../unit/contextaction"; import { CONTEXT_ACTION_COLORS, ContextActionTarget, NO_SUBSTATE, OlympusState, OlympusSubState, UnitControlSubState } from "../../constants/constants"; import { OlDropdownItem } from "../components/oldropdown"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { LatLng } from "leaflet"; import { AppStateChangedEvent, ContextActionChangedEvent, ContextActionSetChangedEvent, MapContextMenuRequestEvent, SelectedUnitsChangedEvent, SelectionClearedEvent, UnitContextMenuRequestEvent, } from "../../events"; import { ContextActionSet } from "../../unit/contextactionset"; import { getApp } from "../../olympusapp"; export function MapContextMenu(props: {}) { const [appState, setAppState] = useState(OlympusState.NOT_INITIALIZED); const [appSubState, setAppSubState] = useState(NO_SUBSTATE as OlympusSubState); const [contextActionSet, setcontextActionSet] = useState(null as ContextActionSet | null); const [xPosition, setXPosition] = useState(0); const [yPosition, setYPosition] = useState(0); const [latLng, setLatLng] = useState(null as null | LatLng); const [unit, setUnit] = useState(null as null | Unit); const [selectedUnits, setSelectedUnits] = useState([] as Unit[]); const [height, setHeight] = useState(0); var contentRef = useRef(null); useEffect(() => { AppStateChangedEvent.on((state, subState) => { setAppState(state); setAppSubState(subState); }); ContextActionSetChangedEvent.on((contextActionSet) => setcontextActionSet(contextActionSet)); MapContextMenuRequestEvent.on((latlng) => { setUnit(null); setLatLng(latlng); const containerPoint = getApp().getMap().latLngToContainerPoint(latlng); setXPosition(getApp().getMap().getContainer().offsetLeft + containerPoint.x); setYPosition(getApp().getMap().getContainer().offsetTop + containerPoint.y); }); UnitContextMenuRequestEvent.on((unit) => { setLatLng(null); setUnit(unit); const containerPoint = getApp().getMap().latLngToContainerPoint(unit.getPosition()); setXPosition(getApp().getMap().getContainer().offsetLeft + containerPoint.x); setYPosition(getApp().getMap().getContainer().offsetTop + containerPoint.y); }); SelectedUnitsChangedEvent.on((selectedUnits) => setSelectedUnits([...selectedUnits])); }, []); useEffect(() => { if (contentRef.current) { const content = contentRef.current as HTMLDivElement; content.style.left = `${xPosition}px`; content.style.top = `${yPosition}px`; let newXPosition = xPosition; let newYposition = yPosition; let [cxr, cyb] = [content.getBoundingClientRect().x + content.clientWidth, content.getBoundingClientRect().y + content.clientHeight]; /* Try and move the content so it is inside the screen */ if (cxr > window.innerWidth) newXPosition -= cxr - window.innerWidth; if (cyb > window.innerHeight) newYposition -= cyb - window.innerHeight; content.style.left = `${newXPosition}px`; content.style.top = `${newYposition}px`; setHeight(content.clientHeight); const resizeObserver = new ResizeObserver(() => { setHeight(content.clientHeight); }); resizeObserver.observe(content); return () => resizeObserver.disconnect(); // clean up } }); let reorderedActions: ContextAction[] = contextActionSet ? Object.values( contextActionSet.getContextActions( selectedUnits.length === 1 && unit === selectedUnits[0] ? ContextActionTarget.NONE : appSubState === UnitControlSubState.MAP_CONTEXT_MENU ? ContextActionTarget.POINT : ContextActionTarget.UNIT ) ).sort((a: ContextAction, b: ContextAction) => (a.getOptions().type < b.getOptions().type ? -1 : 1)) : []; return ( <> {appState === OlympusState.UNIT_CONTROL && (appSubState === UnitControlSubState.MAP_CONTEXT_MENU || appSubState === UnitControlSubState.UNIT_CONTEXT_MENU) && ( <>