|
What this is
Other links
The source code/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun * Microsystems, Inc. All Rights Reserved. */ package org.openide.explorer.view; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.FocusListener; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.swing.*; import javax.swing.tree.*; import javax.swing.event.*; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import javax.swing.plaf.basic.BasicTableUI; import java.util.EventObject; import java.beans.PropertyEditor; import javax.swing.plaf.TableUI; import javax.swing.table.JTableHeader; import javax.swing.table.TableCellEditor; import org.openide.nodes.Node.Property; import org.openide.nodes.Node; import org.openide.ErrorManager; import org.openide.explorer.propertysheet.PropertyPanel; import org.openide.util.NbBundle; import org.openide.awt.MouseUtils; import org.openide.util.Utilities; /** * TreeTable implementation. * * @author Jan Rojcek */ class TreeTable extends JTable implements Runnable { /** A subclass of JTree. */ private TreeTableCellRenderer tree; private NodeTableModel tableModel; private int treeColumnIndex = -1; /** Tree editor stuff. */ private int lastRow = -1; private boolean canEdit; private boolean ignoreScrolling = false; /** Action key for up/down focus action */ private static final String ACTION_FOCUS_NEXT = "focusNext"; //NOI18N /** Flag to ignore clearSelection() called from super.tableChanged(). */ private boolean ignoreClearSelection = false; /** Position of tree renderer, used for horizontal scrolling. */ private int positionX; /** If true, horizontal scrolling of tree column is enabled in TreeTableView */ private boolean treeHScrollingEnabled = true; private final ListToTreeSelectionModelWrapper selectionWrapper; public TreeTable(NodeTreeModel treeModel, NodeTableModel tableModel) { super(); setSurrendersFocusOnKeystroke(true); this.tree = new TreeTableCellRenderer(treeModel); this.tableModel = new TreeTableModelAdapter(tree, tableModel); tree.setCellRenderer(new NodeRenderer()); // Install a tableModel representing the visible rows in the tree. setModel(this.tableModel); // Force the JTable and JTree to share their row selection models. selectionWrapper = new ListToTreeSelectionModelWrapper(); tree.setSelectionModel(selectionWrapper); setSelectionModel(selectionWrapper.getListSelectionModel()); getTableHeader().setReorderingAllowed(false); // Install the tree editor renderer and editor. setDefaultRenderer(TreeTableModelAdapter.class, tree); // Install property renderer and editor. TableSheetCell tableCell = new TableSheetCell(this.tableModel); tableCell.setFlat(true); setDefaultRenderer(Property.class, tableCell); setDefaultEditor(Property.class, tableCell); getTableHeader().setDefaultRenderer(tableCell); getAccessibleContext().setAccessibleName( NbBundle.getBundle(TreeTable.class).getString("ACSN_TreeTable")); // NOI18N getAccessibleContext().setAccessibleDescription( // NOI18N NbBundle.getBundle(TreeTable.class).getString("ACSD_TreeTable")); // NOI18N setFocusCycleRoot(true); setFocusTraversalPolicy(new STPolicy()); putClientProperty("terminateEditOnFocusLost", Boolean.TRUE); putClientProperty("JTable.autoStartsEdit", Boolean.FALSE); initKeysAndActions(); } private void initKeysAndActions() { setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, Collections.EMPTY_SET); setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, Collections.EMPTY_SET); //Next two lines do not work using inputmap/actionmap, but do work //using the older API. We will process ENTER to skip to next row, //not next cell unregisterKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)); unregisterKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, Event.SHIFT_MASK)); InputMap imp = getInputMap(WHEN_FOCUSED); InputMap imp2 = getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); ActionMap am = getActionMap(); // copied from TreeView which tried to fix #18292 // by doing this imp2.put(KeyStroke.getKeyStroke("control C"), "none"); // NOI18N imp2.put(KeyStroke.getKeyStroke("control V"), "none"); // NOI18N imp2.put(KeyStroke.getKeyStroke("control X"), "none"); // NOI18N imp2.put(KeyStroke.getKeyStroke("COPY"), "none"); // NOI18N imp2.put(KeyStroke.getKeyStroke("PASTE"), "none"); // NOI18N imp2.put(KeyStroke.getKeyStroke("CUT"), "none"); // NOI18N /* fix of #23873, then removed - davidjon request getActionMap().put("selectNextColumnExtendSelection", getActionMap().get("selectNextColumn")); getActionMap().put("selectPreviousColumnExtendSelection", getActionMap().get("selectPreviousColumn")); */ //Issue 37919, reinstate support for up/down cycle focus transfer. //being focus cycle root mangles this in some dialogs imp.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, KeyEvent.CTRL_MASK | KeyEvent.SHIFT_MASK, false), ACTION_FOCUS_NEXT); imp.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, KeyEvent.CTRL_MASK, false), ACTION_FOCUS_NEXT); Action ctrlTab = new CTRLTabAction(); am.put(ACTION_FOCUS_NEXT, ctrlTab); getActionMap().put("selectNextColumn", // NOI18N new TreeTableAction(tree.getActionMap().get("selectChild"), // NOI18N getActionMap().get("selectNextColumn"))); // NOI18N getActionMap().put("selectPreviousColumn", // NOI18N new TreeTableAction(tree.getActionMap().get("selectParent"), // NOI18N getActionMap().get("selectPreviousColumn"))); // NOI18N getAccessibleContext ().setAccessibleName ( NbBundle.getBundle (TreeTable.class).getString ("ACSN_TreeTable")); // NOI18N getAccessibleContext ().setAccessibleDescription ( // NOI18N NbBundle.getBundle (TreeTable.class).getString ("ACSD_TreeTable")); // NOI18N imp.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, false), "beginEdit"); getActionMap().put("beginEdit", new EditAction()); imp2.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false), "cancelEdit"); getActionMap().put("cancelEdit", new CancelEditAction()); imp.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false), "enter"); getActionMap().put("enter", new EnterAction()); imp.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), "next"); imp.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, KeyEvent.SHIFT_DOWN_MASK), "previous"); am.put("next", new NavigationAction(true)); am.put("previous", new NavigationAction(false)); } private boolean edCreated = false; public TableCellEditor getDefaultEditor(Class columnClass) { if (!edCreated && columnClass == TreeTableModelAdapter.class) { //Creating this editor in the constructor can take > 100ms even //on a very fast machine, so do it lazily here to improve //performance of creating a TreeTable setDefaultEditor(TreeTableModelAdapter.class, new TreeTableCellEditor()); edCreated = true; } return super.getDefaultEditor(columnClass); } boolean inSelectAll = false; public void selectAll() { //#48242 - select all over 1000 nodes generates 1000 re-sorts inSelectAll = true; try { super.selectAll(); } finally { inSelectAll = false; selectionWrapper.updateSelectedPathsFromSelectedRows(); } } /* * Overridden to message super and forward the method to the tree. */ public void updateUI() { super.updateUI(); if(tree != null) { tree.updateUI(); } // Use the tree's default foreground and background colors in the // table. LookAndFeel.installColorsAndFont(this, "Tree.background", // NOI18N "Tree.foreground", "Tree.font"); // NOI18N if (UIManager.getColor ("Table.selectionBackground") == null) { // NOI18N UIManager.put ("Table.selectionBackground", new JTable ().getSelectionBackground ()); // NOI18N } if (UIManager.getColor ("Table.selectionForeground") == null) { // NOI18N UIManager.put ("Table.selectionForeground", new JTable ().getSelectionForeground ()); // NOI18N } if (UIManager.getColor ("Table.gridColor") == null) { // NOI18N UIManager.put ("Table.gridColor", new JTable ().getGridColor ()); // NOI18N } setUI(new TreeTableUI()); needCalcRowHeight = true; } /* Workaround for BasicTableUI anomaly. Make sure the UI never tries to * paint 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) == TreeTableModelAdapter.class) ? -1 : editingRow; } /** Overridden - JTable's implementation of the method will * actually attach (and leave behind) a gratuitous border * on the enclosing scroll pane. */ protected final void configureEnclosingScrollPane() { Container p = getParent(); if (p instanceof JViewport) { Container gp = p.getParent(); if (gp instanceof JScrollPane) { JScrollPane scrollPane = (JScrollPane)gp; JViewport viewport = scrollPane.getViewport(); if (viewport == null || viewport.getView() != this) { return; } JTableHeader jth = getTableHeader(); if (jth != null) { jth.setBorder(null); } scrollPane.setColumnHeaderView(jth); } } } private boolean needCalcRowHeight = true; public void paint (Graphics g) { if (needCalcRowHeight) { calcRowHeight(g); return; } /* long time = perf.highResCounter(); */ super.paint(g); /* double dur = perf.highResCounter()-time; total += dur; System.err.println("Paint time: " + total + " ticks = " + (total / perf.highResFrequency()) + " ms. "); */ } // private static final sun.misc.Perf perf = sun.misc.Perf.getPerf(); // private static double total = 0; /** Calculate the height of rows based on the current font. This is * done when the first paint occurs, to ensure that a valid Graphics * object is available. * @since 1.25 */ private void calcRowHeight(Graphics g) { Font f = getFont(); FontMetrics fm = g.getFontMetrics(f); int rowHeight = fm.getHeight() + fm.getMaxDescent(); needCalcRowHeight = false; rowHeight = Math.max(20, rowHeight); tree.setRowHeight (rowHeight); setRowHeight(rowHeight); } /** * Returns the tree that is being shared between the model. */ JTree getTree() { return tree; } /** * Returns table column index of the column displaying the tree. */ int getTreeColumnIndex() { return treeColumnIndex; } /** * Sets tree column index and fires property change. */ void setTreeColumnIndex(int index) { if (treeColumnIndex == index) return; int old = treeColumnIndex; treeColumnIndex = index; firePropertyChange("treeColumnIndex", old, treeColumnIndex); } /* Overriden to do not clear a selection upon model changes. */ public void clearSelection() { if (!ignoreClearSelection) { super.clearSelection(); } } /* Updates tree column name and sets ignoreClearSelection flag. */ public void tableChanged(TableModelEvent e) { // update tree column name int modelColumn = getTreeColumnIndex(); if (e.getFirstRow() <= 0 && modelColumn != -1 && getColumnCount() > 0) { String columnName = getModel().getColumnName(modelColumn); TableColumn aColumn = getColumnModel().getColumn(modelColumn); aColumn.setHeaderValue(columnName); } ignoreClearSelection = true; try { super.tableChanged(e); } finally { ignoreClearSelection = false; } } public void processKeyEvent(KeyEvent e) { //Manually hook in the bindings for tab - does not seem to get called //automatically if (isEditing() && (e.getKeyCode() == e.VK_DOWN || e.getKeyCode() == e.VK_UP)) { return; //XXX } //Bypass standard tab and escape handling, and use our registered //actions instead if (!isEditing() || ((e.getKeyCode() != e.VK_TAB && e.getKeyCode() != e.VK_ESCAPE) || (e.getModifiers() & e.CTRL_MASK) != 0)) { super.processKeyEvent(e); } else { processKeyBinding(KeyStroke.getKeyStroke( e.getKeyCode(), e.getModifiersEx(), e.getID() == e.KEY_RELEASED), e, JComponent.WHEN_FOCUSED, e.getID() == e.KEY_PRESSED); } } boolean inEditRequest = false; boolean inEditorChangeRequest=false; int editRow = -1; /* Performs horizontal scrolling of the tree when editing is started. */ public boolean editCellAt(int row, int column, EventObject e) { if (e instanceof MouseEvent && column != 0) { MouseEvent me = (MouseEvent) e; if (!SwingUtilities.isLeftMouseButton(me) || me.getID() != me.MOUSE_PRESSED) { return false; } } if (row >= getRowCount() || row < 0 || column > getColumnCount() || column < 0) { //I don't want to know why this happens, but it does. return false; } inEditRequest = true; editRow = row; if (editingRow == row && editingColumn == column && isEditing()) { //discard edit requests if we're already editing that cell inEditRequest =false; return false; } if (isEditing()) { inEditorChangeRequest = true; try { removeEditor(); changeSelection(row, column, false, false); } finally { inEditorChangeRequest = false; } } //Treat a keyEvent request to edit on a non-editable //column as a request to edit the nearest column that is //editable boolean editable = getModel().isCellEditable(row, column); //We never want to invoke node name editing from the keyboard, //it doesn't work anyway - better to look for an editable property if (editable && (e == null || e instanceof KeyEvent) && column == 0) { editable = false; column = 1; } boolean columnShifted = false; if (!editable && (e instanceof KeyEvent || e == null)) { for (int i=column; i < getColumnCount(); i++) { if (getModel().isCellEditable(row, i)) { columnShifted = i != column; column = i; changeSelection(row, column, false, false); break; } } } final Rectangle r = getCellRect (row, column, true); //#44226 - Provide a way to invoke the custom editor on disabled cells boolean canTryCustomEditor = !columnShifted && e instanceof MouseEvent ? ((MouseEvent) e).getX() > r.x + r.width - 24 && ((MouseEvent) e).getX() < r.x + r.width : true; try { canEdit = (lastRow == row); Object o = getValueAt(row, column); if (o instanceof Property) { // && (e == null || e instanceof KeyEvent)) { //Toggle booleans without instantiating an editor Property p = (Property) o; if (p.canWrite() && (p.getValueType() == Boolean.class || p.getValueType() == Boolean.TYPE)) { try { Boolean val = (Boolean) p.getValue(); if (Boolean.FALSE.equals(val)) { p.setValue(Boolean.TRUE); } else { //This covers null multi-selections too p.setValue(Boolean.FALSE); } repaint (r.x, r.y, r.width, r.height); return false; } catch (Exception e1) { ErrorManager.getDefault().notify(ErrorManager.WARNING, e1); return false; } } else if (canTryCustomEditor && !Boolean.TRUE.equals(p.getValue("suppressCustomEditor"))) { //NOI18N PropertyPanel panel = new PropertyPanel (p); PropertyEditor ed = panel.getPropertyEditor(); if (ed != null && ed.supportsCustomEditor()) { Action act = panel.getActionMap().get("invokeCustomEditor"); //NOI18N if (act != null) { SwingUtilities.invokeLater (new Runnable(){ public void run() { r.x = 0; r.width = getWidth(); TreeTable.this.repaint (r); } }); act.actionPerformed(null); return false; } } } if (!p.canWrite()) { return false; } } boolean ret = super.editCellAt(row, column, e); if (ret) { //InvokeLater to get out of the way of anything the winsys is going to do if (column == getTreeColumnIndex()) { ignoreScrolling = true; tree.scrollRectToVisible(tree.getRowBounds(row)); ignoreScrolling = false; } else { SwingUtilities.invokeLater (this); } } return ret; } finally { inEditRequest = false; } } /** * */ public void run() { if (editorComp != null && editorComp.isShowing()) { editorComp.requestFocus(); } } /* */ public void valueChanged(ListSelectionEvent e) { if (getSelectedRowCount() == 1) lastRow = getSelectedRow(); else lastRow = -1; super.valueChanged(e); } /* Updates tree column index */ public void columnAdded(TableColumnModelEvent e) { super.columnAdded(e); updateTreeColumnIndex(); } /* Updates tree column index */ public void columnRemoved(TableColumnModelEvent e) { super.columnRemoved(e); updateTreeColumnIndex(); } /* Updates tree column index */ public void columnMoved(TableColumnModelEvent e) { super.columnMoved(e); updateTreeColumnIndex(); int from = e.getFromIndex(); int to = e.getToIndex(); if ( from != to ) firePropertyChange( "column_moved", from, to ); // NOI18N } /* Updates tree column index */ private void updateTreeColumnIndex() { for (int i = getColumnCount() - 1; i >= 0; i--) { if (getColumnClass(i) == TreeTableModelAdapter.class) { setTreeColumnIndex(i); return; } } setTreeColumnIndex(-1); } /** Returns x coordinate of tree renderer. */ public int getPositionX() { return positionX; } /** Sets x position. */ public void setPositionX(int x) { if (x == positionX || !treeHScrollingEnabled) return; int old = positionX; positionX = x; firePropertyChange("positionX", old, x); if (isEditing() && getEditingColumn() == getTreeColumnIndex()) { CellEditor editor = getCellEditor(); if (ignoreScrolling && editor instanceof TreeTableCellEditor) { ((TreeTableCellEditor)editor).revalidateTextField(); } else { removeEditor(); } } repaint(); } /** Overridden to manually draw the focused rectangle for the tree column */ public void paintComponent(Graphics g) { super.paintComponent(g); if (hasFocus() && getSelectedColumn() == 0 && getSelectedRow() > 0) { Color bdr = UIManager.getColor("Tree.selectionBorderColor"); //NOI18N if (bdr == null) { //Button focus color doesn't work on win classic - better to //get the color from a value we know will work - Tim if (getForeground().equals(Color.BLACK)) { //typical bdr = getBackground().darker(); } else { bdr = getForeground().darker(); } } g.setColor(bdr); Rectangle r = getCellRect (getSelectedRow(), getSelectedColumn(), false); g.drawRect(r.x+1, r.y+1, r.width - 3, r.height - 3); } } /** Enables horizontal scrolling of tree column */ void setTreeHScrollingEnabled(boolean enabled) { treeHScrollingEnabled = enabled; } /** * A TreeCellRenderer that displays a JTree. */ class TreeTableCellRenderer extends JTree implements TableCellRenderer { /** Last table/tree row asked to renderer. */ protected int visibleRow; /* Last width of the tree. */ private int oldWidth; public TreeTableCellRenderer(TreeModel model) { super(model); setToggleClickCount(0); putClientProperty("JTree.lineStyle", "None"); // NOI18N } public void validate() { //do nothing } public void repaint(long tm, int x, int y, int width, int height) { //do nothing } public void addHierarchyListener (java.awt.event.HierarchyListener hl) { //do nothing } public void addComponentListener (java.awt.event.ComponentListener cl) { //do nothing } /** * Accessor so NodeRenderer can check if the tree table or its child has * focus and paint with the appropriate color. * * @see NodeRenderer#configureFrom * @return The tree table */ TreeTable getTreeTable() { return TreeTable.this; } /** * 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); TreeTable.this.setRowHeight(rowHeight); } } /** * Overridden to always set the size to the height of the TreeTable * and the width of column 0. The paint() method will translate the * coordinates to the correct position. */ public void setBounds(int x, int y, int w, int h) { transY = -y; super.setBounds(0,0, TreeTable.this.getColumnModel().getColumn(0).getWidth(), TreeTable.this.getHeight()); } private int transY = 0; /* Fire width property change so that we can revalidate horizontal scrollbar in TreeTableView. */ public void reshape(int x, int y, int w, int h) { int oldWidth = getWidth(); super.reshape(x, y, w, h); if (oldWidth != w) { firePropertyChange("width", oldWidth, w); } } public void paint (Graphics g) { g.translate(-getPositionX(), transY); super.paint(g); } public Rectangle getVisibleRect() { Rectangle visibleRect = TreeTable.this.getVisibleRect(); visibleRect.x = positionX; visibleRect.width = TreeTable.this.getColumnModel().getColumn(getTreeColumnIndex()).getWidth(); return visibleRect; } /* Overriden to use this call for moving tree renderer. */ public void scrollRectToVisible(Rectangle aRect) { Rectangle rect = getVisibleRect(); rect.y = aRect.y; rect.height = aRect.height; TreeTable.this.scrollRectToVisible(rect); int x = rect.x; if (aRect.width > rect.width) { x = aRect.x; } else if (aRect.x < rect.x) { x = aRect.x; } else if (aRect.x + aRect.width > rect.x + rect.width) { x = aRect.x + aRect.width - rect.width; } TreeTable.this.setPositionX(x); } public String getToolTipText(MouseEvent event) { if(event != null) { Point p = event.getPoint(); p.translate(positionX, visibleRow * getRowHeight()); int selRow = getRowForLocation(p.x, p.y); if(selRow != -1) { TreePath path = getPathForRow(selRow); VisualizerNode v = (VisualizerNode)path.getLastPathComponent(); String tooltip = v.getShortDescription(); String displayName = v.getDisplayName (); if ((tooltip != null) && !tooltip.equals (displayName)) return tooltip; } } return null; } /** * TreeCellRenderer method. Overridden to update the visible row. */ public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { if(isSelected) { Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager(). getFocusOwner(); boolean tableHasFocus = focusOwner == this || focusOwner == TreeTable.this || TreeTable.this.isAncestorOf(focusOwner) || focusOwner instanceof JRootPane; //RootPane == popup menu //TODO - it should be possible to simply set the correct //color in prepareRenderer for the tree's cell renderer, //rather than set it for the whole tree. Might fix a //couple problems. -Tim setBackground(tableHasFocus ? table.getSelectionBackground() : getUnfocusedSelectedBackground()); setForeground(tableHasFocus ? table.getSelectionForeground() : getUnfocusedSelectedForeground()); } else { setBackground(table.getBackground()); setForeground(table.getForeground()); } visibleRow = row; return this; } protected TreeModelListener createTreeModelListener() { return new JTree.TreeModelHandler() { public void treeNodesRemoved(TreeModelEvent e) { if (tree.getSelectionCount () == 0) { TreePath path = TreeView.findSiblingTreePath (e.getTreePath (), e.getChildIndices ()); if (path != null && path.getPathCount () > 0) { tree.setSelectionPath (path); } } } }; } } boolean isKnownComponent (Component c) { if (c == null) return false; if (isAncestorOf (c)) { return true; } if (c == editorComp) { return true; } if (editorComp != null && (editorComp instanceof Container) && ((Container) editorComp).isAncestorOf(c)) { return true; } return false; } public boolean isValidationRoot() { return true; } public void paintImmediately (int x, int y, int w, int h) { //Eliminate duplicate repaints in an editor change request if (inEditorChangeRequest) { return; } super.paintImmediately(x, y, w, h); } protected void processFocusEvent (FocusEvent fe) { super.processFocusEvent(fe); //Remove the editor here if the new focus owner is not //known to the table & the focus event is not temporary if (fe.getID() == fe.FOCUS_LOST && !fe.isTemporary() && !inRemoveRequest && !inEditRequest) { boolean stopEditing = (fe.getOppositeComponent() != getParent() && !isKnownComponent(fe.getOppositeComponent()) && fe.getOppositeComponent() != null); if (stopEditing) { removeEditor(); } } //The UI will only repaint the lead selection, but we need to //paint all selected rows for the color to change when focus //is lost/gained if (!inRemoveRequest && !inEditRequest) { repaintSelection(fe.getID() == fe.FOCUS_GAINED); } } private boolean inRemoveRequest=false; public void removeEditor() { inRemoveRequest = true; try { synchronized (getTreeLock()) { super.removeEditor(); } } finally { inRemoveRequest = false; } } /** Repaint the selected row */ private void repaintSelection(boolean focused) { int start = getSelectionModel().getMinSelectionIndex(); int end = getSelectionModel().getMaxSelectionIndex(); if (end != -1) { if (end != start) { Rectangle begin = getCellRect(start, 0, false); Rectangle r = getCellRect(end, 0, false); r.y =begin.y; r.x = 0; r.width = getWidth(); r.height = r.y + r.height - begin.y; repaint (r.x, r.y, r.width, r.height); } else { Rectangle r = getCellRect(start, 0, false); r.width = getWidth(); r.x = 0; repaint (r.x, r.y, r.width, r.height); } } if (isEditing() && editorComp != null) { editorComp.setBackground(focused ? getSelectionBackground() : getUnfocusedSelectedBackground()); editorComp.setForeground(focused ? getSelectionForeground() : getUnfocusedSelectedForeground()); } } /** * TreeTableCellEditor implementation. */ class TreeTableCellEditor extends DefaultCellEditor implements TreeSelectionListener, ActionListener, FocusListener, CellEditorListener { /** Used in editing. Indicates x position to place editingComponent. */ protected transient int offset; /** Used before starting the editing session. */ protected transient Timer timer; public TreeTableCellEditor() { super(new TreeTableTextField()); tree.addTreeSelectionListener(this); addCellEditorListener(this); super.getComponent().addFocusListener(this); } /** * Overridden to determine an offset that tree would place the * editor at. The offset is determined from the * |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.