diff -r 067c411a9044 openide.explorer/apichanges.xml
--- a/openide.explorer/apichanges.xml Sat Apr 17 09:10:37 2010 +0200
+++ b/openide.explorer/apichanges.xml Sat Apr 17 21:38:39 2010 +0200
@@ -47,6 +47,21 @@
Explorer API
+
+
+ ListView can now display ".." item
+
+
+
+
+
+ To simplify navigation "up" in the ListView
one
+ can turn on showParentNode
+ property.
+
+
+
+
OutlineView.setPropertyColumns
,
diff -r 067c411a9044 openide.explorer/manifest.mf
--- a/openide.explorer/manifest.mf Sat Apr 17 09:10:37 2010 +0200
+++ b/openide.explorer/manifest.mf Sat Apr 17 21:38:39 2010 +0200
@@ -2,5 +2,5 @@
OpenIDE-Module: org.openide.explorer
OpenIDE-Module-Localizing-Bundle: org/openide/explorer/Bundle.properties
AutoUpdate-Essential-Module: true
-OpenIDE-Module-Specification-Version: 6.27
+OpenIDE-Module-Specification-Version: 6.28
diff -r 067c411a9044 openide.explorer/src/org/openide/explorer/view/Bundle.properties
--- a/openide.explorer/src/org/openide/explorer/view/Bundle.properties Sat Apr 17 09:10:37 2010 +0200
+++ b/openide.explorer/src/org/openide/explorer/view/Bundle.properties Sat Apr 17 21:38:39 2010 +0200
@@ -53,6 +53,8 @@
VetoSelectedNodes=Selected Nodes
LBL_QUICKSEARCH=Search:
+LBL_UP=..
+
# TreeViewCellEditor
# {0} - old name
# {1} - new name
diff -r 067c411a9044 openide.explorer/src/org/openide/explorer/view/ListView.java
--- a/openide.explorer/src/org/openide/explorer/view/ListView.java Sat Apr 17 09:10:37 2010 +0200
+++ b/openide.explorer/src/org/openide/explorer/view/ListView.java Sat Apr 17 21:38:39 2010 +0200
@@ -101,6 +101,7 @@
import org.openide.nodes.Node.Property;
import org.openide.nodes.NodeOp;
import org.openide.util.ContextAwareAction;
+import org.openide.util.Exceptions;
import org.openide.util.Mutex;
import org.openide.util.NbBundle;
import org.openide.util.Utilities;
@@ -181,6 +182,9 @@
/** if true, the hierarchy traversal is allowed, if false, it is disabled */
private boolean traversalAllowed = true;
+ /** show parent node */
+ private boolean showParentNode;
+
/** action preformer */
private ActionListener defaultProcessor;
@@ -299,6 +303,26 @@
traversalAllowed = value;
}
+ /** Is parent node (e.g. explored context shown)?
+ * @return true or false. Default is false.
+ * @since 6.28
+ */
+ public boolean isShowParentNode() {
+ return showParentNode;
+ }
+
+ /** Shall the first node in the list be ".." representing currently
+ * explored context? By default it is not, but if you want to simplify
+ * the navigation in the {@link Node} hierarchy, you can turn this
+ * property on.
+ *
+ * @param show true to show the "..", false to not to do so
+ * @since 6.28
+ */
+ public void setShowParentNode(boolean show) {
+ showParentNode = show;
+ }
+
/** Get the current processor for default actions.
* If not null
, double-clicks or pressing Enter on
* items in the view will not perform the default action on the selected node; rather the processor
@@ -557,6 +581,11 @@
// Working methods
//
+ final void setNode(Node n) {
+ boolean show = showParentNode && n != manager.getRootContext();
+ model.setNode(n, show);
+ }
+
/* Initilizes the view.
*/
@Override
@@ -577,7 +606,7 @@
manager.addVetoableChangeListener(wlvc = WeakListeners.vetoableChange(managerListener, manager));
manager.addPropertyChangeListener(wlpc = WeakListeners.propertyChange(managerListener, manager));
- model.setNode(manager.getExploredContext());
+ setNode(manager.getExploredContext());
updateSelection();
} else {
@@ -595,7 +624,7 @@
// bugfix #23974, model doesn't reflect an explorer context change
// because any listener was not active
- model.setNode(manager.getExploredContext());
+ setNode(manager.getExploredContext());
list.addMouseListener(popupSupport);
}
}
@@ -662,6 +691,15 @@
return;
}
+ if (showParentNode && NodeListModel.findVisualizerDepth(model, v) == -1) {
+ try {
+ manager.setExploredContextAndSelection(node.getParentNode(), new Node[] { node });
+ } catch (PropertyVetoException ex) {
+ // OK, let it be
+ }
+ return;
+ }
+
// on double click - invoke default action, if there is any
// (unless user holds CTRL key what means that we should always dive into the context)
Action a = node.getPreferredAction();
@@ -1393,7 +1431,7 @@
}
if (ExplorerManager.PROP_EXPLORED_CONTEXT.equals(evt.getPropertyName())) {
- model.setNode(manager.getExploredContext());
+ setNode(manager.getExploredContext());
//System.out.println("Children: " + java.util.Arrays.asList (list.getValues ())); // NOI18N
return;
diff -r 067c411a9044 openide.explorer/src/org/openide/explorer/view/NodeListModel.java
--- a/openide.explorer/src/org/openide/explorer/view/NodeListModel.java Sat Apr 17 09:10:37 2010 +0200
+++ b/openide.explorer/src/org/openide/explorer/view/NodeListModel.java Sat Apr 17 21:38:39 2010 +0200
@@ -66,6 +66,9 @@
/** parent node */
private transient VisualizerNode parent;
+ /** should parent node be visible? */
+ private transient boolean showParent;
+
/** originally selected item */
private transient Object selectedObject;
@@ -100,7 +103,11 @@
/** Changes the root of the model. This is thread safe method.
* @param root the root of the model
*/
- public void setNode(final Node root) {
+ public void setNode(Node root) {
+ setNode(root, false);
+ }
+
+ final void setNode(final Node root, final boolean showRoot) {
Mutex.EVENT.readAccess(new Runnable() {
@Override
public void run() {
@@ -110,7 +117,7 @@
}
VisualizerNode v = VisualizerNode.getVisualizer(null, root);
- if (v == parent) {
+ if (v == parent && showParent == showRoot) {
// no change
return;
}
@@ -118,6 +125,7 @@
removeAll();
parent.removeNodeModel(listener());
+ showParent = showRoot;
parent = v;
selectedObject = v;
clearChildrenCount();
@@ -172,7 +180,7 @@
*/
@Override
public int getSize() {
- int s = findSize(parent, -1, depth);
+ int s = findSize(parent, showParent, -1, depth);
return s;
}
@@ -180,7 +188,7 @@
*/
@Override
public Object getElementAt(int i) {
- return findElementAt(parent, i, -1, depth);
+ return findElementAt(parent, showParent, i, -1, depth);
}
/** Finds index of given object.
@@ -223,12 +231,16 @@
* @param depth the depth to scan
* @return number of children
*/
- private int findSize(VisualizerNode vis, int index, int depth) {
+ private int findSize(VisualizerNode vis, boolean includeOwnself, int index, int depth) {
Info info = childrenCount.get(vis);
if (info != null) {
return info.childrenCount;
}
+ if (includeOwnself) {
+ index++;
+ }
+
// only my children
int tmp = 0;
@@ -247,11 +259,11 @@
// count node v
tmp++;
// now count children of node v
- tmp += findSize(v, index + tmp, depth);
+ tmp += findSize(v, false, index + tmp, depth);
}
}
- info.childrenCount = tmp;
+ info.childrenCount = includeOwnself ? tmp + 1 : tmp;
childrenCount.put(vis, info);
return tmp;
}
@@ -263,7 +275,15 @@
* @param depth the depth to scan
* @return the children
*/
- private VisualizerNode findElementAt(VisualizerNode vis, int indx, int realIndx, int depth) {
+ private VisualizerNode findElementAt(VisualizerNode vis, boolean countSelf, int indx, int realIndx, int depth) {
+ if (countSelf) {
+ if (indx == 0) {
+ return vis;
+ } else {
+ indx--;
+ }
+ }
+
if (--depth == 0) {
// last depth is handled in special way
return (VisualizerNode) vis.getChildAt(indx);
@@ -277,11 +297,11 @@
return v;
}
- int s = findSize(v, ++realIndx, depth);
+ int s = findSize(v, false, ++realIndx, depth);
if (indx < s) {
// search this child
- return findElementAt(v, indx, realIndx, depth);
+ return findElementAt(v, false, indx, realIndx, depth);
}
// go to next child
diff -r 067c411a9044 openide.explorer/src/org/openide/explorer/view/NodeRenderer.java
--- a/openide.explorer/src/org/openide/explorer/view/NodeRenderer.java Sat Apr 17 09:10:37 2010 +0200
+++ b/openide.explorer/src/org/openide/explorer/view/NodeRenderer.java Sat Apr 17 21:38:39 2010 +0200
@@ -50,6 +50,7 @@
import javax.swing.*;
import javax.swing.tree.TreeCellRenderer;
+import org.openide.util.NbBundle;
/** Default renderer for nodes. Can paint either Nodes directly or
@@ -158,8 +159,13 @@
}
String text = vis.getHtmlDisplayName();
+ if (list.getModel() instanceof NodeListModel) {
+ int depth = NodeListModel.findVisualizerDepth(list.getModel(), vis);
+ if (depth == -1) {
+ text = NbBundle.getMessage(NodeRenderer.class, "LBL_UP");
+ }
+ }
boolean isHtml = text != null;
-
if (!isHtml) {
text = vis.getDisplayName();
}
diff -r 067c411a9044 openide.explorer/test/unit/src/org/openide/explorer/view/ListViewWithUpTest.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/openide.explorer/test/unit/src/org/openide/explorer/view/ListViewWithUpTest.java Sat Apr 17 21:38:39 2010 +0200
@@ -0,0 +1,193 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 1997-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]"
+ *
+ * Contributor(s):
+ *
+ * The Original Software is NetBeans. The Initial Developer of the Original
+ * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
+ * Microsystems, Inc. All Rights Reserved.
+ *
+ * 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.
+ */
+
+package org.openide.explorer.view;
+
+import java.awt.EventQueue;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicReference;
+import javax.swing.JFrame;
+import org.netbeans.junit.NbTestCase;
+import org.openide.explorer.ExplorerManager;
+import org.openide.nodes.AbstractNode;
+import org.openide.nodes.Children;
+import org.openide.nodes.Node;
+
+/**
+ * A test that verifies few aspects of the ListView implementation.
+ *
+ * @author Petr Nejedly
+ */
+public final class ListViewWithUpTest extends NbTestCase {
+
+ private ListView view;
+ private ExplorerWindow testWindow;
+
+ public ListViewWithUpTest(String testName) {
+ super(testName);
+ }
+
+ /**
+ * Tests whether the ListView doesn't try to scroll to a changed node
+ * on a change event. See issue 88209
+ */
+ public void testNoScrollOnIconChange() throws Exception {
+ assert !EventQueue.isDispatchThread();
+
+ testWindow = new ExplorerWindow();
+ testWindow.getContentPane().add(view = new ListView());
+ view.setShowParentNode(true);
+
+ Ch20 ch = new Ch20("");
+ Node root = new AbstractNode(ch);
+ root.setName("Root");
+
+ testWindow.getExplorerManager().setRootContext(root);
+ awtRequest(new Callable() {
+ @Override
+ public Void call() {
+ testWindow.pack();
+ testWindow.setVisible(true);
+ return null;
+ }
+ });
+
+ while (!awtRequest(new Callable() {
+ @Override
+ public Boolean call() throws Exception {
+ return testWindow.isShowing();
+ }
+ })) {
+ Thread.sleep(100);
+ }
+
+ assertEquals("Just 20 items for root", 20, view.model.getSize());
+ testWindow.getExplorerManager().setExploredContext(root.getChildren().getNodeAt(10));
+ awtRequest(new Callable() {
+ @Override
+ public Void call() {
+ return null;
+ }
+ });
+ assertEquals("21 items for non-root", 21, view.model.getSize());
+ awtRequest(new Callable() {
+ @Override
+ public Void call() {
+ view.performObjectAt(0, 0);
+ return null;
+ }
+ });
+ assertEquals("Moved back to root", root, testWindow.getExplorerManager().getExploredContext());
+
+ // cleanup
+ awtRequest(new Callable() {
+ @Override
+ public Void call() {
+ testWindow.setVisible(false);
+ return null;
+ }
+ });
+ }
+
+ private static final class Ch20 extends Children.Keys {
+ private final String prefix;
+
+ public Ch20(String prefix) {
+ this.prefix = prefix;
+ }
+
+
+ @Override
+ protected void addNotify() {
+ List arr = new ArrayList();
+ for (int i = 0; i < 20; i++) {
+ arr.add(i);
+ }
+ setKeys(arr);
+ }
+
+
+ @Override
+ protected Node[] createNodes(Integer key) {
+ AbstractNode an = new AbstractNode(new Ch20(prefix + key));
+ an.setName(prefix + key);
+ return new Node[] { an };
+ }
+
+ }
+
+
+ private static final class ExplorerWindow extends JFrame
+ implements ExplorerManager.Provider {
+
+ private final ExplorerManager explManager = new ExplorerManager();
+
+ ExplorerWindow() {
+ super("ListView test"); //NOI18N
+ }
+
+ @Override
+ public ExplorerManager getExplorerManager() {
+ return explManager;
+ }
+ }
+
+ private static T awtRequest(final Callable call) throws Exception {
+ final AtomicReference value = new AtomicReference();
+ final Exception[] exc = new Exception[1];
+ EventQueue.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ value.set(call.call());
+ } catch (Exception ex) {
+ exc[0] = ex;
+ }
+ }
+ });
+
+ if (exc[0] != null) throw exc[0];
+ return value.get();
+ }
+
+}
diff -r 067c411a9044 openide.explorer/test/unit/src/org/openide/explorer/view/NodeListModelTest.java
--- a/openide.explorer/test/unit/src/org/openide/explorer/view/NodeListModelTest.java Sat Apr 17 09:10:37 2010 +0200
+++ b/openide.explorer/test/unit/src/org/openide/explorer/view/NodeListModelTest.java Sat Apr 17 21:38:39 2010 +0200
@@ -44,6 +44,7 @@
import java.lang.ref.WeakReference;
import java.util.LinkedList;
import java.util.List;
+import javax.swing.tree.TreeNode;
import org.netbeans.junit.NbTestCase;
import org.openide.nodes.AbstractNode;
import org.openide.nodes.Children;
@@ -60,6 +61,7 @@
super(name);
}
+ @Override
protected boolean runInEQ() {
return true;
}
@@ -114,6 +116,24 @@
// childrenCount
model.getSize();
}
+
+ public void testIsRootIncluded() {
+ Node c = new AbstractNode(new CNodeChildren());
+ NodeListModel model = new NodeListModel();
+ model.setNode(c, true);
+
+ assertEquals(NO_OF_NODES + 1, model.getSize());
+
+ assertNode("Parent is first", c, model.getElementAt(0));
+ for (int i= 0; i < NO_OF_NODES; i++) {
+ assertNode(i + "th node", c.getChildren().getNodeAt(i), model.getElementAt(i + 1));
+ }
+ }
+
+ private static void assertNode(String msg, Node n, Object e) {
+ TreeNode v = Visualizer.findVisualizer(n);
+ assertEquals(msg, v, e);
+ }
/*
* Children for testNodesAreReferenced.
@@ -122,12 +142,13 @@
public CNodeChildren() {
List myKeys = new LinkedList();
for (int i = 0; i < NO_OF_NODES; i++) {
- myKeys.add(new Integer(i));
+ myKeys.add(Integer.valueOf(i));
}
setKeys(myKeys);
}
+ @Override
protected Node[] createNodes(Object key) {
AbstractNode an = new AbstractNode(Children.LEAF);
an.setName(key.toString());