<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<!-- -*- xhtml -*- -->
<title>NetBeans Visual Library Tutorial for Java Applications</title>
  <link rel="stylesheet" type="text/css" href="https://netbeans.org/netbeans.css">
  <meta name="AUDIENCE" content="NBUSER">
  <meta name="TYPE" content="ARTICLE">
  <meta name="EXPIRES" content="N">
  <meta name="developer" content="geertjan.wielenga@sun.com">
  <meta name="indexed" content="y">
  <meta name="description"
 content="A walk-through of the basic features of the Visual Library API.">
         <!--      Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. -->
        <!--     Use is subject to license terms.-->
</head>

<body>

<h1>NetBeans Visual Library Tutorial for Java Applications</h1>

<p>In this tutorial, you will learn how to use the main
 features provided by the <a href="http://bits.netbeans.org/dev/javadoc/org-netbeans-api-visual/overview-summary.html">NetBeans Visual Library API</a>.
   
     <p><b>Contents</b></p>
   
   <p><img  src="../images/articles/69/netbeans-stamp7-8-9.png" class="stamp" width="114" height="114" alt="Content on this page applies to NetBeans IDE 6.5, 6.7, 6.8" title="Content on this page applies to NetBeans IDE 6.5, 6.7, 6.8"/></p>
      <ul class="toc">
<li><a href="#getting-started">Setting Up the Application</a>
<li><a href="#add">Adding the Libraries</a>
<li><a href="#widget">Creating the Widgets</a>
<li><a href="#action">Enabling the Actions</a>
       </ul>
         
<p><b>To follow this tutorial, you need the software and resources listed in the following 
table.</b></p>

    <table>
        <tbody>
            <tr>
                <th class="tblheader" scope="col">Software or Resource</th>
                <th class="tblheader" scope="col">Version Required</th>
            </tr> 
            <tr>
                <td class="tbltd1"><a href="https://netbeans.org/downloads/index.html">NetBeans IDE</a></td>
                <td class="tbltd1">version 6.7 or above</td>
            </tr>
            <tr>
                <td class="tbltd1"><a href="http://java.sun.com/javase/downloads/index.jsp">Java Developer Kit (JDK)</a></td>
                <td class="tbltd1">Version 6 or<br/>version 5</td>
            </tr>
        </tbody>
    </table>

  <p>Also, you will use 3 icons in the tutorial. You can right-click
   them here and save them locally, then copy them to the application's
   location, after you create the application later in this tutorial. Here are
   the 3 icons:
  
   <p><img src="../images/tutorials/vislib/red.gif"/>
    <img src="../images/tutorials/vislib/blue.gif"/>
    <img src="../images/tutorials/vislib/green.gif"/>

<!-- ===================================================================================== -->

<p><h2><a name="set"></a>Setting Up the Application</h2>

<p>In this section, we use a wizard to create a Java application.


<ol>
    <li>Choose File &gt; New Project (Ctrl+Shift+N).
        Under Categories, select Java.
        Under Projects, select Java Application. Click Next.</li>
    <li>In the Name and Location panel, type <tt>VisLibDemo</tt> in
    the Project Name field:
    <p><p><img border="1" src="../images/tutorials/vislib/vislib-java-1.png"/>
    <p>Click Finish.</li>
</ol>

<p>The IDE creates the <tt>VisLibDemo</tt> project.
 Add the three images above to the main package. You
 should now see this:
<p><img border="1" src="../images/tutorials/vislib/vislib-java-2.png"/>



<p><h2><a name="add"></a>Adding the Libraries</h2>

<p>In this section, we add the two libraries you need to work
 with the Visual Library.

<ol>
    <li>Right-click the Libraries node and choose "Add JAR/Folder".</li>
    <li>Browse to the installation directory of NetBeans IDE.</li>
    <li>In <tt>platform9/lib</tt>, choose <tt>org-openide-util.jar</tt>.</li>
    <li>In <tt>platform9/modules</tt>, choose <tt>org-netbeans-api-visual.jar</tt>.</li>
</ol>

<p>You now have the only two JARs you will need. You should
 now see this:
<p><img border="1" src="../images/tutorials/vislib/vislib-java-3.png"/>

<p><h2><a name="container"></a>Creating the Container</h2>

<p>In this section, we create the container
 that will hold the <tt>Scene</tt> from the
 Visual Library.

<ol>
    <li>Define <tt>Main.java</tt> as follows:

<pre class=examplecode>
public class Main  extends JPanel {

    <b>//Create the JFrame:</b>
    public static void main(String[] args) {
        JFrame frame = new JFrame("Graph test");
        frame.setMinimumSize(new Dimension(500, 400));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setContentPane(new Main());
        frame.pack();
        frame.setVisible(true);
    }

    public Main() {
        initComponents();
    }

