Phase 6
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
import { h } from 'preact';
|
||||
import { useState } from 'preact/hooks';
|
||||
import type { Interface, Widget, SignalRef } from './lib/types';
|
||||
import TextView from './widgets/TextView';
|
||||
import TextLabel from './widgets/TextLabel';
|
||||
import Gauge from './widgets/Gauge';
|
||||
import BarH from './widgets/BarH';
|
||||
import BarV from './widgets/BarV';
|
||||
import Led from './widgets/Led';
|
||||
import MultiLed from './widgets/MultiLed';
|
||||
import SetValue from './widgets/SetValue';
|
||||
import Button from './widgets/Button';
|
||||
import PlotWidget from './widgets/PlotWidget';
|
||||
import ImageWidget from './widgets/ImageWidget';
|
||||
import LinkWidget from './widgets/LinkWidget';
|
||||
import ContextMenu from './ContextMenu';
|
||||
|
||||
const COMPONENTS: Record<string, any> = {
|
||||
textview: TextView,
|
||||
textlabel: TextLabel,
|
||||
gauge: Gauge,
|
||||
barh: BarH,
|
||||
barv: BarV,
|
||||
led: Led,
|
||||
multiled: MultiLed,
|
||||
setvalue: SetValue,
|
||||
button: Button,
|
||||
plot: PlotWidget,
|
||||
image: ImageWidget,
|
||||
link: LinkWidget,
|
||||
};
|
||||
|
||||
interface CtxState {
|
||||
visible: boolean;
|
||||
x: number;
|
||||
y: number;
|
||||
signal: SignalRef | null;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
iface: Interface | null;
|
||||
onNavigate?: (interfaceId: string) => void;
|
||||
}
|
||||
|
||||
export default function Canvas({ iface, onNavigate }: Props) {
|
||||
const [ctxMenu, setCtxMenu] = useState<CtxState>({
|
||||
visible: false, x: 0, y: 0, signal: null,
|
||||
});
|
||||
|
||||
function onCtxMenu(e: MouseEvent, widget: Widget) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setCtxMenu({ visible: true, x: e.clientX, y: e.clientY, signal: widget.signals[0] ?? null });
|
||||
}
|
||||
|
||||
if (!iface) {
|
||||
return (
|
||||
<div class="canvas-container">
|
||||
<div class="placeholder">
|
||||
<p>Select an interface from the left panel, or import one.</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div class="canvas-container">
|
||||
<div class="canvas-area" style={`width:${iface.w}px;height:${iface.h}px;`}>
|
||||
{iface.widgets.map(widget => {
|
||||
const Comp = COMPONENTS[widget.type];
|
||||
return Comp
|
||||
? <Comp
|
||||
key={widget.id}
|
||||
widget={widget}
|
||||
onContextMenu={(e: MouseEvent) => onCtxMenu(e, widget)}
|
||||
onNavigate={onNavigate}
|
||||
/>
|
||||
: (
|
||||
<div
|
||||
key={widget.id}
|
||||
class="unknown-widget"
|
||||
style={`left:${widget.x}px;top:${widget.y}px;width:${widget.w}px;height:${widget.h}px;`}
|
||||
title={`Unknown widget type: ${widget.type}`}
|
||||
onContextMenu={(e: MouseEvent) => onCtxMenu(e, widget)}
|
||||
>
|
||||
<span class="unknown-label">{widget.type}</span>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<ContextMenu
|
||||
{...ctxMenu}
|
||||
onClose={() => setCtxMenu(c => ({ ...c, visible: false }))}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user