Download pdf - 1.Using Nodes

Transcript
Page 1: 1.Using Nodes

8/29/2014 NetBeans Selection Management Tutorial II—Using Nodes for the NetBeans Platform

https://platform.netbeans.org/tutorials/nbm-selection-2.html 1/12

NetBeans IDE

NetBeans Platform

Plugins

Docs & Support

Community

Partners

Search netbeans.org> projects > platform > Website

NetBeans Selection Management Tutorial II—Using NodesThe previous tutorial covered the basics of component­wide selection handling in NetBeans—how to provideobjects from a TopComponent's Lookup, and how to write other components that are sensitive to the Lookupof whatever component has focus.

This tutorial focuses on the Nodes API, which makes it possible to do more granular views and selection thanjust component­level selection. Of course, you could write a component that reads and writes into its ownLookup whatever it wants, and provides more granular selection logic that way. But the Nodes API makes it veryeasy to do this, and offers a number of advantages over doing it yourself.

Note: This document uses NetBeans Platform 8.0 and NetBeans IDE 8.0. If you are using an earlierversion, see the previous version of this document.

Contents

Introduction to the Nodes APICreating an Explorer ViewImplementing Nodes and Node ChildrenRunning the TutorialExploring ExplorerHandling Multi­SelectionReview of ConceptsNext Steps

To follow this tutorial, you need the software and resources listed in the following table.

Software or Resource Version Required

Login | Join Now | Help

Jump to...

NavigationHome

My Page

Projects

People

ProjectFeaturesMailing Lists

Issue Tracking

Bugzilla

Source CodeRepository

Platform content

Website

Website

Page 2: 1.Using Nodes

8/29/2014 NetBeans Selection Management Tutorial II—Using Nodes for the NetBeans Platform

https://platform.netbeans.org/tutorials/nbm-selection-2.html 2/12

NetBeans IDE version 8.0 or above

Java Developer Kit (JDK) version 7 or above

For troubleshooting purposes, you are welcome to download the completed tutorial source code.

Introduction to the Nodes APIThe first advantage is that the Nodes API provides a presentation layer—a layer between the data model beingedited in some way, and the UI components that expose the data model to the user. This is quite useful andpowerful, as the same model may be presented in multiple ways, or with multiple UIs.

The second advantage is the Explorer API—the module org.openide.explorer provides a vast array ofcomponents—trees, lists, tree tables and more—which can render a Node and its children.

A Node is a generic hierarchical object—a Node has:

Children—Nodes in a hierarchy underneath it, that can be displayed in a tree

Actions—An array of actions that can be displayed in a popup menu

Display Name—A human­readable, localized display name that can be shown in a UI component

Icon—An icon that can be shown in a UI component

and Nodes can fire changes in any of the above, and the explorer UI components will automatically updatethemselves.

This is not to say that the content of the previous tutorial was useless—on the contrary, it is the reason theNodes API can work. The reason: org.openide.nodes.Node has a method, you guessed it, getLookup(). Infact what is happening when you change selection in the Projects tab in the IDE, for example, is...the Projectstab is a TopComponent. It proxies the Lookup of whatever object(s) are currently selected in the tree—just asthe Utilities.actionsGlobalContext() Lookup proxies whichever component is focused and fireschanges when focus changes.

Thanks to the components in the Explorer API, it is very easy to create your own views of a tree of Nodes, andhave this type of proxying in your own components with very little code. Viewer type components such as theMyViewer component in the previous tutorial do not have to do anything special to be able to respond toselection changes in Explorer components—they will automatically be notified as selection changes.

Creating an Explorer ViewThe first thing you will do is some substantial modifications to your MyEditor editor component. This startswith opening it in the editor.

1. First, bring up the properties dialog for the My Editor project by right­clicking the My Editor project andchoosing Properties. On the Libraries tab, click the Add Dependency button, and type "BeanTreeView"in the dialog:

Wiki

NetBeans PlatformWiki

WikiHomePage

WikiHomePage

Project Links» Screenshots

» CustomerTestimonials

» Quick Start

About thisProjectPlatform wasstarted inNovember 2009, isowned by AntoninNebuzelsky, andhas 142 members.

