--- old/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/treetable/JTreeTable.java 2009-08-01 04:07:04.428081560 +0100
+++ new/hotspot/agent/src/share/classes/sun/jvm/hotspot/ui/treetable/JTreeTable.java 2009-08-01 04:07:04.337323573 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright 2001 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -19,7 +19,7 @@
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
- *
+ *
*/
package sun.jvm.hotspot.ui.treetable;
@@ -37,9 +37,9 @@
import java.util.EventObject;
/**
- * This example shows how to create a simple JTreeTable component,
- * by using a JTree as a renderer (and editor) for the cells in a
- * particular column in the JTable.
+ * This example shows how to create a simple JTreeTable component,
+ * by using a JTree as a renderer (and editor) for the cells in a
+ * particular column in the JTable.
*
* @version 1.2 10/27/98
*
@@ -72,7 +72,7 @@
public void setShowsIcons(boolean show) {
showsIcons = show;
}
-
+
public void setRootVisible(boolean visible) {
tree.setRootVisible(visible);
}
@@ -86,36 +86,36 @@
}
public JTreeTable(TreeTableModel treeTableModel) {
- super();
+ super();
- // Create the tree. It will be used as a renderer and editor.
- tree = new TreeTableCellRenderer(treeTableModel);
+ // Create the tree. It will be used as a renderer and editor.
+ tree = new TreeTableCellRenderer(treeTableModel);
- // Install a tableModel representing the visible rows in the tree.
- super.setModel(new TreeTableModelAdapter(treeTableModel, tree));
+ // Install a tableModel representing the visible rows in the tree.
+ super.setModel(new TreeTableModelAdapter(treeTableModel, tree));
- // Force the JTable and JTree to share their row selection models.
- ListToTreeSelectionModelWrapper selectionWrapper = new
- ListToTreeSelectionModelWrapper();
- tree.setSelectionModel(selectionWrapper);
- setSelectionModel(selectionWrapper.getListSelectionModel());
+ // Force the JTable and JTree to share their row selection models.
+ ListToTreeSelectionModelWrapper selectionWrapper = new
+ ListToTreeSelectionModelWrapper();
+ tree.setSelectionModel(selectionWrapper);
+ setSelectionModel(selectionWrapper.getListSelectionModel());
- // Install the tree editor renderer and editor.
- setDefaultRenderer(TreeTableModel.class, tree);
+ // Install the tree editor renderer and editor.
+ setDefaultRenderer(TreeTableModel.class, tree);
setDefaultEditor(TreeTableModel.class, new TreeTableCellEditor());
- // No grid.
- setShowGrid(false);
+ // No grid.
+ setShowGrid(false);
- // No intercell spacing
- setIntercellSpacing(new Dimension(0, 0));
+ // No intercell spacing
+ setIntercellSpacing(new Dimension(0, 0));
- // And update the height of the trees row to match that of
- // the table.
- if (tree.getRowHeight() < 1) {
- // Metal looks better like this.
- setRowHeight(20);
- }
+ // And update the height of the trees row to match that of
+ // the table.
+ if (tree.getRowHeight() < 1) {
+ // Metal looks better like this.
+ setRowHeight(20);
+ }
}
/**
@@ -124,30 +124,30 @@
* never receive this unless we forward it in this manner.
*/
public void updateUI() {
- super.updateUI();
- if(tree != null) {
- tree.updateUI();
- // Do this so that the editor is referencing the current renderer
- // from the tree. The renderer can potentially change each time
- // laf changes.
- setDefaultEditor(TreeTableModel.class, new TreeTableCellEditor());
- }
- // Use the tree's default foreground and background colors in the
- // table.
+ super.updateUI();
+ if(tree != null) {
+ tree.updateUI();
+ // Do this so that the editor is referencing the current renderer
+ // from the tree. The renderer can potentially change each time
+ // laf changes.
+ setDefaultEditor(TreeTableModel.class, new TreeTableCellEditor());
+ }
+ // Use the tree's default foreground and background colors in the
+ // table.
LookAndFeel.installColorsAndFont(this, "Tree.background",
"Tree.foreground", "Tree.font");
}
/**
- * Workaround for BasicTableUI anomaly. Make sure the UI never tries to
- * resize the editor. The UI currently uses different techniques to
- * paint the renderers and editors and overriding setBounds() below
- * is not the right thing to do for an editor. Returning -1 for the
- * editing row in this case, ensures the editor is never painted.
+ * Workaround for BasicTableUI anomaly. Make sure the UI never tries to
+ * resize the editor. The UI currently uses different techniques to
+ * paint the renderers and editors and overriding setBounds() below
+ * is not the right thing to do for an editor. Returning -1 for the
+ * editing row in this case, ensures the editor is never painted.
*/
public int getEditingRow() {
return (getColumnClass(editingColumn) == TreeTableModel.class) ? -1 :
- editingRow;
+ editingRow;
}
/**
@@ -155,7 +155,7 @@
* will always return -1.
*/
private int realEditingRow() {
- return editingRow;
+ return editingRow;
}
/**
@@ -165,33 +165,33 @@
* think the table is being edited, as getEditingRow
returns
* -1, and therefore doesn't automaticly resize the editor for us.
*/
- public void sizeColumnsToFit(int resizingColumn) {
- super.sizeColumnsToFit(resizingColumn);
- if (getEditingColumn() != -1 && getColumnClass(editingColumn) ==
- TreeTableModel.class) {
- Rectangle cellRect = getCellRect(realEditingRow(),
- getEditingColumn(), false);
+ public void sizeColumnsToFit(int resizingColumn) {
+ super.sizeColumnsToFit(resizingColumn);
+ if (getEditingColumn() != -1 && getColumnClass(editingColumn) ==
+ TreeTableModel.class) {
+ Rectangle cellRect = getCellRect(realEditingRow(),
+ getEditingColumn(), false);
Component component = getEditorComponent();
- component.setBounds(cellRect);
+ component.setBounds(cellRect);
component.validate();
- }
+ }
}
/**
* Overridden to pass the new rowHeight to the tree.
*/
- public void setRowHeight(int rowHeight) {
- super.setRowHeight(rowHeight);
- if (tree != null && tree.getRowHeight() != rowHeight) {
- tree.setRowHeight(getRowHeight());
- }
+ public void setRowHeight(int rowHeight) {
+ super.setRowHeight(rowHeight);
+ if (tree != null && tree.getRowHeight() != rowHeight) {
+ tree.setRowHeight(getRowHeight());
+ }
}
/**
* Returns the tree that is being shared between the model.
*/
public JTree getTree() {
- return tree;
+ return tree;
}
/**
@@ -201,11 +201,11 @@
* the tree in the background, and then draw the editor over it.
*/
public boolean editCellAt(int row, int column, EventObject e){
- boolean retValue = super.editCellAt(row, column, e);
- if (retValue && getColumnClass(column) == TreeTableModel.class) {
- repaint(getCellRect(row, column, false));
- }
- return retValue;
+ boolean retValue = super.editCellAt(row, column, e);
+ if (retValue && getColumnClass(column) == TreeTableModel.class) {
+ repaint(getCellRect(row, column, false));
+ }
+ return retValue;
}
/** A DefaultTreeCellRenderer which can optionally skip drawing
@@ -223,128 +223,128 @@
* A TreeCellRenderer that displays a JTree.
*/
public class TreeTableCellRenderer extends JTree implements
- TableCellRenderer {
- /** Last table/tree row asked to renderer. */
- protected int visibleRow;
- /** Border to draw around the tree, if this is non-null, it will
- * be painted. */
- protected Border highlightBorder;
+ TableCellRenderer {
+ /** Last table/tree row asked to renderer. */
+ protected int visibleRow;
+ /** Border to draw around the tree, if this is non-null, it will
+ * be painted. */
+ protected Border highlightBorder;
- public TreeTableCellRenderer(TreeModel model) {
- super(model);
+ public TreeTableCellRenderer(TreeModel model) {
+ super(model);
setCellRenderer(new JTreeTableCellRenderer());
- }
+ }
- /**
- * updateUI is overridden to set the colors of the Tree's renderer
- * to match that of the table.
- */
- public void updateUI() {
- super.updateUI();
- // Make the tree's cell renderer use the table's cell selection
- // colors.
- TreeCellRenderer tcr = getCellRenderer();
- if (tcr instanceof DefaultTreeCellRenderer) {
- DefaultTreeCellRenderer dtcr = ((DefaultTreeCellRenderer)tcr);
- // For 1.1 uncomment this, 1.2 has a bug that will cause an
- // exception to be thrown if the border selection color is
- // null.
- // dtcr.setBorderSelectionColor(null);
- dtcr.setTextSelectionColor(UIManager.getColor
- ("Table.selectionForeground"));
- dtcr.setBackgroundSelectionColor(UIManager.getColor
- ("Table.selectionBackground"));
- }
- }
-
- /**
- * Sets the row height of the tree, and forwards the row height to
- * the table.
- */
- public void setRowHeight(int rowHeight) {
- if (rowHeight > 0) {
- super.setRowHeight(rowHeight);
- if (JTreeTable.this != null &&
- JTreeTable.this.getRowHeight() != rowHeight) {
- JTreeTable.this.setRowHeight(getRowHeight());
- }
- }
- }
-
- /**
- * This is overridden to set the height to match that of the JTable.
- */
- public void setBounds(int x, int y, int w, int h) {
- super.setBounds(x, 0, w, JTreeTable.this.getHeight());
- }
-
- /**
- * Sublcassed to translate the graphics such that the last visible
- * row will be drawn at 0,0.
- */
- public void paint(Graphics g) {
- g.translate(0, -visibleRow * getRowHeight());
- super.paint(g);
- // Draw the Table border if we have focus.
- if (highlightBorder != null) {
- highlightBorder.paintBorder(this, g, 0, visibleRow *
- getRowHeight(), getWidth(),
- getRowHeight());
- }
- }
-
- /**
- * TreeCellRenderer method. Overridden to update the visible row.
- */
- public Component getTableCellRendererComponent(JTable table,
- Object value,
- boolean isSelected,
- boolean hasFocus,
- int row, int column) {
- Color background;
- Color foreground;
-
- if(isSelected) {
- background = table.getSelectionBackground();
- foreground = table.getSelectionForeground();
- }
- else {
- background = table.getBackground();
- foreground = table.getForeground();
- }
- highlightBorder = null;
- if (realEditingRow() == row && getEditingColumn() == column) {
- background = UIManager.getColor("Table.focusCellBackground");
- foreground = UIManager.getColor("Table.focusCellForeground");
- }
- else if (hasFocus) {
- highlightBorder = UIManager.getBorder
- ("Table.focusCellHighlightBorder");
- if (isCellEditable(row, column)) {
- background = UIManager.getColor
- ("Table.focusCellBackground");
- foreground = UIManager.getColor
- ("Table.focusCellForeground");
- }
- }
-
- visibleRow = row;
- setBackground(background);
-
- TreeCellRenderer tcr = getCellRenderer();
- if (tcr instanceof DefaultTreeCellRenderer) {
- DefaultTreeCellRenderer dtcr = ((DefaultTreeCellRenderer)tcr);
- if (isSelected) {
- dtcr.setTextSelectionColor(foreground);
- dtcr.setBackgroundSelectionColor(background);
- }
- else {
- dtcr.setTextNonSelectionColor(foreground);
- dtcr.setBackgroundNonSelectionColor(background);
- }
- }
- return this;
- }
+ /**
+ * updateUI is overridden to set the colors of the Tree's renderer
+ * to match that of the table.
+ */
+ public void updateUI() {
+ super.updateUI();
+ // Make the tree's cell renderer use the table's cell selection
+ // colors.
+ TreeCellRenderer tcr = getCellRenderer();
+ if (tcr instanceof DefaultTreeCellRenderer) {
+ DefaultTreeCellRenderer dtcr = ((DefaultTreeCellRenderer)tcr);
+ // For 1.1 uncomment this, 1.2 has a bug that will cause an
+ // exception to be thrown if the border selection color is
+ // null.
+ // dtcr.setBorderSelectionColor(null);
+ dtcr.setTextSelectionColor(UIManager.getColor
+ ("Table.selectionForeground"));
+ dtcr.setBackgroundSelectionColor(UIManager.getColor
+ ("Table.selectionBackground"));
+ }
+ }
+
+ /**
+ * Sets the row height of the tree, and forwards the row height to
+ * the table.
+ */
+ public void setRowHeight(int rowHeight) {
+ if (rowHeight > 0) {
+ super.setRowHeight(rowHeight);
+ if (JTreeTable.this != null &&
+ JTreeTable.this.getRowHeight() != rowHeight) {
+ JTreeTable.this.setRowHeight(getRowHeight());
+ }
+ }
+ }
+
+ /**
+ * This is overridden to set the height to match that of the JTable.
+ */
+ public void setBounds(int x, int y, int w, int h) {
+ super.setBounds(x, 0, w, JTreeTable.this.getHeight());
+ }
+
+ /**
+ * Sublcassed to translate the graphics such that the last visible
+ * row will be drawn at 0,0.
+ */
+ public void paint(Graphics g) {
+ g.translate(0, -visibleRow * getRowHeight());
+ super.paint(g);
+ // Draw the Table border if we have focus.
+ if (highlightBorder != null) {
+ highlightBorder.paintBorder(this, g, 0, visibleRow *
+ getRowHeight(), getWidth(),
+ getRowHeight());
+ }
+ }
+
+ /**
+ * TreeCellRenderer method. Overridden to update the visible row.
+ */
+ public Component getTableCellRendererComponent(JTable table,
+ Object value,
+ boolean isSelected,
+ boolean hasFocus,
+ int row, int column) {
+ Color background;
+ Color foreground;
+
+ if(isSelected) {
+ background = table.getSelectionBackground();
+ foreground = table.getSelectionForeground();
+ }
+ else {
+ background = table.getBackground();
+ foreground = table.getForeground();
+ }
+ highlightBorder = null;
+ if (realEditingRow() == row && getEditingColumn() == column) {
+ background = UIManager.getColor("Table.focusCellBackground");
+ foreground = UIManager.getColor("Table.focusCellForeground");
+ }
+ else if (hasFocus) {
+ highlightBorder = UIManager.getBorder
+ ("Table.focusCellHighlightBorder");
+ if (isCellEditable(row, column)) {
+ background = UIManager.getColor
+ ("Table.focusCellBackground");
+ foreground = UIManager.getColor
+ ("Table.focusCellForeground");
+ }
+ }
+
+ visibleRow = row;
+ setBackground(background);
+
+ TreeCellRenderer tcr = getCellRenderer();
+ if (tcr instanceof DefaultTreeCellRenderer) {
+ DefaultTreeCellRenderer dtcr = ((DefaultTreeCellRenderer)tcr);
+ if (isSelected) {
+ dtcr.setTextSelectionColor(foreground);
+ dtcr.setBackgroundSelectionColor(background);
+ }
+ else {
+ dtcr.setTextNonSelectionColor(foreground);
+ dtcr.setBackgroundNonSelectionColor(background);
+ }
+ }
+ return this;
+ }
}
@@ -380,93 +380,93 @@
* just work. So, that is what we are doing here. Determining of
* the icon position will only work if the TreeCellRenderer is
* an instance of DefaultTreeCellRenderer. If you need custom
- * TreeCellRenderers, that don't descend from DefaultTreeCellRenderer,
+ * TreeCellRenderers, that don't descend from DefaultTreeCellRenderer,
* and you want to support editing in JTreeTable, you will have
* to do something similiar.
*/
public class TreeTableCellEditor extends DefaultCellEditor {
- public TreeTableCellEditor() {
- super(new TreeTableTextField());
- }
-
- /**
- * Overriden to determine an offset that tree would place the
- * editor at. The offset is determined from the
- * getRowBounds
JTree method, and additionaly
- * from the icon DefaultTreeCellRenderer will use.
- *
The offset is then set on the TreeTableTextField component
- * created in the constructor, and returned.
- */
- public Component getTableCellEditorComponent(JTable table,
- Object value,
- boolean isSelected,
- int r, int c) {
- Component component = super.getTableCellEditorComponent
- (table, value, isSelected, r, c);
- JTree t = getTree();
- boolean rv = t.isRootVisible();
- int offsetRow = rv ? r : r - 1;
- Rectangle bounds = t.getRowBounds(offsetRow);
- int offset = bounds.x;
- TreeCellRenderer tcr = t.getCellRenderer();
- if (tcr instanceof DefaultTreeCellRenderer) {
- Object node = t.getPathForRow(offsetRow).
- getLastPathComponent();
- Icon icon;
- if (t.getModel().isLeaf(node))
- icon = ((DefaultTreeCellRenderer)tcr).getLeafIcon();
- else if (tree.isExpanded(offsetRow))
- icon = ((DefaultTreeCellRenderer)tcr).getOpenIcon();
- else
- icon = ((DefaultTreeCellRenderer)tcr).getClosedIcon();
- if (icon != null) {
- offset += ((DefaultTreeCellRenderer)tcr).getIconTextGap() +
- icon.getIconWidth();
- }
- }
- ((TreeTableTextField)getComponent()).offset = offset;
- return component;
- }
-
- /**
- * This is overriden to forward the event to the tree. This will
- * return true if the click count >= 3, or the event is null.
- */
- public boolean isCellEditable(EventObject e) {
- if (e instanceof MouseEvent) {
- MouseEvent me = (MouseEvent)e;
- // If the modifiers are not 0 (or the left mouse button),
+ public TreeTableCellEditor() {
+ super(new TreeTableTextField());
+ }
+
+ /**
+ * Overriden to determine an offset that tree would place the
+ * editor at. The offset is determined from the
+ * getRowBounds
JTree method, and additionaly
+ * from the icon DefaultTreeCellRenderer will use.
+ *
The offset is then set on the TreeTableTextField component
+ * created in the constructor, and returned.
+ */
+ public Component getTableCellEditorComponent(JTable table,
+ Object value,
+ boolean isSelected,
+ int r, int c) {
+ Component component = super.getTableCellEditorComponent
+ (table, value, isSelected, r, c);
+ JTree t = getTree();
+ boolean rv = t.isRootVisible();
+ int offsetRow = rv ? r : r - 1;
+ Rectangle bounds = t.getRowBounds(offsetRow);
+ int offset = bounds.x;
+ TreeCellRenderer tcr = t.getCellRenderer();
+ if (tcr instanceof DefaultTreeCellRenderer) {
+ Object node = t.getPathForRow(offsetRow).
+ getLastPathComponent();
+ Icon icon;
+ if (t.getModel().isLeaf(node))
+ icon = ((DefaultTreeCellRenderer)tcr).getLeafIcon();
+ else if (tree.isExpanded(offsetRow))
+ icon = ((DefaultTreeCellRenderer)tcr).getOpenIcon();
+ else
+ icon = ((DefaultTreeCellRenderer)tcr).getClosedIcon();
+ if (icon != null) {
+ offset += ((DefaultTreeCellRenderer)tcr).getIconTextGap() +
+ icon.getIconWidth();
+ }
+ }
+ ((TreeTableTextField)getComponent()).offset = offset;
+ return component;
+ }
+
+ /**
+ * This is overriden to forward the event to the tree. This will
+ * return true if the click count >= 3, or the event is null.
+ */
+ public boolean isCellEditable(EventObject e) {
+ if (e instanceof MouseEvent) {
+ MouseEvent me = (MouseEvent)e;
+ // If the modifiers are not 0 (or the left mouse button),
// tree may try and toggle the selection, and table
// will then try and toggle, resulting in the
// selection remaining the same. To avoid this, we
// only dispatch when the modifiers are 0 (or the left mouse
// button).
- if (me.getModifiers() == 0 ||
+ if (me.getModifiers() == 0 ||
me.getModifiers() == InputEvent.BUTTON1_MASK) {
- for (int counter = getColumnCount() - 1; counter >= 0;
- counter--) {
- if (getColumnClass(counter) == TreeTableModel.class) {
- MouseEvent newME = new MouseEvent
- (JTreeTable.this.tree, me.getID(),
- me.getWhen(), me.getModifiers(),
- me.getX() - getCellRect(0, counter, true).x,
- me.getY(), me.getClickCount(),
+ for (int counter = getColumnCount() - 1; counter >= 0;
+ counter--) {
+ if (getColumnClass(counter) == TreeTableModel.class) {
+ MouseEvent newME = new MouseEvent
+ (JTreeTable.this.tree, me.getID(),
+ me.getWhen(), me.getModifiers(),
+ me.getX() - getCellRect(0, counter, true).x,
+ me.getY(), me.getClickCount(),
me.isPopupTrigger());
- JTreeTable.this.tree.dispatchEvent(newME);
- break;
- }
- }
- }
- if (me.getClickCount() >= 3) {
- return treeEditable;
- }
- return false;
- }
- if (e == null) {
- return treeEditable;
- }
- return false;
- }
+ JTreeTable.this.tree.dispatchEvent(newME);
+ break;
+ }
+ }
+ }
+ if (me.getClickCount() >= 3) {
+ return treeEditable;
+ }
+ return false;
+ }
+ if (e == null) {
+ return treeEditable;
+ }
+ return false;
+ }
}
@@ -476,12 +476,12 @@
* make the x location be offset
.
*/
static class TreeTableTextField extends JTextField {
- public int offset;
+ public int offset;
- public void setBounds(int x, int y, int w, int h) {
- int newX = Math.max(x, offset);
- super.setBounds(newX, y, w - (newX - x), h);
- }
+ public void setBounds(int x, int y, int w, int h) {
+ int newX = Math.max(x, offset);
+ super.setBounds(newX, y, w - (newX - x), h);
+ }
}
@@ -491,96 +491,96 @@
* a change in the ListSelectionModel happens, the paths are updated
* in the DefaultTreeSelectionModel.
*/
- class ListToTreeSelectionModelWrapper extends DefaultTreeSelectionModel {
- /** Set to true when we are updating the ListSelectionModel. */
- protected boolean updatingListSelectionModel;
-
- public ListToTreeSelectionModelWrapper() {
- super();
- getListSelectionModel().addListSelectionListener
- (createListSelectionListener());
- }
-
- /**
- * Returns the list selection model. ListToTreeSelectionModelWrapper
- * listens for changes to this model and updates the selected paths
- * accordingly.
- */
- ListSelectionModel getListSelectionModel() {
- return listSelectionModel;
- }
-
- /**
- * This is overridden to set updatingListSelectionModel
- * and message super. This is the only place DefaultTreeSelectionModel
- * alters the ListSelectionModel.
- */
- public void resetRowSelection() {
- if(!updatingListSelectionModel) {
- updatingListSelectionModel = true;
- try {
- super.resetRowSelection();
- }
- finally {
- updatingListSelectionModel = false;
- }
- }
- // Notice how we don't message super if
- // updatingListSelectionModel is true. If
- // updatingListSelectionModel is true, it implies the
- // ListSelectionModel has already been updated and the
- // paths are the only thing that needs to be updated.
- }
-
- /**
- * Creates and returns an instance of ListSelectionHandler.
- */
- protected ListSelectionListener createListSelectionListener() {
- return new ListSelectionHandler();
- }
-
- /**
- * If updatingListSelectionModel
is false, this will
- * reset the selected paths from the selected rows in the list
- * selection model.
- */
- protected void updateSelectedPathsFromSelectedRows() {
- if(!updatingListSelectionModel) {
- updatingListSelectionModel = true;
- try {
- // This is way expensive, ListSelectionModel needs an
- // enumerator for iterating.
- int min = listSelectionModel.getMinSelectionIndex();
- int max = listSelectionModel.getMaxSelectionIndex();
-
- clearSelection();
- if(min != -1 && max != -1) {
- for(int counter = min; counter <= max; counter++) {
- if(listSelectionModel.isSelectedIndex(counter)) {
- TreePath selPath = tree.getPathForRow
- (counter);
-
- if(selPath != null) {
- addSelectionPath(selPath);
- }
- }
- }
- }
- }
- finally {
- updatingListSelectionModel = false;
- }
- }
- }
-
- /**
- * Class responsible for calling updateSelectedPathsFromSelectedRows
- * when the selection of the list changse.
- */
- class ListSelectionHandler implements ListSelectionListener {
- public void valueChanged(ListSelectionEvent e) {
- updateSelectedPathsFromSelectedRows();
- }
- }
+ class ListToTreeSelectionModelWrapper extends DefaultTreeSelectionModel {
+ /** Set to true when we are updating the ListSelectionModel. */
+ protected boolean updatingListSelectionModel;
+
+ public ListToTreeSelectionModelWrapper() {
+ super();
+ getListSelectionModel().addListSelectionListener
+ (createListSelectionListener());
+ }
+
+ /**
+ * Returns the list selection model. ListToTreeSelectionModelWrapper
+ * listens for changes to this model and updates the selected paths
+ * accordingly.
+ */
+ ListSelectionModel getListSelectionModel() {
+ return listSelectionModel;
+ }
+
+ /**
+ * This is overridden to set updatingListSelectionModel
+ * and message super. This is the only place DefaultTreeSelectionModel
+ * alters the ListSelectionModel.
+ */
+ public void resetRowSelection() {
+ if(!updatingListSelectionModel) {
+ updatingListSelectionModel = true;
+ try {
+ super.resetRowSelection();
+ }
+ finally {
+ updatingListSelectionModel = false;
+ }
+ }
+ // Notice how we don't message super if
+ // updatingListSelectionModel is true. If
+ // updatingListSelectionModel is true, it implies the
+ // ListSelectionModel has already been updated and the
+ // paths are the only thing that needs to be updated.
+ }
+
+ /**
+ * Creates and returns an instance of ListSelectionHandler.
+ */
+ protected ListSelectionListener createListSelectionListener() {
+ return new ListSelectionHandler();
+ }
+
+ /**
+ * If updatingListSelectionModel
is false, this will
+ * reset the selected paths from the selected rows in the list
+ * selection model.
+ */
+ protected void updateSelectedPathsFromSelectedRows() {
+ if(!updatingListSelectionModel) {
+ updatingListSelectionModel = true;
+ try {
+ // This is way expensive, ListSelectionModel needs an
+ // enumerator for iterating.
+ int min = listSelectionModel.getMinSelectionIndex();
+ int max = listSelectionModel.getMaxSelectionIndex();
+
+ clearSelection();
+ if(min != -1 && max != -1) {
+ for(int counter = min; counter <= max; counter++) {
+ if(listSelectionModel.isSelectedIndex(counter)) {
+ TreePath selPath = tree.getPathForRow
+ (counter);
+
+ if(selPath != null) {
+ addSelectionPath(selPath);
+ }
+ }
+ }
+ }
+ }
+ finally {
+ updatingListSelectionModel = false;
+ }
+ }
+ }
+
+ /**
+ * Class responsible for calling updateSelectedPathsFromSelectedRows
+ * when the selection of the list changse.
+ */
+ class ListSelectionHandler implements ListSelectionListener {
+ public void valueChanged(ListSelectionEvent e) {
+ updateSelectedPathsFromSelectedRows();
+ }
+ }
}
}