react-diagrams icon indicating copy to clipboard operation
react-diagrams copied to clipboard

Changing a node's or size on canvas programmatically

Open tabdon opened this issue 3 years ago • 1 comments

I am trying to create a format bar that can change a node's properties. I'd like to be able to:

  1. Drag a node to the canvas
  2. Select the node
  3. Use the format bars control to change things about the node (size, border, color, etc)

The below code is my attempt to get this working. I am able to change properties (attributes?) on the selected node. However, after doing so, the node doesn't actually change.

(side note: I used Renato's Logossim project as a playground to learn about React Diagrams)

In the NodeWidget code below, I am trying to base the height of the node on the value of the node model. Then, I try to set node model height value from my diagram engine code. I think I'm missing something fundamental about how this is all supposed to work :)

NodeWidget:

export const Shape = ({ size = 90 }, props) => (
  <svg
    height={props.height}
    width={size}
    // omitted
  >
    // omitted
  </svg>
);

const NodeWidget = props => {
  const { model } = props;

  const inputPorts = Object.values(model.getInputPorts());
  const portPositions = distributePorts(inputPorts.length);
  
  return (
    <Wrapper selected={model.isSelected()}>
      <PortExtension
        selected={model.isSelected()}
        portPositions={portPositions}
      />
      {inputPorts.map((port, i) => (
        <PositionedPort
          key={port.getName()}
          name={port.getName()}
          position={portPositions[i]}
        />
      ))}
      <PositionedPort name="out" />
      <Shape height={model.height} />
    </Wrapper>
  );
};

App.js File:

import components from "./components";
import Diagram from "./Diagram";
import DiagramEngine from "./DiagramEngine";

function App() {
  const [diagram, setDiagram] = useState();

  useEffect(() => {
    const newDiagram = new DiagramEngine(components);
    setDiagram(newDiagram);
  }, []);
  
  return (
    <>
      {loading ?
        '' :
        <div>
          <button onClick={diagram.changeNodeSize}>
            Click Me
          </button>
          <Diagram engine={diagram}/>
        </div>
      }
  </>
  );
}

App.js File:

class DiagramEngine {
  constructor(components) {
    this.components = components;
    this.initializeEngine();
    this.initializeModel();
  }
  
  //... code omitted
  
  changeNodeSize = () => {
    const selectedNodes = this.engine
      .getModel()
      .getSelectedEntities()
      .filter(entity => entity instanceof BaseModel)
      .forEach(node => {
          node.height = 200
       }
      )
    this.engine.repaintCanvas();
  }
}

tabdon avatar Apr 14 '21 09:04 tabdon

You can try node.updateDimensions

kobajs avatar May 21 '21 11:05 kobajs