X

Geertjan's Blog

  • March 30, 2013

Adding & Removing Connection Widgets

Geertjan Wielenga
Product Manager

Let's extend the example referred to yesterday. We'll let the user connect widgets with each other, after the Ctrl key is pressed and the mouse is moved from one widget to another.

Add the below to the AccountBuchWidget class:

private class AccountBuchConnectProvider implements ConnectProvider {
    @Override
    public boolean isSourceWidget(Widget source) {
        return source instanceof AccountBuchWidget
                && source != null ? true : false;
    }
    @Override
    public ConnectorState isTargetWidget(Widget src, Widget trg) {
        return src != trg && trg instanceof AccountBuchWidget
                ? ConnectorState.ACCEPT : ConnectorState.REJECT;
    }
    @Override
    public boolean hasCustomTargetWidgetResolver(Scene arg0) {
        return false;
    }
    @Override
    public Widget resolveTargetWidget(Scene arg0, Point arg1) {
        return null;
    }
    @Override
    public void createConnection(Widget source, Widget target) {
        ConnectionWidget conn = new ConnectionWidget(scene);
        conn.setTargetAnchorShape(AnchorShape.TRIANGLE_FILLED);
        conn.setTargetAnchor(AnchorFactory.createRectangularAnchor(target));
        conn.setSourceAnchor(AnchorFactory.createRectangularAnchor(source));
        connectionLayerWidget.addChild(conn);
    }
}

Next, in the TopComponent constructor, create a new LayerWidget, add it to the Scene, and change the initialization of the AccountBuchWidget so that the new LayerWidget is passed to the AccountBuchWidget constructor:

        final LayerWidget connectionLayerWidget = new LayerWidget(scene);

        layerWidget.addChild(new AccountBuchWidget(scene, ab, point, connectionLayerWidget));

        scene.addChild(connectionLayerWidget);

Then you can add the AccountBuchConnectionProvider to the list of Actions in the constructor of the AccountBuchWidget:

        getActions().addAction(ActionFactory.createExtendedConnectAction(
           connectionLayerWidget,
           new AccountBuchConnectProvider())
        );

Finally, if you incorporated the Delete key, mentioned by Mike in the comments yesterday, make sure to also remove the related ConnectionWidgets when deleting an AccountBuchWidget:

} else if (event.getKeyCode() == KeyEvent.VK_DELETE) {
    widget.removeFromParent();
    List<Widget> connectionsToRemove = new ArrayList<Widget>();
    for (Widget clwKid : connectionLayerWidget.getChildren()) {
        ConnectionWidget connectionWidget = (ConnectionWidget) clwKid;
        if (connectionWidget.getSourceAnchor().getRelatedWidget().equals(widget)) {
            connectionsToRemove.add(connectionWidget);
        }
        if (connectionWidget.getTargetAnchor().getRelatedWidget().equals(widget)) {
            connectionsToRemove.add(connectionWidget);
        }
    }
    connectionLayerWidget.removeChildren(connectionsToRemove);
}

Tip: Make sure to hold down the Ctrl key when using the mouse to connect two widgets.

Join the discussion

Comments ( 7 )
  • Sean Phillips Sunday, March 31, 2013

    Very nice Geertjan. Having not run the code yet I have a question:

    Would extending this connection technique to VMD pins be as simple as updating the isSourceWidget() and isTargetWidget() to include instances of VMDPinWidget?


  • Mike Sunday, March 31, 2013

    This connector function doesn't seem to work to me. After you hold the ctrl key, do you double-click on the source widget and then double-click the target widget? By the way, is the ctrl key used by default? since I don't see where this key function shows up in the code.


  • Geertjan Sunday, March 31, 2013

    Hold down the Ctrl key, then drag from one widget to another widget. No it doesn't show up in the code, it's just the way connection widgets work. Again, hold down the Ctrl key, start dragging from one widget, and you will see the connector, then continue dragging to the widget you want to drag to, then release the mouse.


  • Geertjan Sunday, March 31, 2013

    Sean, yes, you can also connect pin widgets to each other. Change the methods you describe, but also make sure to set the action on the pin widget instead of to the node widget.


  • Mike Monday, April 1, 2013

    Thank you Geertjan! So the order of addAction on the widget also matters. I quote from you email "The SelectProvider MUST be AFTER the ConnectProvider."

    On a different note, as I also mentioned last week, would it be straightforward to implement simple plot function through visual library? something like on this showcase: https://netbeans.org/images_www/screenshots/platform/sandia-cognitive.png

    The bottom line plot is sth. I really want to use. Could you also blog it up?


  • Sean Phillips Monday, April 1, 2013

    For those out there wondering: For most of my scenes I only want the user connecting pins to pins so I use the following replacements (which also prevents a self connection):

    @Override

    public boolean isSourceWidget (Widget sourceWidget) {

    return sourceWidget instanceof VMDPinWidget;

    }

    @Override

    public ConnectorState isTargetWidget(Widget wid1, Widget wid2) {

    if(!wid1.getParentWidget().equals(wid2.getParentWidget())

    && (wid2 instanceof VMDPinWidget))

    return ConnectorState.ACCEPT;

    return ConnectorState.REJECT;

    }

    And as GJ said before you need to add this action to pins... since I extend a custom VMDGraphScene, I override the attachPinWidget() and add the action to each new Pin like this:

    @Override

    protected Widget attachPinWidget(String arg0, String arg1) {

    final Widget wid = super.attachPinWidget(arg0, arg1);

    if(wid != null){

    VMDPinWidget pin = (VMDPinWidget) wid;

    pin.getActions().addAction (connectAction);

    wid.getActions ().addAction (reconnectAction);

    pin.getPinNameWidget().getActions ().addAction (editorAction);

    }

    return wid;

    }


  • Neil C Smith Sunday, April 28, 2013

    A slightly belated comment that may be useful (was searching for another post of yours on visual library) ...

    The default extended connect action has an issue on Mac. The hardcoded CTRL key modifier conflicts with the popup menu action. Noticed when I had a bug report on an early version of Praxis LIVE that no-one could connect anything! :) I guess using the version that allows to specify the modifier should be recommended (is SHIFT better cross-platform? or just ALT on Mac?)


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.