Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to connect two default nodes programmatically #42

Closed
danielemaddaluno opened this issue Oct 11, 2020 · 4 comments
Closed

How to connect two default nodes programmatically #42

danielemaddaluno opened this issue Oct 11, 2020 · 4 comments
Labels

Comments

@danielemaddaluno
Copy link
Contributor

I didn't manage to connect two simple nodes together programmatically.
In the demo it is done with the tree skin, but what if I just want to do it with the default skin?
I would add this to the wiki documentation too if possible.

@issue-label-bot
Copy link

Issue-Label Bot is automatically applying the label question to this issue, with a confidence of 0.83. Please mark this comment with 👍 or 👎 to give our bot feedback!

Links: app homepage, dashboard and code for this bot.

@midrare
Copy link

midrare commented Oct 11, 2020

You can use this method

    private void createLink(GNode srcNode, GNode targetNode) {
        EReference NODES = GraphPackage.Literals.GMODEL__NODES;
        EReference CONNECTIONS = GraphPackage.Literals.GMODEL__CONNECTIONS;
        EReference CONNECTOR_CONNECTIONS = GraphPackage.Literals.GCONNECTOR__CONNECTIONS;

        EditingDomain editingDomain = AdapterFactoryEditingDomain.getEditingDomainFor(this.model);

        GConnector input = targetNode.getConnectors().get(0);
        GConnector parentOutput = srcNode.getConnectors().get(1);
        GConnection connection = GraphFactory.eINSTANCE.createGConnection();

        connection.setSource(parentOutput);
        connection.setTarget(input);

        GJoint joint1 = GraphFactory.eINSTANCE.createGJoint();
        GJoint joint2 = GraphFactory.eINSTANCE.createGJoint();

        joint1.setX(parentOutput.getX());
        joint1.setY(parentOutput.getY());

        joint2.setX(input.getX());
        joint2.setY(input.getY());

        connection.getJoints().add(joint1);
        connection.getJoints().add(joint2);

        input.getConnections().add(connection);

        // Set the rest of the values via EMF commands because they touch the currently-edited model.
        CompoundCommand command = new CompoundCommand();

        command.append(AddCommand.create(editingDomain, this.model, CONNECTIONS, connection));
        command.append(AddCommand.create(editingDomain, parentOutput, CONNECTOR_CONNECTIONS, connection));

        editingDomain.getCommandStack().execute(command);
    }

You'll want to edit the snippet to make sure you get the correct connectors, and to position the joints. (If the joints are positioned improperly, the link won't show up in the view.)


Maybe there should be a convenience method in Commands (ie. Commands.addLink(model, node1, node2)) for this.

@eckig
Copy link
Owner

eckig commented Oct 12, 2020

In general @drinkitup777 is right. But lets break it up:

  1. You can not connect two GNodes directly, but you can connect two GConnectors.
  2. So you need to add at least one GConnector to each GNode.
  3. In order to create a GConnection between the two GConnectors you need the points (GJoint) where the line will be drawn.

Guessing from your question 1 & 2 should be done here.

There is a utility to create a rectangular path for the "default" skin: List<Point2D> points = RectangularPathCreator.createPath(sourcePoint, targetPoint, startSide, endSide);

You can convert each Point2D into a GJoint:

final GJoint gj = GraphFactory.eINSTANCE.createGJoint();
gj.setX(point.getX());
gj.setY(point.getY());

Then you can create the GConnection:

final GConnection connection = GraphFactory.eINSTANCE.createGConnection();
connection.setSource(source);
connection.setTarget(target);
connection.getJoints().addAll(joints);

And finally you can register the new GConnection, you can look this up in the following utility: ConnectionCommands.addConnection(GModel, GConnector, GConnector, String, List<GJoint>, ConnectionEventManager)


@drinkitup777 And I don't think that we can create a general utility for this as every implemention behaves differently (default skins use rectangular connections with points as joints whereas the tree skins use direct connection lines with no points)

@danielemaddaluno
Copy link
Contributor Author

danielemaddaluno commented Oct 12, 2020

Ok thank you, I think I have resolved my doubt.
I'll post a complete example, from generating nodes+connectors to adding connections+joints, here:

import java.util.List;

import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.edit.command.AddCommand;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.domain.EditingDomain;

import de.tesis.dynaware.grapheditor.Commands;
import de.tesis.dynaware.grapheditor.GraphEditor;
import de.tesis.dynaware.grapheditor.core.DefaultGraphEditor;
import de.tesis.dynaware.grapheditor.core.skins.defaults.tail.RectangularPathCreator;
import de.tesis.dynaware.grapheditor.model.GConnection;
import de.tesis.dynaware.grapheditor.model.GConnector;
import de.tesis.dynaware.grapheditor.model.GJoint;
import de.tesis.dynaware.grapheditor.model.GModel;
import de.tesis.dynaware.grapheditor.model.GNode;
import de.tesis.dynaware.grapheditor.model.GraphFactory;
import de.tesis.dynaware.grapheditor.model.GraphPackage;
import javafx.application.Application;
import javafx.geometry.Point2D;
import javafx.geometry.Side;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class GraphEditorTutorial extends Application {

	GraphEditor graphEditor;

	public static void main(final String[] args) {
		launch(args);
	}

	@Override
	@SuppressWarnings("exports")
	public void start(final Stage primaryStage) throws Exception {
		graphEditor = new DefaultGraphEditor();

		Scene scene = new Scene(graphEditor.getView(), 800, 600);

		GModel model = GraphFactory.eINSTANCE.createGModel();
		graphEditor.setModel(model);
		addNodes(model);

		primaryStage.setScene(scene);
		primaryStage.show();
	}

	private void addNodes(GModel model) {
		GNode n1 = createNode();
		GNode n2 = createNode();

		n1.setX(150);
		n1.setY(150);

		n2.setX(400);
		n2.setY(200);
		n2.setWidth(200);
		n2.setHeight(150);

		Commands.addNode(model, n1);
		Commands.addNode(model, n2);

		GConnector source = n1.getConnectors().get(1);
		GConnector target = n2.getConnectors().get(0);
		Point2D sourcePoint = new Point2D(n1.getX() + n1.getWidth(), n1.getY());
		Point2D targetPoint = new Point2D(n2.getX(), n2.getY());
		List<Point2D> points = RectangularPathCreator.createPath(sourcePoint, targetPoint, Side.RIGHT, Side.LEFT);

		createLink(model, source, target, points);
	}

	private GNode createNode() {
		GNode node = GraphFactory.eINSTANCE.createGNode();

		GConnector input = GraphFactory.eINSTANCE.createGConnector();
		GConnector output = GraphFactory.eINSTANCE.createGConnector();

		input.setType("left-input");
		output.setType("right-output");

		node.getConnectors().add(input);
		node.getConnectors().add(output);

		return node;
	}

	private void createLink(GModel model, GConnector source, GConnector target, List<Point2D> points) {
		EReference CONNECTIONS = GraphPackage.Literals.GMODEL__CONNECTIONS;
		EReference CONNECTOR_CONNECTIONS = GraphPackage.Literals.GCONNECTOR__CONNECTIONS;

		EditingDomain editingDomain = AdapterFactoryEditingDomain.getEditingDomainFor(model);

		GConnection connection = GraphFactory.eINSTANCE.createGConnection();

		connection.setSource(target);
		connection.setTarget(source);

		GJoint joint1 = GraphFactory.eINSTANCE.createGJoint();
		GJoint joint2 = GraphFactory.eINSTANCE.createGJoint();

		joint1.setX(points.get(0).getX());
		joint1.setY(points.get(0).getY());

		joint2.setX(points.get(1).getX());
		joint2.setY(points.get(1).getY());

		connection.getJoints().add(joint1);
		connection.getJoints().add(joint2);

		source.getConnections().add(connection);

		// Set the rest of the values via EMF commands because they touch the
		// currently-edited model.
		CompoundCommand command = new CompoundCommand();

		command.append(AddCommand.create(editingDomain, model, CONNECTIONS, connection));
		command.append(AddCommand.create(editingDomain, target, CONNECTOR_CONNECTIONS, connection));

		editingDomain.getCommandStack().execute(command);
	}

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants