Browse Source

disable node props panel

main
Stephanie Gredell 4 months ago
parent
commit
3fc71b782f
  1. 364
      static/node.js

364
static/node.js

@ -2,186 +2,186 @@ import { Connection } from './connection.js';
import { generateNodeId, createSVGElement } from './utils.js'; import { generateNodeId, createSVGElement } from './utils.js';
export class ComponentNode { export class ComponentNode {
constructor(type, x, y, app, props = {}) { constructor(type, x, y, app, props = {}) {
this.id = generateNodeId(); this.id = generateNodeId();
this.type = type; this.type = type;
this.app = app; this.app = app;
this.props = { this.props = {
label: type, label: type,
replication: 1, replication: 1,
cacheTTL: 0, cacheTTL: 0,
instanceSize: 'medium', instanceSize: 'medium',
...props ...props
}; };
this.group = createSVGElement('g', { class: 'dropped', 'data-type': type }); this.group = createSVGElement('g', { class: 'dropped', 'data-type': type });
const rect = createSVGElement('rect', { const rect = createSVGElement('rect', {
x, x,
y, y,
width: 0, // will be updated after measuring text width: 0, // will be updated after measuring text
height: app.componentSize.height, height: app.componentSize.height,
fill: '#121212', fill: '#121212',
stroke: '#00ff88', stroke: '#00ff88',
'stroke-width': 1, 'stroke-width': 1,
rx: 4, rx: 4,
ry: 4 ry: 4
}); });
this.text = createSVGElement('text', { this.text = createSVGElement('text', {
x: x + app.componentSize.width / 2, x: x + app.componentSize.width / 2,
y: y + app.componentSize.height / 2 + 5, y: y + app.componentSize.height / 2 + 5,
'text-anchor': 'middle', 'text-anchor': 'middle',
'font-size': 16, 'font-size': 16,
fill: '#ccc' fill: '#ccc'
}); });
this.text.textContent = this.props.label; this.text.textContent = this.props.label;
// Temporarily add text to canvas to measure its width // Temporarily add text to canvas to measure its width
app.canvas.appendChild(this.text); app.canvas.appendChild(this.text);
const textWidth = this.text.getBBox().width; const textWidth = this.text.getBBox().width;
const padding = 20; const padding = 20;
const finalWidth = textWidth + padding; const finalWidth = textWidth + padding;
// Update rect width and center text // Update rect width and center text
rect.setAttribute('width', finalWidth); rect.setAttribute('width', finalWidth);
this.text.setAttribute('x', x + finalWidth / 2); this.text.setAttribute('x', x + finalWidth / 2);
// Clean up temporary text // Clean up temporary text
app.canvas.removeChild(this.text); app.canvas.removeChild(this.text);
this.group.appendChild(rect); this.group.appendChild(rect);
this.group.appendChild(this.text); this.group.appendChild(this.text);
this.group.__nodeObj = this; this.group.__nodeObj = this;
this.initDrag(); this.initDrag();
this.group.addEventListener('click', (e) => { this.group.addEventListener('click', (e) => {
e.stopPropagation(); e.stopPropagation();
if (app.arrowMode) { if (app.arrowMode) {
Connection.handleClick(this, app); Connection.handleClick(this, app);
} else { } else {
// Use observer to notify node selection // Use observer to notify node selection
app.nodeSelectionSubject.notifyNodeSelected(this); app.nodeSelectionSubject.notifyNodeSelected(this);
app.selectedNode = this; // Keep app state in sync for now app.selectedNode = this; // Keep app state in sync for now
} }
}); });
this.group.addEventListener('dblclick', (e) => { this.group.addEventListener('dblclick', (e) => {
e.stopPropagation(); e.stopPropagation();
if (!app.arrowMode) { if (!app.arrowMode) {
// Use observer pattern instead of direct call // Use observer pattern instead of direct call
app.propertiesPanelSubject.notifyPropertiesPanelRequested(this); //app.propertiesPanelSubject.notifyPropertiesPanelRequested(this);
} }
}); });
app.canvas.appendChild(this.group); // ✅ now correctly adding full group app.canvas.appendChild(this.group); // ✅ now correctly adding full group
app.placedComponents.push(this); app.placedComponents.push(this);
app.runButton.disabled = false; app.runButton.disabled = false;
this.x = x; this.x = x;
this.y = y; this.y = y;
} }
initDrag() { initDrag() {
let offsetX, offsetY; let offsetX, offsetY;
const onMouseMove = (e) => { const onMouseMove = (e) => {
const pt = this.app.canvas.createSVGPoint(); const pt = this.app.canvas.createSVGPoint();
pt.x = e.clientX; pt.x = e.clientX;
pt.y = e.clientY; pt.y = e.clientY;
const svgP = pt.matrixTransform(this.app.canvas.getScreenCTM().inverse()); const svgP = pt.matrixTransform(this.app.canvas.getScreenCTM().inverse());
const newX = svgP.x - offsetX; const newX = svgP.x - offsetX;
const newY = svgP.y - offsetY; const newY = svgP.y - offsetY;
this.group.setAttribute('transform', `translate(${newX}, ${newY})`); this.group.setAttribute('transform', `translate(${newX}, ${newY})`);
this.x = newX; this.x = newX;
this.y = newY; this.y = newY;
this.app.updateConnectionsFor(this); this.app.updateConnectionsFor(this);
}; };
const onMouseUp = () => { const onMouseUp = () => {
window.removeEventListener('mousemove', onMouseMove); window.removeEventListener('mousemove', onMouseMove);
window.removeEventListener('mouseup', onMouseUp); window.removeEventListener('mouseup', onMouseUp);
}; };
this.group.addEventListener('mousedown', (e) => { this.group.addEventListener('mousedown', (e) => {
e.preventDefault(); e.preventDefault();
const pt = this.app.canvas.createSVGPoint(); const pt = this.app.canvas.createSVGPoint();
pt.x = e.clientX; pt.x = e.clientX;
pt.y = e.clientY; pt.y = e.clientY;
const svgP = pt.matrixTransform(this.app.canvas.getScreenCTM().inverse()); const svgP = pt.matrixTransform(this.app.canvas.getScreenCTM().inverse());
const ctm = this.group.getCTM(); const ctm = this.group.getCTM();
offsetX = svgP.x - ctm.e; offsetX = svgP.x - ctm.e;
offsetY = svgP.y - ctm.f; offsetY = svgP.y - ctm.f;
window.addEventListener('mousemove', onMouseMove); window.addEventListener('mousemove', onMouseMove);
window.addEventListener('mouseup', onMouseUp); window.addEventListener('mouseup', onMouseUp);
}); });
} }
updateLabel(newLabel) { updateLabel(newLabel) {
this.props.label = newLabel; this.props.label = newLabel;
this.text.textContent = newLabel; this.text.textContent = newLabel;
const textWidth = this.text.getBBox().width; const textWidth = this.text.getBBox().width;
const padding = 20; const padding = 20;
const finalWidth = textWidth + padding; const finalWidth = textWidth + padding;
this.group.querySelector('rect').setAttribute('width', finalWidth); this.group.querySelector('rect').setAttribute('width', finalWidth);
this.text.setAttribute('x', parseFloat(this.group.querySelector('rect').getAttribute('x')) + finalWidth / 2); this.text.setAttribute('x', parseFloat(this.group.querySelector('rect').getAttribute('x')) + finalWidth / 2);
} }
getCenter() { getCenter() {
const bbox = this.group.getBBox(); const bbox = this.group.getBBox();
const ctm = this.group.getCTM(); const ctm = this.group.getCTM();
const x = ctm.e + bbox.x + bbox.width / 2; const x = ctm.e + bbox.x + bbox.width / 2;
const y = ctm.f + bbox.y + bbox.height / 2; const y = ctm.f + bbox.y + bbox.height / 2;
return { x, y }; return { x, y };
} }
select() { select() {
// Use observer to clear previous selection and select this node // Use observer to clear previous selection and select this node
if (this.app.selectedNode && this.app.selectedNode !== this) { if (this.app.selectedNode && this.app.selectedNode !== this) {
this.app.nodeSelectionSubject.notifyNodeDeselected(this.app.selectedNode); this.app.nodeSelectionSubject.notifyNodeDeselected(this.app.selectedNode);
} }
this.group.classList.add('selected'); this.group.classList.add('selected');
this.app.selectedNode = this; this.app.selectedNode = this;
} }
deselect() { deselect() {
this.group.classList.remove('selected'); this.group.classList.remove('selected');
if (this.app.selectedNode === this) { if (this.app.selectedNode === this) {
this.app.selectedNode = null; this.app.selectedNode = null;
} }
} }
getConnectionPointToward(otherNode) { getConnectionPointToward(otherNode) {
const bbox = this.group.getBBox(); const bbox = this.group.getBBox();
const ctm = this.group.getCTM(); const ctm = this.group.getCTM();
const centerX = ctm.e + bbox.x + bbox.width / 2; const centerX = ctm.e + bbox.x + bbox.width / 2;
const centerY = ctm.f + bbox.y + bbox.height / 2; const centerY = ctm.f + bbox.y + bbox.height / 2;
const otherCenter = otherNode.getCenter(); const otherCenter = otherNode.getCenter();
let edgeX = centerX; let edgeX = centerX;
let edgeY = centerY; let edgeY = centerY;
const dx = otherCenter.x - centerX; const dx = otherCenter.x - centerX;
const dy = otherCenter.y - centerY; const dy = otherCenter.y - centerY;
if (Math.abs(dx) > Math.abs(dy)) { if (Math.abs(dx) > Math.abs(dy)) {
edgeX += dx > 0 ? bbox.width / 2 : -bbox.width / 2; edgeX += dx > 0 ? bbox.width / 2 : -bbox.width / 2;
} else { } else {
edgeY += dy > 0 ? bbox.height / 2 : -bbox.height / 2; edgeY += dy > 0 ? bbox.height / 2 : -bbox.height / 2;
} }
return { x: edgeX, y: edgeY }; return { x: edgeX, y: edgeY };
} }
} }

Loading…
Cancel
Save