1 19 package org.openide.explorer.view; 20 import javax.swing.table.TableColumnModel ; 21 import org.openide.awt.MouseUtils; 22 import org.openide.explorer.propertysheet.PropertyPanel; 23 import org.openide.nodes.Node; 24 import org.openide.nodes.Node.Property; 25 import org.openide.util.NbBundle; 26 import org.openide.util.Utilities; 27 28 import java.awt.*; 29 import java.awt.event.ActionEvent ; 30 import java.awt.event.ActionListener ; 31 import java.awt.event.FocusEvent ; 32 import java.awt.event.FocusListener ; 33 import java.awt.event.KeyEvent ; 34 import java.awt.event.MouseEvent ; 35 36 import java.beans.PropertyEditor ; 37 38 import java.util.ArrayList ; 39 import java.util.Collections ; 40 import java.util.EventObject ; 41 import java.util.List ; 42 import java.util.logging.Level ; 43 import java.util.logging.Logger ; 44 45 import javax.swing.*; 46 import javax.swing.event.*; 47 import javax.swing.plaf.basic.BasicTableUI ; 48 import javax.swing.plaf.basic.BasicTreeUI ; 49 import javax.swing.table.JTableHeader ; 50 import javax.swing.table.TableCellEditor ; 51 import javax.swing.table.TableCellRenderer ; 52 import javax.swing.table.TableColumn ; 53 import javax.swing.tree.*; 54 import org.openide.util.Exceptions; 55 56 57 62 class TreeTable extends JTable implements Runnable { 63 64 private static final String ACTION_FOCUS_NEXT = "focusNext"; private static Color unfocusedSelBg = null; 66 private static Color unfocusedSelFg = null; 67 68 69 private TreeTableCellRenderer tree; 70 private NodeTableModel tableModel; 71 private int treeColumnIndex = -1; 72 73 74 private int lastRow = -1; 75 private boolean canEdit; 76 private boolean ignoreScrolling = false; 77 78 79 private boolean ignoreClearSelection = false; 80 81 82 private int positionX; 83 84 85 private boolean treeHScrollingEnabled = true; 86 private final ListToTreeSelectionModelWrapper selectionWrapper; 87 private boolean edCreated = false; 88 boolean inSelectAll = false; 89 private boolean needCalcRowHeight = true; 90 boolean inEditRequest = false; 91 boolean inEditorChangeRequest = false; 92 int editRow = -1; 93 private boolean inRemoveRequest = false; 94 95 public TreeTable(NodeTreeModel treeModel, NodeTableModel tableModel) { 96 super(); 97 98 setSurrendersFocusOnKeystroke(true); 99 100 this.tree = new TreeTableCellRenderer(treeModel); 101 this.tableModel = new TreeTableModelAdapter(tree, tableModel); 102 103 tree.setCellRenderer(new NodeRenderer()); 104 105 setModel(this.tableModel); 107 108 selectionWrapper = new ListToTreeSelectionModelWrapper(); 110 tree.setSelectionModel(selectionWrapper); 111 setSelectionModel(selectionWrapper.getListSelectionModel()); 112 getTableHeader().setReorderingAllowed(false); 113 114 setDefaultRenderer(TreeTableModelAdapter.class, tree); 116 117 TableSheetCell tableCell = new TableSheetCell(this.tableModel); 119 tableCell.setFlat(true); 120 setDefaultRenderer(Property.class, tableCell); 121 setDefaultEditor(Property.class, tableCell); 122 getTableHeader().setDefaultRenderer(tableCell); 123 getAccessibleContext().setAccessibleName(NbBundle.getBundle(TreeTable.class).getString("ACSN_TreeTable")); getAccessibleContext().setAccessibleDescription( NbBundle.getBundle(TreeTable.class).getString("ACSD_TreeTable")); 127 setFocusCycleRoot(true); 128 setFocusTraversalPolicy(new STPolicy()); 129 putClientProperty("terminateEditOnFocusLost", Boolean.TRUE); 130 putClientProperty("JTable.autoStartsEdit", Boolean.FALSE); 131 132 initKeysAndActions(); 133 } 134 135 private void initKeysAndActions() { 136 setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, Collections.<AWTKeyStroke>emptySet()); 137 setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, Collections.<AWTKeyStroke>emptySet()); 138 139 unregisterKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)); 143 unregisterKeyboardAction(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, Event.SHIFT_MASK)); 144 145 InputMap imp = getInputMap(WHEN_FOCUSED); 146 InputMap imp2 = getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 147 ActionMap am = getActionMap(); 148 149 imp2.put(KeyStroke.getKeyStroke("control C"), "none"); imp2.put(KeyStroke.getKeyStroke("control V"), "none"); imp2.put(KeyStroke.getKeyStroke("control X"), "none"); imp2.put(KeyStroke.getKeyStroke("COPY"), "none"); imp2.put(KeyStroke.getKeyStroke("PASTE"), "none"); imp2.put(KeyStroke.getKeyStroke("CUT"), "none"); 158 imp.put( 159 KeyStroke.getKeyStroke(KeyEvent.VK_TAB, KeyEvent.CTRL_MASK | KeyEvent.SHIFT_MASK, false), ACTION_FOCUS_NEXT 160 ); 161 imp.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, KeyEvent.CTRL_MASK, false), ACTION_FOCUS_NEXT); 162 163 Action ctrlTab = new CTRLTabAction(); 164 am.put(ACTION_FOCUS_NEXT, ctrlTab); 165 166 getActionMap().put( 167 "selectNextColumn", new TreeTableAction( 169 tree.getActionMap().get("selectChild"), getActionMap().get("selectNextColumn") 171 ) 172 ); getActionMap().put( 174 "selectPreviousColumn", new TreeTableAction( 176 tree.getActionMap().get("selectParent"), getActionMap().get("selectPreviousColumn") 178 ) 179 ); 181 getAccessibleContext().setAccessibleName(NbBundle.getBundle(TreeTable.class).getString("ACSN_TreeTable")); getAccessibleContext().setAccessibleDescription( NbBundle.getBundle(TreeTable.class).getString("ACSD_TreeTable")); 185 imp.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, false), "beginEdit"); 186 getActionMap().put("beginEdit", new EditAction()); 187 188 imp2.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false), "cancelEdit"); 189 getActionMap().put("cancelEdit", new CancelEditAction()); 190 191 imp.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false), "enter"); 192 getActionMap().put("enter", new EnterAction()); 193 194 imp.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), "next"); 195 196 imp.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, KeyEvent.SHIFT_DOWN_MASK), "previous"); 197 198 am.put("next", new NavigationAction(true)); 199 am.put("previous", new NavigationAction(false)); 200 } 201 202 public TableCellEditor getDefaultEditor(Class columnClass) { 203 if (!edCreated && (columnClass == TreeTableModelAdapter.class)) { 204 setDefaultEditor(TreeTableModelAdapter.class, new TreeTableCellEditor()); 208 edCreated = true; 209 } 210 211 return super.getDefaultEditor(columnClass); 212 } 213 214 public void selectAll() { 215 inSelectAll = true; 217 218 try { 219 super.selectAll(); 220 } finally { 221 inSelectAll = false; 222 selectionWrapper.updateSelectedPathsFromSelectedRows(); 223 } 224 } 225 226 229 public void updateUI() { 230 super.updateUI(); 231 232 if (tree != null) { 233 tree.updateUI(); 234 } 235 236 LookAndFeel.installColorsAndFont(this, "Tree.background", "Tree.foreground", "Tree.font" 240 ); 242 if (UIManager.getColor("Table.selectionBackground") == null) { UIManager.put("Table.selectionBackground", new JTable().getSelectionBackground()); } 245 246 if (UIManager.getColor("Table.selectionForeground") == null) { UIManager.put("Table.selectionForeground", new JTable().getSelectionForeground()); } 249 250 if (UIManager.getColor("Table.gridColor") == null) { UIManager.put("Table.gridColor", new JTable().getGridColor()); } 253 254 setUI(new TreeTableUI()); 255 needCalcRowHeight = true; 256 } 257 258 264 public int getEditingRow() { 265 return (getColumnClass(editingColumn) == TreeTableModelAdapter.class) ? (-1) : editingRow; 266 } 267 268 271 protected final void configureEnclosingScrollPane() { 272 Container p = getParent(); 273 274 if (p instanceof JViewport) { 275 Container gp = p.getParent(); 276 277 if (gp instanceof JScrollPane) { 278 JScrollPane scrollPane = (JScrollPane) gp; 279 JViewport viewport = scrollPane.getViewport(); 280 281 if ((viewport == null) || (viewport.getView() != this)) { 282 return; 283 } 284 285 JTableHeader jth = getTableHeader(); 286 287 if (jth != null) { 288 jth.setBorder(null); 289 } 290 291 scrollPane.setColumnHeaderView(jth); 292 } 293 } 294 } 295 296 public void paint(Graphics g) { 297 if (needCalcRowHeight) { 298 calcRowHeight(g); 299 300 return; 301 } 302 303 306 super.paint(g); 307 308 314 } 315 316 319 323 private void calcRowHeight(Graphics g) { 324 Font f = getFont(); 325 FontMetrics fm = g.getFontMetrics(f); 326 int rowHeight = fm.getHeight() + fm.getMaxDescent(); 327 needCalcRowHeight = false; 328 rowHeight = Math.max(20, rowHeight); 329 tree.setRowHeight(rowHeight); 330 setRowHeight(rowHeight); 331 } 332 333 336 JTree getTree() { 337 return tree; 338 } 339 340 343 int getTreeColumnIndex() { 344 return treeColumnIndex; 345 } 346 347 350 void setTreeColumnIndex(int index) { 351 if (treeColumnIndex == index) { 352 return; 353 } 354 355 int old = treeColumnIndex; 356 treeColumnIndex = index; 357 firePropertyChange("treeColumnIndex", old, treeColumnIndex); 358 } 359 360 362 public void clearSelection() { 363 if (!ignoreClearSelection) { 364 super.clearSelection(); 365 } 366 } 367 368 370 public void tableChanged(TableModelEvent e) { 371 int modelColumn = getTreeColumnIndex(); 373 374 if ((e.getFirstRow() <= 0) && (modelColumn != -1) && (getColumnCount() > 0)) { 375 String columnName = getModel().getColumnName(modelColumn); 376 TableColumn aColumn = getColumnModel().getColumn(modelColumn); 377 aColumn.setHeaderValue(columnName); 378 } 379 380 ignoreClearSelection = true; 381 382 try { 383 super.tableChanged(e); 384 if( null != getTree() ) { 386 firePropertyChange( "positionX", -1, getPositionX() ); 387 } 388 } finally { 389 ignoreClearSelection = false; 390 } 391 } 392 393 public void processKeyEvent(KeyEvent e) { 394 if (isEditing() && ((e.getKeyCode() == e.VK_DOWN) || (e.getKeyCode() == e.VK_UP))) { 397 return; } 399 400 if ( 403 !isEditing() || 404 (((e.getKeyCode() != e.VK_TAB) && (e.getKeyCode() != e.VK_ESCAPE)) || 405 ((e.getModifiers() & e.CTRL_MASK) != 0)) 406 ) { 407 super.processKeyEvent(e); 408 } else { 409 processKeyBinding( 410 KeyStroke.getKeyStroke(e.getKeyCode(), e.getModifiersEx(), e.getID() == e.KEY_RELEASED), e, 411 JComponent.WHEN_FOCUSED, e.getID() == e.KEY_PRESSED 412 ); 413 } 414 } 415 416 418 public boolean editCellAt(int row, int column, EventObject e) { 419 if (e instanceof MouseEvent && (column != 0)) { 420 MouseEvent me = (MouseEvent ) e; 421 422 if (!SwingUtilities.isLeftMouseButton(me) || (me.getID() != me.MOUSE_PRESSED)) { 423 return false; 424 } 425 } 426 427 if ((row >= getRowCount()) || (row < 0) || (column > getColumnCount()) || (column < 0)) { 428 return false; 430 } 431 432 inEditRequest = true; 433 editRow = row; 434 435 if ((editingRow == row) && (editingColumn == column) && isEditing()) { 436 inEditRequest = false; 438 439 return false; 440 } 441 442 if (isEditing()) { 443 inEditorChangeRequest = true; 444 445 try { 446 removeEditor(); 447 changeSelection(row, column, false, false); 448 } finally { 449 inEditorChangeRequest = false; 450 } 451 } 452 453 boolean editable = getModel().isCellEditable(row, column); 457 458 if (editable && ((e == null) || e instanceof KeyEvent ) && (column == 0)) { 461 editable = false; 462 column = 1; 463 } 464 465 boolean columnShifted = false; 466 467 if (!editable && (e instanceof KeyEvent || (e == null))) { 468 for (int i = column; i < getColumnCount(); i++) { 469 if (getModel().isCellEditable(row, i)) { 470 columnShifted = i != column; 471 column = i; 472 changeSelection(row, column, false, false); 473 474 break; 475 } 476 } 477 } 478 479 final Rectangle r = getCellRect(row, column, true); 480 481 boolean canTryCustomEditor = (!columnShifted && e instanceof MouseEvent ) 483 ? ((((MouseEvent ) e).getX() > ((r.x + r.width) - 24)) && (((MouseEvent ) e).getX() < (r.x + r.width))) : true; 484 485 try { 486 canEdit = (lastRow == row); 487 488 Object o = getValueAt(row, column); 489 490 if (o instanceof Property) { 492 Property p = (Property) o; 494 495 if (p.canWrite() && ((p.getValueType() == Boolean .class) || (p.getValueType() == Boolean.TYPE))) { 496 try { 497 Boolean val = (Boolean ) p.getValue(); 498 499 if (Boolean.FALSE.equals(val)) { 500 p.setValue(Boolean.TRUE); 501 } else { 502 p.setValue(Boolean.FALSE); 504 } 505 506 repaint(r.x, r.y, r.width, r.height); 507 508 return false; 509 } catch (Exception e1) { 510 Logger.getLogger(TreeTable.class.getName()).log(Level.WARNING, null, e1); 511 512 return false; 513 } 514 } else if (canTryCustomEditor && !Boolean.TRUE.equals(p.getValue("suppressCustomEditor"))) { 516 PropertyPanel panel = new PropertyPanel(p); 517 PropertyEditor ed = panel.getPropertyEditor(); 518 519 if ((ed != null) && ed.supportsCustomEditor()) { 520 Action act = panel.getActionMap().get("invokeCustomEditor"); 522 if (act != null) { 523 SwingUtilities.invokeLater( 524 new Runnable () { 525 public void run() { 526 r.x = 0; 527 r.width = getWidth(); 528 TreeTable.this.repaint(r); 529 } 530 } 531 ); 532 act.actionPerformed(null); 533 534 return false; 535 } 536 } 537 } 538 539 if (!p.canWrite()) { 540 return false; 541 } 542 } 543 544 boolean ret = super.editCellAt(row, column, e); 545 546 if (ret) { 547 if (column == getTreeColumnIndex()) { 549 ignoreScrolling = true; 550 tree.scrollRectToVisible(tree.getRowBounds(row)); 551 ignoreScrolling = false; 552 } else { 553 SwingUtilities.invokeLater(this); 554 } 555 } 556 557 return ret; 558 } finally { 559 inEditRequest = false; 560 } 561 } 562 563 566 public void run() { 567 if ((editorComp != null) && editorComp.isShowing()) { 568 editorComp.requestFocus(); 569 } 570 } 571 572 574 public void valueChanged(ListSelectionEvent e) { 575 if (getSelectedRowCount() == 1) { 576 lastRow = getSelectedRow(); 577 } else { 578 lastRow = -1; 579 } 580 581 super.valueChanged(e); 582 } 583 584 586 public void columnAdded(TableColumnModelEvent e) { 587 super.columnAdded(e); 588 updateTreeColumnIndex(); 589 } 590 591 593 public void columnRemoved(TableColumnModelEvent e) { 594 super.columnRemoved(e); 595 updateTreeColumnIndex(); 596 } 597 598 600 public void columnMoved(TableColumnModelEvent e) { 601 super.columnMoved(e); 602 updateTreeColumnIndex(); 603 604 int from = e.getFromIndex(); 605 int to = e.getToIndex(); 606 607 if (from != to) { 608 firePropertyChange("column_moved", from, to); } 610 } 611 612 614 private void updateTreeColumnIndex() { 615 for (int i = getColumnCount() - 1; i >= 0; i--) { 616 if (getColumnClass(i) == TreeTableModelAdapter.class) { 617 setTreeColumnIndex(i); 618 619 return; 620 } 621 } 622 623 setTreeColumnIndex(-1); 624 } 625 626 628 public int getPositionX() { 629 return positionX; 630 } 631 632 634 public void setPositionX(int x) { 635 if ((x == positionX) || !treeHScrollingEnabled) { 636 return; 637 } 638 639 int old = positionX; 640 positionX = x; 641 642 firePropertyChange("positionX", old, x); 643 644 if (isEditing() && (getEditingColumn() == getTreeColumnIndex())) { 645 CellEditor editor = getCellEditor(); 646 647 if (ignoreScrolling && editor instanceof TreeTableCellEditor) { 648 ((TreeTableCellEditor) editor).revalidateTextField(); 649 } else { 650 removeEditor(); 651 } 652 } 653 654 repaint(); 655 } 656 657 658 public void paintComponent(Graphics g) { 659 super.paintComponent(g); 660 661 if (hasFocus() && (getSelectedColumn() == 0) && (getSelectedRow() > 0)) { 662 Color bdr = UIManager.getColor("Tree.selectionBorderColor"); 664 if (bdr == null) { 665 if (getForeground().equals(Color.BLACK)) { bdr = getBackground().darker(); 669 } else { 670 bdr = getForeground().darker(); 671 } 672 } 673 674 g.setColor(bdr); 675 676 Rectangle r = getCellRect(getSelectedRow(), getSelectedColumn(), false); 677 g.drawRect(r.x + 1, r.y + 1, r.width - 3, r.height - 3); 678 } 679 } 680 681 682 void setTreeHScrollingEnabled(boolean enabled) { 683 treeHScrollingEnabled = enabled; 684 } 685 686 boolean isKnownComponent(Component c) { 687 if (c == null) { 688 return false; 689 } 690 691 if (isAncestorOf(c)) { 692 return true; 693 } 694 695 if (c == editorComp) { 696 return true; 697 } 698 699 if ((editorComp != null) && (editorComp instanceof Container) && ((Container) editorComp).isAncestorOf(c)) { 700 return true; 701 } 702 703 return false; 704 } 705 706 public boolean isValidationRoot() { 707 return true; 708 } 709 710 public void paintImmediately(int x, int y, int w, int h) { 711 if (inEditorChangeRequest) { 713 return; 714 } 715 716 super.paintImmediately(x, y, w, h); 717 } 718 719 protected void processFocusEvent(FocusEvent fe) { 720 super.processFocusEvent(fe); 721 722 if ((fe.getID() == fe.FOCUS_LOST) && !fe.isTemporary() && !inRemoveRequest && !inEditRequest) { 725 boolean stopEditing = ((fe.getOppositeComponent() != getParent()) && 726 !isKnownComponent(fe.getOppositeComponent()) && (fe.getOppositeComponent() != null)); 727 728 if (stopEditing) { 729 removeEditor(); 730 } 731 } 732 733 if (!inRemoveRequest && !inEditRequest) { 737 repaintSelection(fe.getID() == fe.FOCUS_GAINED); 738 } 739 } 740 741 public void removeEditor() { 742 inRemoveRequest = true; 743 744 try { 745 synchronized (getTreeLock()) { 746 super.removeEditor(); 747 } 748 } finally { 749 inRemoveRequest = false; 750 } 751 } 752 753 754 private void repaintSelection(boolean focused) { 755 int start = getSelectionModel().getMinSelectionIndex(); 756 int end = getSelectionModel().getMaxSelectionIndex(); 757 758 if (end != -1) { 759 if (end != start) { 760 Rectangle begin = getCellRect(start, 0, false); 761 Rectangle r = getCellRect(end, 0, false); 762 763 r.y = begin.y; 764 r.x = 0; 765 r.width = getWidth(); 766 r.height = (r.y + r.height) - begin.y; 767 repaint(r.x, r.y, r.width, r.height); 768 } else { 769 Rectangle r = getCellRect(start, 0, false); 770 r.width = getWidth(); 771 r.x = 0; 772 repaint(r.x, r.y, r.width, r.height); 773 } 774 } 775 776 if (isEditing() && (editorComp != null)) { 777 editorComp.setBackground(focused ? getSelectionBackground() : getUnfocusedSelectedBackground()); 778 editorComp.setForeground(focused ? getSelectionForeground() : getUnfocusedSelectedForeground()); 779 } 780 } 781 782 783 static Color getUnfocusedSelectedBackground() { 784 if (unfocusedSelBg == null) { 785 unfocusedSelBg = UIManager.getColor("nb.explorer.unfocusedSelBg"); 788 if (unfocusedSelBg == null) { 789 unfocusedSelBg = UIManager.getColor("controlShadow"); 792 if (unfocusedSelBg == null) { 793 unfocusedSelBg = Color.lightGray; 795 } 796 797 unfocusedSelBg = unfocusedSelBg.brighter(); 800 } 801 } 802 803 return unfocusedSelBg; 804 } 805 806 807 static Color getUnfocusedSelectedForeground() { 808 if (unfocusedSelFg == null) { 809 unfocusedSelFg = UIManager.getColor("nb.explorer.unfocusedSelFg"); 812 if (unfocusedSelFg == null) { 813 unfocusedSelFg = UIManager.getColor("textText"); 816 if (unfocusedSelFg == null) { 817 unfocusedSelFg = Color.BLACK; 819 } 820 } 821 } 822 823 return unfocusedSelFg; 824 } 825 826 protected JTableHeader createDefaultTableHeader() { 827 return new TreeTableHeader( getColumnModel() ); 828 } 829 830 834 private static class TreeTableHeader extends JTableHeader { 835 public TreeTableHeader( TableColumnModel columnModel ) { 836 super( columnModel ); 837 } 838 839 public Dimension getPreferredSize() { 840 841 Dimension retValue = super.getPreferredSize(); 842 843 Component comp = getDefaultRenderer().getTableCellRendererComponent( getTable(), 844 "X", false, false, -1, 0 ); 845 int rendererHeight = comp.getPreferredSize().height; 846 retValue.height = Math.max(retValue.height, rendererHeight); 847 return retValue; 848 } 849 } 850 851 854 class TreeTableCellRenderer extends JTree implements TableCellRenderer { 855 856 protected int visibleRow; 857 858 860 private int oldWidth; 861 private int transY = 0; 862 863 public TreeTableCellRenderer(TreeModel model) { 864 super(model); 865 setToggleClickCount(0); 866 putClientProperty("JTree.lineStyle", "None"); } 868 869 public void validate() { 870 } 872 873 public void repaint(long tm, int x, int y, int width, int height) { 874 } 876 877 public void addHierarchyListener(java.awt.event.HierarchyListener hl) { 878 } 880 881 public void addComponentListener(java.awt.event.ComponentListener cl) { 882 } 884 885 892 TreeTable getTreeTable() { 893 return TreeTable.this; 894 } 895 896 900 public void setRowHeight(int rowHeight) { 901 if (rowHeight > 0) { 902 super.setRowHeight(rowHeight); 903 TreeTable.this.setRowHeight(rowHeight); 904 } 905 } 906 907 911 public void setBounds(int x, int y, int w, int h) { 912 transY = -y; 913 super.setBounds(0, 0, TreeTable.this.getColumnModel().getColumn(0).getWidth(), TreeTable.this.getHeight()); 914 } 915 916 918 @SuppressWarnings ("deprecation") 919 public void reshape(int x, int y, int w, int h) { 920 int oldWidth = getWidth(); 921 super.reshape(x, y, w, h); 922 923 if (oldWidth != w) { 924 firePropertyChange("width", oldWidth, w); 925 } 926 } 927 928 public void paint(Graphics g) { 929 g.translate(-getPositionX(), transY); 930 super.paint(g); 931 } 932 933 public Rectangle getVisibleRect() { 934 Rectangle visibleRect = TreeTable.this.getVisibleRect(); 935 visibleRect.x = positionX; 936 visibleRect.width = TreeTable.this.getColumnModel().getColumn(getTreeColumnIndex()).getWidth(); 937 938 return visibleRect; 939 } 940 941 943 public void scrollRectToVisible(Rectangle aRect) { 944 Rectangle rect = getVisibleRect(); 945 rect.y = aRect.y; 946 rect.height = aRect.height; 947 948 TreeTable.this.scrollRectToVisible(rect); 949 950 int x = rect.x; 951 952 if (aRect.width > rect.width) { 953 x = aRect.x; 954 } else if (aRect.x < rect.x) { 955 x = aRect.x; 956 } else if ((aRect.x + aRect.width) > (rect.x + rect.width)) { 957 x = (aRect.x + aRect.width) - rect.width; 958 } 959 960 TreeTable.this.setPositionX(x); 961 } 962 963 public String getToolTipText(MouseEvent event) { 964 if (event != null) { 965 Point p = event.getPoint(); 966 p.translate(positionX, visibleRow * getRowHeight()); 967 968 int selRow = getRowForLocation(p.x, p.y); 969 970 if (selRow != -1) { 971 TreePath path = getPathForRow(selRow); 972 VisualizerNode v = (VisualizerNode) path.getLastPathComponent(); 973 String tooltip = v.getShortDescription(); 974 String displayName = v.getDisplayName(); 975 976 if ((tooltip != null) && !tooltip.equals(displayName)) { 977 return tooltip; 978 } 979 } 980 } 981 982 return null; 983 } 984 985 988 public Component getTableCellRendererComponent( 989 JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column 990 ) { 991 if (isSelected) { 992 Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); 993 994 boolean tableHasFocus = (focusOwner == this) || (focusOwner == TreeTable.this) || 995 TreeTable.this.isAncestorOf(focusOwner) || focusOwner instanceof JRootPane; 997 setBackground(tableHasFocus ? table.getSelectionBackground() : getUnfocusedSelectedBackground()); 998 setForeground(tableHasFocus ? table.getSelectionForeground() : getUnfocusedSelectedForeground()); 999 } else { 1000 setBackground(table.getBackground()); 1001 setForeground(table.getForeground()); 1002 } 1003 1004 visibleRow = row; 1005 1006 return this; 1007 } 1008 1009 protected TreeModelListener createTreeModelListener() { 1010 return new JTree.TreeModelHandler() { 1011 public void treeNodesRemoved(TreeModelEvent e) { 1012 if (tree.getSelectionCount() == 0) { 1013 TreePath path = TreeView.findSiblingTreePath(e.getTreePath(), e.getChildIndices()); 1014 1015 if ((path != null) && (path.getPathCount() > 0)) { 1016 tree.setSelectionPath(path); 1017 } 1018 } 1019 } 1020 }; 1021 } 1022 1023 public void fireTreeCollapsed(TreePath path) { 1024 super.fireTreeCollapsed(path); 1025 firePropertyChange("width", -1, getWidth()); 1026 } 1027 1028 public void fireTreeExpanded(TreePath path) { 1029 super.fireTreeExpanded(path); 1030 firePropertyChange("width", -1, getWidth()); 1031 } 1032 } 1033 1034 1037 class TreeTableCellEditor extends DefaultCellEditor implements TreeSelectionListener, ActionListener , FocusListener , 1038 CellEditorListener { 1039 1040 protected transient int offset; 1041 1042 1043 protected transient Timer timer; 1044 1045 public TreeTableCellEditor() { 1046 super(new TreeTableTextField()); 1047 1048 tree.addTreeSelectionListener(this); 1049 addCellEditorListener(this); 1050 super.getComponent().addFocusListener(this); 1051 } 1052 1053 1061 public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int r, int c) { 1062 Component component = super.getTableCellEditorComponent(table, value, isSelected, r, c); 1063 1064 determineOffset(value, isSelected, r); 1065 ((TreeTableTextField) getComponent()).offset = offset; 1066 1067 return component; 1068 } 1069 1070 1073 public boolean isCellEditable(EventObject e) { 1074 if (lastRow != -1) { 1075 org.openide.nodes.Node n = Visualizer.findNode(tree.getPathForRow(lastRow).getLastPathComponent()); 1076 1077 if ((n == null) || !n.canRename()) { 1078 canEdit = false; 1080 } 1081 } 1082 1083 if (canEdit && (e != null) && (e.getSource() instanceof Timer)) { 1084 return true; 1085 } 1086 1087 if (canEdit && shouldStartEditingTimer(e)) { 1088 startEditingTimer(); 1089 } else if (shouldStopEditingTimer(e)) { 1090 timer.stop(); 1091 } 1092 1093 if (e instanceof MouseEvent ) { 1094 MouseEvent me = (MouseEvent ) e; 1095 int column = getTreeColumnIndex(); 1096 1097 if (MouseUtils.isLeftMouseButton(me) && (me.getClickCount() == 2)) { 1098 TreePath path = tree.getPathForRow(TreeTable.this.rowAtPoint(me.getPoint())); 1099 Rectangle r = tree.getPathBounds(path); 1100 1101 if ((me.getX() < (r.x - positionX)) || (me.getX() > (r.x - positionX + r.width))) { 1102 me.translatePoint(r.x - me.getX(), 0); 1103 } 1104 } 1105 1106 MouseEvent newME = new MouseEvent ( 1107 TreeTable.this.tree, me.getID(), me.getWhen(), me.getModifiers(), 1108 me.getX() - getCellRect(0, column, true).x + positionX, me.getY(), me.getClickCount(), 1109 me.isPopupTrigger() 1110 ); 1111 TreeTable.this.tree.dispatchEvent(newME); 1112 } 1113 1114 return false; 1115 } 1116 1117 1119 public void valueChanged(TreeSelectionEvent e) { 1120 if (timer != null) { 1121 timer.stop(); 1122 } 1123 } 1124 1125 1127 public void actionPerformed(java.awt.event.ActionEvent e) { 1128 if (lastRow != -1) { 1129 editCellAt(lastRow, getTreeColumnIndex(), new EventObject (timer)); 1130 } 1131 } 1132 1133 1135 private boolean shouldStartEditingTimer(EventObject event) { 1136 if ((event instanceof MouseEvent ) && SwingUtilities.isLeftMouseButton((MouseEvent ) event)) { 1137 MouseEvent me = (MouseEvent ) event; 1138 1139 return ((me.getID() == me.MOUSE_PRESSED) && (me.getClickCount() == 1) && inHitRegion(me)); 1140 } 1141 1142 return false; 1143 } 1144 1145 1147 private boolean shouldStopEditingTimer(EventObject event) { 1148 if (timer == null) { 1149 return false; 1150 } 1151 1152 if (event instanceof MouseEvent ) { 1153 MouseEvent me = (MouseEvent ) event; 1154 1155 return (!SwingUtilities.isLeftMouseButton(me) || (me.getClickCount() > 1)); 1156 } 1157 1158 return false; 1159 } 1160 1161 1164 private void startEditingTimer() { 1165 if (timer == null) { 1166 timer = new Timer(1200, this); 1167 timer.setRepeats(false); 1168 } 1169 1170 timer.start(); 1171 } 1172 1173 1175 private boolean inHitRegion(MouseEvent me) { 1176 determineOffset(me); 1177 1178 if (me.getX() <= offset) { 1179 return false; 1180 } 1181 1182 return true; 1183 } 1184 1185 1187 private void determineOffset(MouseEvent me) { 1188 int row = TreeTable.this.rowAtPoint(me.getPoint()); 1189 1190 if (row == -1) { 1191 offset = 0; 1192 1193 return; 1194 } 1195 1196 determineOffset(tree.getPathForRow(row).getLastPathComponent(), TreeTable.this.isRowSelected(row), row); 1197 } 1198 1199 1201 private void determineOffset(Object value, boolean isSelected, int row) { 1202 JTree t = getTree(); 1203 boolean rv = t.isRootVisible(); 1204 int offsetRow = row; 1205 1206 if (!rv && (row > 0)) { 1207 offsetRow--; 1208 } 1209 1210 Rectangle bounds = t.getRowBounds(offsetRow); 1211 offset = bounds.x; 1212 1213 TreeCellRenderer tcr = t.getCellRenderer(); 1214 Object node = t.getPathForRow(offsetRow).getLastPathComponent(); 1215 Component comp = tcr.getTreeCellRendererComponent( 1216 t, node, isSelected, t.isExpanded(offsetRow), t.getModel().isLeaf(node), offsetRow, false 1217 ); 1218 1219 if (comp instanceof JLabel) { 1220 Icon icon = ((JLabel) comp).getIcon(); 1221 1222 if (icon != null) { 1223 offset += (((JLabel) comp).getIconTextGap() + icon.getIconWidth()); 1224 } 1225 } 1226 1227 offset -= positionX; 1228 } 1229 1230 1232 private void revalidateTextField() { 1233 int row = TreeTable.this.editingRow; 1234 1235 if (row == -1) { 1236 offset = 0; 1237 1238 return; 1239 } 1240 1241 determineOffset(tree.getPathForRow(row).getLastPathComponent(), TreeTable.this.isRowSelected(row), row); 1242 ((TreeTableTextField) super.getComponent()).offset = offset; 1243 getComponent().setBounds(TreeTable.this.getCellRect(row, getTreeColumnIndex(), false)); 1244 } 1245 1246 1248 1250 public void focusLost(java.awt.event.FocusEvent evt) { 1251 1255 } 1256 1257 1259 public void focusGained(java.awt.event.FocusEvent evt) { 1260 ((TreeTableTextField) super.getComponent()).selectAll(); 1261 } 1262 1263 1265 1266 public void editingStopped(ChangeEvent e) { 1267 TreePath lastP = tree.getPathForRow(lastRow); 1268 1269 if (lastP != null) { 1270 Node n = Visualizer.findNode(lastP.getLastPathComponent()); 1271 1272 if ((n != null) && n.canRename()) { 1273 String newStr = (String ) getCellEditorValue(); 1274 1275 try { 1276 if (!n.getName().equals(newStr)) { 1278 n.setName(newStr); 1279 } 1280 } catch (IllegalArgumentException exc) { 1281 boolean needToAnnotate = Exceptions.findLocalizedMessage(exc) == null; 1282 1283 if (needToAnnotate) { 1285 String msg = NbBundle.getMessage( 1286 TreeViewCellEditor.class, "RenameFailed", n.getName(), newStr 1287 ); 1288 Exceptions.attachLocalizedMessage(exc, msg); 1289 } 1290 1291 Exceptions.printStackTrace(exc); 1292 } 1293 } 1294 } 1295 } 1296 1297 1298 public void editingCanceled(ChangeEvent e) { 1299 } 1300 } 1301 1302 1307 static class TreeTableTextField extends JTextField { 1308 public int offset; 1309 1310 @SuppressWarnings ("deprecation") 1311 public void reshape(int x, int y, int w, int h) { 1312 int newX = Math.max(x, offset); 1313 super.reshape(newX, y, w - (newX - x), h); 1314 } 1315 1316 public void addNotify() { 1317 super.addNotify(); 1318 1319 } 1321 } 1322 1328 class ListToTreeSelectionModelWrapper extends DefaultTreeSelectionModel { 1329 1330 protected boolean updatingListSelectionModel; 1331 1332 public ListToTreeSelectionModelWrapper() { 1333 super(); 1334 listSelectionModel = new TreeTableSelectionModel(); 1335 getListSelectionModel().addListSelectionListener(createListSelectionListener()); 1336 } 1337 1338 1343 ListSelectionModel getListSelectionModel() { 1344 return listSelectionModel; 1345 } 1346 1347 1352 public void resetRowSelection() { 1353 if (!updatingListSelectionModel) { 1354 updatingListSelectionModel = true; 1355 1356 try { 1357 super.resetRowSelection(); 1358 } finally { 1359 updatingListSelectionModel = false; 1360 } 1361 } 1362 1363 } 1369 1370 1373 protected ListSelectionListener createListSelectionListener() { 1374 return new ListSelectionHandler(); 1375 } 1376 1377 1382 protected void updateSelectedPathsFromSelectedRows() { 1383 if (!updatingListSelectionModel) { 1384 updatingListSelectionModel = true; 1385 1386 try { 1387 int min = listSelectionModel.getMinSelectionIndex(); 1388 int max = listSelectionModel.getMaxSelectionIndex(); 1389 1390 if ((min == 0) && (max == getRowCount())) { 1391 int[] rows = new int[max]; 1393 1394 for (int i = 0; i < rows.length; i++) { 1395 rows[i] = i; 1396 } 1397 1398 tree.setSelectionRows(rows); 1399 } else { 1400 List <Integer > list = new ArrayList <Integer >(11); 1401 1402 for (int i = min; i <= max; i++) { 1403 if (listSelectionModel.isSelectedIndex(i)) { 1404 list.add(Integer.valueOf(i)); 1405 } 1406 } 1407 1408 if (list.isEmpty()) { 1409 clearSelection(); 1410 } else { 1411 int[] rows = (int[]) Utilities.toPrimitiveArray( 1412 list.toArray(new Integer [list.size()]) 1413 ); 1414 tree.setSelectionRows(rows); 1415 } 1416 } 1417 } finally { 1418 updatingListSelectionModel = false; 1419 } 1420 } 1421 } 1422 1423 1427 class ListSelectionHandler implements ListSelectionListener { 1428 public void valueChanged(ListSelectionEvent e) { 1429 if( inSelectAll || e.getValueIsAdjusting() ) { 1430 return; 1431 } 1432 1433 updateSelectedPathsFromSelectedRows(); 1434 } 1435 } 1436 } 1437 1438 1443 class TreeTableSelectionModel extends DefaultListSelectionModel { 1444 public void setAnchorSelectionIndex(int anchorIndex) { 1445 if( ignoreClearSelection ) 1446 return; 1447 super.setAnchorSelectionIndex(anchorIndex); 1448 } 1449 1450 public void setLeadSelectionIndex(int leadIndex) { 1451 if( ignoreClearSelection ) 1452 return; 1453 super.setLeadSelectionIndex(leadIndex); 1454 } 1455 } 1456 1457 1460 class TreeTableUI extends BasicTableUI { 1461 1464 protected MouseInputListener createMouseInputListener() { 1465 return new TreeTableMouseInputHandler(); 1466 } 1467 1468 public class TreeTableMouseInputHandler extends MouseInputHandler { 1469 private Component dispatchComponent; 1471 1472 public void mouseClicked(MouseEvent e) { 1474 processMouseEvent(e); 1475 } 1476 1477 public void mousePressed(MouseEvent e) { 1478 processMouseEvent(e); 1479 } 1480 1481 public void mouseReleased(MouseEvent e) { 1482 if (shouldIgnore(e)) { 1483 return; 1484 } 1485 1486 repostEvent(e); 1487 dispatchComponent = null; 1488 setValueIsAdjusting(false); 1489 1490 if (!TreeTable.this.isEditing()) { 1491 processMouseEvent(e); 1492 } 1493 } 1494 1495 public void mouseDragged(MouseEvent e) { 1496 return; 1497 } 1498 1499 private void setDispatchComponent(MouseEvent e) { 1500 Component editorComponent = table.getEditorComponent(); 1501 Point p = e.getPoint(); 1502 Point p2 = SwingUtilities.convertPoint(table, p, editorComponent); 1503 dispatchComponent = SwingUtilities.getDeepestComponentAt(editorComponent, p2.x, p2.y); 1504 } 1505 1506 private boolean repostEvent(MouseEvent e) { 1507 if (dispatchComponent == null) { 1508 return false; 1509 } 1510 1511 MouseEvent e2 = SwingUtilities.convertMouseEvent(table, e, dispatchComponent); 1512 dispatchComponent.dispatchEvent(e2); 1513 1514 return true; 1515 } 1516 1517 private void setValueIsAdjusting(boolean flag) { 1518 table.getSelectionModel().setValueIsAdjusting(flag); 1519 table.getColumnModel().getSelectionModel().setValueIsAdjusting(flag); 1520 } 1521 1522 private boolean shouldIgnore(MouseEvent e) { 1523 return !table.isEnabled() || 1524 ((e.getButton() == MouseEvent.BUTTON3) && (e.getClickCount() == 1) && !e.isPopupTrigger()); 1525 } 1526 1527 private boolean isTreeColumn(int column) { 1528 return TreeTable.this.getColumnClass(column) == TreeTableModelAdapter.class; 1529 } 1530 1531 1533 private void processMouseEvent(MouseEvent e) { 1534 if (shouldIgnore(e)) { 1535 return; 1536 } 1537 1538 Point p = e.getPoint(); 1539 int row = table.rowAtPoint(p); 1540 int column = table.columnAtPoint(p); 1541 1542 if ((column == -1) || (row == -1)) { 1544 return; 1545 } 1546 1547 if ((getEditingColumn() == column) && (getEditingRow() == row)) { 1549 return; 1550 } 1551 1552 boolean changeSelection = true; 1553 1554 if (isTreeColumn(column)) { 1555 TreePath path = tree.getPathForRow(TreeTable.this.rowAtPoint(e.getPoint())); 1556 Rectangle r = tree.getPathBounds(path); 1557 1558 if ((e.getX() >= (r.x - positionX)) && (e.getX() <= (r.x - positionX + r.width)) 1559 || isLocationInExpandControl( path, p ) ) { 1560 changeSelection = false; 1561 } 1562 } 1563 1564 if (table.getSelectionModel().isSelectedIndex(row) && e.isPopupTrigger()) { 1565 return; 1566 } 1567 1568 if (table.editCellAt(row, column, e)) { 1569 setDispatchComponent(e); 1570 repostEvent(e); 1571 } 1572 1573 if (e.getID() == MouseEvent.MOUSE_PRESSED) { 1574 table.requestFocus(); 1575 } 1576 1577 CellEditor editor = table.getCellEditor(); 1578 1579 if (changeSelection && ((editor == null) || editor.shouldSelectCell(e))) { 1580 setValueIsAdjusting(true); 1581 table.changeSelection(row, column, e.isControlDown(), e.isShiftDown()); 1582 } 1583 } 1584 1585 private boolean isLocationInExpandControl( TreePath path, Point location ) { 1586 if( tree.getModel().isLeaf( path.getLastPathComponent() ) ) 1587 return false; 1588 1589 Rectangle r = tree.getPathBounds(path); 1590 int boxWidth = 8; 1591 Insets i = tree.getInsets(); 1592 int indent = 0; 1593 1594 if( tree.getUI() instanceof BasicTreeUI ) { 1595 BasicTreeUI ui = (BasicTreeUI )tree.getUI(); 1596 if( null != ui.getExpandedIcon() ) 1597 boxWidth = ui.getExpandedIcon().getIconWidth(); 1598 1599 indent = ui.getLeftChildIndent(); 1600 } 1601 int boxX; 1602 if( tree.getComponentOrientation().isLeftToRight() ) { 1603 boxX = r.x - positionX - indent - boxWidth; 1604 } else { 1605 boxX = r.x - positionX + indent + r.width; 1606 } 1607 return location.getX() >= boxX && location.getX() <= (boxX + boxWidth); 1608 } 1609 } 1610 } 1611 1612 1614 class TreeTableAction extends AbstractAction { 1615 Action treeAction; 1616 Action tableAction; 1617 1618 TreeTableAction(Action treeAction, Action tableAction) { 1619 this.treeAction = treeAction; 1620 this.tableAction = tableAction; 1621 } 1622 1623 public void actionPerformed(ActionEvent e) { 1624 if (TreeTable.this.getSelectedColumn() == getTreeColumnIndex()) { 1625 e.setSource(getTree()); 1629 treeAction.actionPerformed(e); 1630 } else { 1631 tableAction.actionPerformed(e); 1632 } 1633 } 1634 } 1635 1636 1638 private class STPolicy extends ContainerOrderFocusTraversalPolicy { 1639 public Component getComponentAfter(Container focusCycleRoot, Component aComponent) { 1640 if (inRemoveRequest) { 1641 return TreeTable.this; 1642 } else { 1643 Component result = super.getComponentAfter(focusCycleRoot, aComponent); 1644 1645 return result; 1646 } 1647 } 1648 1649 public Component getComponentBefore(Container focusCycleRoot, Component aComponent) { 1650 if (inRemoveRequest) { 1651 return TreeTable.this; 1652 } else { 1653 return super.getComponentBefore(focusCycleRoot, aComponent); 1654 } 1655 } 1656 1657 public Component getFirstComponent(Container focusCycleRoot) { 1658 if (!inRemoveRequest && isEditing()) { 1659 return editorComp; 1660 } else { 1661 return TreeTable.this; 1662 } 1663 } 1664 1665 public Component getDefaultComponent(Container focusCycleRoot) { 1666 if (inRemoveRequest && isEditing() && editorComp.isShowing()) { 1667 return editorComp; 1668 } else { 1669 return TreeTable.this; 1670 } 1671 } 1672 1673 protected boolean accept(Component aComponent) { 1674 if (isEditing() && inEditRequest) { 1677 return isKnownComponent(aComponent); 1678 } 1679 1680 return super.accept(aComponent) && aComponent.isShowing(); 1681 } 1682 } 1683 1684 1686 private final class NavigationAction extends AbstractAction { 1687 private boolean direction; 1688 1689 public NavigationAction(boolean direction) { 1690 this.direction = direction; 1691 } 1692 1693 public void actionPerformed(ActionEvent e) { 1694 if (isEditing()) { 1695 removeEditor(); 1696 } 1697 1698 int targetRow; 1699 int targetColumn; 1700 1701 if (direction) { 1702 if (getSelectedColumn() == (getColumnCount() - 1)) { 1703 targetColumn = 0; 1704 targetRow = getSelectedRow() + 1; 1705 } else { 1706 targetColumn = getSelectedColumn() + 1; 1707 targetRow = getSelectedRow(); 1708 } 1709 } else { 1710 if (getSelectedColumn() <= 0) { 1711 targetColumn = getColumnCount() - 1; 1712 targetRow = getSelectedRow() - 1; 1713 } else { 1714 targetRow = getSelectedRow(); 1715 targetColumn = getSelectedColumn() - 1; 1716 } 1717 } 1718 1719 if ((targetRow >= getRowCount()) || (targetRow < 0)) { 1722 Container ancestor = getFocusCycleRootAncestor(); 1724 1725 Component sibling = direction 1727 ? ancestor.getFocusTraversalPolicy().getComponentAfter(ancestor, TreeTable.this.getParent()) 1728 : ancestor.getFocusTraversalPolicy().getComponentBefore(ancestor, TreeTable.this); 1729 1730 if (sibling == TreeTable.this) { 1734 Container grandcestor = ancestor.getFocusCycleRootAncestor(); 1735 1736 if (grandcestor != null) { 1737 sibling = direction 1738 ? grandcestor.getFocusTraversalPolicy().getComponentAfter(grandcestor, ancestor) 1739 : grandcestor.getFocusTraversalPolicy().getComponentBefore(grandcestor, ancestor); 1740 ancestor = grandcestor; 1741 } 1742 } 1743 1744 if (sibling == TreeTable.this) { 1748 if (ancestor.getFocusTraversalPolicy().getFirstComponent(ancestor) != null) { 1749 sibling = ancestor.getFocusTraversalPolicy().getFirstComponent(ancestor); 1750 } 1751 } 1752 1753 if (sibling == TreeTable.this) { 1755 JRootPane rp = getRootPane(); 1756 JButton jb = rp.getDefaultButton(); 1757 1758 if (jb != null) { 1759 sibling = jb; 1760 } 1761 } 1762 1763 if (sibling != null) { 1767 if (sibling == TreeTable.this) { 1768 changeSelection( 1770 direction ? 0 : (getRowCount() - 1), direction ? 0 : (getColumnCount() - 1), false, false 1771 ); 1772 } else { 1773 sibling.requestFocus(); 1775 } 1776 1777 return; 1778 } 1779 } 1780 1781 changeSelection(targetRow, targetColumn, false, false); 1782 } 1783 } 1784 1785 1786 private class EditAction extends AbstractAction { 1787 public void actionPerformed(ActionEvent e) { 1788 int row = getSelectedRow(); 1789 int col = getSelectedColumn(); 1790 1791 if (col == 0) { 1792 col = 1; 1793 } 1794 1795 editCellAt(row, col, null); 1796 } 1797 1798 public boolean isEnabled() { 1799 return (getSelectedRow() != -1) && (getSelectedColumn() != -1) && !isEditing(); 1800 } 1801 } 1802 1803 1804 private class CancelEditAction extends AbstractAction { 1805 public void actionPerformed(ActionEvent e) { 1806 if (isEditing() || (editorComp != null)) { 1807 removeEditor(); 1808 1809 return; 1810 } else { 1811 Component c = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); 1812 1813 InputMap imp = getRootPane().getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); 1814 ActionMap am = getRootPane().getActionMap(); 1815 1816 KeyStroke escape = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false); 1817 Object key = imp.get(escape); 1818 1819 if (key == null) { 1820 key = "Cancel"; 1822 } 1823 1824 if (key != null) { 1825 Action a = am.get(key); 1826 1827 if (a != null) { 1828 String commandKey = (String ) a.getValue(Action.ACTION_COMMAND_KEY); 1829 1830 if (commandKey == null) { 1831 commandKey = key.toString(); 1832 } 1833 1834 a.actionPerformed(new ActionEvent (this, ActionEvent.ACTION_PERFORMED, commandKey)); } 1836 } 1837 } 1838 } 1839 1840 public boolean isEnabled() { 1841 return isEditing(); 1842 } 1843 } 1844 1845 private class EnterAction extends AbstractAction { 1846 public void actionPerformed(ActionEvent e) { 1847 JRootPane jrp = getRootPane(); 1848 1849 if (jrp != null) { 1850 JButton b = getRootPane().getDefaultButton(); 1851 1852 if ((b != null) && b.isEnabled()) { 1853 b.doClick(); 1854 } 1855 } 1856 } 1857 1858 public boolean isEnabled() { 1859 return !isEditing() && !inRemoveRequest; 1860 } 1861 } 1862 1863 private class CTRLTabAction extends AbstractAction { 1864 public void actionPerformed(ActionEvent e) { 1865 setFocusCycleRoot(false); 1866 1867 try { 1868 Container con = TreeTable.this.getFocusCycleRootAncestor(); 1869 1870 if (con != null) { 1871 Component target = TreeTable.this; 1872 1873 if (getParent() instanceof JViewport) { 1874 target = getParent().getParent(); 1875 1876 if (target == con) { 1877 target = TreeTable.this; 1878 } 1879 } 1880 1881 EventObject eo = EventQueue.getCurrentEvent(); 1882 boolean backward = false; 1883 1884 if (eo instanceof KeyEvent ) { 1885 backward = ((((KeyEvent ) eo).getModifiers() & KeyEvent.SHIFT_MASK) != 0) && 1886 ((((KeyEvent ) eo).getModifiersEx() & KeyEvent.SHIFT_DOWN_MASK) != 0); 1887 } 1888 1889 Component to = backward ? con.getFocusTraversalPolicy().getComponentAfter(con, TreeTable.this) 1890 : con.getFocusTraversalPolicy().getComponentAfter(con, TreeTable.this); 1891 1892 if (to == TreeTable.this) { 1893 to = backward ? con.getFocusTraversalPolicy().getFirstComponent(con) 1894 : con.getFocusTraversalPolicy().getLastComponent(con); 1895 } 1896 1897 to.requestFocus(); 1898 } 1899 } finally { 1900 setFocusCycleRoot(true); 1901 } 1902 } 1903 } 1904} 1905 | Popular Tags |