public enum EditorElement
{
    CONNECTOR,
    NODE,
    JOINT;
}
 public abstract class GConnectorSkin extends GSkin<GConnector> {

    /**
     * Creates a new {@link GConnectorSkin}.
     *
     * @param connector the {@link GConnector} represented by the skin
     */
    public GConnectorSkin(final GConnector connector) {
        super(connector);
    }

    /**
     * Gets the width of the connector skin.
     *
     * @return the width of the connector skin
     */
    public abstract double getWidth();

    /**
     * Gets the height of the connector skin.
     *
     * @return the height of the connector skin
     */
    public abstract double getHeight();

    /**
     * Applys the specified style to the connector.
     *
     * <p>
     * This is called by the library during various mouse events. For example when a connector is dragged over another
     * connector in an attempt to create a new connection.
     * </p>
     *
     * @param style the {@link GConnectorStyle} to apply
     */
    public abstract void applyStyle(GConnectorStyle style);
} public enum GConnectorStyle
{
    /**
     * Default style
     */
    DEFAULT,
    /**
     * Drag over allowed
     */
    DRAG_OVER_ALLOWED,
    /**
     * Drag over forbidden
     */
    DRAG_OVER_FORBIDDEN;
} public interface GConnectorValidator {

    /**
     * Pre-validate check made during drag-over events.
     *
     * <p>
     * If the pre-validate check fails, the dragged connector will not interact with the dragged-over connector at all.
     * </p>
     *
     * @param source the {@link GConnector} that was dragged
     * @param target the {@link GConnector} that was dragged-over
     *
     * @return {@code true} if a validate check should be made, {@code false} if not
     */
    boolean prevalidate(GConnector source, GConnector target);

    /**
     * Validate check made during drag-over events. Only made if the pre-validate check passes.
     *
     * @param source the {@link GConnector} that was dragged
     * @param target the {@link GConnector} that was dragged-over
     *
     * @return {@code true} if connection is allowed, {@code false} if it is forbidden
     */
    boolean validate(GConnector source, GConnector target);

    /**
     * Creates the 'type' string to be used in a new connection.
     *
     * <p>
     * If both prevalidate and validate checks pass, a new connection will be created of the type returned by this
     * method.
     * </p>
     *
     * @param source the {@link GConnector} that was dragged
     * @param target the {@link GConnector} that was dragged-over
     *
     * @return a {@link String} specifying the type for the new connection
     */
    String createConnectionType(GConnector source, GConnector target);

    /**
     * Creates the 'type' string to be used in the joints inside a new connection.
     *
     * @param source the {@link GConnector} that was dragged
     * @param target the {@link GConnector} that was dragged-over
     *
     * @return a {@link String} specifying the type for the new connection
     */
    String createJointType(GConnector source, GConnector target);
}
 public interface SkinLookup {

    /**
     * Gets the skin for the given node.
     *
     * @param node a {@link GNode} instance
     *
     * @return the associated {@link GNodeSkin} instance
     */
    GNodeSkin lookupNode(final GNode node);

    /**
     * Gets the skin for the given connector.
     *
     * @param connector a {@link GConnector} instance
     *
     * @return the associated {@link GConnectorSkin} instance
     */
    GConnectorSkin lookupConnector(final GConnector connector);

    /**
     * Gets the skin for the given connection.
     *
     * @param connection a {@link GConnection} instance
     *
     * @return the associated {@link GConnectionSkin} instance
     */
    GConnectionSkin lookupConnection(final GConnection connection);

    /**
     * Gets the skin for the given joint.
     *
     * @param joint a {@link GJoint} instance
     *
     * @return the associated {@link GJointSkin} instance
     */
    GJointSkin lookupJoint(final GJoint joint);

    /**
     * Gets the tail skin for the given connector.
     *
     * @param connector a {@link GConnector} instance
     *
     * @return the associated {@link GTailSkin} instance
     */
    GTailSkin lookupTail(final GConnector connector);
} public interface VirtualSkin
{
    // empty just for tagging
}
 public class DefaultGraphEditor implements GraphEditor
{

    private final GraphEditorProperties mProperties;
    private final GraphEditorView mView;
    private final ConnectionEventManager mConnectionEventManager = new ConnectionEventManager();
    private final GraphEditorSkinManager mSkinManager;
    private final GraphEditorController<DefaultGraphEditor> mController;

    private final ObjectProperty<GModel> mModelProperty = new ObjectPropertyBase<GModel>()
    {

        @Override
        public Object getBean()
        {
            return DefaultGraphEditor.this;
        }

        @Override
        public String getName()
        {
            return "model";
        }

    };

    /**
     * Creates a new default implementation of the {@link GraphEditor}.
     */
    public DefaultGraphEditor()
    {
        this(null);
    }

    /**
     * Creates a new default implementation of the {@link GraphEditor}.
     */
    public DefaultGraphEditor(final GraphEditorProperties pProperties)
    {
        mProperties = pProperties == null ? new GraphEditorProperties() : pProperties;
        mView = new GraphEditorView(mProperties);
        mSkinManager = new GraphEditorSkinManager(this, mView);
        mController = new GraphEditorController<>(this, mSkinManager, mView, mConnectionEventManager, mProperties);

        final ConnectionLayouter connectionLayouter = mController.getConnectionLayouter();
        mView.setConnectionLayouter(connectionLayouter);
        mSkinManager.setConnectionLayouter(connectionLayouter);
    }

    @Override
    public void setNodeSkinFactory(final Callback<GNode, GNodeSkin> pSkinFactory)
    {
        mSkinManager.setNodeSkinFactory(pSkinFactory);
    }

    @Override
    public void setConnectorSkinFactory(final Callback<GConnector, GConnectorSkin> pConnectorSkinFactory)
    {
        mSkinManager.setConnectorSkinFactory(pConnectorSkinFactory);
    }

    @Override
    public void setConnectionSkinFactory(final Callback<GConnection, GConnectionSkin> pConnectionSkinFactory)
    {
        mSkinManager.setConnectionSkinFactory(pConnectionSkinFactory);
    }

    @Override
    public void setJointSkinFactory(final Callback<GJoint, GJointSkin> pJointSkinFactory)
    {
        mSkinManager.setJointSkinFactory(pJointSkinFactory);
    }

    @Override
    public void setTailSkinFactory(final Callback<GConnector, GTailSkin> pTailSkinFactory)
    {
        mSkinManager.setTailSkinFactory(pTailSkinFactory);
    }

    @Override
    public void setConnectorValidator(final GConnectorValidator pValidator)
    {
        mController.setConnectorValidator(pValidator);
    }

    @Override
    public void setModel(final GModel pModel)
    {
        mModelProperty.set(pModel);
    }

    @Override
    public GModel getModel()
    {
        return mModelProperty.get();
    }

    @Override
    public void reload()
    {
        mController.process();
    }

