diff --git a/openide.nodes/apichanges.xml b/openide.nodes/apichanges.xml
--- a/openide.nodes/apichanges.xml
+++ b/openide.nodes/apichanges.xml
@@ -46,6 +46,39 @@
Nodes API
+
+
+ Adding SimpleNode, an AbstractNode subclass which handles
+ a number of common cases and can eliminate some AbstractNode subclasses
+
+
+
+
+
+
+ SimpleNode is
+ an AbstractNode subclass which simplifies some common usage patterns
+ of Nodes:
+
+
Children object not necessary - simply override
+ createKeys() and createNodeForKey() to handle child nodes
+
No lookup, or fixed lookup contents may be passed into constructor,
+ or createLookup() can be overridden (but not both)
+
Icon can be passed as constructor parameter, without a subclass being
+ required
+
Display name can be annotated with HTML without subclassing, either
+ using setValue (SimpleNode.ERROR, Boolean.TRUE) or, e.g.,
+ setValue(SimpleNode.HTML_PREFIX, "<b>")
+
Children objects do not need to be dealt with directly - simply
+ override createKeys() and createNodeForKey()
+
Actions can be handled more simply, and the default Properties action
+ is suppressed
+
Fixed Lookup contents can be passed in directly
+
+
+
+
+ Support for declarative Node registrations
diff --git a/openide.nodes/nbproject/project.properties b/openide.nodes/nbproject/project.properties
--- a/openide.nodes/nbproject/project.properties
+++ b/openide.nodes/nbproject/project.properties
@@ -44,4 +44,4 @@
javadoc.arch=${basedir}/arch.xml
javadoc.apichanges=${basedir}/apichanges.xml
-spec.version.base=7.11.0
+spec.version.base=7.12.0
diff --git a/openide.nodes/src/org/openide/nodes/AbstractNode.java b/openide.nodes/src/org/openide/nodes/AbstractNode.java
--- a/openide.nodes/src/org/openide/nodes/AbstractNode.java
+++ b/openide.nodes/src/org/openide/nodes/AbstractNode.java
@@ -571,6 +571,10 @@
*/
private boolean overridesAMethod(String name, Class[] arguments) {
// we are subclass of AbstractNode
+ if (getClass() == SimpleNode.class) {
+ return false;
+ }
+
try {
java.lang.reflect.Method m = getClass().getMethod(name, arguments);
diff --git a/openide.nodes/src/org/openide/nodes/SimpleNode.java b/openide.nodes/src/org/openide/nodes/SimpleNode.java
new file mode 100644
--- /dev/null
+++ b/openide.nodes/src/org/openide/nodes/SimpleNode.java
@@ -0,0 +1,603 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License. When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2009 Sun Microsystems, Inc.
+ */
+
+package org.openide.nodes;
+
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.WeakHashMap;
+import javax.swing.Action;
+import org.openide.util.Exceptions;
+import org.openide.util.ImageUtilities;
+import org.openide.util.Lookup;
+import org.openide.util.lookup.Lookups;
+import org.openide.util.lookup.ProxyLookup;
+
+/**
+ * Node subclass for simple use-cases where the icon and display name are
+ * known ahead of time, lookup contents may be known ahead of time, which
+ * takes care of computing its child nodes without exposing a Children
+ * object.
+ *
+ * This class basically simplifies the following common cases for using
+ * AbstractNode + Children.Keys:
+ *
+ *
Icon can be passed as constructor parameter, without a subclass being
+ * required
+ *
Display name can be annotated with HTML without subclassing, either
+ * using setValue (SimpleNode.ERROR, Boolean.TRUE) or, e.g.,
+ * setValue(SimpleNode.HTML_PREFIX, "<b>")
+ *
Children objects do not need to be dealt with directly - simply
+ * override createKeys(List) and createNodeForKey(KeyType)
+ *
Actions can be handled more simply, and the default Properties action
+ * is suppressed
+ *
Fixed Lookup contents can be passed in directly using one of the
+ * static factory methods
+ *
No lookup, or fixed lookup contents may be passed into constructor,
+ * or createLookup() can be overridden (but not both). The Lookup does not
+ * need to exist at the time the node is constructed, eliminating some
+ * awkward code constructs that would otherwise be needed.
+ *
+ *
+ * Note: Do not call getCookieSet() to alter the contents of the
+ * lookup of a SimpleNode - it is not used. Instead, pass an appropriate
+ * lookup as a constructor parameter.
+ *
+ *
Managing Child Nodes
+ * If your node should have a set of child nodes that can be shown when your
+ * node is expanded, subclass SimpleNode and override createKeys(List)
+ * and createNodeForKey(KeyType).
+ *
+ * How this works: In createKeys(List), you create (or fetch
+ * somehow) model objects each of which represents one child node, and add them
+ * to the passed list. Later, when the nodes really need to be shown,
+ * createNodeForKey(KeyType) is called once for every object you
+ * added to the list in createKeys(List).
+ *
+ * If you need to update the set of child nodes because something has changed,
+ * simply call refreshChildren() - this will trigger another call
+ * to createKeys(List) and so forth.
+ *
+ * If the set of child nodes can change due to external code, and you can
+ * listen for those changes, override onStartListeningForChildChanges()
+ * to attach your listeners and onStopListeningForChildChanges()
+ *
+ * If you override createKeys(List), you must also override
+ * createNodeForKey(KeyType).
+ *
+ *
+ * @since 7.12
+ * @author Tim Boudreau
+ * @param KeyType the type of object used for the key objects that
+ * represent child nodes. If your node has no children, use
+ * SimpleNode<Void>
+ */
+public class SimpleNode extends AbstractNode {
+ private final Image icon;
+ /**
+ * Key which can be used in a call to setValue(ERROR, Boolean), to
+ * specify that this node should receive error badging in its display
+ * name and/or icon
+ */
+ public static final String ERROR = "_error"; //NOI18N
+
+ /**
+ * Key which can be used in a call to setValue(HTML_PREFIX, String), to
+ * specify an HTML prefix for the display name of this node, to affect
+ * its appearance somehow
+ */
+ public static final String HTML_PREFIX = "_prefix"; //NOI18N
+ /**
+ * Flag which is true if setValue() has ever been called - an optimization
+ * for handling getHtmlDisplayName()
+ */
+ private volatile boolean valueSet;
+ private final CF childFactory;
+
+ /**
+ * Create a new SimpleNode with unspecified lookup, display name,
+ * and lookup contents
+ */
+ public SimpleNode() {
+ this (null, (Image) null, (Lookup) null);
+ }
+
+ /**
+ * Create a new SimpleNode with the passed display name and
+ * icon resource path
+ * @param displayName A localized display name
+ * @param iconResourcePath A resource path to an icon, e.g. com/foo/bar/Icon.png
+ */
+ public SimpleNode (String displayName, String iconResourcePath) {
+ this (displayName, new PathIcon(iconResourcePath));
+ }
+
+ /**
+ * Create a new SimpleNode with the specified display name and icon
+ * @param displayName The display name, or null
+ * @param icon The icon, or null
+ */
+ public SimpleNode (String displayName, Image icon) {
+ this (displayName, icon, (Lookup) null);
+ }
+
+ /**
+ * Create a new SimpleNode with the specified display name and lookup
+ * contents
+ * @param displayName The display name, or null
+ * @param lookupContents The lookup contents, or null
+ */
+ public static Node create (String displayName, Object... lookupContents) {
+ return new SimpleNode(displayName, lookupContents);
+ }
+
+ /**
+ * Create a new SimpleNode with the specified display name, icon and lookup
+ * contents
+ * @param displayName The display name, or null
+ * @param lookupContents The lookup contents, or null
+ */
+ public static Node create (String displayName, Image icon, Object... lookupContents) {
+ return new SimpleNode(displayName, icon, lookupContents);
+ }
+
+ /**
+ * Create a new SimpleNode with the specified display name, icon and lookup
+ * contents
+ * @param displayName The display name, or null
+ * @param iconResourcePath A resource path to an icon, e.g. com/foo/bar/Icon.png
+ * @param lookupContents The lookup contents, or null
+ */
+ public static Node create (String displayName, String iconResourcePath, Object... lookupContents) {
+ return new SimpleNode(displayName, iconResourcePath == null ? null : new PathIcon(iconResourcePath), lookupContents);
+ }
+
+
+ /**
+ * Create a new SimpleNode with the specified display name and lookup
+ * contents
+ * @param displayName The display name, or null
+ * @param lookupContents The lookup contents, or null
+ */
+ SimpleNode (String displayName, Object... lookupContents) {
+ //package private to avoid constructor calls requiring extra casts
+ this (displayName, null, lookupContents);
+ }
+
+ /**
+ * Create a new SimpleNode with the specified display name, icon and lookup contents
+ * @param displayName The display name, or null
+ * @param icon The icon, or null
+ * @param lookupContents the contents of the lookup (may be empty but not
+ * null)
+ */
+ SimpleNode (String displayName, Image icon, Object... lookupContents) {
+ //package private to avoid constructor calls requiring extra casts
+ this (displayName, icon, Lookups.fixed(lookupContents));
+ }
+
+ /**
+ * Create a new SimpleNode with the specified display name, icon and lookup
+ * @param displayName The display name, or null
+ * @param iconResourcePath A resource path to an icon, e.g. com/foo/bar/Icon.png
+ * @param lookup The lookup, or null
+ */
+ public SimpleNode (String displayName, String iconResourcePath, Lookup lookup) {
+ this (displayName, iconResourcePath == null ? null : new PathIcon (iconResourcePath), lookup);
+ }
+
+ /**
+ * Create a new SimpleNode with the specified display name, icon and lookup
+ * @param displayName The display name, or null
+ * @param icon The icon, or null
+ * @param lookup The lookup, or null
+ */
+ public SimpleNode (String displayName, Image icon, Lookup lookup) {
+ super(Children.LEAF, new L());
+ if (lookup != null) assert !overridesCreateLookup() : "Passing a " + //NOI18N
+ "non-null lookup to a SimpleNode which overrides createLookup." + //NOI18N
+ "Passed lookup will not be used"; //NOI18N
+ if (displayName != null) {
+ setName (displayName);
+ setDisplayName(displayName);
+ }
+ ((L) getLookup()).set(lookup == null ? createLookup() : lookup);
+ if (overridesCreateKeys()) {
+ setChildren (Children.create(childFactory = new CF(this), true));
+ } else {
+ childFactory = null;
+ }
+ this.icon = icon;
+ }
+
+ /**
+ * Create this node's lookup. This method is called once, from the
+ * superclass constructor (be careful not to refer to instance fields
+ * if you override this method), and only if no Lookup or array of
+ * Lookup contents was passed to the constructor.
+ *
+ * @return A Lookup. The default implementation returns
+ * Lookups.singleton(this)
+ */
+ protected Lookup createLookup() {
+ return Lookups.singleton(this);
+ }
+
+ /**
+ * Populate a list of "key" objects which will be passed
+ * individually to createNodeForKey() to create this node's child nodes.
+ * Think of this as keys in a map, where the values are Nodes. Create
+ * your collection of keys in this method, and add them all to the passed
+ * list. Later, when the nodes need to be displayed, the system will
+ * call createNodeForKey(), passing each key you provided individually,
+ * at which point you create a child node.
+ *
+ * If you override this method, you must also override createNodeForKey()
+ * or an exception will be thrown if your node is expanded at runtime.
+ *
+ * Note that this method is not called on the AWT event thread, but on a
+ * background thread. Code inside this method should not directly
+ * call other code that is not thread-safe.
+ *
+ * If your node should not have child nodes, simply do not override this
+ * method.
+ * @param toPopulate A list which can be added to
+ * @return true if the list has been fully populated, false if another call
+ * to createKeys() should be enqueued to add more key objects to the list
+ * (do this if computing the keys is very slow, perhaps involving I/O,
+ * and you want to show a partial result).
+ */
+ protected boolean createKeys(List toPopulate) {
+ return true;
+ }
+
+ /**
+ * Call this method if the list of children of this node changes, to trigger
+ * an update of its children.
+ *
+ * @param immediate If true, the children should be updated immediately
+ * (resulting in a synchronous call to createKeys() - if creating the keys
+ * is slow, do not call this method with an argument of true from the
+ * AWT event thread)
+ */
+ protected final void refreshChildren(boolean immediate) {
+ if (childFactory != null) {
+ childFactory.refresh(immediate);
+ }
+ }
+
+ /**
+ * Create a child node for the passed key object. The key abject is one
+ * of the objects created and added to the passed list in toPopulate.
+ *
+ * @param key The key object
+ * @return A node
+ */
+ protected Node createChildNodeFor(KeyType key) {
+ // XXX new BeanNode(key) ?
+ throw new UnsupportedOperationException("Must override createNodeForKey"); //NOI18N
+ }
+
+ /**
+ * Called when the user expands this node in the UI, or something
+ * programmatically expresses an interest in the children of this node.
+ * If the set of child nodes can change due to external events, such as
+ * a file being deleted or created, start listening for changes in whatever
+ * model object determines the set of child nodes here.
+ *
+ * The default implementation does nothing. This method will only ever
+ * be called if you are overriding createKeys() and
+ * createNodeForKey()
+ */
+ protected void onStartListeningForChildChanges() {
+ //do nothing
+ }
+
+ /**
+ * Called some time after the user has collapsed this node in the UI, or the
+ * last listener interested in the children of this node is removed or
+ * garbage collected..
+ * If the set of child nodes can change due to external events, such as
+ * a file being deleted or created, detach your listeners from whatever
+ * model object determines the children here.
+ *
+ * The default implementation does nothing. This method will only ever
+ * be called if you are overriding createKeys() and
+ * createNodeForKey()
+ */
+ protected void onStopListeningForChildChanges() {
+ //do nothing
+ }
+
+
+ /**
+ * Overridden to be final, to prevent overriding in subclasses. To
+ * affect the contents of this Node's Lookup (and thus the return values
+ * of getCookie()), provide your own Lookup as a constructor parameter or
+ * as the return value from createLookup()
+ * @param the cookie type
+ * @param type the cookie type
+ * @return a object of type T
+ * @deprecated use getLookup().lookup(Class) instead
+ */
+ @Deprecated
+ @Override
+ public final T getCookie(Class type) {
+ return super.getCookie(type);
+ }
+
+ /**
+ * Overridden to make use of flags that can be set on this node.
+ * Call setValue(SimpleNode.ERROR, Boolean.TRUE) to have this node's
+ * title show up in the default error color (usually red). Call
+ * setValue (SimpleNode.HTML_PREFIX, "") with an html prefix
+ * to prepend to the display name.
+ *
+ * Note that if you override this method, calls to setValue(HTML_PREFIX, String)
+ * and setValue(ERROR, Boolean) will have no effect unless you handle these
+ * values in your own code or call super.getHtmlDisplayName() and decorate
+ * but do not replace the result.
+ *
+ * @return The node's display name decorated with HTML or null if HTML
+ * is not needed
+ */
+ @Override
+ public String getHtmlDisplayName() {
+ if (valueSet) {
+ String pfix = (String) getValue(HTML_PREFIX);
+ boolean err = Boolean.TRUE.equals(getValue(ERROR));
+ if (err) {
+ String errHead = ""; //NOI18N
+ pfix = pfix == null ? errHead : pfix + errHead;
+ return pfix + getDisplayName();
+ } else if (pfix != null) {
+ return pfix + getDisplayName();
+ }
+ }
+ return super.getHtmlDisplayName();
+ }
+
+ /**
+ * Allows nodes to contain ad-hoc key/value pairs. Will trigger a
+ * display name change event if a key which affects html display name
+ * is passed
+ * @param key The key
+ * @param o The value
+ */
+ @Override
+ public final void setValue(String key, Object o) {
+ valueSet = true;
+ boolean isChange = ERROR.equals(key) || HTML_PREFIX.equals(key);
+ String oldName = isChange ? getDisplayName() : null;
+ super.setValue(key, o);
+ if (isChange) {
+ fireDisplayNameChange(oldName, getDisplayName());
+ if (ERROR.equals(key)) {
+ fireIconChange();
+ }
+ }
+ }
+
+ /**
+ * Overridden to return the icon passed as a constructor argument, if any.
+ * @param type The icon type,
+ * @return the icon passed to the constructor, or the return value of
+ * a call to super.getIcon(type) if that was null
+ */
+ @Override
+ public Image getIcon(int type) {
+ Image result = icon == null ? super.getIcon(type) :
+ icon instanceof PathIcon ? ((PathIcon) icon).actualImage() : icon;
+ return badge(result);
+ }
+
+ /**
+ * Overridden to return the icon passed as a constructor argument, or
+ * if null, the return value of super.getOpenedIcon(type).
+ * @param type The icon type,
+ * @return the icon passed to the constructor, or the return value of
+ * a call to super.getOpenedIcon(type) if that was null.
+ */
+ @Override
+ public Image getOpenedIcon(int type) {
+ Image result = icon == null ? super.getOpenedIcon(type) :
+ icon instanceof PathIcon ? ((PathIcon) icon).actualImage() : icon;
+ return badge(result);
+ }
+
+ private Image badge(Image img) {
+ if (img != null && valueSet && Boolean.TRUE.equals(getValue(ERROR))) {
+ Image badge = ImageUtilities.loadImage(
+ "org/openide/nodes/errorBadge.png"); //NOI18N
+ img = ImageUtilities.mergeImages(img, badge, 8, 8);
+ }
+ return img;
+ }
+
+ /**
+ * Populate the passed list with any actions which should be available
+ * @param actions A list of actions which can be added to
+ */
+ public void createActions(List actions) {
+ //do nothing
+ }
+
+ /**
+ * Overridden as final to delegate to createActions(List)
+ * @param context ignored
+ * @return an array of actions
+ */
+ @Override
+ public final Action[] getActions(boolean context) {
+ List l = new LinkedList();
+ createActions(l);
+ return l.toArray(new Action[0]);
+ }
+
+ private static class CF extends ChildFactory.Detachable {
+ private final SimpleNode nd;
+ CF (SimpleNode nd) {
+ this.nd = nd;
+ }
+
+ @Override
+ protected boolean createKeys(List toPopulate) {
+ return nd.createKeys(toPopulate);
+ }
+
+ @Override
+ protected Node createNodeForKey(KeyType key) {
+ return nd.createChildNodeFor(key);
+ }
+
+ @Override
+ protected void addNotify() {
+ nd.onStartListeningForChildChanges();
+ }
+
+ @Override
+ protected void removeNotify() {
+ nd.onStopListeningForChildChanges();
+ }
+ }
+
+ private static final class L extends ProxyLookup {
+ void set(Lookup real) {
+ setLookups(real);
+ }
+ }
+
+ private static final Map, Boolean> CREATE_KEYS_OVERRIDERS =
+ Collections.synchronizedMap(new WeakHashMap,Boolean>());
+ /**
+ * Used to determine if Children.LEAF should be retained as the
+ * Children object
+ * @return true if this class overrides the createKeys() method
+ */
+ private boolean overridesCreateKeys() {
+ if (getClass() == SimpleNode.class) return false;
+ Boolean val = CREATE_KEYS_OVERRIDERS.get(getClass());
+ if (val == null) {
+ try {
+ val = overrides ("createKeys", List.class);
+ CREATE_KEYS_OVERRIDERS.put (getClass(), val);
+ } catch (SecurityException ex) {
+ Exceptions.printStackTrace(ex);
+ val = false;
+ }
+ }
+ return val;
+ }
+
+ private boolean overrides (String name, Class... ptypes) {
+ Class> type = getClass();
+ boolean result = false;
+ while (type != SimpleNode.class) {
+ try {
+ type.getDeclaredMethod(name, ptypes);
+ result = true;
+ break;
+ } catch (NoSuchMethodException e) {
+ //do nothing
+ }
+ type = type.getSuperclass();
+ }
+ return result;
+ }
+
+ /**
+ * Used to trigger an assertion error of createLookup() is overridden
+ * and a non-null lookup is also passed to the constructor
+ * @return whether or not this subclass overrides createLookup()
+ */
+ private boolean overridesCreateLookup() {
+ if (getClass() == SimpleNode.class) return false;
+ try {
+ return overrides ("createLookup");
+ } catch (SecurityException ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ return false;
+ }
+
+ private static final class PathIcon extends Image {
+ private final String path;
+ PathIcon(String path) {
+ this.path = path;
+ }
+
+ Image actualImage() {
+ return ImageUtilities.loadImage(path);
+ }
+
+
+ @Override
+ public int getWidth(ImageObserver observer) {
+ throw new AssertionError();
+ }
+
+ @Override
+ public int getHeight(ImageObserver observer) {
+ throw new AssertionError();
+ }
+
+ @Override
+ public ImageProducer getSource() {
+ throw new AssertionError();
+ }
+
+ @Override
+ public Graphics getGraphics() {
+ throw new AssertionError();
+ }
+
+ @Override
+ public Object getProperty(String name, ImageObserver observer) {
+ throw new AssertionError();
+ }
+
+ }
+}
diff --git a/openide.nodes/src/org/openide/nodes/errorBadge.png b/openide.nodes/src/org/openide/nodes/errorBadge.png
new file mode 100644
index 0000000000000000000000000000000000000000..a903aa2b56245164715b9f81c9893eaf523474af
GIT binary patch
literal 373
zc%17D@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqoCO|{#S9GG!XV7ZFl&wkP>?0v
z(btiIVPjv-@4(4GzCyA`kS_y6l_~>6Lo)-z&;LOBB?CjL0RzLU1O^7H84L{K`IF+0
zx&hU`_H=O!skoK2$8;_u&%ZxO0x1vED%jIL8+L5kV6caABO_DC%gf?yZQtb^bi~?J
zuBMo>T}@$SYkSV~F@L?0LCubn2N(n#eBRp|8|Ec1&B5UW$i~cJ(
z-z0=*udLx^znzB3VotXU?Ad(AJ@Wk>RINK-RtHjo*OY
OX7F_Nb6Mw<&;$UY8ialT
diff --git a/openide.nodes/test/unit/src/org/openide/nodes/SimpleNodeTest.java b/openide.nodes/test/unit/src/org/openide/nodes/SimpleNodeTest.java
new file mode 100644
--- /dev/null
+++ b/openide.nodes/test/unit/src/org/openide/nodes/SimpleNodeTest.java
@@ -0,0 +1,327 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License. When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2009 Sun Microsystems, Inc.
+ */
+
+package org.openide.nodes;
+
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.event.ActionEvent;
+import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
+import java.util.Collection;
+import java.util.List;
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openide.util.ImageUtilities;
+import static org.junit.Assert.*;
+import org.openide.util.Lookup;
+import org.openide.util.lookup.Lookups;
+
+/**
+ *
+ * @author tim
+ */
+public class SimpleNodeTest {
+
+ public SimpleNodeTest() {
+ }
+
+ @BeforeClass
+ public static void setUpClass() throws Exception {
+ }
+
+ @AfterClass
+ public static void tearDownClass() throws Exception {
+ }
+
+ @Before
+ public void setUp() {
+ }
+
+ @After
+ public void tearDown() {
+ }
+
+ /**
+ * Test of create method, of class SimpleNode.
+ */
+ @Test
+ public void testCreate_String_ObjectArr() {
+ System.out.println("create");
+ String displayName = "Boo";
+ Object[] lookupContents = new String[] { "A", "B", "C" };
+ Node n = SimpleNode.create(displayName, lookupContents);
+ assertEquals ("Boo", n.getDisplayName());
+ Collection extends String> c = n.getLookup().lookupAll(String.class);
+ assertTrue (c.contains("A"));
+ assertTrue (c.contains("B"));
+ assertTrue (c.contains("C"));
+ assertFalse (c.contains("D"));
+ assertEquals(3, c.size());
+ }
+
+ /**
+ * Test of create method, of class SimpleNode.
+ */
+ @Test
+ public void testCreate_3args_1() {
+ System.out.println("create");
+ String displayName = "X";
+ Image icon = ImageUtilities.loadImage("org/openide/nodes/beans.gif");
+ Object[] lookupContents = new Object [] { displayName, icon };
+ Node n = SimpleNode.create(displayName, icon, lookupContents);
+ assertSame (icon, n.getLookup().lookup(Image.class));
+ assertEquals (displayName, n.getLookup().lookup(String.class));
+ assertEquals (displayName, n.getDisplayName());
+ assertNull (n.getHtmlDisplayName());
+ assertSame (icon, n.getOpenedIcon(0));
+ }
+
+ /**
+ * Test of create method, of class SimpleNode.
+ */
+ @Test
+ public void testCreate_3args_2() {
+ System.out.println("create");
+ String displayName = "X";
+ String iconResourcePath = "org/openide/nodes/beans.gif";
+ Object[] lookupContents = new Object[] { displayName, iconResourcePath };
+ Node n = SimpleNode.create(displayName, iconResourcePath, lookupContents);
+ assertNotNull (n.getIcon(0));
+ assertEquals (displayName, n.getDisplayName());
+ assertNotNull (n.getDisplayName());
+ Collection extends String> c = n.getLookup().lookupAll(String.class);
+ assertTrue (c.contains(displayName));
+ assertTrue (c.contains(iconResourcePath));
+ assertEquals(2, c.size());
+ }
+
+ /**
+ * Test of createLookup method, of class SimpleNode.
+ */
+ @Test
+ public void testCreateLookup() {
+ System.out.println("createLookup");
+ StringBuilder thing1 = new StringBuilder("Thing 1");
+ StringBuilder thing2 = new StringBuilder("Thing 2");
+ final Lookup lkp = Lookups.fixed(thing1, thing2);
+ final boolean[] called = new boolean[1];
+ SimpleNode