#33281 - Outline & OutlineView
authorS. Aubrecht <saubrecht@netbeans.org>
Thu May 29 16:43:25 2008 +0200 (3 months ago)
changeset 820765ca2a45fd6a1
parent 820700dee3fb85f16
child 8207786114892017b
#33281 - Outline & OutlineView
nbbuild/cluster.properties
o.n.swing.outline/build.xml
o.n.swing.outline/manifest.mf
o.n.swing.outline/nbproject/project.properties
o.n.swing.outline/nbproject/project.xml
o.n.swing.outline/src/org/netbeans/swing/etable/ColumnSelectionPanel.java
o.n.swing.outline/src/org/netbeans/swing/etable/ETable.java
o.n.swing.outline/src/org/netbeans/swing/etable/ETableColumn.java
o.n.swing.outline/src/org/netbeans/swing/etable/ETableColumnModel.java
o.n.swing.outline/src/org/netbeans/swing/etable/ETableTransferHandler.java
o.n.swing.outline/src/org/netbeans/swing/etable/ETableTransferable.java
o.n.swing.outline/src/org/netbeans/swing/etable/QuickFilter.java
o.n.swing.outline/src/org/netbeans/swing/etable/TableColumnSelector.java
o.n.swing.outline/src/org/netbeans/swing/etable/columns.gif
o.n.swing.outline/src/org/netbeans/swing/outline/Bundle.properties
o.n.swing.outline/src/org/netbeans/swing/outline/DefaultOutlineCellRenderer.java
o.n.swing.outline/src/org/netbeans/swing/outline/DefaultOutlineModel.java
o.n.swing.outline/src/org/netbeans/swing/outline/EventBroadcaster.java
o.n.swing.outline/src/org/netbeans/swing/outline/ExtTreeWillExpandListener.java
o.n.swing.outline/src/org/netbeans/swing/outline/Outline.java
o.n.swing.outline/src/org/netbeans/swing/outline/OutlineModel.java
o.n.swing.outline/src/org/netbeans/swing/outline/ProxyTableModel.java
o.n.swing.outline/src/org/netbeans/swing/outline/RenderDataProvider.java
o.n.swing.outline/src/org/netbeans/swing/outline/RowModel.java
o.n.swing.outline/src/org/netbeans/swing/outline/TreePathSupport.java
o.n.swing.outline/test/unit/src/org/netbeans/swing/etable/ETableColumnModelTest.java
o.n.swing.outline/test/unit/src/org/netbeans/swing/etable/ETableColumnTest.java
o.n.swing.outline/test/unit/src/org/netbeans/swing/etable/ETableTest.java
openide.explorer/apichanges.xml
openide.explorer/manifest.mf
openide.explorer/nbproject/project.xml
openide.explorer/src/org/openide/explorer/view/Bundle.properties
openide.explorer/src/org/openide/explorer/view/DropGlassPane.java
openide.explorer/src/org/openide/explorer/view/ExplorerDnDManager.java
openide.explorer/src/org/openide/explorer/view/NodePopupFactory.java
openide.explorer/src/org/openide/explorer/view/NodeRenderDataProvider.java
openide.explorer/src/org/openide/explorer/view/OutlineView.java
openide.explorer/src/org/openide/explorer/view/OutlineViewDragSupport.java
openide.explorer/src/org/openide/explorer/view/OutlineViewDropSupport.java
openide.explorer/src/org/openide/explorer/view/PropertiesRowModel.java
openide.explorer/src/org/openide/explorer/view/SheetCell.java
openide.explorer/src/org/openide/explorer/view/TableView.java
openide.explorer/src/org/openide/explorer/view/TableViewDragSupport.java
openide.explorer/src/org/openide/explorer/view/TableViewDropSupport.java
diff -r n -r b -r b -r u -r i -r l -r d -r / -r c -r l -r u -r s -r t -r e -r r -r . -r p -r r -r o -r p -r e -r r -r t -r i -r e -r s nbbuild/cluster.properties
--- a/nbbuild/cluster.properties
+++ b/nbbuild/cluster.properties
@@ -184,6 +184,7 @@ nb.cluster.platform=\
o.jdesktop.layout,\
o.n.bootstrap,\
o.n.core,\
+ o.n.swing.outline,\
o.n.swing.plaf,\
o.n.swing.tabcontrol,\
openide.actions,\
diff -r o -r p -r e -r n -r i -r d -r e -r . -r e -r x -r p -r l -r o -r r -r e -r r -r / -r a -r p -r i -r c -r h -r a -r n -r g -r e -r s -r . -r x -r m -r l openide.explorer/apichanges.xml
--- a/openide.explorer/apichanges.xml
+++ b/openide.explorer/apichanges.xml
@@ -47,6 +47,19 @@ made subject to such option by the copyr
<apidef name="explorer">Explorer API</apidef>
</apidefs>
<changes>
+ <change id="OutlineView">
+ <api name="explorer"/>
+ <summary>Added OutlineView component which is a replacement for buggy TreeTableView.</summary>
+ <version major="6" minor="15"/>
+ <date day="29" month="5" year="2008"/>
+ <author login="saubrecht"/>
+ <compatibility binary="compatible" source="compatible" deprecation="no" deletion="no" addition="yes"/>
+ <description>Added new OutlineView component which is a table with expandable
+ tree-like part and which replaces the current buggy TreeTableView.
+ </description>
+ <class package="org.openide.explorer.view" name="OutlineView"/>
+ <issue number="33281"/>
+ </change>
<change id="ColumnDisplayNameWithMnemonicTTV">
<api name="explorer"/>
<summary>Added support for property ColumnDisplayNameWithMnemonicTTV.</summary>
diff -r o -r p -r e -r n -r i -r d -r e -r . -r e -r x -r p -r l -r o -r r -r e -r r -r / -r m -r a -r n -r i -r f -r e -r s -r t -r . -r m -r f openide.explorer/manifest.mf
--- a/openide.explorer/manifest.mf
+++ b/openide.explorer/manifest.mf
@@ -1,6 +1,6 @@ Manifest-Version: 1.0
Manifest-Version: 1.0
OpenIDE-Module: org.openide.explorer
-OpenIDE-Module-Specification-Version: 6.14
+OpenIDE-Module-Specification-Version: 6.15
OpenIDE-Module-Implementation-Version: 1
OpenIDE-Module-Localizing-Bundle: org/openide/explorer/Bundle.properties
AutoUpdate-Essential-Module: true
diff -r o -r p -r e -r n -r i -r d -r e -r . -r e -r x -r p -r l -r o -r r -r e -r r -r / -r n -r b -r p -r r -r o -r j -r e -r c -r t -r / -r p -r r -r o -r j -r e -r c -r t -r . -r x -r m -r l openide.explorer/nbproject/project.xml
--- a/openide.explorer/nbproject/project.xml
+++ b/openide.explorer/nbproject/project.xml
@@ -46,6 +46,14 @@ made subject to such option by the copyr
<data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
<code-name-base>org.openide.explorer</code-name-base>
<module-dependencies>
+ <dependency>
+ <code-name-base>org.netbeans.swing.outline</code-name-base>
+ <build-prerequisite/>
+ <compile-dependency/>
+ <run-dependency>
+ <specification-version>1.0</specification-version>
+ </run-dependency>
+ </dependency>
<dependency>
<code-name-base>org.openide.awt</code-name-base>
<build-prerequisite/>
diff -r o -r p -r e -r n -r i -r d -r e -r . -r e -r x -r p -r l -r o -r r -r e -r r -r / -r s -r r -r c -r / -r o -r r -r g -r / -r o -r p -r e -r n -r i -r d -r e -r / -r e -r x -r p -r l -r o -r r -r e -r r -r / -r v -r i -r e -r w -r / -r B -r u -r n -r d -r l -r e -r . -r p -r r -r o -r p -r e -r r -r t -r i -r e -r s openide.explorer/src/org/openide/explorer/view/Bundle.properties
--- a/openide.explorer/src/org/openide/explorer/view/Bundle.properties
+++ b/openide.explorer/src/org/openide/explorer/view/Bundle.properties
@@ -105,3 +105,5 @@ ACSD_TreeTable=N/A
#Something to append to ridiculously long tooltips that can't be fully
#displayed without taking up most of the screen
MSG_ELLIPSIS=...
+
+LBL_QuickFilter=Show only rows where
\ No newline at end of file
diff -r o -r p -r e -r n -r i -r d -r e -r . -r e -r x -r p -r l -r o -r r -r e -r r -r / -r s -r r -r c -r / -r o -r r -r g -r / -r o -r p -r e -r n -r i -r d -r e -r / -r e -r x -r p -r l -r o -r r -r e -r r -r / -r v -r i -r e -r w -r / -r D -r r -r o -r p -r G -r l -r a -r s -r s -r P -r a -r n -r e -r . -r j -r a -r v -r a openide.explorer/src/org/openide/explorer/view/DropGlassPane.java
--- a/openide.explorer/src/org/openide/explorer/view/DropGlassPane.java
+++ b/openide.explorer/src/org/openide/explorer/view/DropGlassPane.java
@@ -69,7 +69,7 @@ final class DropGlassPane extends JPanel
final static private int MIN_WIDTH = 10;
final static private int MIN_HEIGTH = 3;
transient static private Component oldPane;
- transient static private JTree originalSource;
+ transient static private JComponent originalSource;
transient static private boolean wasVisible;
Line2D line = null;
@@ -97,7 +97,7 @@ final class DropGlassPane extends JPanel
* @param pane the original glass
* @param visible was glass pane visible
*/
- static void setOriginalPane(JTree source, Component pane, boolean visible) {
+ static void setOriginalPane(JComponent source, Component pane, boolean visible) {
// pending, should throw an exception that original is set already
oldPane = pane;
originalSource = source;
diff -r o -r p -r e -r n -r i -r d -r e -r . -r e -r x -r p -r l -r o -r r -r e -r r -r / -r s -r r -r c -r / -r o -r r -r g -r / -r o -r p -r e -r n -r i -r d -r e -r / -r e -r x -r p -r l -r o -r r -r e -r r -r / -r v -r i -r e -r w -r / -r E -r x -r p -r l -r o -r r -r e -r r -r D -r n -r D -r M -r a -r n -r a -r g -r e -r r -r . -r j -r a -r v -r a openide.explorer/src/org/openide/explorer/view/ExplorerDnDManager.java
--- a/openide.explorer/src/org/openide/explorer/view/ExplorerDnDManager.java
+++ b/openide.explorer/src/org/openide/explorer/view/ExplorerDnDManager.java
@@ -41,15 +41,10 @@ package org.openide.explorer.view;
package org.openide.explorer.view;
import org.openide.nodes.Node;
-import org.openide.util.WeakSet;
-import java.awt.Cursor;
import java.awt.datatransfer.Transferable;
-import java.awt.dnd.DnDConstants; // TEMP
+import java.awt.dnd.DnDConstants;
-import java.util.Iterator;
-
-import javax.swing.JScrollPane;
/**
@@ -69,7 +64,6 @@ final class ExplorerDnDManager {
private Transferable draggedTransForCopy;
private boolean isDnDActive = false;
private int nodeAllowed = 0;
- private Cursor cursor = null;
private boolean maybeExternalDnD = false;
/** Creates a new instance of <code>WindowsDnDManager</code>. */
@@ -146,12 +140,4 @@ final class ExplorerDnDManager {
void setMaybeExternalDragAndDrop( boolean maybeExternalDnD ) {
this.maybeExternalDnD = maybeExternalDnD;
}
-
- void prepareCursor(Cursor c) {
- this.cursor = c;
- }
-
- Cursor getCursor() {
- return this.cursor;
- }
}
diff -r o -r . -r n -r . -r s -r w -r i -r n -r g -r . -r o -r u -r t -r l -r i -r n -r e -r / -r b -r u -r i -r l -r d -r . -r x -r m -r l o.n.swing.outline/build.xml
--- /dev/null
+++ b/o.n.swing.outline/build.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project basedir="." default="netbeans" name="o.n.swing.outline">
+ <description>Builds, tests, and runs the project org.netbeans.swing.outline</description>
+ <import file="../nbbuild/templates/projectized.xml"/>
+</project>
diff -r o -r . -r n -r . -r s -r w -r i -r n -r g -r . -r o -r u -r t -r l -r i -r n -r e -r / -r m -r a -r n -r i -r f -r e -r s -r t -r . -r m -r f o.n.swing.outline/manifest.mf
--- /dev/null
+++ b/o.n.swing.outline/manifest.mf
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+OpenIDE-Module: org.netbeans.swing.outline
+OpenIDE-Module-Localizing-Bundle: org/netbeans/swing/outline/Bundle.properties
+OpenIDE-Module-Specification-Version: 1.0
+
diff -r o -r . -r n -r . -r s -r w -r i -r n -r g -r . -r o -r u -r t -r l -r i -r n -r e -r / -r n -r b -r p -r r -r o -r j -r e -r c -r t -r / -r p -r r -r o -r j -r e -r c -r t -r . -r p -r r -r o -r p -r e -r r -r t -r i -r e -r s o.n.swing.outline/nbproject/project.properties
--- /dev/null
+++ b/o.n.swing.outline/nbproject/project.properties
@@ -0,0 +1,2 @@
+javac.source=1.5
+javac.compilerargs=-Xlint -Xlint:-serial
diff -r o -r . -r n -r . -r s -r w -r i -r n -r g -r . -r o -r u -r t -r l -r i -r n -r e -r / -r n -r b -r p -r r -r o -r j -r e -r c -r t -r / -r p -r r -r o -r j -r e -r c -r t -r . -r x -r m -r l o.n.swing.outline/nbproject/project.xml
--- /dev/null
+++ b/o.n.swing.outline/nbproject/project.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+ <type>org.netbeans.modules.apisupport.project</type>
+ <configuration>
+ <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
+ <code-name-base>org.netbeans.swing.outline</code-name-base>
+ <module-dependencies/>
+ <public-packages>
+ <package>org.netbeans.swing.etable</package>
+ <package>org.netbeans.swing.outline</package>
+ </public-packages>
+ </data>
+ </configuration>
+</project>
diff -r o -r . -r n -r . -r s -r w -r i -r n -r g -r . -r o -r u -r t -r l -r i -r n -r e -r / -r s -r r -r c -r / -r o -r r -r g -r / -r n -r e -r t -r b -r e -r a -r n -r s -r / -r s -r w -r i -r n -r g -r / -r e -r t -r a -r b -r l -r e -r / -r C -r o -r l -r u -r m -r n -r S -r e -r l -r e -r c -r t -r i -r o -r n -r P -r a -r n -r e -r l -r . -r j -r a -r v -r a o.n.swing.outline/src/org/netbeans/swing/etable/ColumnSelectionPanel.java
--- /dev/null
+++ b/o.n.swing.outline/src/org/netbeans/swing/etable/ColumnSelectionPanel.java
@@ -0,0 +1,367 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 1997-2007 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.netbeans.swing.etable;
+
+import java.awt.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.text.Collator;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import javax.swing.JCheckBox;
+import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.table.TableColumn;
+import javax.swing.table.TableColumnModel;
+
+/**
+ * Panel containing checkboxes for selecting visible columns
+ * of a table.
+ * @author David Strupl
+ */
+class ColumnSelectionPanel extends JPanel {
+
+ /**
+ * Map: ETableColumn --> JCheckBox
+ */
+ private Map<ETableColumn,JCheckBox> checkBoxes = new HashMap<ETableColumn,JCheckBox>();
+
+ /**
+ * Model allowing to show/hide columns.
+ */
+ private ETableColumnModel columnModel;
+
+ /** Creates a new instance of ColumnSelectionPanel */
+ public ColumnSelectionPanel(ETable table) {
+ TableColumnModel colModel = table.getColumnModel();
+ setLayout(new GridBagLayout());
+ if (! (colModel instanceof ETableColumnModel)) {
+ return;
+ }
+ ETableColumnModel etcm = (ETableColumnModel)colModel;
+ this.columnModel = etcm;
+ List<TableColumn> columns = Collections.list(etcm.getColumns());
+ columns.addAll(etcm.hiddenColumns);
+ Collections.sort(columns, ETableColumnComparator.DEFAULT );
+ int width = columns.size() / 10 + 1;
+ layoutPanel(columns, width, table);
+ }
+
+ /**
+ * Adds checkbox for each ETableColumn contained in the columns parameter.
+ */
+ private void layoutPanel(List columns, int width, ETable table) {
+ Map<String, Object> displayNameToCheckBox = new HashMap<String, Object>();
+ ArrayList<String> displayNames = new ArrayList<String>();
+ for (Iterator it = columns.iterator(); it.hasNext(); ) {
+ ETableColumn etc = (ETableColumn)it.next();
+ JCheckBox checkBox = new JCheckBox();
+ checkBoxes.put(etc, checkBox);
+ String dName = table.getColumnDisplayName(etc.getHeaderValue().toString());
+ checkBox.setText(dName);
+ checkBox.setSelected(! columnModel.isColumnHidden(etc));
+ checkBox.setEnabled(etc.isHidingAllowed());
+ if (! displayNames.contains(dName)) {
+ // the expected case
+ displayNameToCheckBox.put(dName, checkBox);
+ } else {
+ // the same display name is used for more columns - fuj
+ ArrayList<JCheckBox> al = null;
+ Object theFirstOne = displayNameToCheckBox.get(dName);
+ if (theFirstOne instanceof JCheckBox) {
+ JCheckBox firstCheckBox = (JCheckBox)theFirstOne;
+ al = new ArrayList<JCheckBox>();
+ al.add(firstCheckBox);
+ } else {
+ // already a list there
+ if (theFirstOne instanceof ArrayList) {
+ al = (ArrayList<JCheckBox>)theFirstOne;
+ } else {
+ throw new IllegalStateException("Wrong object theFirstOne is " + theFirstOne);
+ }
+ }
+ al.add(checkBox);
+ displayNameToCheckBox.put(dName, al);
+ }
+ displayNames.add(dName);
+ }
+ Collections.sort(displayNames, Collator.getInstance());
+ int i = 0;
+ int j = 0;
+ int index = 0;
+ int rows = columns.size() / width;
+ for (Iterator<String> it = displayNames.iterator(); it.hasNext(); i++) {
+ if (i >= rows) {
+ i = 0;
+ j++;
+ }
+ String displayName = it.next();
+ Object obj = displayNameToCheckBox.get(displayName);
+ JCheckBox checkBox = null;
+ if (obj instanceof JCheckBox) {
+ checkBox = (JCheckBox)obj;
+ } else {
+ // in case there are duplicate names we store ArrayLists
+ // of JCheckBoxes
+ if (obj instanceof ArrayList) {
+ ArrayList<JCheckBox> al = (ArrayList<JCheckBox>)obj;
+ if (index >= al.size()) {
+ index = 0;
+ }
+ checkBox = al.get(index++);
+ } else {
+ throw new IllegalStateException("Wrong object obj is " + obj);
+ }
+ }
+ GridBagConstraints gridBagConstraints = new GridBagConstraints();
+ gridBagConstraints.gridx = j;
+ gridBagConstraints.gridy = i;
+ gridBagConstraints.insets = new java.awt.Insets(5, 12, 0, 12);
+ gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
+ gridBagConstraints.weightx = 1;
+ add(checkBox, gridBagConstraints);
+ }
+ }
+
+ /**
+ * After the user clicks Ok this method will hide/un-hide the
+ * columns according to the selected checkboxes.
+ */
+ public void changeColumnVisibility() {
+ if (columnModel == null) {
+ return;
+ }
+ for (Iterator it = checkBoxes.keySet().iterator(); it.hasNext(); ) {
+ ETableColumn etc = (ETableColumn) it.next();
+ JCheckBox checkBox = (JCheckBox)checkBoxes.get(etc);
+ columnModel.setColumnHidden(etc,! checkBox.isSelected());
+ }
+ }
+
+ /**
+ * Shows the popup allowing to show/hide columns.
+ */
+ static void showColumnSelectionPopup(Component c, final ETable table) {
+ if (! table.isPopupUsedFromTheCorner()) {
+ showColumnSelectionDialog(table);
+ return;
+ }
+ JPopupMenu popup = new JPopupMenu();
+ TableColumnModel columnModel = table.getColumnModel();
+ if (! (columnModel instanceof ETableColumnModel)) {
+ return;
+ }
+ final ETableColumnModel etcm = (ETableColumnModel)columnModel;
+ List<TableColumn> columns = Collections.list(etcm.getColumns());
+ columns.addAll(etcm.hiddenColumns);
+ Collections.sort(columns, ETableColumnComparator.DEFAULT);
+ Map<String,Object> displayNameToCheckBox = new HashMap<String,Object>();
+ ArrayList<String> displayNames = new ArrayList<String>();
+ for (Iterator<TableColumn> it = columns.iterator(); it.hasNext(); ) {
+ final ETableColumn etc = (ETableColumn)it.next();
+ final JCheckBoxMenuItem checkBox = new JCheckBoxMenuItem();
+ String dName = table.getColumnDisplayName(etc.getHeaderValue().toString());
+ checkBox.setText(dName);
+ checkBox.setSelected(! etcm.isColumnHidden(etc));
+ checkBox.setEnabled(etc.isHidingAllowed());
+ checkBox.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent evt) {
+ etcm.setColumnHidden(etc,! checkBox.isSelected());
+ table.updateColumnSelectionMouseListener();
+ }
+ });
+ if (! displayNames.contains(dName)) {
+ // the expected case
+ displayNameToCheckBox.put(dName, checkBox);
+ } else {
+ // the same display name is used for more columns - fuj
+ ArrayList<JCheckBoxMenuItem> al = null;
+ Object theFirstOne = displayNameToCheckBox.get(dName);
+ if (theFirstOne instanceof JCheckBoxMenuItem) {
+ JCheckBoxMenuItem firstCheckBox = (JCheckBoxMenuItem)theFirstOne;
+ al = new ArrayList<JCheckBoxMenuItem>();
+ al.add(firstCheckBox);
+ } else {
+ // already a list there
+ if (theFirstOne instanceof ArrayList) {
+ al = (ArrayList<JCheckBoxMenuItem>)theFirstOne;
+ } else {
+ throw new IllegalStateException("Wrong object theFirstOne is " + theFirstOne);
+ }
+ }
+ al.add(checkBox);
+ displayNameToCheckBox.put(dName, al);
+ }
+ displayNames.add(dName);
+ }
+ Collections.sort(displayNames, Collator.getInstance());
+ int index = 0;
+ for (Iterator<String> it = displayNames.iterator(); it.hasNext(); ) {
+ String displayName = it.next();
+ Object obj = displayNameToCheckBox.get(displayName);
+ JCheckBoxMenuItem checkBox = null;
+ if (obj instanceof JCheckBoxMenuItem) {
+ checkBox = (JCheckBoxMenuItem)obj;
+ } else {
+ // in case there are duplicate names we store ArrayLists
+ // of JCheckBoxes
+ if (obj instanceof ArrayList) {
+ ArrayList<JCheckBoxMenuItem> al = (ArrayList<JCheckBoxMenuItem>)obj;
+ if (index >= al.size()) {
+ index = 0;
+ }
+ checkBox = al.get(index++);
+ } else {
+ throw new IllegalStateException("Wrong object obj is " + obj);
+ }
+ }
+ popup.add(checkBox);
+ }
+ popup.show(c, 8, 8);
+ }
+
+ /**
+ * Shows dialog allowing to show/hide columns.
+ */
+ static void showColumnSelectionDialog(ETable table) {
+ TableColumnSelector tcs = table.getColumnSelector();
+ if (tcs != null) {
+ ETableColumnModel etcm = (ETableColumnModel)table.getColumnModel();
+ TableColumnSelector.TreeNode root = etcm.getColumnHierarchyRoot();
+ if (root != null) {
+ String[] origVisible = getAvailableColumnNames(table, true);
+ String[] visibleColumns = tcs.selectVisibleColumns(root, origVisible);
+ makeVisibleColumns(table, visibleColumns);
+ } else {
+ String[] availableColumns = getAvailableColumnNames(table, false);
+ String[] origVisible = getAvailableColumnNames(table, true);
+ String[] visibleColumns = tcs.selectVisibleColumns(availableColumns, origVisible);
+ makeVisibleColumns(table, visibleColumns);
+ }
+ return;
+ }
+ // The default behaviour:
+ ColumnSelectionPanel panel = new ColumnSelectionPanel(table);
+ int res = JOptionPane.showConfirmDialog(null, panel, table.selectVisibleColumnsLabel, JOptionPane.OK_CANCEL_OPTION);
+ if (res == JOptionPane.OK_OPTION) {
+ panel.changeColumnVisibility();
+ table.updateColumnSelectionMouseListener();
+ }
+ }
+
+ /**
+ * This method is called after the user made a selection. Applies the
+ * changes to the visible column for the given table.
+ */
+ private static void makeVisibleColumns(ETable table, String[] visibleColumns) {
+ HashSet<String> visible = new HashSet<String>(Arrays.asList(visibleColumns));
+ TableColumnModel columnModel = table.getColumnModel();
+ if (! (columnModel instanceof ETableColumnModel)) {
+ return;
+ }
+ final ETableColumnModel etcm = (ETableColumnModel)columnModel;
+ List<TableColumn> columns = Collections.list(etcm.getColumns());
+ columns.addAll(etcm.hiddenColumns);
+ Collections.sort(columns, ETableColumnComparator.DEFAULT);
+ Map<String, ETableColumn> nameToColumn = new HashMap<String, ETableColumn>();
+ for (Iterator<TableColumn> it = columns.iterator(); it.hasNext(); ) {
+ final ETableColumn etc = (ETableColumn)it.next();
+ String dName = table.getColumnDisplayName(etc.getHeaderValue().toString());
+ etcm.setColumnHidden(etc, !visible.contains(dName));
+ nameToColumn.put(dName, etc);
+ }
+ for (int i = 0; i < visibleColumns.length; i++) {
+ ETableColumn etc = nameToColumn.get(visibleColumns[i]);
+ if (etc == null) {
+ throw new IllegalStateException("Cannot find column with name " + visibleColumns[i]);
+ }
+ int currentIndex = etcm.getColumnIndex(etc.getIdentifier());
+ etcm.moveColumn(currentIndex, i);
+ }
+ }
+
+ /**
+ * Computes the strings shown to the user in the selection dialog.
+ */
+ private static String[] getAvailableColumnNames(ETable table, boolean visibleOnly) {
+ TableColumnModel columnModel = table.getColumnModel();
+ if (! (columnModel instanceof ETableColumnModel)) {
+ return new String[0];
+ }
+ final ETableColumnModel etcm = (ETableColumnModel)columnModel;
+ List<TableColumn> columns = Collections.list(etcm.getColumns());
+ if (!visibleOnly) {
+ columns.addAll(etcm.hiddenColumns);
+ }
+ Collections.sort(columns, ETableColumnComparator.DEFAULT);
+ ArrayList<String> displayNames = new ArrayList<String>();
+ for (Iterator<TableColumn> it = columns.iterator(); it.hasNext(); ) {
+ final ETableColumn etc = (ETableColumn)it.next();
+ String dName = table.getColumnDisplayName(etc.getHeaderValue().toString());
+ displayNames.add(dName);
+ }
+ Collections.sort(displayNames, Collator.getInstance());
+ return displayNames.toArray(new String[displayNames.size()]);
+ }
+
+ private static class ETableColumnComparator implements Comparator<TableColumn> {
+ public static final ETableColumnComparator DEFAULT = new ETableColumnComparator();
+
+ public int compare(TableColumn o1, TableColumn o2) {
+ if( o1 instanceof ETableColumn && o2 instanceof ETableColumn ) {
+ ((ETableColumn)o1).compareTo((ETableColumn)o2);
+ }
+ return 0;
+ }
+
+ }
+}
diff -r o -r . -r n -r . -r s -r w -r i -r n -r g -r . -r o -r u -r t -r l -r i -r n -r e -r / -r s -r r -r c -r / -r o -r r -r g -r / -r n -r e -r t -r b -r e -r a -r n -r s -r / -r s -r w -r i -r n -r g -r / -r e -r t -r a -r b -r l -r e -r / -r E -r T -r a -r b -r l -r e -r . -r j -r a -r v -r a o.n.swing.outline/src/org/netbeans/swing/etable/ETable.java
--- /dev/null
+++ b/o.n.swing.outline/src/org/netbeans/swing/etable/ETable.java
@@ -0,0 +1,2390 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 1997-2007 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.netbeans.swing.etable;
+
+import java.awt.AWTKeyStroke;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.ContainerOrderFocusTraversalPolicy;
+import java.awt.Event;
+import java.awt.EventQueue;
+import java.awt.KeyboardFocusManager;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.InputEvent;
+import java.awt.event.ItemListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Enumeration;
+import java.util.EventObject;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.Vector;
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.ActionMap;
+import javax.swing.BorderFactory;
+import javax.swing.BoxLayout;
+import javax.swing.ComboBoxModel;
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+import javax.swing.InputMap;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+import javax.swing.JPanel;
+import javax.swing.JRootPane;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.JTextField;
+import javax.swing.JViewport;
+import javax.swing.KeyStroke;
+import javax.swing.ListSelectionModel;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.border.Border;
+import javax.swing.border.CompoundBorder;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.event.TableModelEvent;
+import javax.swing.table.*;
+import javax.swing.table.TableCellRenderer;
+
+/**
+ * <UL>Extended JTable (ETable) adds these features to JTable:
+ * <LI> The notion of fully editable (non-editable) table. </LI>
+ * <LI> <strong>Sorting</strong> the rows of the table by clicking the header.
+ * Shift-Click allows to use more columns for the sort. The sort is
+ * based on the values implementing Comparable interface. </LI>
+ * <LI> Automatic <strong>column width</strong> after init or after
+ * the model is changed (or triggered by "Ctrl-+" shortcut).
+ * Automatic resize the column after double-click
+ * in the header column divider araa. </LI>
+ * <LI> <strong>Persistence</strong> of the user customized settings via
+ * methods readSettings and writeSettings.
+ * <LI> <strong>Quick-Filter</strong> features allowing to show only
+ * certain rows from the model (see setQuickFilter()). </LI>
+ * <LI>
+ * </UL>
+ * @author David Strupl
+ */
+public class ETable extends JTable {
+
+ /** Action key for up/down focus action */
+ private static final String ACTION_FOCUS_NEXT = "focusNext"; //NOI18N
+
+ /** Possible value for editing property */
+ private final static int FULLY_EDITABLE = 1;
+ /** Possible value for editing property */
+ private final static int FULLY_NONEDITABLE = 2;
+ /** Possible value for editing property */
+ private final static int DEFAULT = 3;
+
+ /** Key for storing the currently searched column's index. */
+ private static final String SEARCH_COLUMN = "SearchColumn";
+
+ // icon of column button
+ private static final String DEFAULT_COLUMNS_ICON = "columns.gif"; // NOI18N
+
+ /**
+ * Property allowing to make the table FULLY_NONEDITABLE and
+ * FULLY_EDITABLE.
+ */
+ private int editing = DEFAULT;
+
+ /**
+ * Array with size exactly sama as the number of rows in the data model
+ * or null. If it is not null the row originally at index i will be
+ * displayed on index sortingPermutation[i].
+ */
+ protected transient int [] sortingPermutation;
+
+ /** Inverse of the above */
+ protected transient int [] inverseSortingPermutation;
+
+ /**
+ *
+ */
+ private transient int filteredRowCount;
+
+ /**
+ *
+ */
+ private Object quickFilterObject;
+
+ /**
+ *
+ */
+ private int quickFilterColumn = -1;
+
+ // Search text field related variables:
+ /** */
+ private String maxPrefix;
+ /** */
+ int SEARCH_FIELD_PREFERRED_SIZE = 160;
+ /** */
+ int SEARCH_FIELD_SPACE = 3;
+ /** */
+ final private JTextField searchTextField = new SearchTextField();
+ /** */
+ final private int heightOfTextField = searchTextField.getPreferredSize().height;
+
+ /** */
+ private JPanel searchPanel = null;
+
+ /** */
+ private JComboBox searchCombo = null;
+
+ /** */
+ private ETableColumn searchColumn = null;
+
+ /**
+ * This text can be customized using setSelectVisibleColumnsLabel(...) method.
+ */
+ String selectVisibleColumnsLabel = "Select Visible Columns";
+
+ private boolean inEditRequest = false;
+ private boolean inEditorChangeRequest=false;
+ private boolean inRemoveRequest=false;
+
+ private static String COMPUTING_TOOLTIP = "ComputingTooltip";
+
+ /**
+ * Default formatting strings for the Quick Filter feature.
+ * Can be customized by setQuickFilterFormatStrings(...) method.
+ */
+ private String[] quickFilterFormatStrings = new String [] {
+ "{0} == {1}", "{0} <> {1}", "{0} > {1}",
+ "{0} < {1}", "{0} >= {1}", "{0} <= {1}",
+ "No Filter"
+ };
+
+ /**
+ * Listener reacting to the user clicks on the header.
+ */
+ private MouseListener headerMouseListener = new HeaderMouseListener();
+
+ /**
+ * Listener reacting to the user clicks on the table invoking the
+ * column selection dialog.
+ */
+ private MouseListener columnSelectionMouseListener = new ColumnSelectionMouseListener();
+
+ /**
+ * Allows to supply alternative implementation of the column
+ * selection functionality in ETable.
+ */
+ private TableColumnSelector columnSelector;
+
+ /**
+ * Allows to supply alternative implementation of the column
+ * selection functionality globally for all instances.
+ */
+ private static TableColumnSelector defaultColumnSelector;
+
+ /**
+ * The column selection corner can use either dialog or popup menu.
+ */
+ private boolean popupUsedFromTheCorner;
+
+ /**
+ * Constructs a default <code>JTable</code> that is initialized with a default
+ * data model, a default column model, and a default selection
+ * model.
+ *
+ * @see #createDefaultDataModel
+ * @see #createDefaultColumnModel
+ * @see #createDefaultSelectionModel
+ */
+ public ETable() {
+ updateMouseListener();
+ }
+
+ /**
+ * Constructs a <code>JTable</code> that is initialized with
+ * <code>dm</code> as the data model, a default column model,
+ * and a default selection model.
+ *
+ * @param dm the data model for the table
+ * @see #createDefaultColumnModel
+ * @see #createDefaultSelectionModel
+ */
+ public ETable(TableModel dm) {
+ super(dm);
+ updateMouseListener();
+ }
+
+ /**
+ * Constructs a <code>JTable</code> that is initialized with
+ * <code>dm</code> as the data model, <code>cm</code>
+ * as the column model, and a default selection model.
+ *
+ * @param dm the data model for the table
+ * @param cm the column model for the table
+ * @see #createDefaultSelectionModel
+ */
+ public ETable(TableModel dm, TableColumnModel cm) {
+ super(dm, cm);
+ updateMouseListener();
+ }
+
+ /**
+ * Constructs a <code>JTable</code> that is initialized with
+ * <code>dm</code> as the data model, <code>cm</code> as the
+ * column model, and <code>sm</code> as the selection model.
+ * If any of the parameters are <code>null</code> this method
+ * will initialize the table with the corresponding default model.
+ * The <code>autoCreateColumnsFromModel</code> flag is set to false
+ * if <code>cm</code> is non-null, otherwise it is set to true
+ * and the column model is populated with suitable
+ * <code>TableColumns</code> for the columns in <code>dm</code>.
+ *
+ * @param dm the data model for the table
+ * @param cm the column model for the table
+ * @param sm the row selection model for the table
+ * @see #createDefaultDataModel
+ * @see #createDefaultColumnModel
+ * @see #createDefaultSelectionModel
+ */
+ public ETable(TableModel dm, TableColumnModel cm, ListSelectionModel sm) {
+ super(dm, cm, sm);
+ updateMouseListener();
+ }
+
+ /**
+ * Constructs a <code>JTable</code> with <code>numRows</code>
+ * and <code>numColumns</code> of empty cells using
+ * <code>DefaultTableModel</code>. The columns will have
+ * names of the form "A", "B", "C", etc.
+ *
+ * @param numRows the number of rows the table holds
+ * @param numColumns the number of columns the table holds
+ * @see javax.swing.table.DefaultTableModel
+ */
+ public ETable(int numRows, int numColumns) {
+ super(numRows, numColumns);
+ updateMouseListener();
+ }
+
+ /**
+ * Constructs a <code>JTable</code> to display the values in the
+ * <code>Vector</code> of <code>Vectors</code>, <code>rowData</code>,
+ * with column names, <code>columnNames</code>. The
+ * <code>Vectors</code> contained in <code>rowData</code>
+ * should contain the values for that row. In other words,
+ * the value of the cell at row 1, column 5 can be obtained
+ * with the following code:
+ * <p>
+ * <pre>((Vector)rowData.elementAt(1)).elementAt(5);</pre>
+ * <p>
+ * @param rowData the data for the new table
+ * @param columnNames names of each column
+ */
+ public ETable(Vector rowData, Vector columnNames) {
+ super(rowData, columnNames);
+ updateMouseListener();
+ }
+
+ /**
+ * Constructs a <code>JTable</code> to display the values in the two dimensional array,
+ * <code>rowData</code>, with column names, <code>columnNames</code>.
+ * <code>rowData</code> is an array of rows, so the value of the cell at row 1,
+ * column 5 can be obtained with the following code:
+ * <p>
+ * <pre> rowData[1][5]; </pre>
+ * <p>
+ * All rows must be of the same length as <code>columnNames</code>.
+ * <p>
+ * @param rowData the data for the new table
+ * @param columnNames names of each column
+ */
+ public ETable(final Object[][] rowData, final Object[] columnNames) {
+ super(rowData, columnNames);
+ updateMouseListener();
+ }
+
+ /**
+ * Returns true if the cell at <code>row</code> and <code>column</code>
+ * is editable. Otherwise, invoking <code>setValueAt</code> on the cell
+ * will have no effect.
+ * <p>
+ * Returns true always if the <code>ETable</code> is fully editable.
+ * <p>
+ * Returns false always if the <code>ETable</code> is fully non-editable.
+ *
+ * @param row the row whose value is to be queried
+ * @param column the column whose value is to be queried
+ * @return true if the cell is editable
+ * @see #setValueAt
+ * @see #setFullyEditable
+ * @see #setFullyNonEditable
+ */
+ @Override
+ public boolean isCellEditable(int row, int column) {
+ if(editing == FULLY_EDITABLE) {
+ return true;
+ }
+ if(editing == FULLY_NONEDITABLE) {
+ return false;
+ }
+ int modelRow = convertRowIndexToModel(row);
+ return super.isCellEditable(modelRow, column);
+ }
+
+ /**
+ * Overriden to call convertRowIndexToModel(...).
+ * @see javax.swing.JTable#getCellRenderer(int, int)
+ */
+ @Override
+ public TableCellRenderer getCellRenderer(int row, int column) {
+ int modelRow = convertRowIndexToModel(row);
+ return super.getCellRenderer(modelRow, column);
+ }
+
+ /**
+ * Overriden to call convertRowIndexToModel(...).
+ * @see javax.swing.JTable#getCellEditor(int, int)
+ */
+ @Override
+ public TableCellEditor getCellEditor(int row, int column) {
+ int modelRow = convertRowIndexToModel(row);
+ return super.getCellEditor(modelRow, column);
+ }
+
+ /**