--- 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(); + } + } } }