    private void initComponents() {
        <b>//Set the layout:</b>
        setLayout(new BorderLayout());
        <b>//Create a JScrollPane:</b>
        JScrollPane scrollPane = new JScrollPane();
        <b>//Add the JScrollPane to the JPanel:</b>
        add(scrollPane, BorderLayout.CENTER);
    }

}
</pre>

    </li>

    <li>Run the application and you should see a simple
     JFrame:

<p><img border="1" src="../images/tutorials/vislib/vislib-java-4.png"/>

     </li>
</ol>

<p>Now that you have a <tt>JScrollPane</tt>, you're
 ready to create a scene!

<p><h2><a name="widget"></a>Creating the Widgets</h2>

<p>In this section, we create a separate
 class containing our scene. We then
 hook it into our <tt>JPanel</tt>.

<ol>
    <li>Create a new class
     called <tt>GraphSceneImpl.java</tt>.
    <li>Let it extend GraphScene&lt;String, String&gt;.
    <li>Use the lightbulb at the side of the IDE
     to add import statements and abstract
     methods. You should now see this:

<pre class=examplecode>
package vislibdemo;

import org.netbeans.api.visual.graph.GraphScene;
import org.netbeans.api.visual.widget.Widget;

public class GraphSceneImpl extends GraphScene&lt;String, String&gt; {

    @Override
    protected Widget attachNodeWidget(String arg0) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    protected Widget attachEdgeWidget(String arg0) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    protected void attachEdgeSourceAnchor(String arg0, String arg1, String arg2) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    protected void attachEdgeTargetAnchor(String arg0, String arg1, String arg2) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

}
</pre>
    </li>

    <li>We'll be using three <tt>LayerWidgets</tt>, which are
     like <tt>JGlassPanes</tt> in Swing. Declare them at the top
     of the class:
<pre class=examplecode>
private LayerWidget mainLayer;
private LayerWidget connectionLayer;
private LayerWidget interactionLayer;
</pre>
     </li>
     <li>Create a constructor, initialize your <tt>LayerWidgets</tt>
      and add them to the <tt>Scene</tt>:

<pre class=examplecode>
public GraphSceneImpl() {
    mainLayer = new LayerWidget(this);
    connectionLayer = new LayerWidget(this);
    interactionLayer = new LayerWidget(this);
    addChild(mainLayer);
    addChild(connectionLayer);
    addChild(interactionLayer);
}
</pre>

<li>Next, define what will happen when a new Widget
 is created:

<pre class=examplecode>@Override
protected Widget attachNodeWidget(String arg) {
    IconNodeWidget widget = new IconNodeWidget(this);
    if (arg.startsWith("1")) {
        widget.setImage(ImageUtilities.loadImage("vislibdemo/red.gif"));
    } else if (arg.startsWith("2")) {
        widget.setImage(ImageUtilities.loadImage("vislibdemo/green.gif"));
    } else {
        widget.setImage(ImageUtilities.loadImage("vislibdemo/blue.gif"));
    }
    widget.setLabel(arg);
    mainLayer.addChild(widget);
    return widget;
}</pre>

<p class="tips"> The above is triggered whenever
 <tt>addNode</tt> is called on the scene.

<p><li>At the end of the constructor, trigger the
 method above 4 times:

<pre class=examplecode>
Widget w1 = addNode("1. Hammer");
w1.setPreferredLocation(new Point(10, 100));
Widget w2 = addNode("2. Saw");
w2.setPreferredLocation(new Point(100, 250));
Widget w3 = addNode("Nail");
w3.setPreferredLocation(new Point(250, 250));
Widget w4 = addNode("Bolt");
w4.setPreferredLocation(new Point(250, 350));
</pre>

<p>Above, you have created four widgets, you
 have passed in a string, and you have set
 the widget's position. Now, the <tt>attachNodeWidget</tt>
 method is triggered, which you defined in
 the previous step. The <tt>arg</tt> parameter
 in the <tt>attachNodeWidget</tt> is the string
 you passed to <tt>addNode</tt>. Therefore,
 the string will set the label of the widget. Then
 the widget is added to the <tt>mainLayer</tt>.

<li>Back in the <tt>Main.java</tt> class, add the
 lines in bold to the <tt>initComponents</tt> method:

<pre class=examplecode>
private void initComponents() {
    //Set the layout:
    setLayout(new BorderLayout());
    //Create a JScrollPane:
    JScrollPane scrollPane = new JScrollPane();
    //Add the JScrollPane to the JPanel:
    add(scrollPane, BorderLayout.CENTER);
    <b>//Create the GraphSceneImpl:
    GraphScene scene = new GraphSceneImpl();
    //Add it to the JScrollPane:
    scrollPane.setViewportView(scene.createView());
    //Add the SatellitView to the scene:
    add(scene.createSatelliteView(), BorderLayout.WEST);</b>
}
</pre>

<li>Run the application and you should see this:

<p><img border="1" src="../images/tutorials/vislib/vislib-java-5.png"/>

</ol>

<p>Now that you have a scene with some widgets,
 we can begin integrating some actions!

<p><h2><a name="action"></a>Enabling the Actions</h2>

<p>In this section, we enable actions
 on the widgets we created previously.

<ol>
    <li>Change the <tt>attachNodeWidget</tt> by
     adding the lines in bold below:

<pre class=examplecode>
@Override
protected Widget attachNodeWidget(String arg) {
    IconNodeWidget widget = new IconNodeWidget(this);
    if (arg.startsWith("1")) {
        widget.setImage(ImageUtilities.loadImage("vislibdemo/red.gif"));
    } else if (arg.startsWith("2")) {
        widget.setImage(ImageUtilities.loadImage("vislibdemo/green.gif"));
    } else {
        widget.setImage(ImageUtilities.loadImage("vislibdemo/blue.gif"));
    }
    <b>widget.getActions().addAction(
            ActionFactory.createAlignWithMoveAction(
            mainLayer, interactionLayer,
            ActionFactory.createDefaultAlignWithMoveDecorator()));</b>
    widget.setLabel(arg);
    mainLayer.addChild(widget);
    return widget;
}
</pre>
    </li>

<li>Run the application. Drag a widget around
 and notice that alignment markers appear
 that help the user position a widget in
 relation to other widgets:

 <p><p><img border="1" src="../images/tutorials/vislib/vislib-java-7.png"/>

    <li>Change the
     <tt>GraphSceneImpl</tt> class by
     adding the line below to the
     end of the constructor:

<pre class=examplecode>
getActions().addAction(ActionFactory.createZoomAction());
</pre>
    </li>

<li>Run the application. Scroll the middle
 mousebutton, or do whatever your operating
 system requires for "zooming", and notice
 that the whole scene increases/decreases
 in size.

 <li>Add a custom <tt>ConnectProvider</tt>
  to the end of the <tt>GraphSceneImpl</tt>:

<pre class=examplecode>
private class MyConnectProvider implements ConnectProvider {

    public boolean isSourceWidget(Widget source) {
        return source instanceof IconNodeWidget && source != null? true : false;
    }

    public ConnectorState isTargetWidget(Widget src, Widget trg) {
        return src != trg && trg instanceof IconNodeWidget ? ConnectorState.ACCEPT : ConnectorState.REJECT;
    }

    public boolean hasCustomTargetWidgetResolver(Scene arg0) {
        return false;
    }

    public Widget resolveTargetWidget(Scene arg0, Point arg1) {
        return null;
    }

    public void createConnection(Widget source, Widget target) {
        ConnectionWidget conn = new ConnectionWidget(GraphSceneImpl.this);
        conn.setTargetAnchorShape(AnchorShape.TRIANGLE_FILLED);
        conn.setTargetAnchor(AnchorFactory.createRectangularAnchor(target));
        conn.setSourceAnchor(AnchorFactory.createRectangularAnchor(source));
        connectionLayer.addChild(conn);
    }

}
</pre>

<p>Hook the custom <tt>ConnectProvider</tt>
 into the widget as follows:

<pre class=examplecode>
@Override
protected Widget attachNodeWidget(String arg0) {
    IconNodeWidget widget = new IconNodeWidget(this);
    if (arg0.startsWith("1")) {
        widget.setImage(ImageUtilities.loadImage("vislibdemo/red.gif"));
    } else if (arg0.startsWith("2")) {
        widget.setImage(ImageUtilities.loadImage("vislibdemo/green.gif"));
    } else {
        widget.setImage(ImageUtilities.loadImage("vislibdemo/blue.gif"));
    }
    <b>widget.getActions().addAction(
            ActionFactory.createExtendedConnectAction(
            connectionLayer, new MyConnectProvider()));</b>
    widget.getActions().addAction(
            ActionFactory.createAlignWithMoveAction(
            mainLayer, interactionLayer,
            ActionFactory.createDefaultAlignWithMoveDecorator()));
    widget.setLabel(arg0);
    mainLayer.addChild(widget);
    return widget;
}
</pre>

<li>Run the application, select a widget,
 hold down the Ctrl key, and then drag
 the mouse to another widget. You should
 then be able to connect widgets to
 each other, like this:

<p><p><img border="1" src="../images/tutorials/vislib/vislib-java-6.png"/>

</ol>

<p>Now that you have a basic idea
 of the features that the Visual Library API
 provides, see the section called
 "NetBeans APIs for Visualizing Data"
 on the <a href="https://netbeans.org/kb/trails/platform.html">NetBeans Platform Learning Trail</a>.

    </body>
</html>