    @Override
    public ObjectProperty<GModel> modelProperty()
    {
        return mModelProperty;
    }

    @Override
    public Region getView()
    {
        return mView;
    }

    @Override
    public GraphEditorProperties getProperties()
    {
        return mProperties;
    }

    @Override
    public SkinLookup getSkinLookup()
    {
        return mSkinManager;
    }

    @Override
    public SelectionManager getSelectionManager()
    {
        return mController.getSelectionManager();
    }

    @Override
    public void setOnConnectionCreated(final Function<GConnection, Command> pConsumer)
    {
        mConnectionEventManager.setOnConnectionCreated(pConsumer);
    }

    @Override
    public void setOnConnectionRemoved(final BiFunction<RemoveContext, GConnection, Command> pOnConnectionRemoved)
    {
        mConnectionEventManager.setOnConnectionRemoved(pOnConnectionRemoved);
        getModelEditingManager().setOnConnectionRemoved(pOnConnectionRemoved);
    }

    @Override
    public void setOnNodeRemoved(final BiFunction<RemoveContext, GNode, Command> pOnNodeRemoved)
    {
        getModelEditingManager().setOnNodeRemoved(pOnNodeRemoved);
    }

    @Override
    public void delete(Collection<EObject> pItems)
    {
        getModelEditingManager().remove(pItems);
    }

    private ModelEditingManager getModelEditingManager()
    {
        return mController.getModelEditingManager();
    }
} public class ConnectionCommands
{

    /**
     * Static class, not to be instantiated.
     */
    private ConnectionCommands()
    {
    }

    /**
     * Adds a connection to the model.
     *
     * @param model
     *            the {@link GModel} to which the connection should be added
     * @param source
     *            the source {@link GConnector} of the new connection
     * @param target
     *            the target {@link GConnector} of the new connection
     * @param type
     *            the type attribute for the new connection
     * @param joints
     *            the list of {@link GJoint} instances to be added inside the
     *            new connection
     */
    public static void addConnection(final GModel model, final GConnector source, final GConnector target, final String type,
            final List<GJoint> joints, final ConnectionEventManager connectionEventManager)
    {
        final EditingDomain editingDomain = AdapterFactoryEditingDomain.getEditingDomainFor(model);

        if (editingDomain != null)
        {
            final CompoundCommand command = new CompoundCommand();

            // prepare new connection:
            final GConnection connection = GraphFactory.eINSTANCE.createGConnection();
            connection.setType(type);
            connection.setSource(source);
            connection.setTarget(target);
            connection.getJoints().addAll(joints);

            // attributes that involve other members of the model, are modified through commands:
            command.append(AddCommand.create(editingDomain, model, GraphPackage.Literals.GMODEL__CONNECTIONS, connection));
            command.append(AddCommand.create(editingDomain, source, GraphPackage.Literals.GCONNECTOR__CONNECTIONS, connection));
            command.append(AddCommand.create(editingDomain, target, GraphPackage.Literals.GCONNECTOR__CONNECTIONS, connection));

            final Command onCreate;
            if (connectionEventManager != null && (onCreate = connectionEventManager.notifyConnectionAdded(connection)) != null)
            {
                command.append(onCreate);
            }

            if (command.canExecute())
            {
                editingDomain.getCommandStack().execute(command);
            }
        }
    }

    /**
     * Removes a connection from the model.
     *
     * @param model
     *            the {@link GModel} from which the connection should be removed
     * @param connection
     *            the {@link GConnection} to be removed
     * @param connectionEventManager
     */
    public static void removeConnection(final GModel model, final GConnection connection, ConnectionEventManager connectionEventManager)
    {
        final EditingDomain editingDomain = AdapterFactoryEditingDomain.getEditingDomainFor(model);

        if (editingDomain != null)
        {
            final CompoundCommand command = new CompoundCommand();

            final GConnector source = connection.getSource();
            final GConnector target = connection.getTarget();

            command.append(RemoveCommand.create(editingDomain, model, GraphPackage.Literals.GMODEL__CONNECTIONS, connection));
            command.append(RemoveCommand.create(editingDomain, source, GraphPackage.Literals.GCONNECTOR__CONNECTIONS, connection));
            command.append(RemoveCommand.create(editingDomain, target, GraphPackage.Literals.GCONNECTOR__CONNECTIONS, connection));

            final Command onRemove;
            if (connectionEventManager != null && (onRemove = connectionEventManager.notifyConnectionRemoved(connection)) != null)
            {
                command.append(onRemove);
            }

            if (command.canExecute())
            {
                editingDomain.getCommandStack().execute(command);
            }

        }
    }
}
 public class EventUtils
{

