Adding & Removing Connection Widgets

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.

Comments:

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?

Posted by Sean Phillips on March 31, 2013 at 05:58 AM PDT #

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.

Posted by Mike on March 31, 2013 at 09:51 AM PDT #

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.

Posted by Geertjan on March 31, 2013 at 09:58 AM PDT #

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.

Posted by Geertjan on March 31, 2013 at 10:00 AM PDT #

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?

Posted by Mike on April 01, 2013 at 05:31 AM PDT #

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;
}

Posted by Sean Phillips on April 01, 2013 at 07:00 AM PDT #

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?)

Posted by Neil C Smith on April 28, 2013 at 06:21 AM PDT #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
12
13
14
19
21
22
23
24
25
26
27
28
29
30
   
       
Today