routing for canvase level object is finished.

This commit is contained in:
2026-05-30 16:37:37 +08:00
parent bf223b52ac
commit e3f708a1a7
10 changed files with 1647 additions and 567 deletions
+54 -18
View File
@@ -1186,7 +1186,7 @@ Organization : OptiHK Limited
border: 1px solid var(--floating-label-border);
color: var(--port-label-text);
box-shadow: 0 5px 12px rgba(0, 0, 0, 0.18);
font-size: 0.42rem;
font-size: 0.3rem;
line-height: 1.2;
font-family: 'IBM Plex Mono', Consolas, Monaco, monospace;
white-space: nowrap;
@@ -1278,6 +1278,10 @@ Organization : OptiHK Limited
box-shadow: var(--floating-label-shadow);
}
.canvas-text-hidden .component-floating-label {
display: none;
}
body.light-mode .port-name-label {
background: var(--port-label-bg);
border-color: var(--floating-label-border);
@@ -1312,14 +1316,14 @@ Organization : OptiHK Limited
}
.component-floating-label strong {
font-size: 0.52rem;
font-size: 0.4rem;
font-weight: 650;
}
.component-floating-label span {
margin-top: 1px;
color: var(--text-muted);
font-size: 0.44rem;
font-size: 0.32rem;
}
.canvas-size-panel {
@@ -1379,7 +1383,7 @@ Organization : OptiHK Limited
background: rgba(9, 18, 28, 0.94);
color: #e2f7f3;
box-shadow: 0 10px 24px rgba(0, 0, 0, 0.3);
font: 600 0.62rem/1.35 'IBM Plex Mono', Consolas, Monaco, monospace;
font: 600 0.5rem/1.35 'IBM Plex Mono', Consolas, Monaco, monospace;
text-align: center;
transform: translate(-50%, -50%);
pointer-events: none;
@@ -1594,7 +1598,7 @@ Organization : OptiHK Limited
}, [id, data.ports, data.componentName, data.boxSize]);
const baseHandleStyle = {
width: 10, height: 10,
width: 8, height: 8,
background: 'var(--bg-main)',
border: '2px solid var(--accent)',
borderRadius: '50%',
@@ -1611,6 +1615,7 @@ Organization : OptiHK Limited
);
const componentSize = normalizeBoxSize({ box_size: data.boxSize }, DEFAULT_COMPONENT_BOX_SIZE);
const isAnchorElement = data.elementType === 'anchor';
const isBasicCompactComponent = isBasicComponent(data.componentName) && ['waveguide', 'taper', '90 bend'].includes(data.componentName);
const visualSize = isAnchorElement ? { width: PORT_NODE_SIZE, height: PORT_NODE_SIZE } : componentSize;
const iconSize = createComponentSymbolMetrics(componentSize);
const portLabelStyle = (portHandle) => {
@@ -1643,9 +1648,16 @@ Organization : OptiHK Limited
style={{
width: componentSize.width,
height: visualSize.height,
minHeight: visualSize.height,
border: selected ? '2px solid var(--accent)' : '1px solid var(--border)',
transform: `rotate(${data.rotation || 0}deg) scaleX(${data.flop ? -1 : 1}) scaleY(${data.flip ? -1 : 1})`,
boxShadow: selected ? '0 0 15px rgba(56, 189, 248, 0.2)' : '0 4px 6px rgba(0,0,0,0.3)',
...(isBasicCompactComponent ? {
padding: 0,
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
} : {}),
...(isAnchorElement ? {
width: PORT_NODE_SIZE,
minHeight: PORT_NODE_SIZE,
@@ -1658,7 +1670,7 @@ Organization : OptiHK Limited
}}
>
{isAnchorElement ? (
<span style={{ fontSize: 10, fontWeight: 800, color: selected ? 'var(--accent)' : 'var(--text-main)' }}>A</span>
<span style={{ fontSize: 8, fontWeight: 800, color: selected ? 'var(--accent)' : 'var(--text-main)' }}>A</span>
) : (
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: '8px', minHeight: '100%' }}>
{!data.hideIcon && data.category && (
@@ -1733,8 +1745,8 @@ Organization : OptiHK Limited
};
const baseHandleStyle = {
background: 'var(--accent)',
width: 8,
height: 8
width: 6,
height: 6
};
return (
<div style={{
@@ -1743,7 +1755,7 @@ Organization : OptiHK Limited
border: selected ? '2px solid white' : '2px solid var(--accent)',
display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
color: selected ? 'white' : 'var(--accent)',
fontSize: 10, fontWeight: 'bold',
fontSize: 8, fontWeight: 'bold',
boxShadow: selected ? '0 0 10px rgba(56,189,248,0.4)' : 'none',
transform: `rotate(${angle}deg)`,
}}>
@@ -1783,8 +1795,8 @@ Organization : OptiHK Limited
bottom: Position.Bottom
};
const baseHandleStyle = {
width: 8,
height: 8,
width: 6,
height: 6,
background: 'var(--accent)',
border: '1px solid var(--bg-main)',
borderRadius: '50%'
@@ -2729,6 +2741,7 @@ Organization : OptiHK Limited
const selectedNodeBoxSize = selectedNode?.data?.componentName && !selectedNode?.data?.elementType
? normalizeBoxSize({ box_size: selectedNode.data?.boxSize }, DEFAULT_COMPONENT_BOX_SIZE)
: null;
const xsections = Object.keys((technologyManifest || FALLBACK_TECHNOLOGY_MANIFEST).xsections || {});
const selectedRouteEdges = selectedEdges.length > 0 ? selectedEdges : (selectedEdge ? [selectedEdge] : []);
if (selectedRouteEdges.length > 0) {
@@ -2744,7 +2757,6 @@ Organization : OptiHK Limited
radius: mixedValue('radius'),
routing_type: mixedValue('routing_type')
};
const xsections = Object.keys((technologyManifest || FALLBACK_TECHNOLOGY_MANIFEST).xsections || {});
const routingTypes = (technologyManifest || FALLBACK_TECHNOLOGY_MANIFEST).routing_types || ['euler_bend', 'standard_bend'];
return (
<aside style={{
@@ -3164,12 +3176,26 @@ Organization : OptiHK Limited
{Object.entries(basicArguments).map(([key, value]) => (
<label key={key} style={{ display: 'grid', gap: 4 }}>
<span style={{ color: 'var(--text-muted)' }}>{key}</span>
<input
type={typeof value === 'number' ? 'number' : 'text'}
step="any"
value={value ?? ''}
onChange={(event) => updateBasicArgument(key, event.target.value)}
/>
{key === 'xsection' ? (
<select
value={value ?? ''}
onChange={(event) => updateBasicArgument(key, event.target.value)}
>
{value && !xsections.includes(value) && (
<option value={value}>{value}</option>
)}
{xsections.map(xsection => (
<option key={xsection} value={xsection}>{xsection}</option>
))}
</select>
) : (
<input
type={typeof value === 'number' ? 'number' : 'text'}
step="any"
value={value ?? ''}
onChange={(event) => updateBasicArgument(key, event.target.value)}
/>
)}
</label>
))}
</div>
@@ -3461,6 +3487,7 @@ Organization : OptiHK Limited
const [dragging, setDragging] = useState(null);
const [gridSnap, setGridSnap] = useState(false);
const [canvasTextVisible, setCanvasTextVisible] = useState(true);
const [themeMode, setThemeMode] = useState(() => localStorage.getItem('mxpic-theme') || 'dark');
const [logs, setLogs] = useState([{ time: new Date().toLocaleTimeString(), message: 'Editor ready.' }]);
const [buildLayoutBusy, setBuildLayoutBusy] = useState(false);
@@ -5463,6 +5490,11 @@ Organization : OptiHK Limited
setGridSnap(prev => !prev);
}, []);
// Toggle the instance name/PDK labels shown above canvas components.
const toggleCanvasText = useCallback(() => {
setCanvasTextVisible(prev => !prev);
}, []);
// Toggle the measurement ruler and clear partial measurements.
const toggleRulerMode = useCallback(() => {
setRulerMode(prev => {
@@ -5999,6 +6031,9 @@ ${bundlesBlock}`;
transition: 'transform 0.2s',
}} />
</div>
<button className="mini-btn" onClick={toggleCanvasText} aria-pressed={canvasTextVisible ? 'true' : 'false'}>
{canvasTextVisible ? 'Text On' : 'Text Off'}
</button>
<details className="link-mode-tabs" title="Route type used for new links">
<summary className="link-mode-summary">
<span className="link-mode-label">Link</span>
@@ -6069,6 +6104,7 @@ ${bundlesBlock}`;
<LayoutSvgPreview page={activePage} />
) : (
<ReactFlow
className={canvasTextVisible ? '' : 'canvas-text-hidden'}
nodes={renderNodes}
edges={renderEdges}
onNodesChange={onNodesChange}