» Join This Project

NetBeans.orgJoin

News

Releases &Planning

Mailing Lists

Bugzilla

Contribute

Teams

Guidelines

Page 3: 1.Using Nodes

8/29/2014 NetBeans Selection Management Tutorial II—Using Nodes for the NetBeans Platform

https://platform.netbeans.org/tutorials/nbm-selection-2.html 3/12

Click OK once you see the Explorer & Property Sheet API listed, as shown above. This will add adependency on the Explorer API module, so you can use classes from it.

2. Switch to the form designer, select all of the components, and delete them. In the next steps, we willuse a component from the Explorer & Property Sheet API, instead of the text fields and button we havebeen using so far.

3. Rewrite the constructor of the MyEditor class as shown below:

public MyEditor()

initComponents(); Event obj = new Event(); associateLookup(new AbstractLookup(content));

setLayout(new BorderLayout()); add(new BeanTreeView(), BorderLayout.CENTER);

setDisplayName("MyEditor " + obj.getIndex());

Page 4: 1.Using Nodes

8/29/2014 NetBeans Selection Management Tutorial II—Using Nodes for the NetBeans Platform

https://platform.netbeans.org/tutorials/nbm-selection-2.html 4/12

BeanTreeView is a component from the Explorer & Property Sheet API—a basic JTree­based viewover a Node and its children, with built­in handling of popup menus, searching and more. Press Ctrl­Shift­I to import BeanTreeView, because the import statement needs to be added.

4. The next step is to give your tree something to show. Explorer UI components work like this: Whenadded to a container, they search that container and their ancestors until they find one thatimplements ExplorerManager.Provider. So you don't set the node to be viewed directly on thecomponent—you set it on the component's manager. This makes it possible to have multiple views,master/detail views and such, all managed by a single manager. Add to the signature of MyEditor asfollows:

public class MyEditor extends TopComponent implements ExplorerManager.Provider

Then press Ctrl­Shift­I to fix imports. Keeping the caret in the signature line, a lightbulb glyph shouldappear in the margin. Press Alt­Enter, and accept the hint "Implement all abstract methods". This willadd one method, getExplorerManager(). Implement it as follows:

private final ExplorerManager mgr = new ExplorerManager();

public ExplorerManager getExplorerManager() return mgr;

5. Now, since the goal is one component that can display multiple Events, you need a Node or two todisplay in your component. Each one will own its own instance of Event. So, right now you'll just addthe code that will create a root node for your tree view. Add the following line to the constructor:

mgr.setRootContext(new AbstractNode(Children.create(new EventChildFactory(), true)));

This is the code that sets the root node for all of the explorer views that are child components ofMyEditor. The Children.create is a static call from the NetBeans APIs that will, thanks to the trueparameter, create the child components asynchronously, that is, as needed, instead of all at once.

6. If you tried Fix Imports, you may have seen the error dialog telling you that neither AbstractNode,Children, nor EventChildFactory could be resolved. To resolve AbstractNode and Children,you need to add one dependency, on the Nodes API module. Right click the My Editor project, go to the

Page 5: 1.Using Nodes

8/29/2014 NetBeans Selection Management Tutorial II—Using Nodes for the NetBeans Platform

https://platform.netbeans.org/tutorials/nbm-selection-2.html 5/12

Libraries page and click Add Dependency. Type "AbstractNode" in the Add dialog, and when the item"Nodes API" in the list is selected, click OK or press Enter.

7. Now, back in the source editor, press Ctrl­Shift­I to Fix Imports. You will be notified thatEventChildFactory could not be resolved. That's okay—you're about to write it, in the next section.

Implementing Nodes and Node ChildrenYou'll notice you're using a class called AbstractNode above. Despite its name, it is not an abstract class! It isa utility implementation of org.openide.nodes.Node which can save you some time and trouble—rather thanimplement Node yourself, you can just create an AbstractNode and pass it a Children object which will providechild nodes for it, and then set its icon and display name as needed. So it is a simple way to get a Node objectto represent something, without needing to do any subclassing of Node itself.

The next step is to implement EventChildFactory, so that there are subnodes underneath the initial node.

1. Right click the org.myorg.myeditor package in the My Editor project, and choose New > Java Classfrom the popup menu. In the New Java Class wizard, name the class "EventChildFactory", and clickFinish or press Enter to create the class.

2. Modify the signature of the class so it extends ChildFactory:

class EventChildFactory extends ChildFactory<Event>

Press Ctrl­Shift­I to Fix Imports.

3. Position the caret in the class signature line. When the lightbulb glyph appears in the margin, press Alt­Enter and then Enter again to accept the hint "Implement all Abstract Methods". This will add acreateKeys(List<Event> toPopulate) method—this is where you will create the keys, on abackground thread, that will be used to create the children of your root node.

4. But first, you want to override one method—createKeys. ChildrenFactory.createKeys is calledthe first time something pays attention to this Children object—the first time it is asked for its childnodes. So you can delay creation of child Nodes until the user has really expanded the parent node in aview and needs to see them. Implement the method as follows:

@Overrideprotected boolean createKeys(List toPopulate) Event[] objs = new Event[5]; for (int i = 0; i < objs.length; i++) objs[i] = new Event(); toPopulate.addAll(Arrays.asList(objs));

Page 6: 1.Using Nodes

8/29/2014 NetBeans Selection Management Tutorial II—Using Nodes for the NetBeans Platform

https://platform.netbeans.org/tutorials/nbm-selection-2.html 6/12

return true;

As you may have guessed from the name ChildFactory, what your parent class does is take an arrayor Collection of key objects, and act as a factory for Nodes for them. For each element in the arrayor collection you pass to the toPopulate list above, the createNodeForKey() shown below will becalled once when true is returned (note this means that if you want, you can have more than onenode to represent one object).

5. Now you need to implement the code that actually creates Node objects for all of these. ImplementcreateNodeForKey as follows:

@Overrideprotected Node createNodeForKey(Event key) Node result = new AbstractNode( Children.create(new EventChildFactory(), true), Lookups.singleton(key)); result.setDisplayName(key.toString()); return result;

The new Node is created by passing in the definition of its Children, together with the current Event,which is put into the Lookup of the Node. When the user selects the Node, the object in its Lookupwill be proxied by the Lookup of the TopComponent, which in turn is proxied by the global Lookup. Inthis way, you make the current Event object available to any object that is interested in it, wheneverthe Node is selected. Press Ctrl­Shift­I to Fix Imports.

6. The last step is to install a bit of plumbing code that will wire up your explorer manager to yourTopComponent's lookup. First, delete the line

private final InstanceContent content = new InstanceContent();

from the head of the class definition—you will be using a utility to wire up the selected Node's Lookupto your component's Lookup.

7. Modify the constructor of MyEditor so it looks like this:

public MyEditor()

initComponents(); Event obj = new Event();

Page 7: 1.Using Nodes

8/29/2014 NetBeans Selection Management Tutorial II—Using Nodes for the NetBeans Platform

https://platform.netbeans.org/tutorials/nbm-selection-2.html 7/12

associateLookup(ExplorerUtils.createLookup(mgr, getActionMap()));

setLayout(new BorderLayout()); add(new BeanTreeView(), BorderLayout.CENTER);

setDisplayName("MyEditor " + obj.getIndex());

mgr.setRootContext(new AbstractNode(Children.create(new EventChildFactory(), true)));

Running the TutorialYou may have noticed that because you pass a new instance of EventChildFactory to each AbstractNodeyou create, that you will end up with an infinitely deep tree of Events—each Node will have five child Nodes,each with its own Event.

You are now ready to run, so right­click EventManager and choose Clean and Build, and then right­click againand choose Run from the popup menu. When the application starts, you should be able to browse the Events,as shown below:

Page 8: 1.Using Nodes

8/29/2014 NetBeans Selection Management Tutorial II—Using Nodes for the NetBeans Platform

https://platform.netbeans.org/tutorials/nbm-selection-2.html 8/12

Notice that as you click and/or expand different nodes, the viewer and the property sheet update themselves toshow the Event belonging to each node, as shown below:

Page 9: 1.Using Nodes

8/29/2014 NetBeans Selection Management Tutorial II—Using Nodes for the NetBeans Platform

https://platform.netbeans.org/tutorials/nbm-selection-2.html 9/12

Exploring ExplorerNow that you have the above code, it can be interesting to explore some of the other components available inthe Explorer & Property Sheet API, which can also render a Node and it's children. You can do this by openingMyEditor in the Source view and changing add (new BeanTreeView(), BorderLayout.CENTER) tosomething different, in the constructor.

Some of the options are:

OutlineView—a tree­table—a table whose leftmost column is a tree

IconView—a component that shows Node children in equally spaced icons, rather like Windows Explorer

ListView—display nodes in a JList (you can set how deep into the Node hierarchy it should go)

ChoiceView—a combo­box view of a Node and its children

MenuView—a JButton that pops up a menu of a Node and its children

Handling Multi­SelectionYou may have noticed that BeanTreeView, the basic tree view for Nodes, lets you select more than one Nodeat a time. Therefore, it might be desirable to modify your viewer component to display information about all ofthe selected nodes:

1. Open org.myorg.myviewer.MyViewerTopComponent from the My Viewer project, in the editor.

Page 10: 1.Using Nodes

8/29/2014 NetBeans Selection Management Tutorial II—Using Nodes for the NetBeans Platform

https://platform.netbeans.org/tutorials/nbm-selection-2.html 10/12

2. Replace the resultChanged() listener method with the following code:

@Overridepublic void resultChanged(LookupEvent lookupEvent) Collection<? extends Event> allEvents = result.allInstances(); if (!allEvents.isEmpty()) StringBuilder text1 = new StringBuilder(); StringBuilder text2 = new StringBuilder(); for (Iterator i = allEvents.iterator(); i.hasNext();) Event o = (Event) i.next(); text1.append(o.getIndex()); text2.append(o.getDate().toString()); if (i.hasNext()) text1.append(','); text2.append(','); jLabel1.setText(text1.toString()); jLabel2.setText(text2.toString()); else jLabel1.setText("[no selection]"); jLabel2.setText("");

So you can see that, not only does the Lookup created by ExplorerUtils handle proxying the Lookup ofwhatever Node is selected; it also correctly proxies the Lookups of multiple Nodes.

Page 11: 1.Using Nodes

8/29/2014 NetBeans Selection Management Tutorial II—Using Nodes for the NetBeans Platform

https://platform.netbeans.org/tutorials/nbm-selection-2.html 11/12

Review of ConceptsTo review a few of the concepts you've covered here:

A Lookup is like a Map where the keys are classes and the values are instances of those classes. It's alsouseful to think of a Lookup as a place that objects swim into and out of, and you can subscribe to benotified of the arrival and departure of specific types of object.

Utilities.actionsGlobalContext() is a Lookup which proxies the Lookup of whicheverTopComponent currently has keyboard focus, and fires changes when focus moves to a differentcomponent.

Nodes are presentation objects that can be displayed in a tree, list or other component from the ExplorerAPI. Each Node has its own Lookup.

Just as Utilities.actionsGlobalContext proxies the Lookup of TopComponents (so you can justask that lookup for a result and listen for changes in it, rather than having to track focus changesyourself), so also the Lookup created by ExplorerUtils.createLookup(ExplorerManager,ActionMap) will create a Lookup which automatically proxies the Lookup of whatever Node(s) areselected in an Explorer component.

Page 12: 1.Using Nodes

8/29/2014 NetBeans Selection Management Tutorial II—Using Nodes for the NetBeans Platform

https://platform.netbeans.org/tutorials/nbm-selection-2.html 12/12

Send Us Your Feedback

Next StepsSo you now have a view that can display Nodes that expose some underlying model object (Event in yourcase). In the next tutorial, you will cover how to enhance the Nodes you have already created with actions,properties and more colorful display names.

SiteMap

About Us

Contact

Legal & Licences

By use of this website, you agree to the NetBeans Policies and Terms of Use (revision 20140718.4a68f04). © 2014, Oracle Corporationand/or its affiliates. Sponsored by


Recommended