<!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.">
</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>
   
       <img  src="../images/articles/65/netbeans-stamp65.gif" class="stamp" width="114" height="114" alt="Content on this page applies to NetBeans IDE 6.5" title="Content on this page applies to NetBeans IDE 6.5"> </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.5</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>
