Added better rail systems list.
This commit is contained in:
parent
ee165f6d8b
commit
b5bcdc12e1
|
@ -0,0 +1,39 @@
|
||||||
|
<template>
|
||||||
|
<q-list>
|
||||||
|
<q-item-label header>Rail Systems</q-item-label>
|
||||||
|
|
||||||
|
<rail-system-link
|
||||||
|
v-for="rs in railSystems"
|
||||||
|
:key="rs.id"
|
||||||
|
:rail-system="rs"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<q-item>
|
||||||
|
<q-input
|
||||||
|
dense
|
||||||
|
type="text"
|
||||||
|
label="Name"
|
||||||
|
/>
|
||||||
|
<q-btn label="Add" color="primary"></q-btn>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import RailSystemLink from "components/RailSystemLink.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "RailSystemsList",
|
||||||
|
components: { RailSystemLink },
|
||||||
|
props: {
|
||||||
|
railSystems: {
|
||||||
|
type: Array,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -1,14 +1,12 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="row bg-green-4">
|
<div class="row">
|
||||||
<div class="col-md-8 bg-blue-2" id="railSystemMapCanvasContainer">
|
<div class="col-md-8" id="railSystemMapCanvasContainer">
|
||||||
<canvas id="railSystemMapCanvas" height="800">
|
<canvas id="railSystemMapCanvas" height="800">
|
||||||
Your browser doesn't support canvas.
|
Your browser doesn't support canvas.
|
||||||
</canvas>
|
</canvas>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4 bg-amber">
|
<div class="col-md-4" v-if="railSystem.selectedComponent">
|
||||||
<p>
|
<selected-component-view :component="railSystem.selectedComponent" />
|
||||||
Info panel
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -17,9 +15,11 @@
|
||||||
<script>
|
<script>
|
||||||
import { RailSystem } from "src/api/railSystems";
|
import { RailSystem } from "src/api/railSystems";
|
||||||
import { draw, initMap } from "src/render/mapRenderer";
|
import { draw, initMap } from "src/render/mapRenderer";
|
||||||
|
import SelectedComponentView from "components/rs/SelectedComponentView.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MapView",
|
name: "MapView",
|
||||||
|
components: { SelectedComponentView },
|
||||||
props: {
|
props: {
|
||||||
railSystem: {
|
railSystem: {
|
||||||
type: RailSystem,
|
type: RailSystem,
|
||||||
|
|
|
@ -1,12 +1,153 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="q-pa-md">
|
<div class="q-pa-md">
|
||||||
|
<div class="text-h6">{{component.name}}</div>
|
||||||
|
<q-list bordered>
|
||||||
|
<q-item clickable>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>{{component.type}}</q-item-label>
|
||||||
|
<q-item-label caption>Id: {{component.id}}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
|
||||||
|
<q-item clickable>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>Position</q-item-label>
|
||||||
|
<q-item-label caption>
|
||||||
|
X: {{component.position.x}},
|
||||||
|
Y: {{component.position.y}},
|
||||||
|
Z: {{component.position.z}}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
|
||||||
|
<!-- Signal info -->
|
||||||
|
<q-expansion-item
|
||||||
|
id="signalInfo"
|
||||||
|
label="Signal Information"
|
||||||
|
v-if="component.type === 'SIGNAL'"
|
||||||
|
content-inset-level="0.5"
|
||||||
|
switch-toggle-side
|
||||||
|
expand-separator
|
||||||
|
>
|
||||||
|
<q-list>
|
||||||
|
<q-item
|
||||||
|
v-for="segment in [component.segment]"
|
||||||
|
:key="segment.id"
|
||||||
|
clickable
|
||||||
|
v-ripple
|
||||||
|
>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>Linked to segment: {{segment.name}}</q-item-label>
|
||||||
|
<q-item-label caption>Id: {{segment.id}}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</q-expansion-item>
|
||||||
|
|
||||||
|
<!-- Path node info -->
|
||||||
|
<q-expansion-item
|
||||||
|
label="Path Node Information"
|
||||||
|
v-if="component.connectedNodes !== undefined && component.connectedNodes !== null"
|
||||||
|
content-inset-level="0.5"
|
||||||
|
switch-toggle-side
|
||||||
|
expand-separator
|
||||||
|
>
|
||||||
|
<q-list>
|
||||||
|
<q-item
|
||||||
|
v-for="node in component.connectedNodes"
|
||||||
|
:key="node.id"
|
||||||
|
clickable
|
||||||
|
v-ripple
|
||||||
|
@click="select(node)"
|
||||||
|
>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>{{node.name}}</q-item-label>
|
||||||
|
<q-item-label caption>Id: {{node.id}}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</q-expansion-item>
|
||||||
|
|
||||||
|
<!-- Segment boundary info -->
|
||||||
|
<q-expansion-item
|
||||||
|
label="Segment Boundary Information"
|
||||||
|
v-if="component.type === 'SEGMENT_BOUNDARY'"
|
||||||
|
content-inset-level="0.5"
|
||||||
|
switch-toggle-side
|
||||||
|
expand-separator
|
||||||
|
>
|
||||||
|
<q-list>
|
||||||
|
<q-item
|
||||||
|
v-for="segment in component.segments"
|
||||||
|
:key="segment.id"
|
||||||
|
clickable
|
||||||
|
v-ripple
|
||||||
|
>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label>{{segment.name}}</q-item-label>
|
||||||
|
<q-item-label caption>Id: {{segment.id}}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</q-expansion-item>
|
||||||
|
|
||||||
|
<!-- Switch info -->
|
||||||
|
<q-expansion-item
|
||||||
|
label="Switch Information"
|
||||||
|
v-if="component.type === 'SWITCH'"
|
||||||
|
content-inset-level="0.5"
|
||||||
|
switch-toggle-side
|
||||||
|
expand-separator
|
||||||
|
>
|
||||||
|
<q-list>
|
||||||
|
<q-item
|
||||||
|
v-for="config in component.possibleConfigurations"
|
||||||
|
:key="config.id"
|
||||||
|
>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label class="q-gutter-md">
|
||||||
|
<q-btn
|
||||||
|
v-for="node in config.nodes"
|
||||||
|
:key="node.id"
|
||||||
|
dense
|
||||||
|
size="sm"
|
||||||
|
:label="node.name"
|
||||||
|
:color="component.activeConfiguration && component.activeConfiguration.id === config.id ? 'primary' : 'secondary'"
|
||||||
|
@click="select(node)"
|
||||||
|
/>
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</q-expansion-item>
|
||||||
|
</q-list>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { RailSystem } from "src/api/railSystems";
|
||||||
|
import { useRailSystemsStore } from "stores/railSystemsStore";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "SelectedComponentView"
|
name: "SelectedComponentView",
|
||||||
|
setup() {
|
||||||
|
const rsStore = useRailSystemsStore();
|
||||||
|
return {rsStore};
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
component: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
select(component) {
|
||||||
|
const c = this.rsStore.selectedRailSystem.components.find(cp => cp.id === component.id);
|
||||||
|
if (c) {
|
||||||
|
this.rsStore.selectedRailSystem.selectedComponent = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -25,15 +25,7 @@
|
||||||
show-if-above
|
show-if-above
|
||||||
bordered
|
bordered
|
||||||
>
|
>
|
||||||
<q-list>
|
<rail-systems-list :rail-systems="rsStore.railSystems" />
|
||||||
<q-item-label header>Rail Systems</q-item-label>
|
|
||||||
|
|
||||||
<rail-system-link
|
|
||||||
v-for="rs in rsStore.railSystems"
|
|
||||||
:key="rs.id"
|
|
||||||
:rail-system="rs"
|
|
||||||
/>
|
|
||||||
</q-list>
|
|
||||||
</q-drawer>
|
</q-drawer>
|
||||||
|
|
||||||
<q-page-container>
|
<q-page-container>
|
||||||
|
@ -44,17 +36,15 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { defineComponent, ref } from "vue";
|
import { defineComponent, ref } from "vue";
|
||||||
import RailSystemLink from "components/RailSystemLink.vue";
|
import RailSystemsList from "components/RailSystemsList.vue";
|
||||||
import { useRailSystemsStore } from "stores/railSystemsStore";
|
import { useRailSystemsStore } from "stores/railSystemsStore";
|
||||||
import { refreshRailSystems } from "src/api/railSystems";
|
import { refreshRailSystems } from "src/api/railSystems";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'MainLayout',
|
name: 'MainLayout',
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
RailSystemLink
|
RailSystemsList
|
||||||
},
|
},
|
||||||
|
|
||||||
setup () {
|
setup () {
|
||||||
const rsStore = useRailSystemsStore()
|
const rsStore = useRailSystemsStore()
|
||||||
const leftDrawerOpen = ref(false)
|
const leftDrawerOpen = ref(false)
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
Helper functions to actually perform rendering of different components.
|
Helper functions to actually perform rendering of different components.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {getScaleFactor, isComponentHovered} from "./mapRenderer";
|
import { getScaleFactor, isComponentHovered, isComponentSelected } from "./mapRenderer";
|
||||||
import {roundedRect, circle} from "./canvasUtils";
|
import { circle, roundedRect } from "./canvasUtils";
|
||||||
|
|
||||||
export function drawComponent(ctx, worldTx, component) {
|
export function drawComponent(ctx, worldTx, component) {
|
||||||
const tx = DOMMatrix.fromMatrix(worldTx);
|
const tx = DOMMatrix.fromMatrix(worldTx);
|
||||||
|
@ -28,7 +28,7 @@ export function drawComponent(ctx, worldTx, component) {
|
||||||
|
|
||||||
ctx.setTransform(tx);
|
ctx.setTransform(tx);
|
||||||
// Draw hovered status.
|
// Draw hovered status.
|
||||||
if (isComponentHovered(component)) {
|
if (isComponentHovered(component) || isComponentSelected(component)) {
|
||||||
ctx.fillStyle = `rgba(255, 255, 0, 0.5)`;
|
ctx.fillStyle = `rgba(255, 255, 0, 0.5)`;
|
||||||
circle(ctx, 0, 0, 0.75);
|
circle(ctx, 0, 0, 0.75);
|
||||||
ctx.fill();
|
ctx.fill();
|
||||||
|
|
|
@ -129,6 +129,10 @@ export function getScaleFactor() {
|
||||||
return SCALE_VALUES[mapScaleIndex];
|
return SCALE_VALUES[mapScaleIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a matrix that transforms world coordinates to canvas.
|
||||||
|
* @returns {DOMMatrix}
|
||||||
|
*/
|
||||||
function getWorldTransform() {
|
function getWorldTransform() {
|
||||||
const canvasRect = mapCanvas.getBoundingClientRect();
|
const canvasRect = mapCanvas.getBoundingClientRect();
|
||||||
const scale = getScaleFactor();
|
const scale = getScaleFactor();
|
||||||
|
@ -149,6 +153,10 @@ export function isComponentHovered(component) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isComponentSelected(component) {
|
||||||
|
return railSystem.selectedComponent !== null && railSystem.selectedComponent.id === component.id;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps a point on the map coordinates to world coordinates.
|
* Maps a point on the map coordinates to world coordinates.
|
||||||
* @param {DOMPoint} p
|
* @param {DOMPoint} p
|
||||||
|
@ -195,13 +203,15 @@ function onMouseDown(event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function onMouseUp() {
|
function onMouseUp() {
|
||||||
|
let finishedDrag = false;
|
||||||
if (mapDragTranslation !== null) {
|
if (mapDragTranslation !== null) {
|
||||||
mapTranslation.x += mapDragTranslation.x;
|
mapTranslation.x += mapDragTranslation.x;
|
||||||
mapTranslation.y += mapDragTranslation.y;
|
mapTranslation.y += mapDragTranslation.y;
|
||||||
|
finishedDrag = true;
|
||||||
}
|
}
|
||||||
if (hoveredElements.length === 1) {
|
if (hoveredElements.length === 1) {
|
||||||
railSystem.selectedComponent = hoveredElements[0];
|
railSystem.selectedComponent = hoveredElements[0];
|
||||||
} else {
|
} else if (!finishedDrag) {
|
||||||
railSystem.selectedComponent = null;
|
railSystem.selectedComponent = null;
|
||||||
}
|
}
|
||||||
mapDragOrigin = null;
|
mapDragOrigin = null;
|
||||||
|
|
Loading…
Reference in New Issue