Skip to content

Commit

Permalink
feat(ui): Reintroduce live map mode toggle
Browse files Browse the repository at this point in the history
  • Loading branch information
Hypfer committed Jan 2, 2023
1 parent dec5efb commit 27554be
Show file tree
Hide file tree
Showing 9 changed files with 493 additions and 387 deletions.
1 change: 0 additions & 1 deletion .eslintrc.json
Expand Up @@ -57,7 +57,6 @@
"sort-requires/sort-requires": "warn",
"operator-linebreak": ["error", "after"],
"no-unneeded-ternary": ["error", { "defaultAssignment": false }],
"arrow-body-style": ["error", "always"],
"regexp/no-unused-capturing-group": "off",
"regexp/prefer-w": "off",
"regexp/prefer-d": "off",
Expand Down
387 changes: 199 additions & 188 deletions frontend/src/map/EditMap.tsx

Large diffs are not rendered by default.

282 changes: 169 additions & 113 deletions frontend/src/map/LiveMap.tsx
@@ -1,34 +1,54 @@
import Map, {MapProps, MapState, usePendingMapAction} from "./Map";
import Map, {MapContainer, MapProps, MapState, usePendingMapAction} from "./Map";
import {Capability} from "../api";
import GoToTargetClientStructure from "./structures/client_structures/GoToTargetClientStructure";
import LocateAction from "./actions/live_map_actions/LocateAction";
import {ActionsContainer} from "./Styled";
import SegmentActions from "./actions/live_map_actions/SegmentActions";
import SegmentLabelMapStructure from "./structures/map_structures/SegmentLabelMapStructure";
import ZoneActions from "./actions/live_map_actions/ZoneActions";
import ZoneClientStructure from "./structures/client_structures/ZoneClientStructure";
import GoToActions from "./actions/live_map_actions/GoToActions";
import {TapTouchHandlerEvent} from "./utils/touch_handling/events/TapTouchHandlerEvent";
import React from "react";
import {LiveMapModeSwitcher} from "./LiveMapModeSwitcher";


export type LiveMapMode = "segments" | "zones" | "goto" | "none";

interface LiveMapProps extends MapProps {
supportedCapabilities: {
[Capability.MapSegmentation]: boolean,
[Capability.ZoneCleaning]: boolean,
[Capability.GoToLocation]: boolean,
[Capability.Locate]: boolean
[Capability.GoToLocation]: boolean
}
}

interface LiveMapState extends MapState {
mode: LiveMapMode,
zones: Array<ZoneClientStructure>,
goToTarget: GoToTargetClientStructure | undefined
}

class LiveMap extends Map<LiveMapProps, LiveMapState> {
private readonly supportedModes: Array<LiveMapMode>;

constructor(props: LiveMapProps) {
super(props);

this.supportedModes = [];

if (props.supportedCapabilities[Capability.MapSegmentation]) {
this.supportedModes.push("segments");
}
if (props.supportedCapabilities[Capability.ZoneCleaning]) {
this.supportedModes.push("zones");
}
if (props.supportedCapabilities[Capability.GoToLocation]) {
this.supportedModes.push("goto");
}


this.state = {
mode: this.supportedModes[0] ?? "none",
selectedSegmentIds: [],
zones: [],
goToTarget: undefined
Expand Down Expand Up @@ -57,53 +77,54 @@ class LiveMap extends Map<LiveMapProps, LiveMapState> {
const {x, y} = this.relativeCoordinatesToCanvas(evt.x0, evt.y0);
const tappedPointInMapSpace = this.ctxWrapper.mapPointToCurrentTransform(x, y);

if (this.props.supportedCapabilities[Capability.GoToLocation]) {
if (
this.structureManager.getClientStructures().filter(s => {
return s.type !== GoToTargetClientStructure.TYPE;
}).length === 0 &&
this.state.selectedSegmentIds.length === 0 &&
evt.duration >= TapTouchHandlerEvent.LONG_PRESS_DURATION
) {
this.structureManager.getClientStructures().forEach(s => {
if (s.type === GoToTargetClientStructure.TYPE) {
this.structureManager.removeClientStructure(s);
}
});
this.structureManager.addClientStructure(new GoToTargetClientStructure(tappedPointInMapSpace.x, tappedPointInMapSpace.y));
switch (this.state.mode) {
case "segments": {
const intersectingSegmentId = this.mapLayerManager.getIntersectingSegment(tappedPointInMapSpace.x, tappedPointInMapSpace.y);

if (intersectingSegmentId) {
const segmentLabels = this.structureManager.getMapStructures().filter(s => {
return s.type === SegmentLabelMapStructure.TYPE;
}) as Array<SegmentLabelMapStructure>;

this.updateState();
this.draw();
const matchedSegmentLabel = segmentLabels.find(l => {
return l.id === intersectingSegmentId;
});

return true;
}
}

if (
this.state.zones.length === 0 &&
this.state.goToTarget === undefined
) {
const intersectingSegmentId = this.mapLayerManager.getIntersectingSegment(tappedPointInMapSpace.x, tappedPointInMapSpace.y);
if (matchedSegmentLabel) {
matchedSegmentLabel.onTap();

this.updateState();
this.redrawLayers();

if (intersectingSegmentId) {
const segmentLabels = this.structureManager.getMapStructures().filter(s => {
return s.type === SegmentLabelMapStructure.TYPE;
}) as Array<SegmentLabelMapStructure>;
return true;
}
}

const matchedSegmentLabel = segmentLabels.find(l => {
return l.id === intersectingSegmentId;
});
break;
}

case "goto": {
if (
this.structureManager.getClientStructures().filter(s => {
return s.type !== GoToTargetClientStructure.TYPE;
}).length === 0
) {
this.structureManager.getClientStructures().forEach(s => {
if (s.type === GoToTargetClientStructure.TYPE) {
this.structureManager.removeClientStructure(s);
}
});
this.structureManager.addClientStructure(new GoToTargetClientStructure(tappedPointInMapSpace.x, tappedPointInMapSpace.y));

if (matchedSegmentLabel) {
matchedSegmentLabel.onTap();

this.updateState();
this.redrawLayers();
this.draw();

return true;
}

break;
}
}
}
Expand All @@ -122,103 +143,138 @@ class LiveMap extends Map<LiveMapProps, LiveMapState> {
}
}

protected renderAdditionalElements(): JSX.Element {
return <>
{
this.props.supportedCapabilities[Capability.Locate] &&
<LocateAction/>
}

<ActionsContainer>
render(): JSX.Element {
return (
<MapContainer style={{overflow: "hidden"}}>
<canvas
ref={this.canvasRef}
style={{
width: "100%",
height: "100%",
imageRendering: "crisp-edges"
}}
/>
{
this.props.supportedCapabilities[Capability.MapSegmentation] &&
this.state.selectedSegmentIds.length > 0 &&
this.state.goToTarget === undefined &&

<SegmentActions
segments={this.state.selectedSegmentIds}
onClear={() => {
this.supportedModes.length > 0 &&
<LiveMapModeSwitcher
supportedModes={this.supportedModes}
currentMode={this.state.mode}
setMode={(newMode) => {
this.structureManager.getMapStructures().forEach(s => {
if (s.type === SegmentLabelMapStructure.TYPE) {
const label = s as SegmentLabelMapStructure;

label.selected = false;
}
});
this.updateState();

this.redrawLayers();
}}
/>
}
{
this.props.supportedCapabilities[Capability.ZoneCleaning] &&
this.state.selectedSegmentIds.length === 0 &&
this.state.goToTarget === undefined &&

<ZoneActions
zones={this.state.zones}
convertPixelCoordinatesToCMSpace={(coordinates => {
return this.structureManager.convertPixelCoordinatesToCMSpace(coordinates);
})}
onClear={() => {
this.structureManager.getClientStructures().forEach(s => {
if (s.type === GoToTargetClientStructure.TYPE) {
this.structureManager.removeClientStructure(s);
}

if (s.type === ZoneClientStructure.TYPE) {
this.structureManager.removeClientStructure(s);
}
});

this.updateState();

this.draw();
}}
onAdd={() => {
const currentCenter = this.getCurrentViewportCenterCoordinatesInPixelSpace();

const p0 = {
x: currentCenter.x -15,
y: currentCenter.y -15
};
const p1 = {
x: currentCenter.x +15,
y: currentCenter.y +15
};

this.structureManager.addClientStructure(new ZoneClientStructure(
p0.x, p0.y,
p1.x, p1.y,
true
));

this.updateState();
this.redrawLayers();

this.draw();
}}
/>
}
{
this.props.supportedCapabilities[Capability.GoToLocation] &&
this.state.goToTarget !== undefined &&

<GoToActions
goToTarget={this.state.goToTarget}
convertPixelCoordinatesToCMSpace={(coordinates => {
return this.structureManager.convertPixelCoordinatesToCMSpace(coordinates);
})}
onClear={() => {
this.structureManager.getClientStructures().forEach(s => {
if (s.type === GoToTargetClientStructure.TYPE) {
this.structureManager.removeClientStructure(s);
}
this.setState({
mode: newMode
});
this.updateState();

this.draw();
}}
/>
}
</ActionsContainer>
</>;

<ActionsContainer>
{
this.state.mode === "segments" &&

<SegmentActions
segments={this.state.selectedSegmentIds}
onClear={() => {
this.structureManager.getMapStructures().forEach(s => {
if (s.type === SegmentLabelMapStructure.TYPE) {
const label = s as SegmentLabelMapStructure;

label.selected = false;
}
});
this.updateState();

this.redrawLayers();
}}
/>
}
{
this.state.mode === "zones" &&

<ZoneActions
zones={this.state.zones}
convertPixelCoordinatesToCMSpace={(coordinates => {
return this.structureManager.convertPixelCoordinatesToCMSpace(coordinates);
})}
onClear={() => {
this.structureManager.getClientStructures().forEach(s => {
if (s.type === ZoneClientStructure.TYPE) {
this.structureManager.removeClientStructure(s);
}
});

this.updateState();

this.draw();
}}
onAdd={() => {
const currentCenter = this.getCurrentViewportCenterCoordinatesInPixelSpace();

const p0 = {
x: currentCenter.x -15,
y: currentCenter.y -15
};
const p1 = {
x: currentCenter.x +15,
y: currentCenter.y +15
};

this.structureManager.addClientStructure(new ZoneClientStructure(
p0.x, p0.y,
p1.x, p1.y,
true
));

this.updateState();

this.draw();
}}
/>
}
{
this.state.mode === "goto" &&

<GoToActions
goToTarget={this.state.goToTarget}
convertPixelCoordinatesToCMSpace={(coordinates => {
return this.structureManager.convertPixelCoordinatesToCMSpace(coordinates);
})}
onClear={() => {
this.structureManager.getClientStructures().forEach(s => {
if (s.type === GoToTargetClientStructure.TYPE) {
this.structureManager.removeClientStructure(s);
}
});
this.updateState();

this.draw();
}}
/>
}
</ActionsContainer>
</MapContainer>
);
}
}

Expand Down

0 comments on commit 27554be

Please sign in to comment.