    public static <N extends Node, T extends Event> void removeEventHandlers(final Map<N, EventHandler<T>> pEventHandlers,
            final EventType<T> pType)
    {
        for (final Iterator<Entry<N, EventHandler<T>>> iter = pEventHandlers.entrySet().iterator(); iter.hasNext();)
        {
            final Entry<N, EventHandler<T>> next = iter.next();
            final N node = next.getKey();
            final EventHandler<T> eventHandler = next.getValue();
            if (node != null && eventHandler != null)
            {
                node.removeEventHandler(pType, eventHandler);
            }
            iter.remove();
        }
    }

} public class GraphEditorView extends Region
{

    private static final String STYLE_CLASS = "graph-editor";
    private static final String STYLE_CLASS_NODE_LAYER = "graph-editor-node-layer";
    private static final String STYLE_CLASS_CONNECTION_LAYER = "graph-editor-connection-layer";

    private final Pane mNodeLayer = new Pane();

    private final Pane mConnectionLayer = new Pane()
    {

        @Override
        protected void layoutChildren()
        {
            super.layoutChildren();
            drawConnections();
        }
    };

    private final GraphEditorGrid mGrid = new GraphEditorGrid();
    private ConnectionLayouter mConnectionLayouter;

    private final SelectionBox mSelectionBox = new SelectionBox();

    private final GraphEditorProperties mEditorProperties;

    /**
     * Creates a new {@link GraphEditorView} to which skin instances can be
     * added and removed.
     */
    public GraphEditorView(final GraphEditorProperties pEditorProperties)
    {
        getStyleClass().addAll(STYLE_CLASS);

        setMaxWidth(GraphEditorProperties.DEFAULT_MAX_WIDTH);
        setMaxHeight(GraphEditorProperties.DEFAULT_MAX_HEIGHT);

        initializeLayers();

        mEditorProperties = pEditorProperties;

        if (mEditorProperties != null)
        {
            mGrid.visibleProperty().bind(mEditorProperties.gridVisibleProperty());
            mGrid.gridSpacingProperty().bind(mEditorProperties.gridSpacingProperty());
        }
    }

    /**
     * Sets the connection-layouter to be used by the view.
     *
     * @param pConnectionLayouter
     *            the graph editor's {@link ConnectionLayouter} instance
     */
    public void setConnectionLayouter(final ConnectionLayouter pConnectionLayouter)
    {
        mConnectionLayouter = pConnectionLayouter;
    }

    /**
     * Clears all elements from the view.
     */
    public void clear()
    {
        mNodeLayer.getChildren().clear();
        mConnectionLayer.getChildren().clear();
    }

    /**
     * Adds a node skin to the view.
     *
     * @param pNodeSkin
     *            the {@link GNodeSkin} instance to be added
     */
    public void add(final GNodeSkin pNodeSkin)
    {
        if (pNodeSkin != null && !(pNodeSkin instanceof VirtualSkin))
        {
            mNodeLayer.getChildren().add(pNodeSkin.getRoot());
        }
    }

    /**
     * Adds a connection skin to the view.
     *
     * @param pConnectionSkin
     *            the {@link GConnectionSkin} instance to be added
     */
    public void add(final GConnectionSkin pConnectionSkin)
    {
        if (pConnectionSkin != null && !(pConnectionSkin instanceof VirtualSkin))
        {
            mConnectionLayer.getChildren().add(0, pConnectionSkin.getRoot());
        }
    }

    /**
     * Adds a joint skin to the view.
     *
     * @param pJointSkin
     *            the {@link GJointSkin} instance to be added
     */
    public void add(final GJointSkin pJointSkin)
    {
        if (pJointSkin != null && !(pJointSkin instanceof VirtualSkin))
        {
            mConnectionLayer.getChildren().add(pJointSkin.getRoot());
        }
    }

    /**
     * Adds a tail skin to the view.
     *
     * @param pTailSkin
     *            the {@link GTailSkin} instance to be added
     */
    public void add(final GTailSkin pTailSkin)
    {
        if (pTailSkin != null && !(pTailSkin instanceof VirtualSkin))
        {
            // add to back:
            mConnectionLayer.getChildren().add(0, pTailSkin.getRoot());
        }
    }

    /**
     * Removes a node skin from the view. Does nothing if the skin is not
     * present.
     *
     * @param pNodeSkin
     *            the {@link GNodeSkin} instance to remove
     */
    public void remove(final GNodeSkin pNodeSkin)
    {
        if (pNodeSkin != null && !(pNodeSkin instanceof VirtualSkin))
        {
            mNodeLayer.getChildren().remove(pNodeSkin.getRoot());
        }
    }

    /**
     * Removes a connection skin from the view. Does nothing if the skin is not
     * present.
     *
     * @param pConnectionSkin
     *            the {@link GConnectionSkin} instance to remove
     */
    public void remove(final GConnectionSkin pConnectionSkin)
    {
        if (pConnectionSkin != null && !(pConnectionSkin instanceof VirtualSkin))
        {
            mConnectionLayer.getChildren().remove(pConnectionSkin.getRoot());
        }
    }

    /**
     * Removes a joint skin from the view. Does nothing if the skin is not
     * present.
     *
     * @param pJointSkin
     *            the {@link GJointSkin} instance to remove
     */
    public void remove(final GJointSkin pJointSkin)
    {
        if (pJointSkin != null && !(pJointSkin instanceof VirtualSkin))
        {
            mConnectionLayer.getChildren().remove(pJointSkin.getRoot());
        }
    }

    /**
     * Removes a tail skin from the view. Does nothing if the skin is not
     * present.
     *
     * @param pTailSkin
     *            the {@link GTailSkin} instance to remove
     */
    public void remove(final GTailSkin pTailSkin)
    {
        if (pTailSkin != null && !(pTailSkin instanceof VirtualSkin))
        {
            mConnectionLayer.getChildren().remove(pTailSkin.getRoot());
        }
    }

    /**
     * Gets the editor properties instance used by the view.
     *
     * @return editorProperties the {@link GraphEditorProperties} instance used
     *         by the view
     */
    public GraphEditorProperties getEditorProperties()
    {
        return mEditorProperties;
    }

    /**
     * Draws a selection box in the view.
     *
     * @param pX
     *            the x position of the selection box
     * @param pY
     *            the y position of the selection box
     * @param pWidth
     *            the width of the selection box
     * @param pHeight
     *            the height of the selection box
     */
    public void drawSelectionBox(final double pX, final double pY, final double pWidth, final double pHeight)
    {
        mSelectionBox.draw(pX, pY, pWidth, pHeight);
    }

    /**
     * Hides the selection box.
     */
    public void hideSelectionBox()
    {
        mSelectionBox.setVisible(false);
    }

    @Override
    protected void layoutChildren()
    {
        final double width = getWidth();
        final double height = getHeight();
        mNodeLayer.resizeRelocate(0, 0, width, height);
        mConnectionLayer.resizeRelocate(0, 0, width, height);
        mGrid.resizeRelocate(0, 0, width, height);
        drawConnections();
    }

    /**
     * calls {@link ConnectionLayouter#draw()}
     *
     * @since 31.01.2019
     */
    void drawConnections()
    {
        if (mConnectionLayouter != null)
        {
            mConnectionLayouter.draw();
        }
    }

    /**
     * Initializes the two layers (node and connection) that the view is
     * composed of.
     */
    private void initializeLayers()
    {
        mNodeLayer.setPickOnBounds(false);
        mConnectionLayer.setPickOnBounds(false);

        mNodeLayer.getStyleClass().add(STYLE_CLASS_NODE_LAYER);
        mConnectionLayer.getStyleClass().add(STYLE_CLASS_CONNECTION_LAYER);

        // Node layer should be on top of connection layer, so we add it second.
        getChildren().addAll(mGrid, mConnectionLayer, mNodeLayer, mSelectionBox);
    }
} public interface GConnection extends EObject {
	/**
	 * Returns the value of the '<em><b>Id</b></em>' attribute.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Id</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Id</em>' attribute.
	 * @see #setId(String)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGConnection_Id()
	 * @model id="true"
	 * @generated
	 */
	String getId();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GConnection#getId <em>Id</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Id</em>' attribute.
	 * @see #getId()
	 * @generated
	 */
	void setId(String value);

	/**
	 * Returns the value of the '<em><b>Type</b></em>' attribute.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Type</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Type</em>' attribute.
	 * @see #setType(String)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGConnection_Type()
	 * @model
	 * @generated
	 */
	String getType();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GConnection#getType <em>Type</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Type</em>' attribute.
	 * @see #getType()
	 * @generated
	 */
	void setType(String value);

	/**
	 * Returns the value of the '<em><b>Source</b></em>' reference.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Source</em>' reference isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Source</em>' reference.
	 * @see #setSource(GConnector)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGConnection_Source()
	 * @model required="true"
	 * @generated
	 */
	GConnector getSource();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GConnection#getSource <em>Source</em>}' reference.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Source</em>' reference.
	 * @see #getSource()
	 * @generated
	 */
	void setSource(GConnector value);

	/**
	 * Returns the value of the '<em><b>Target</b></em>' reference.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Target</em>' reference isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Target</em>' reference.
	 * @see #setTarget(GConnector)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGConnection_Target()
	 * @model required="true"
	 * @generated
	 */
	GConnector getTarget();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GConnection#getTarget <em>Target</em>}' reference.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Target</em>' reference.
	 * @see #getTarget()
	 * @generated
	 */
	void setTarget(GConnector value);

	/**
	 * Returns the value of the '<em><b>Joints</b></em>' containment reference list.
	 * The list contents are of type {@link de.tesis.dynaware.grapheditor.model.GJoint}.
	 * It is bidirectional and its opposite is '{@link de.tesis.dynaware.grapheditor.model.GJoint#getConnection <em>Connection</em>}'.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Joints</em>' containment reference list isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Joints</em>' containment reference list.
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGConnection_Joints()
	 * @see de.tesis.dynaware.grapheditor.model.GJoint#getConnection
	 * @model opposite="connection" containment="true"
	 * @generated
	 */
	EList<GJoint> getJoints();

} // GConnection public interface GConnector extends EObject {
	/**
	 * Returns the value of the '<em><b>Id</b></em>' attribute.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Id</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Id</em>' attribute.
	 * @see #setId(String)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGConnector_Id()
	 * @model id="true"
	 * @generated
	 */
	String getId();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GConnector#getId <em>Id</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Id</em>' attribute.
	 * @see #getId()
	 * @generated
	 */
	void setId(String value);

	/**
	 * Returns the value of the '<em><b>Type</b></em>' attribute.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Type</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Type</em>' attribute.
	 * @see #setType(String)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGConnector_Type()
	 * @model
	 * @generated
	 */
	String getType();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GConnector#getType <em>Type</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Type</em>' attribute.
	 * @see #getType()
	 * @generated
	 */
	void setType(String value);

	/**
	 * Returns the value of the '<em><b>Parent</b></em>' container reference.
	 * It is bidirectional and its opposite is '{@link de.tesis.dynaware.grapheditor.model.GNode#getConnectors <em>Connectors</em>}'.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Parent</em>' container reference isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Parent</em>' container reference.
	 * @see #setParent(GNode)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGConnector_Parent()
	 * @see de.tesis.dynaware.grapheditor.model.GNode#getConnectors
	 * @model opposite="connectors" required="true" transient="false"
	 * @generated
	 */
	GNode getParent();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GConnector#getParent <em>Parent</em>}' container reference.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Parent</em>' container reference.
	 * @see #getParent()
	 * @generated
	 */
	void setParent(GNode value);

	/**
	 * Returns the value of the '<em><b>Connections</b></em>' reference list.
	 * The list contents are of type {@link de.tesis.dynaware.grapheditor.model.GConnection}.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Connections</em>' reference list isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Connections</em>' reference list.
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGConnector_Connections()
	 * @model
	 * @generated
	 */
	EList<GConnection> getConnections();

	/**
	 * Returns the value of the '<em><b>X</b></em>' attribute.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>X</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>X</em>' attribute.
	 * @see #setX(double)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGConnector_X()
	 * @model
	 * @generated
	 */
	double getX();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GConnector#getX <em>X</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>X</em>' attribute.
	 * @see #getX()
	 * @generated
	 */
	void setX(double value);

	/**
	 * Returns the value of the '<em><b>Y</b></em>' attribute.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Y</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Y</em>' attribute.
	 * @see #setY(double)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGConnector_Y()
	 * @model
	 * @generated
	 */
	double getY();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GConnector#getY <em>Y</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Y</em>' attribute.
	 * @see #getY()
	 * @generated
	 */
	void setY(double value);

	/**
	 * Returns the value of the '<em><b>Connection Detached On Drag</b></em>' attribute.
	 * The default value is <code>"true"</code>.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Connection Detached On Drag</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Connection Detached On Drag</em>' attribute.
	 * @see #setConnectionDetachedOnDrag(boolean)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGConnector_ConnectionDetachedOnDrag()
	 * @model default="true" required="true"
	 * @generated
	 */
	boolean isConnectionDetachedOnDrag();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GConnector#isConnectionDetachedOnDrag <em>Connection Detached On Drag</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Connection Detached On Drag</em>' attribute.
	 * @see #isConnectionDetachedOnDrag()
	 * @generated
	 */
	void setConnectionDetachedOnDrag(boolean value);

} // GConnector public interface GJoint extends EObject {
	/**
	 * Returns the value of the '<em><b>Id</b></em>' attribute.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Id</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Id</em>' attribute.
	 * @see #setId(String)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGJoint_Id()
	 * @model id="true"
	 * @generated
	 */
	String getId();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GJoint#getId <em>Id</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Id</em>' attribute.
	 * @see #getId()
	 * @generated
	 */
	void setId(String value);

	/**
	 * Returns the value of the '<em><b>Type</b></em>' attribute.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Type</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Type</em>' attribute.
	 * @see #setType(String)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGJoint_Type()
	 * @model
	 * @generated
	 */
	String getType();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GJoint#getType <em>Type</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Type</em>' attribute.
	 * @see #getType()
	 * @generated
	 */
	void setType(String value);

	/**
	 * Returns the value of the '<em><b>Connection</b></em>' container reference.
	 * It is bidirectional and its opposite is '{@link de.tesis.dynaware.grapheditor.model.GConnection#getJoints <em>Joints</em>}'.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Connection</em>' container reference isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Connection</em>' container reference.
	 * @see #setConnection(GConnection)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGJoint_Connection()
	 * @see de.tesis.dynaware.grapheditor.model.GConnection#getJoints
	 * @model opposite="joints" required="true" transient="false"
	 * @generated
	 */
	GConnection getConnection();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GJoint#getConnection <em>Connection</em>}' container reference.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Connection</em>' container reference.
	 * @see #getConnection()
	 * @generated
	 */
	void setConnection(GConnection value);

	/**
	 * Returns the value of the '<em><b>X</b></em>' attribute.
	 * The default value is <code>"0"</code>.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>X</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>X</em>' attribute.
	 * @see #setX(double)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGJoint_X()
	 * @model default="0" required="true"
	 * @generated
	 */
	double getX();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GJoint#getX <em>X</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>X</em>' attribute.
	 * @see #getX()
	 * @generated
	 */
	void setX(double value);

	/**
	 * Returns the value of the '<em><b>Y</b></em>' attribute.
	 * The default value is <code>"0"</code>.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Y</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Y</em>' attribute.
	 * @see #setY(double)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGJoint_Y()
	 * @model default="0" required="true"
	 * @generated
	 */
	double getY();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GJoint#getY <em>Y</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Y</em>' attribute.
	 * @see #getY()
	 * @generated
	 */
	void setY(double value);

} // GJoint public interface GModel extends EObject {
	/**
	 * Returns the value of the '<em><b>Nodes</b></em>' containment reference list.
	 * The list contents are of type {@link de.tesis.dynaware.grapheditor.model.GNode}.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Nodes</em>' containment reference list isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Nodes</em>' containment reference list.
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGModel_Nodes()
	 * @model containment="true"
	 * @generated
	 */
	EList<GNode> getNodes();

	/**
	 * Returns the value of the '<em><b>Connections</b></em>' containment reference list.
	 * The list contents are of type {@link de.tesis.dynaware.grapheditor.model.GConnection}.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Connections</em>' containment reference list isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Connections</em>' containment reference list.
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGModel_Connections()
	 * @model containment="true"
	 * @generated
	 */
	EList<GConnection> getConnections();

	/**
	 * Returns the value of the '<em><b>Type</b></em>' attribute.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Type</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Type</em>' attribute.
	 * @see #setType(String)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGModel_Type()
	 * @model
	 * @generated
	 */
	String getType();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GModel#getType <em>Type</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Type</em>' attribute.
	 * @see #getType()
	 * @generated
	 */
	void setType(String value);

	/**
	 * Returns the value of the '<em><b>Content Width</b></em>' attribute.
	 * The default value is <code>"3000"</code>.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Content Width</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Content Width</em>' attribute.
	 * @see #setContentWidth(double)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGModel_ContentWidth()
	 * @model default="3000" required="true"
	 * @generated
	 */
	double getContentWidth();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GModel#getContentWidth <em>Content Width</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Content Width</em>' attribute.
	 * @see #getContentWidth()
	 * @generated
	 */
	void setContentWidth(double value);

	/**
	 * Returns the value of the '<em><b>Content Height</b></em>' attribute.
	 * The default value is <code>"2250"</code>.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Content Height</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Content Height</em>' attribute.
	 * @see #setContentHeight(double)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGModel_ContentHeight()
	 * @model default="2250" required="true"
	 * @generated
	 */
	double getContentHeight();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GModel#getContentHeight <em>Content Height</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Content Height</em>' attribute.
	 * @see #getContentHeight()
	 * @generated
	 */
	void setContentHeight(double value);

} // GModel public interface GNode extends EObject {
	/**
	 * Returns the value of the '<em><b>Id</b></em>' attribute.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Id</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Id</em>' attribute.
	 * @see #setId(String)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGNode_Id()
	 * @model id="true"
	 * @generated
	 */
	String getId();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GNode#getId <em>Id</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Id</em>' attribute.
	 * @see #getId()
	 * @generated
	 */
	void setId(String value);

	/**
	 * Returns the value of the '<em><b>Type</b></em>' attribute.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Type</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Type</em>' attribute.
	 * @see #setType(String)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGNode_Type()
	 * @model
	 * @generated
	 */
	String getType();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GNode#getType <em>Type</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Type</em>' attribute.
	 * @see #getType()
	 * @generated
	 */
	void setType(String value);

	/**
	 * Returns the value of the '<em><b>X</b></em>' attribute.
	 * The default value is <code>"0"</code>.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>X</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>X</em>' attribute.
	 * @see #setX(double)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGNode_X()
	 * @model default="0" required="true"
	 * @generated
	 */
	double getX();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GNode#getX <em>X</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>X</em>' attribute.
	 * @see #getX()
	 * @generated
	 */
	void setX(double value);

	/**
	 * Returns the value of the '<em><b>Y</b></em>' attribute.
	 * The default value is <code>"0"</code>.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Y</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Y</em>' attribute.
	 * @see #setY(double)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGNode_Y()
	 * @model default="0" required="true"
	 * @generated
	 */
	double getY();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GNode#getY <em>Y</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Y</em>' attribute.
	 * @see #getY()
	 * @generated
	 */
	void setY(double value);

	/**
	 * Returns the value of the '<em><b>Width</b></em>' attribute.
	 * The default value is <code>"151"</code>.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Width</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Width</em>' attribute.
	 * @see #setWidth(double)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGNode_Width()
	 * @model default="151" required="true"
	 * @generated
	 */
	double getWidth();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GNode#getWidth <em>Width</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Width</em>' attribute.
	 * @see #getWidth()
	 * @generated
	 */
	void setWidth(double value);

	/**
	 * Returns the value of the '<em><b>Height</b></em>' attribute.
	 * The default value is <code>"101"</code>.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Height</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Height</em>' attribute.
	 * @see #setHeight(double)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGNode_Height()
	 * @model default="101" required="true"
	 * @generated
	 */
	double getHeight();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GNode#getHeight <em>Height</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Height</em>' attribute.
	 * @see #getHeight()
	 * @generated
	 */
	void setHeight(double value);

	/**
	 * Returns the value of the '<em><b>Connectors</b></em>' containment reference list.
	 * The list contents are of type {@link de.tesis.dynaware.grapheditor.model.GConnector}.
	 * It is bidirectional and its opposite is '{@link de.tesis.dynaware.grapheditor.model.GConnector#getParent <em>Parent</em>}'.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Connectors</em>' containment reference list isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Connectors</em>' containment reference list.
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGNode_Connectors()
	 * @see de.tesis.dynaware.grapheditor.model.GConnector#getParent
	 * @model opposite="parent" containment="true"
	 * @generated
	 */
	EList<GConnector> getConnectors();

} // GNode public interface GraphFactory extends EFactory {
	/**
	 * The singleton instance of the factory.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	GraphFactory eINSTANCE = de.tesis.dynaware.grapheditor.model.impl.GraphFactoryImpl.init();

	/**
	 * Returns a new object of class '<em>GModel</em>'.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @return a new object of class '<em>GModel</em>'.
	 * @generated
	 */
	GModel createGModel();

	/**
	 * Returns a new object of class '<em>GNode</em>'.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @return a new object of class '<em>GNode</em>'.
	 * @generated
	 */
	GNode createGNode();

	/**
	 * Returns a new object of class '<em>GConnection</em>'.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @return a new object of class '<em>GConnection</em>'.
	 * @generated
	 */
	GConnection createGConnection();

	/**
	 * Returns a new object of class '<em>GConnector</em>'.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @return a new object of class '<em>GConnector</em>'.
	 * @generated
	 */
	GConnector createGConnector();

	/**
	 * Returns a new object of class '<em>GJoint</em>'.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @return a new object of class '<em>GJoint</em>'.
	 * @generated
	 */
	GJoint createGJoint();

	/**
	 * Returns the package supported by this factory.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @return the package supported by this factory.
	 * @generated
	 */
	GraphPackage getGraphPackage();

} //GraphFactory public class GeometryUtils {

    private static final double HALF_A_PIXEL = 0.5;

    /**
     * Gets the position of the <b>center</b> of a connector in the coordinate system of the view.
     *
     * <p>
     * Only works for connectors that are attached to nodes.
     * <p>
     *
     * @param connector the {@link GConnector} whose position is desired
     * @param skinLookup the {@link SkinLookup} instance for this graph editor
     *
     * @return the x and y coordinates of the connector, or {@code null} if the connector isn't attached to a node
     */
    public static Point2D getConnectorPosition(final GConnector connector, final SkinLookup skinLookup) {

        final GConnectorSkin connectorSkin = skinLookup.lookupConnector(connector);
        final GNode parent = connector.getParent();

        final GNodeSkin nodeSkin = skinLookup.lookupNode(parent);
        if (nodeSkin == null) {
            return null;
        }

        nodeSkin.layoutConnectors();

        final double nodeX = nodeSkin.getRoot().getLayoutX();
        final double nodeY = nodeSkin.getRoot().getLayoutY();

        final Point2D connectorPosition = nodeSkin.getConnectorPosition(connectorSkin);

        final double connectorX = connectorPosition.getX();
        final double connectorY = connectorPosition.getY();

        return new Point2D(moveOnPixel(nodeX + connectorX), moveOnPixel(nodeY + connectorY));
    }

    /**
     * Gets the position of the cursor relative to some node.
     *
     * @param event a {@link MouseEvent} storing the cursor position
     * @param node some {@link Node}
     *
     * @return the position of the cursor relative to the node origin
     */
    public static Point2D getCursorPosition(final MouseEvent event, final Node node)
    {
        final double sceneX = event.getSceneX();
        final double sceneY = event.getSceneY();

        final Point2D containerScene = node.localToScene(0, 0);
        return new Point2D(sceneX - containerScene.getX(), sceneY - containerScene.getY());
    }

    /**
     * Gets the layout x and y values from all joints in a list of joint skins.
     *
     * @param jointSkins a list of joint skin instances
     *
     * @return a {@link List} of {@link Point2D} objects containing joint x and y values
     */
    public static List<Point2D> getJointPositions(final List<GJointSkin> jointSkins) {

        final List<Point2D> jointPositions = new ArrayList<>(jointSkins.size());

        for (final GJointSkin jointSkin : jointSkins) {

            final Region region = jointSkin.getRoot();

            final double x = region.getLayoutX() + jointSkin.getWidth() / 2;
            final double y = region.getLayoutY() + jointSkin.getHeight() / 2;

            jointPositions.add(new Point2D(x, y));
        }

        return jointPositions;
    }

    /**
     * Gets the layout x and y values from all joints within a connection.
     *
     * <p>
     * Uses the JavaFX properties of the skins, not the model values. Is
     * therefore always up-to-date, even during a drag gesture where the model
     * is not necessarily updated.
     * <p>
     *
     * @param connection
     *            the {@link GConnection} for which the positions are desired
     * @param skinLookup
     *            the {@link SkinLookup} instance for this graph editor
     * @param pTarget
     *            the array where to write the points to
     */
    public static void fillJointPositions(final GConnection connection, final SkinLookup skinLookup, final Point2D[] pTarget)
    {
        for (int i = 0; i < connection.getJoints().size(); i++)
        {
            final GJoint joint = connection.getJoints().get(i);
            pTarget[i + 1] = getJointPosition(joint, skinLookup);
        }
    }

    /**
     * Gets the layout x and y values from all joints within a connection.
     *
     * <p>
     * Uses the JavaFX properties of the skins, not the model values. Is
     * therefore always up-to-date, even during a drag gesture where the model
     * is not necessarily updated.
     * <p>
     *
     * @param connection
     *            the {@link GConnection} for which the positions are desired
     * @param skinLookup
     *            the {@link SkinLookup} instance for this graph editor
     *
     * @return a {@link List} of {@link Point2D} objects containing joint x and
     *         y values
     */
    public static List<Point2D> getJointPositions(final GConnection connection, final SkinLookup skinLookup)
    {
        final List<Point2D> jointPositions = new ArrayList<>(connection.getJoints().size());
        for (final GJoint joint : connection.getJoints())
        {
            jointPositions.add(getJointPosition(joint, skinLookup));
        }
        return jointPositions;
    }

    /**
     * Gets the layout x and y values from all joints within a connection.
     *
     * <p>
     * Uses the JavaFX properties of the skins, not the model values. Is
     * therefore always up-to-date, even during a drag gesture where the model
     * is not necessarily updated.
     * <p>
     *
     * @param joint
     *            the {@link GJoint} for which the position is desired
     * @param skinLookup
     *            the {@link SkinLookup} instance for this graph editor
     * @return {@link Point2D} object containing joint x and y values
     */
    public static Point2D getJointPosition(final GJoint joint, final SkinLookup skinLookup)
    {
        final GJointSkin jointSkin = skinLookup.lookupJoint(joint);
        final Region region = jointSkin.getRoot();

        final double x = region.getLayoutX() + jointSkin.getWidth() / 2;
        final double y = region.getLayoutY() + jointSkin.getHeight() / 2;

        return new Point2D(x, y);
    }

    /**
     * Gets the x and y values from all joints within a connection.
     *
     * @param connection a {@link GConnection} instance
     *
     * @return a {@link List} of {@link Point2D} objects containing joint x and y values
     */
    public static List<Point2D> getJointPositions(final GConnection connection) {

        final List<Point2D> jointPositions = new ArrayList<>(connection.getJoints().size());

        for (final GJoint joint : connection.getJoints()) {
            jointPositions.add(new Point2D(joint.getX(), joint.getY()));
        }

        return jointPositions;
    }

    /**
     * Moves an x or y position value on-pixel.
     *
     * <p>
     * Lines drawn off-pixel look blurry. They should therefore have integer x and y values.
     * </p>
     *
     * @param position the position to move on-pixel
     *
     * @return the position rounded to the nearest integer
     */
    public static double moveOnPixel(final double position) {
        return Math.ceil(position);
    }

    /**
     * Moves an x or y position value off-pixel.
     *
     * <p>
     * This is for example useful for a 1-pixel-wide stroke with a stroke-type of centered. The x and y positions need
     * to be off-pixel so that the stroke is on-pixel.
     * </p>
     *
     * @param position the position to move off-pixel
     *
     * @return the position moved to the nearest value halfway between two integers
     */
    public static double moveOffPixel(final double position) {
        return Math.ceil(position) - HALF_A_PIXEL;
    }

    /**
     * Checks if the given position is between two values.
     *
     * <p>
     * Also returns true if the given position is equal to either of the values.
     * </p>
     *
     * @param firstValue an x or y position value
     * @param secondValue another x or y position value
     * @param position the cursor's position value
     *
     * @return {@code true} if the cursor position is between the two points
     */
    public static boolean checkInRange(final double firstValue, final double secondValue, final double position) {

        if (secondValue >= firstValue) {
            return firstValue <= position && position <= secondValue;
        }
        // ELSE:
        return secondValue <= position && position <= firstValue;
    }

    /**
     * Checks if a horizontal line segment AB intersects with a vertical line segment CD.
     *
     * @param a start of line segment AB
     * @param b end of line segment AB
     * @param c start of line segment CD
     * @param d end of line segment CD
     * @return {@code true} if AB and CD intersect, {@code false} otherwise
     */
    public static boolean checkIntersection(final Point2D a, final Point2D b, final Point2D c, final Point2D d) {

        if (!(c.getX() > a.getX() && c.getX() < b.getX()) && !(c.getX() > b.getX() && c.getX() < a.getX())) {
            return false;
        }

        if (!(a.getY() > c.getY() && a.getY() < d.getY()) && !(a.getY() > d.getY() && a.getY() < c.getY())) {
            return false;
        }

        return true;
    }

    /**
     * Rounds some value to the nearest multiple of the grid spacing.
     *
     * @param pProperties
     *            {@link GraphEditorProperties} or {@code null}
     * @param pValue
     *            a double value
     * @return the input value rounded to the nearest multiple of the grid
     *         spacing
     */
    public static double roundToGridSpacing(final GraphEditorProperties pProperties, final double pValue)
    {
        if (pProperties == null || !pProperties.isSnapToGridOn())
        {
            return pValue;
        }
        final double spacing = pProperties.getGridSpacing();
        return spacing * Math.round(pValue / spacing);
    }
} public class GraphEditorProperties implements GraphEventManager
{

    /**
     * The default max width of the editor region, set on startup.
     */
    public static final double DEFAULT_MAX_WIDTH = Double.MAX_VALUE;
    /**
     * The default max height of the editor region, set on startup.
     */
    public static final double DEFAULT_MAX_HEIGHT = Double.MAX_VALUE;

    public static final double DEFAULT_BOUND_VALUE = 15;
    public static final double DEFAULT_GRID_SPACING = 12;

    // The distance from the editor edge at which the objects should stop when dragged / resized.
    private double northBoundValue = DEFAULT_BOUND_VALUE;
    private double southBoundValue = DEFAULT_BOUND_VALUE;
    private double eastBoundValue = DEFAULT_BOUND_VALUE;
    private double westBoundValue = DEFAULT_BOUND_VALUE;

    // Off by default.
    private final BooleanProperty gridVisible = new SimpleBooleanProperty(this, "gridVisible"); //$NON-NLS-1$
    private final BooleanProperty snapToGrid = new SimpleBooleanProperty(this, "snapToGrid"); //$NON-NLS-1$
    private final DoubleProperty gridSpacing = new SimpleDoubleProperty(this, "gridSpacing", DEFAULT_GRID_SPACING); //$NON-NLS-1$

    private final Map<EditorElement, BooleanProperty> readOnly = new EnumMap<>(EditorElement.class);

    private final ObservableMap<String, String> customProperties = FXCollections.observableHashMap();

    private final GraphEventManager eventManager = new GraphEventManagerImpl();

    /**
     * Creates a new editor properties instance containing a set of default
     * properties.
     */
    public GraphEditorProperties()
    {
    }

    /**
     * Copy constructor.
     *
     * <p>
     * Creates a new editor properties instance with all values copied over from
     * an existing instance.
     * </p>
     *
     * @param editorProperties
     *         an existing {@link GraphEditorProperties} instance
     */
    public GraphEditorProperties(final GraphEditorProperties editorProperties)
    {
        northBoundValue = editorProperties.getNorthBoundValue();
        southBoundValue = editorProperties.getSouthBoundValue();
        eastBoundValue = editorProperties.getEastBoundValue();
        westBoundValue = editorProperties.getWestBoundValue();

        gridVisible.set(editorProperties.isGridVisible());
        snapToGrid.set(editorProperties.isSnapToGridOn());
        gridSpacing.set(editorProperties.getGridSpacing());

        for (final Map.Entry<EditorElement, BooleanProperty> entry : editorProperties.readOnly.entrySet())
        {
            readOnly.computeIfAbsent(entry.getKey(), k -> new SimpleBooleanProperty()).set(entry.getValue().get());
        }

        customProperties.putAll(editorProperties.getCustomProperties());
    }

    /**
     * Gets the value of the north bound.
     *
     * @return the value of the north bound
     */
    public double getNorthBoundValue()
    {
        return northBoundValue;
    }

    /**
     * Sets the value of the north bound.
     *
     * @param pNorthBoundValue
     *         the value of the north bound
     */
    public void setNorthBoundValue(final double pNorthBoundValue)
    {
        northBoundValue = pNorthBoundValue;
    }

    /**
     * Gets the value of the south bound.
     *
     * @return the value of the south bound
     */
    public double getSouthBoundValue()
    {
        return southBoundValue;
    }

    /**
     * Sets the value of the south bound.
     *
     * @param pSouthBoundValue
     *         the value of the south bound
     */
    public void setSouthBoundValue(final double pSouthBoundValue)
    {
        southBoundValue = pSouthBoundValue;
    }

    /**
     * Gets the value of the east bound.
     *
     * @return the value of the east bound
     */
    public double getEastBoundValue()
    {
        return eastBoundValue;
    }

    /**
     * Sets the value of the east bound.
     *
     * @param pEastBoundValue
     *         the value of the east bound
     */
    public void setEastBoundValue(final double pEastBoundValue)
    {
        eastBoundValue = pEastBoundValue;
    }

    /**
     * Gets the value of the west bound.
     *
     * @return the value of the west bound
     */
    public double getWestBoundValue()
    {
        return westBoundValue;
    }

    /**
     * Sets the value of the west bound.
     *
     * @param pWestBoundValue
     *         the value of the west bound
     */
    public void setWestBoundValue(final double pWestBoundValue)
    {
        westBoundValue = pWestBoundValue;
    }

    /**
     * Checks if the background grid is visible.
     *
     * @return {@code true} if the background grid is visible, {@code false} if
     *         not
     */
    public boolean isGridVisible()
    {
        return gridVisible.get();
    }

    /**
     * Sets whether the background grid should be visible or not.
     *
     * @param pGridVisible
     *            {@code true} if the background grid should be visible,
     *            {@code false} if not
     */
    public void setGridVisible(final boolean pGridVisible)
    {
        gridVisible.set(pGridVisible);
    }

    /**
     * Gets the grid-visible property.
     *
     * @return a {@link BooleanProperty} tracking whether the grid is visible or
     *         not
     */
    public BooleanProperty gridVisibleProperty()
    {
        return gridVisible;
    }

    /**
     * Checks if snap-to-grid is on.
     *
     * @return {@code true} if snap-to-grid is on, {@code false} if not
     */
    public boolean isSnapToGridOn()
    {
        return snapToGrid.get();
    }

    /**
     * Sets whether snap-to-grid should be on.
     *
     * @param pSnapToGrid
     *            {@code true} if snap-to-grid should be on, {@code false} if
     *            not
     */
    public void setSnapToGrid(final boolean pSnapToGrid)
    {
        snapToGrid.set(pSnapToGrid);
    }

    /**
     * Gets the snap-to-grid property.
     *
     * @return a {@link BooleanProperty} tracking whether snap-to-grid is on or
     *         off
     */
    public BooleanProperty snapToGridProperty()
    {
        return snapToGrid;
    }

    /**
     * Gets the current grid spacing in pixels.
     *
     * @return the current grid spacing
     */
    public double getGridSpacing()
    {
        return gridSpacing.get();
    }

    /**
     * Sets the grid spacing to be used if the grid is visible and/or
     * snap-to-grid is enabled.
     *
     * <p>
     * Integer values are recommended to avoid sub-pixel positioning effects.
     * </p>
     *
     * @param pGridSpacing
     *         the grid spacing to be used
     */
    public void setGridSpacing(final double pGridSpacing)
    {
        gridSpacing.set(pGridSpacing);
    }

    /**
     * Gets the grid spacing property.
     *
     * @return the grid spacing {@link DoubleProperty}.
     */
    public DoubleProperty gridSpacingProperty()
    {
        return gridSpacing;
    }

    /**
     * Gets the read only property
     *
     * @param pType
     *         {@link EditorElement}
     * @return read only {@link BooleanProperty}
     */
    public BooleanProperty readOnlyProperty(final EditorElement pType)
    {
        Objects.requireNonNull(pType, "ElementType may not be null!");
        return readOnly.computeIfAbsent(pType, k -> new SimpleBooleanProperty());
    }

    /**
     * Returns whether or not the graph is in read only state.
     *
     * @param pType
     *         {@link EditorElement}
     * @return whether or not the graph is in read only state.
     */
    public boolean isReadOnly(final EditorElement pType)
    {
        return pType != null && readOnly.computeIfAbsent(pType, k -> new SimpleBooleanProperty()).get();
    }

    /**
     * @param pType
     *         {@link EditorElement}
     * @param pReadOnly
     *         {@code true} to set the graph editor in read only state or {@code false} (default) for edit state.
     */
    public void setReadOnly(final EditorElement pType, final boolean pReadOnly)
    {
        if (pType != null)
        {
            readOnly.computeIfAbsent(pType, k -> new SimpleBooleanProperty()).set(pReadOnly);
        }
    }

    /**
     * Additional properties that may be added and referred to in custom skin
     * implementations.
     *
     * @return a map of custom properties
     */
    public ObservableMap<String, String> getCustomProperties()
    {
        return customProperties;
    }

    @Override
    public boolean activateGesture(GraphInputGesture pGesture, Event pEvent, Object pOwner)
    {
        return eventManager.activateGesture(pGesture, pEvent, pOwner);
    }

    @Override
    public boolean finishGesture(GraphInputGesture pExpected, Object pOwner)
    {
        return eventManager.finishGesture(pExpected, pOwner);
    }
} public interface GraphEventManager
{

    /**
     * <p>
     * This method is called by the framework. Custom skins should <b>not</b>
     * call it.
     * </p>
     *
     * @param pGesture
     *            {@link GraphInputGesture} to check
     * @param pEvent
     *            {@link Event}
     * @param pOwner
     *            owner
     * @return {@code true} if the given gesture was activated otherwise
     *         {@code false}
     */
    boolean activateGesture(final GraphInputGesture pGesture, final Event pEvent, final Object pOwner);

    /**
     * <p>
     * This method is called by the framework. Custom skins should <b>not</b>
     * call it.
     * </p>
     *
     * @param pExpected
     *            the expected gesture that should be finished
     * @param pOwner
     *            owner
     * @return {@code true} if the state changed as a result of this operation
     *         or {@code false}
     */
    boolean finishGesture(final GraphInputGesture pExpected, final Object pOwner);
} public enum GraphInputGesture
{

    /**
     * Panning / moving the graph editor viewport
     */
    PAN,

    /**
     * Zooming the graph editor viewport
     */
    ZOOM,

    /**
     * Resizing graph editor elements
     */
    RESIZE,

    /**
     * Moving graph editor elements
     */
    MOVE,

    /**
     * Connecting graph editor elements
     */
    CONNECT,

    /**
     * Selecting graph editor elements
     */
    SELECT;
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import de.tesis.dynaware.grapheditor.EditorElement;
import de.tesis.dynaware.grapheditor.GConnectorSkin;
import de.tesis.dynaware.grapheditor.GConnectorStyle;
import de.tesis.dynaware.grapheditor.GConnectorValidator;
import de.tesis.dynaware.grapheditor.SkinLookup;
import de.tesis.dynaware.grapheditor.VirtualSkin;
import de.tesis.dynaware.grapheditor.core.DefaultGraphEditor;
import de.tesis.dynaware.grapheditor.core.skins.defaults.utils.ConnectionCommands;
import de.tesis.dynaware.grapheditor.core.utils.EventUtils;
import de.tesis.dynaware.grapheditor.core.view.GraphEditorView;
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.utils.GeometryUtils;
import de.tesis.dynaware.grapheditor.utils.GraphEditorProperties;
import de.tesis.dynaware.grapheditor.utils.GraphEventManager;
import de.tesis.dynaware.grapheditor.utils.GraphInputGesture;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.event.EventType;
import javafx.geometry.Point2D;
import javafx.scene.Node;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseDragEvent;
import javafx.scene.input.MouseEvent;
/*
 * Copyright (C) 2005 - 2014 by TESIS DYNAware GmbH
 */
package de.tesis.dynaware.grapheditor.core.connections;



/**
 * Responsible for what happens when connectors are dragged in the graph editor.
 *
 * <p>
 * Namely, the creation, removal, and repositioning of connections.
 * </p>
 */
public class ConnectorDragManager {

    private final TailManager tailManager;

    private final GraphEditorView view;
    private final SkinLookup skinLookup;
    private final ConnectionEventManager connectionEventManager;

    private GModel model;

    private final EventHandler<MouseEvent> mouseExitedHandler = this::handleMouseExited;
    /**
     * Consume the Event so the parent container (ResizableBox/DraggableBox) does
     * not move on connection detach
     */
    private final EventHandler<MouseEvent> mousePressedHandler = Event::consume;

    private final Map<Node, EventHandler<MouseEvent>> mouseEnteredHandlers = new HashMap<>();
    private final Map<Node, EventHandler<MouseEvent>> mouseReleasedHandlers = new HashMap<>();
    private final Map<Node, EventHandler<MouseEvent>> dragDetectedHandlers = new HashMap<>();
    private final Map<Node, EventHandler<MouseEvent>> mouseDraggedHandlers = new HashMap<>();
    private final Map<Node, EventHandler<MouseDragEvent>> mouseDragEnteredHandlers = new HashMap<>();
    private final Map<Node, EventHandler<MouseDragEvent>> mouseDragExitedHandlers = new HashMap<>();
    private final Map<Node, EventHandler<MouseDragEvent>> mouseDragReleasedHandlers = new HashMap<>();

    private GConnectorValidator validator = new DefaultConnectorValidator();