| <!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 Nodes, Explorer Manager, and Component Palette Tutorial</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="tboudreau@netbeans.org"/> |
| <meta name="indexed" content="y"/> |
| <meta name="description" |
| content="A walk-through of enhancing Nodes with properties and other decorations."/> |
| <!-- Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. --> |
| <!-- Use is subject to license terms.--> |
| </head> |
| <body> |
| <h1>NetBeans Nodes, Explorer Manager, and Component Palette Tutorial</h1> |
| |
| <p>In this tutorial, you will learn how to create a BeanTreeView with drag and drop |
| functionality. You will view the nodes in a variety of explorer views and create |
| a Component Palette containing items created from your nodes.</p> |
| |
| <p>The main points of this tutorial are threefold:</p> |
| |
| <ul> |
| <li>To demonstrate how a fully functional yet simple BeanTreeView is created.</li> |
| <li>To demonstrate a key feature in the NetBeans APIs, that of loosely coupled views.</li> |
| <li>To demonstrate how nodes can be turned into items in a Component Palette, |
| without the intervention of a <tt>layer.xml</tt> file.</li> |
| </ul> |
| |
| <p>Once this tutorial is finished, you will have a BeanTreeView that provides |
| the following menu items, in addition to the support for dragging and dropping |
| the child nodes:</p> |
| |
| <p><img alt="" src="../../images/tutorials/nodes-3/final-result.png"/></p> |
| |
| <p>You will be shown how to change the explorer view from BeanTreeView |
| to MenuView, ListView, and several other views supported |
| by the <a href="https://netbeans.org/download/dev/javadoc/org-openide-explorer/overview-summary.html">Explorer and Property Sheet API</a>.</p> |
| |
| <p>This is what the completed project will look like in the Projects window:</p> |
| |
| <p><img alt="" src="../../images/tutorials/nodes-3/projects-window.png"/></p> |
| |
| |
| <!-- ===================================================================================== --> |
| |
| <h3 class="tutorial"><a name="installing-software"></a>Installing the Software</h3> |
| |
| |
| <p>Before you begin, you need to install the following software on your |
| computer:</p> |
| <ul> |
| <li>NetBeans IDE version 6.7 or above.</li> |
| <li>Java Standard Development Kit (JDK™) version |
| 1.4.2 (<a href="http://java.sun.com/j2se/1.4.2/download.html">download</a>) |
| or 5.0 (<a href="http://java.sun.com/j2se/1.5.0/download.jsp">download</a>)</li> |
| </ul> |
| |
| <p>Also, you will use 4 icons in the tutorial. You can right-click |
| them here and save them locally, then copy them to the module project's |
| location, after you create the module project later in this tutorial. Here are |
| the 4 icons:</p> |
| |
| <p><img alt="" src="../../images/tutorials/nodes-3/down-rectangle.png"/></p> |
| <p><img alt="" src="../../images/tutorials/nodes-3/right-rectangle.png"/></p> |
| <p><img alt="" src="../../images/tutorials/nodes-3/marilyn.gif"/></p> |
| <p><img alt="" src="../../images/tutorials/nodes-3/marilyn_category.gif"/></p> |
| |
| <h2><a name="gettingtoknowthesample"></a>Getting Started</h2> |
| |
| <p>In this section, we use wizards to create a module project and |
| a custom window component. We add a JScrollPane and create a new |
| <a href="https://netbeans.org/download/dev/javadoc/org-openide-explorer/org/openide/explorer/view/BeanTreeView.html">BeanTreeView</a>. |
| We then install the module project and display |
| our view's top node.</p> |
| |
| <ol> |
| |
| <li>Choose File > New Project. In the New Project wizard, |
| choose NetBeans Plug-in Modules under Categories and Module Project |
| under Projects. Click Next. Type <tt>ExplorerBeanTreeView</tt> in Project Name |
| and set Project Location to an appropriate folder on your disk. If they |
| are not selected, select |
| Standalone Module and Set as Main Project. Click Next. |
| |
| </li><li>Type <tt>org.netbeans.myfirstexplorer</tt> in Code Name Base |
| and <tt>Explorer Bean Tree View</tt> in Module Display Name. Click Finish. |
| |
| |
| </li><li>Right-click the project, choose Properties, click Libraries |
| in the Project Properties dialog box and declare a dependency on the following APIs: |
| |
| <ul> |
| <li><a href="https://netbeans.org/download/dev/javadoc/org-openide-actions/overview-summary.html">Actions API</a> |
| </li><li><a href="https://netbeans.org/download/dev/javadoc/org-openide-explorer/overview-summary.html">Explorer and Property Sheet API</a> |
| </li><li><a href="https://netbeans.org/download/dev/javadoc/org-openide-explorer/overview-summary.html">Nodes API</a> |
| </li></ul></li> |
| |
| |
| <li>Right-click the module project, choose |
| New > File/Folder and choose Window Component from the |
| NetBeans Module Development category. Click Next. Choose <tt>editor</tt> |
| in the drop-down list and select Open on Application Start. Click Next. |
| |
| </li><li>Type <tt>MyFirst</tt> in Class Name Prefix. Optionally, |
| add an icon with a dimension of 16x16 pixels. Click Finish. |
| |
| |
| </li><li>Open <tt>MyFirstTopComponent.java</tt> in the Design view. |
| Right-click in the TopComponent, choose Set Layout, |
| and select BorderLayout. |
| |
| </li><li>Use the Palette (Ctrl-Shift-8) to drop a |
| <tt>JScrollPane</tt> on <tt>MyFirstTopComponent.java</tt>. Resize the |
| <tt>JScrollPane</tt> so that it covers the entire TopComponent. Right-click |
| the <tt>JScrollPane</tt>, choose Change Variable Name and type <tt>moviePane</tt>. |
| |
| </li><li>Open the Inspector, if it isn't open. (Use the Window menu.) |
| In the Inspector, select the <tt>moviePane</tt>, open the |
| Properties window (Ctrl-Shift-7), click the "Code" tab, and add this |
| line to the Custom Creation Code property (the very last property in the list): |
| |
| <pre class="examplecode">new <a href="https://netbeans.org/download/dev/javadoc/org-openide-explorer/org/openide/explorer/view/BeanTreeView.html">BeanTreeView()</a>;</pre> |
| |
| <p>Click OK.</p> |
| |
| <p>BeanTreeView is one of several views provided by the Explorer and Property Sheet API. |
| We will look at the other views later in this tutorial.</p> |
| |
| </li><li>Click the Source toggle button in the GUI Builder. |
| Right-click in the Source Editor, |
| and choose Fix imports. The dependency you set on "Explorer and Property Sheet API" will |
| cause the import statement for the BeanTreeView being generated for you by the IDE. |
| |
| |
| </li><li>In the <tt>Bundle.properties</tt> file, change the <tt>CTL_MyFirstTopComponent</tt> |
| key to the value "Marilyn Explorer". |
| |
| |
| </li><li>Right-click the project node and choose "Install/Reload |
| in Development IDE". If a warning message appears, click OK. |
| When the module installs, look under the Window menu and you will find a new menu item |
| called "Open MyFirst Window", at the top of the list of menu items. |
| Choose it and you will see the start of your explorer view: |
| |
| <p><img alt="" src="../../images/tutorials/nodes-3/marilyn-result.png"/></p> |
| |
| |
| |
| <p>Without any coding, you have created the start of your BeanTreeView.</p> |
| </li> |
| </ol> |
| |
| <!-- ===================================================================================== --> |
| <h2><a name="gettingtoknowthesample"></a>Using Nodes to Represent Data</h2> |
| |
| <p>Using nodes to represent data involves adding an Explorer Manager |
| to our TopComponent's Lookup. The Explorer Manager controls the view, especially |
| the top node of our view. Next we will create a Category object and a Movie object and display |
| each via a separate <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/AbstractNode.html">AbstractNode</a> |
| object and Children.Keys object. The <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/AbstractNode.html">AbstractNode</a> provides the |
| basic implementation of a node, allowing you to provide icons, as well |
| as actions such as Cut and Delete. With the Children.Keys object, you simplify |
| the handling of the nodes, using lightweight keys instead of the nodes themselves. |
| Further details on the specific approaches taken are explained where appropriate below.</p> |
| |
| <div class="indent"> |
| <h3 class="tutorial"><a name="installing-sample"></a>Setting Up an Explorer Manager</h3> |
| |
| <p>An <a href="https://netbeans.org/download/dev/javadoc/org-openide-explorer/org/openide/explorer/ExplorerManager.html">Explorer Manager</a> |
| is the NetBeans API class that manages a view. For example, it notifies PropertyChangeListeners |
| about changes to the nodes in the view. It also controls the root node |
| in a view. For example, when you want to define a root node, you need |
| to use the Explorer Manager's <tt>setRootContext()</tt> method. |
| To provide an Explorer Manager in a TopComponent, you |
| must implement <tt>ExplorerManager.Provider</tt>, as shown in this subsection.</p> |
| |
| <ol> |
| |
| |
| |
| <li>Open the <tt>MyFirstTopComponent.java</tt> in the |
| Source view and add <tt>implements ExplorerManager.Provider</tt> |
| to the signature at the top of the class. |
| |
| </li><li>Next, instantiate the <tt><a href="https://netbeans.org/download/dev/javadoc/org-openide-explorer/org/openide/explorer/ExplorerManager.html">ExplorerManager</a></tt> as a transient object: |
| |
| <pre class="examplecode">private transient ExplorerManager explorerManager = new ExplorerManager();</pre> |
| |
| </li><li>Place the cursor in the signature. |
| A lightbulb will prompt you to let the IDE insert an import statement and implement the abstract methods. |
| Follow its advice, by clicking on the suggestion, |
| and then fill out the generated <tt>getExplorerManager()</tt> as follows: |
| |
| <pre class="examplecode">public ExplorerManager getExplorerManager() { |
| return explorerManager; |
| }</pre> |
| |
| </li><li>Now go to the Constructor and add the following after the last existing line: |
| |
| <pre class="examplecode"><a href="https://netbeans.org/download/dev/javadoc/org-openide-windows/org/openide/windows/TopComponent.html#associateLookup(org.openide.util.Lookup)">associateLookup</a>(<a href="http://www.netbeans.org/download/dev/javadoc/org-openide-explorer/org/openide/explorer/ExplorerUtils.html">ExplorerUtils</a>.<a href="http://www.netbeans.org/download/dev/javadoc/org-openide-explorer/org/openide/explorer/ExplorerUtils.html#createLookup(org.openide.explorer.ExplorerManager,%20javax.swing.ActionMap)">createLookup(explorerManager, getActionMap())</a>); |
| explorerManager.setRootContext(new <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/AbstractNode.html">AbstractNode(new CategoryChildren())</a>); |
| explorerManager.getRootContext().setDisplayName("Marilyn Monroe's Movies");</pre> |
| |
| <p>Here we place the Explorer Manager in the TopComponent's Lookup. |
| We set a class called "CategoryChildren" as the root node. We will create |
| this class in the next section, and we will display it |
| as the first node in our view. As display name it receives "Marilyn Monroe's Movies".</p> |
| |
| </li><li>Fix imports. A red underline will remain because we have not created |
| the CategoryChildren class yet. We will do so in the next section.</li> |
| |
| </ol> |
| </div> |
| |
| <div class="indent"> |
| <h3 class="tutorial"><a name="installing-sample"></a>Creating a Category</h3> |
| |
| <p>Let's first define what a "Category" is. </p> |
| <ol> |
| <li>Create a class |
| called <tt>Category.java</tt> and add the following content: |
| |
| |
| <pre class="examplecode">public class Category { |
| |
| private String name; |
| |
| /** Creates a new instance of Category */ |
| public Category() { |
| } |
| |
| public String getName() { |
| return name; |
| } |
| |
| public void setName(String name) { |
| this.name = name; |
| } |
| |
| }</pre> |
| |
| <p>From the above, you can see that a category has a name, and nothing more.</p> |
| |
| |
| |
| </li><li>Create |
| another class, this time for creating the nodes for the categories: |
| |
| <pre class="examplecode">public class CategoryChildren extends <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/Children.Keys.html">Children.Keys</a> { |
| |
| private String[] Categories = new String[]{ |
| "Adventure", |
| "Drama", |
| "Comedy", |
| "Romance", |
| "Thriller"}; |
| |
| public CategoryChildren() { |
| } |
| |
| protected Node[] <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/Children.Keys.html#createNodes%28java.lang.Object%29">createNodes(Object key)</a> { |
| Category obj = (Category) key; |
| return new Node[] { new CategoryNode( obj ) }; |
| } |
| |
| protected void <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/Children.html#addNotify%28%29">addNotify()</a> { |
| super.addNotify(); |
| Category[] objs = new Category[Categories.length]; |
| for (int i = 0; i < objs.length; i++) { |
| Category cat = new Category(); |
| cat.setName(Categories[i]); |
| objs[i] = cat; |
| } |
| setKeys(objs); |
| } |
| |
| }</pre> |
| |
| <p>In this example, a popular children implementation called <tt>Children.Keys</tt> is used. |
| By subclassing <tt>Children.Keys</tt>, you need not explicitly keep track of the nodes. |
| Instead, you keep track of a set of keys, which are lighter |
| weight objects. Each key typically represents one node. You must tell the implementation how |
| to create a node for each key. You can decide for yourself what type of keys to use.</p> |
| |
| <p><tt>addNotify()</tt> is called the first time that a list of nodes is needed. |
| An example of this is when a node is expanded. Here, when <tt>addNotify()</tt> is called, |
| a new category is instantiated. When a child node needs to be constructed, |
| the <tt>createNodes()</tt> method is called. It is passed the key for which it is making a node. It returns either none, |
| one, or more nodes corresponding to what should be displayed for the key. |
| In this example, a new instance of one category node is being created, and the |
| key is passed into its constructor.</p> |
| |
| </li><li>Fix imports, choosing <tt>org.openide.nodes.Children</tt> and <tt>org.openide.nodes.Node</tt>. |
| |
| |
| |
| <p>Note that in the code above, |
| we create a node called <tt>CategoryNode</tt>. We will create it in the next step.</p> |
| |
| </li><li>Create a class called <tt>CategoryNode.java</tt> |
| and define it as follows: |
| |
| |
| <pre class="examplecode">public class CategoryNode extends <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/AbstractNode.html">AbstractNode</a> { |
| |
| /** Creates a new instance of CategoryNode */ |
| public CategoryNode( Category category ) { |
| super( new MovieChildren(category), Lookups.singleton(category) ); |
| <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/Node.html#setDisplayName(java.lang.String)">setDisplayName(category.getName())</a>; |
| <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/Node.html#setDisplayName(java.lang.String)">setIconBaseWithExtension("org/netbeans/myfirstexplorer/marilyn_category.gif")</a>; |
| } |
| |
| public PasteType <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/AbstractNode.html#getDropType(java.awt.datatransfer.Transferable,%20int,%20int)">getDropType(Transferable t, final int action, int index)</a> { |
| final Node dropNode = NodeTransfer.node( t, |
| DnDConstants.ACTION_COPY_OR_MOVE+NodeTransfer.CLIPBOARD_CUT ); |
| if( null != dropNode ) { |
| final Movie movie = (Movie)dropNode.getLookup().lookup( Movie.class ); |
| if( null != movie && !this.equals( dropNode.getParentNode() )) { |
| return new PasteType() { |
| public Transferable paste() throws IOException { |
| getChildren().add( new Node[] { new MovieNode(movie) } ); |
| if( (action & DnDConstants.ACTION_MOVE) != 0 ) { |
| dropNode.getParentNode().getChildren().remove( new Node[] {dropNode} ); |
| } |
| return null; |
| } |
| }; |
| } |
| } |
| return null; |
| } |
| |
| public Cookie <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/AbstractNode.html#getCookie(java.lang.Class)">getCookie(Class clazz)</a> { |
| Children ch = getChildren(); |
| |
| if (clazz.isInstance(ch)) { |
| return (Cookie) ch; |
| } |
| |
| return super.getCookie(clazz); |
| } |
| |
| protected void <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/AbstractNode.html#createPasteTypes(java.awt.datatransfer.Transferable,%20java.util.List)">createPasteTypes(Transferable t, List s)</a> { |
| super.createPasteTypes(t, s); |
| PasteType paste = getDropType( t, DnDConstants.ACTION_COPY, -1 ); |
| if( null != paste ) |
| s.add( paste ); |
| } |
| |
| public Action[] <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/Node.html#getActions(boolean)">getActions(boolean context)</a> { |
| return new Action[] { |
| SystemAction.get( NewAction.class ), |
| SystemAction.get( PasteAction.class ) }; |
| } |
| |
| public boolean <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/AbstractNode.html#canDestroy()">canDestroy()</a> { |
| return true; |
| } |
| |
| }</pre> |
| |
| <p>An AbstractNode is a basic implementation of a node. It simplifies common |
| requirements, such as the creation of the display name and the handling of icons. |
| Other common requirements are handled as well. To understand what each of the methods |
| in the code above does, |
| click the method's link to jump to the related Javadoc.</p> |
| |
| </li><li>Fix imports. After you fic the import statements, several red underlines |
| will remain, because we have not created <tt>Movie.java</tt>, <tt>MovieChildren.java</tt>, |
| and <tt>MovieNode.java</tt>. yet. We will do so in the next section.</li> |
| |
| </ol> |
| </div> |
| |
| <div class="indent"> |
| <h3 class="tutorial"><a name="installing-sample"></a>Creating a Movie</h3> |
| |
| |
| <p>Next, we'll work on adding the children belonging to the categories. |
| And the children are movies. Let's begin by defining what a "movie" is.</p> |
| |
| <ol> |
| <li>Create a |
| class called <tt>Movie.java</tt>, with the following content: |
| |
| |
| |
| <pre class="examplecode">public class Movie { |
| |
| private Integer number; |
| private String category; |
| private String title; |
| |
| /** Creates a new instance of Instrument */ |
| public Movie() { |
| } |
| |
| public Integer getNumber() { |
| return number; |
| } |
| |
| public void setNumber(Integer number) { |
| this.number = number; |
| } |
| |
| public String getCategory() { |
| return category; |
| } |
| |
| public void setCategory(String category) { |
| this.category = category; |
| } |
| |
| public String getTitle() { |
| return title; |
| } |
| |
| public void setTitle(String title) { |
| this.title = title; |
| } |
| |
| }</pre> |
| |
| <p>From the above, you can see that a movie has a number, belongs to a category, and has a title.</p> |
| |
| </li><li>Now let's create the category's children. The |
| class to be created is called <tt>MovieChildren.java</tt>. We use |
| <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/Index.ArrayChildren.html">Index.ArrayChildren</a>, |
| so that we can put the nodes in an array list, which is loaded as needed. Until a |
| child node is needed, such as when the parent node is expanded, it is not created. This is the content of the class: |
| |
| <pre class="examplecode">public class MovieChildren extends <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/Index.ArrayChildren.html">Index.ArrayChildren</a> { |
| |
| private Category category; |
| |
| private String[][] items = new String[][]{ |
| {"0", "Adventure", "River of No Return"}, |
| {"1", "Drama", "All About Eve"}, |
| {"2", "Drama", "Home Town Story"}, |
| {"3", "Comedy", "We're Not Married!"}, |
| {"4", "Comedy", "Love Happy"}, |
| {"5", "Romance", "Some Like It Hot"}, |
| {"6", "Romance", "Let's Make Love"}, |
| {"7", "Romance", "How to Marry a Millionaire"}, |
| {"8", "Thriller", "Don't Bother to Knock"}, |
| {"9", "Thriller", "Niagara"}, |
| }; |
| |
| public MovieChildren(Category Category) { |
| this.category = Category; |
| } |
| |
| protected java.util.List<Node> <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/Index.ArrayChildren.html#initCollection()">initCollection()</a> { |
| ArrayList childrenNodes = new ArrayList( items.length ); |
| for( int i=0; i<items.length; i++ ) { |
| if( category.getName().equals( items[i][1] ) ) { |
| Movie item = new Movie(); |
| item.setNumber(new Integer(items[i][0])); |
| item.setCategory(items[i][1]); |
| item.setTitle(items[i][2]); |
| childrenNodes.add( new MovieNode( item ) ); |
| } |
| } |
| return childrenNodes; |
| } |
| }</pre> |
| |
| </li><li>Right-click the project, choose Properties, and use the Sources category |
| to change the source level from 1.4 to 1.5. Click OK. |
| |
| </li><li>Fix imports. A red underline will remain because we have |
| not create <tt>MovieNode.java</tt>, which we will do in the next step. |
| |
| </li><li>Create a class called <tt>MovieNode.java</tt> |
| and define it as follows: |
| |
| <pre class="examplecode">public class MovieNode extends <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/AbstractNode.html">AbstractNode</a> { |
| |
| private Movie movie; |
| |
| /** Creates a new instance of InstrumentNode */ |
| public MovieNode(Movie key) { |
| super(Children.LEAF, Lookups.fixed( new Object[] {key} ) ); |
| this.movie = key; |
| <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/Node.html#setDisplayName(java.lang.String)">setDisplayName(key.getTitle())</a>; |
| <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/AbstractNode.html#setIconBaseWithExtension(java.lang.String)">setIconBaseWithExtension("org/netbeans/myfirstexplorer/marilyn.gif")</a>; |
| } |
| |
| public boolean <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/AbstractNode.html#canCut()">canCut()</a> { |
| |
| return true; |
| } |
| |
| public boolean <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/AbstractNode.html#canDestroy()">canDestroy()</a> { |
| return true; |
| } |
| |
| public Action[] <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/Node.html#getActions(boolean)">getActions(boolean popup)</a> { |
| return new Action[] { |
| SystemAction.get( CopyAction.class ), |
| SystemAction.get( CutAction.class ), |
| null, |
| SystemAction.get( DeleteAction.class ) }; |
| } |
| |
| }</pre> |
| |
| <p>Fix imports.</p> |
| |
| <p>Notice that most of this class is about defining actions on |
| the movie nodes. When you right-click a movie, you'll be |
| able to choose "Copy" or "Cut" or "Delete". </p></li> |
| </ol> |
| </div> |
| |
| <div class="indent"> |
| <h3 class="tutorial"><a name="installing-sample"></a>Creating a Root Node</h3> |
| |
| <p>Now we are going to install our module. When we do so, we will test |
| our module's functionality and see if everything is as we would want it to be.</p> |
| |
| <ol> |
| <li>Right-click the module and choose Install/Reload in Development IDE. |
| </li><li>Examine the result: |
| |
| <p><img alt="" src="../../images/tutorials/nodes-3/marilyn-result2.png"/></p> |
| |
| </li><li>Notice that even though you can drag and drop movies from |
| one category to another (by dragging with your mouse, with the Ctrl |
| key held down when you want to copy a node), |
| the menu items are greyed out. Also, notice that |
| the root node does not have an icon. |
| |
| </li><li>First, we need to enable the menu items by adding the actions |
| to the TopComponent's action map. Do this by adding the following |
| snippet to the end of the TopComponent's Constructor: |
| |
| <pre class="examplecode">ActionMap map = getActionMap(); |
| map.put(DefaultEditorKit.copyAction, ExplorerUtils.actionCopy(explorerManager)); |
| map.put(DefaultEditorKit.cutAction, ExplorerUtils.actionCut(explorerManager)); |
| map.put(DefaultEditorKit.pasteAction, ExplorerUtils.actionPaste(explorerManager)); |
| map.put("delete", ExplorerUtils.actionDelete(explorerManager, true));</pre> |
| |
| </li><li>Next, to be able to control the icon displayed by the root node, |
| we need to create a class for that node. Currently, we are using a default |
| <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/AbstractNode.html">AbstractNode</a>, over which we have no control. |
| |
| <p>Create a class called <tt>RootNode.java</tt>, with this content:</p> |
| |
| <pre class="examplecode">public class RootNode extends <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/AbstractNode.html">AbstractNode</a> { |
| |
| /** Creates a new instance of RootNode */ |
| public RootNode(Children children) { |
| super(children); |
| } |
| |
| public Image getIcon(int type) { |
| return Utilities.loadImage("org/netbeans/myfirstexplorer/right-rectangle.png"); |
| } |
| |
| public Image getOpenedIcon(int type) { |
| return Utilities.loadImage("org/netbeans/myfirstexplorer/down-rectangle.png"); |
| } |
| |
| }</pre> |
| |
| <p>Notice that here we set one icon for when the node is in its closed state |
| and another for when it is expanded. To use this node, we need to change this line |
| in the TopComponent:</p> |
| |
| <pre class="examplecode">explorerManager.setRootContext(new <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/AbstractNode.html">AbstractNode</a>(new CategoryChildren()));</pre> |
| |
| <p>We need to replace that line with this line:</p> |
| |
| <pre class="examplecode">explorerManager.setRootContext(new RootNode(new CategoryChildren()));</pre> |
| |
| </li><li>Install the module again and notice the icons displayed for the root node's |
| collapsed and expanded states. Here, the icon for the expanded state is shown: |
| |
| |
| <p><img alt="" src="../../images/tutorials/nodes-3/marilyn-result3.png"/></p> |
| |
| <p>Also notice that the movie node's menu items are now enabled and functional.</p></li> |
| |
| </ol> |
| </div> |
| |
| |
| |
| <!-- ===================================================================================== --> |
| <h2><a name="gettingtoknowthesample"></a>Using Explorer Views to View Data</h2> |
| |
| <p>The NetBeans APIs provide a variety of explorer views, which are very |
| simple to add to your TopComponent. After adding one or two lines of code, |
| the view on your data can be completely different, creating a radically |
| altered display for your end users and a wide range of choices for you |
| and your development team. </p> |
| |
| <p>However, note that only the BeanTreeView supports |
| the drag and drop functionality you added earlier in this tutorial. When you |
| change to a different explorer view, as shown below, the drag and drop functionality |
| will simply be disabled.</p> |
| |
| |
| <div class="indent"> |
| |
| |
| <h3 class="tutorial"><a name="installing-software"></a>List View</h3> |
| |
| <p>List view is an explorer view that displays items in a list. It is provided by |
| the <a href="https://netbeans.org/download/dev/javadoc/org-openide-explorer/org/openide/explorer/view/ListView.html">ListView</a> |
| class, which belongs to the Explorer And Property Sheet API.</p> |
| |
| <ol> |
| |
| <li>Add this line to the end of the TopComponent's Constructor: |
| |
| <pre class="examplecode">listView = new ListView();</pre> |
| |
| <p>Put the cursor in the line and let the IDE generate |
| an import statement for <tt>org.openide.explorer.view.ListView</tt>. |
| Also let the IDE create the <tt>listView</tt> field.</p> |
| |
| </li><li>Below the line above, add this line, which adds the view to the TopComponent: |
| |
| <pre class="examplecode">add(listView, BorderLayout.CENTER);</pre> |
| |
| <p>Let the IDE generate the <tt>java.awt.BorderLayout</tt> import statement for BorderLayout.</p> |
| |
| <p><b>Note:</b> When you created the TopComponent earlier in this tutorial, |
| you should have set the layout manager to BorderLayout. If you did not do this, |
| make the JScrollPane smaller, right-click the TopComponent, choose Set Layout, |
| and select BorderLayout.</p> |
| |
| </li><li>Install the module again. Notice that the view is now as follows: |
| |
| <p><img alt="" src="../../images/tutorials/nodes-3/listview1.png"/></p> |
| |
| <p>When you click on a category, the movies are displayed:</p> |
| |
| <p><img alt="" src="../../images/tutorials/nodes-3/listview2.png"/></p></li> |
| |
| </ol> |
| </div> |
| |
| <div class="indent"> |
| |
| |
| <h3 class="tutorial"><a name="installing-software"></a>Choice View</h3> |
| |
| <p>Choice view is an explorer view based on a combo box. It is provided by |
| the <a href="https://netbeans.org/download/dev/javadoc/org-openide-explorer/org/openide/explorer/view/ChoiceView.html">ChoiceView</a> |
| class, which belongs to the Explorer And Property Sheet API.</p> |
| |
| <ol> |
| <li>Add this line to the end of the TopComponent's Constructor: |
| |
| <pre class="examplecode">choiceView = new ChoiceView();</pre> |
| |
| <p>Put the cursor in the line and let the IDE generate |
| an import statement for <tt>org.openide.explorer.view.ChoiceView</tt>. |
| Also let the IDE create the <tt>choiceView</tt> field.</p> |
| |
| </li><li>Instead of the line that |
| adds a ListView to the TopComponent, write a line that |
| adds the ChoiceView: |
| |
| <pre class="examplecode">add(choiceView, BorderLayout.CENTER);</pre> |
| |
| |
| |
| </li><li>Install the module again. Notice that the view is now as follows: |
| |
| <p><img alt="" src="../../images/tutorials/nodes-3/choiceview1.png"/></p> |
| |
| <p><b>Note:</b> If your TopComponent is very large, the combo box |
| provided by the choice view will be very large as well.</p></li> |
| |
| </ol> |
| </div> |
| |
| <div class="indent"> |
| |
| |
| <h3 class="tutorial"><a name="installing-software"></a>Menu View</h3> |
| |
| <p>Menu view is an explorer view that displays the hierarchy |
| of nodes in a popup menu. Initially, it shows a left button which |
| opens a popup menu from the root context and a right button which |
| opens a popup menu from the currently explored context. It is provided by |
| the <a href="https://netbeans.org/download/dev/javadoc/org-openide-explorer/org/openide/explorer/view/MenuView.html">MenuView</a> |
| class, which belongs to the Explorer And Property Sheet API.</p> |
| |
| |
| <ol> |
| <li>Add this line to the end of the TopComponent's Constructor: |
| |
| <pre class="examplecode">menuView = new MenuView();</pre> |
| |
| <p>Put the cursor in the line and let the IDE generate |
| an import statement for <tt>org.openide.explorer.view.MenuView</tt>. |
| Also let the IDE create the <tt>menuView</tt> field.</p> |
| |
| </li><li>Instead of the line that |
| adds a ChoiceView to the TopComponent, write a line that |
| adds the MenuView: |
| |
| <pre class="examplecode">add(menuView, BorderLayout.CENTER);</pre> |
| |
| </li><li>Install the module again. Notice that the view is now as follows: |
| |
| <p><img alt="" src="../../images/tutorials/nodes-3/menuview1.png"/></p> |
| |
| <p>When you click on the first button, the complete list of categories is displayed:</p> |
| |
| <p><img alt="" src="../../images/tutorials/nodes-3/menuview2.png"/></p> |
| |
| <p>When you click with the right mouse button on the "Browse from root" button, |
| the "Browse from current point" button is enabled and you can browse |
| to movies within the selected category:</p> |
| |
| <p><img alt="" src="../../images/tutorials/nodes-3/menuview3.png"/></p></li> |
| |
| |
| </ol> |
| </div> |
| |
| <div class="indent"> |
| |
| <h3 class="tutorial"><a name="installing-software"></a>Other Views</h3> |
| |
| <p>The <tt><a href="https://netbeans.org/download/dev/javadoc/org-openide-explorer/org/openide/explorer/view/package-summary.html">org.openide.explorer.view</a></tt> package provides many other |
| explorer views, in addition to those outlined above. For example, <a href="https://netbeans.org/download/dev/javadoc/org-openide-explorer/org/openide/explorer/view/IconView.html">IconView</a> |
| presents the categories and its contents as icons:</p> |
| |
| <p><img alt="" src="../../images/tutorials/nodes-3/iconview1.png"/></p> |
| |
| <p><img alt="" src="../../images/tutorials/nodes-3/iconview2.png"/></p> |
| |
| <p>Other views include <a href="https://netbeans.org/download/dev/javadoc/org-openide-explorer/org/openide/explorer/view/ContextTreeView.html">ContextTreeView</a> |
| and <a href="https://netbeans.org/download/dev/javadoc/org-openide-explorer/org/openide/explorer/view/ListTableView.html">ListTableView</a>.</p> |
| |
| <p>Finally, a <a href="https://netbeans.org/download/dev/javadoc/org-openide-explorer/org/openide/explorer/view/TreeTableView.html">TreeTableView</a> |
| could also be used. This NetBeans API class lets you |
| create a view tree of nodes on the left and its properties in a table on the right. This is |
| an area that deserves a tutorial of its own. Similarly, creating you own explorer view is a |
| worthwhile but complex project that will be described in a separate tutorial.</p> |
| </div> |
| |
| <!-- ===================================================================================== --> |
| <h2><a name="gettingtoknowthesample"></a>Using Palette Items to Reuse Nodes</h2> |
| |
| <p>Alternatively, the nodes can form the basis of palette items, as shown below:</p> |
| |
| <p><img alt="" src="../../images/tutorials/nodes-3/comp-pal.png"/></p> |
| |
| <p>In this section, |
| you are shown how to add the items to a Component Palette and how to add some |
| simple drag and drop functionality to the items in the palette. Only a brief |
| overview will be given here, because other tutorials exist that provide |
| details on the Component Palette API.</p> |
| |
| <p>Instead of adding an Explorer Manager to the TopComponent's Lookup, |
| you will need to add a <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-spi-palette/org/netbeans/spi/palette/PaletteController.html">PaletteController</a>. |
| When you do this, the Component Palette opens when the TopComponent opens, displaying |
| its content, consisting of palette items. <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-spi-palette/org/netbeans/spi/palette/PaletteController.html">PaletteController</a> |
| is provided by the Core - Component Palette API.</p> |
| |
| <ol> |
| <li>Right-click the project, choose |
| Properties, and add a dependency on Core - Component Palette in the Libraries category |
| of the Project Properties dialog box. |
| |
| </li><li>Declare a new <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-spi-palette/org/netbeans/spi/palette/PaletteController.html">PaletteController</a> |
| and set the root node as the palette's root: |
| |
| <pre class="examplecode">private <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-spi-palette/org/netbeans/spi/palette/PaletteController.html">PaletteController</a> palette = null; |
| private RootNode paletteRoot;</pre> |
| |
| </li><li>In the TopComponent's Constructor, comment out the calls to the Explorer Manager. |
| You can also comment out the definition of the action map, since the Component |
| Palette automatically provides Copy, Cut, Paste, and Delete actions to palette items. |
| |
| <p>In the Inspector, select the <tt>moviePane</tt>, open the |
| Properties window (Ctrl-Shift-7), click the "Code" tab, and <i>delete</i> the |
| line in the Custom Creation Code property (the very last property in the list).</p> |
| |
| </li><li>At the end of the Constructor, add this line to add the Component |
| Palette to the TopComponent's Lookup: |
| |
| <pre class="examplecode">associateLookup( Lookups.fixed( new Object[] {getPalette()} ));</pre> |
| |
| </li><li>Here, we create a new instance of the <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-spi-palette/org/netbeans/spi/palette/PaletteController.html">PaletteController</a> |
| and return it to the TopComponent's Lookup: |
| |
| <pre class="examplecode">private <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-spi-palette/org/netbeans/spi/palette/PaletteController.html">PaletteController</a> getPalette() { |
| if( null == palette ) { |
| paletteRoot = new RootNode(new CategoryChildren()); |
| paletteRoot.setName( "Palette Root"); |
| |
| palette = <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-spi-palette/org/netbeans/spi/palette/PaletteFactory.html">PaletteFactory</a>.createPalette( paletteRoot, |
| new MyPaletteActions(), null, new MyDragAndDropHandler() ); |
| } |
| return palette; |
| }</pre> |
| |
| </li><li>A palette consists of a root, a set of actions, |
| and a handler for drag and drop events. For purposes of this |
| simple example, we will set our palette actions to null: |
| |
| <pre class="examplecode">private static class MyPaletteActions extends <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-spi-palette/org/netbeans/spi/palette/PaletteActions.html">PaletteActions</a> { |
| public Action[] getImportActions() { |
| return null; |
| } |
| |
| public Action[] getCustomPaletteActions() { |
| return null; |
| } |
| |
| public Action[] getCustomCategoryActions(Lookup lookup) { |
| return null; |
| } |
| |
| public Action[] getCustomItemActions(Lookup lookup) { |
| return null; |
| } |
| |
| public Action getPreferredAction(Lookup lookup) { |
| return null; |
| } |
| |
| }</pre> |
| |
| |
| </li><li>And here is the definition of our drag and drop handler, using |
| the NetBeans API class <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-spi-palette/org/netbeans/spi/palette/DragAndDropHandler.html">DragAndDropHandler</a>: |
| |
| <pre class="examplecode">public static final DataFlavor MyCustomDataFlavor |
| = new DataFlavor( Object.class, "MyDND" ); |
| private static class MyDragAndDropHandler extends <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-spi-palette/org/netbeans/spi/palette/DragAndDropHandler.html">DragAndDropHandler</a> { |
| public void <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-spi-palette/org/netbeans/spi/palette/DragAndDropHandler.html#customize(org.openide.util.datatransfer.ExTransferable,%20org.openide.util.Lookup)">customize(ExTransferable exTransferable, Lookup lookup)</a> { |
| final MovieNode item = (MovieNode)lookup.lookup( MovieNode.class ); |
| if( null != item ) { |
| exTransferable.<a href="https://netbeans.org/download/dev/javadoc/org-openide-util/org/openide/util/datatransfer/ExTransferable.html#put(org.openide.util.datatransfer.ExTransferable.Single)">put</a>( new <a href="http://www.netbeans.org/download/dev/javadoc/org-openide-util/org/openide/util/datatransfer/ExTransferable.Single.html">ExTransferable.Single( MyCustomDataFlavor )</a> { |
| protected Object <a href="https://netbeans.org/download/dev/javadoc/org-openide-util/org/openide/util/datatransfer/ExTransferable.Single.html#getData()">getData()</a> throws IOException, UnsupportedFlavorException { |
| //return item.getSomeData(); |
| return null; |
| } |
| }); |
| } |
| } |
| }</pre></li> |
| |
| <li>Install the module again. When the TopComponent opens, the new |
| Component Palette is shown. The categories you created in this tutorial |
| are now categories in the Component Palette, while the movies are items |
| within the categories. Next, you need to add drag and drop functionality |
| to the items in the palette, as described in the <a href="https://platform.netbeans.org/tutorials/nbm-palette-api4.html">NetBeans Drag and Drop Tutorial</a>. |
| </li> |
| </ol> |
| |
| <div class="feedback-box"><a href="https://netbeans.org/about/contact_form.html?to=3&subject=Feedback:%20Nodes,%20Explorer%20Manager,%20and%20Component%20Palette%20Tutorial">Send Us Your Feedback</a></div> |
| |
| </body> |
| </html> |