Source Code Cross Referenced for TreeTable.java in  » IDE-Netbeans » openide » org » openide » explorer » view » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Netbeans » openide » org.openide.explorer.view 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         *
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common
0008:         * Development and Distribution License("CDDL") (collectively, the
0009:         * "License"). You may not use this file except in compliance with the
0010:         * License. You can obtain a copy of the License at
0011:         * http://www.netbeans.org/cddl-gplv2.html
0012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013:         * specific language governing permissions and limitations under the
0014:         * License.  When distributing the software, include this License Header
0015:         * Notice in each file and include the License file at
0016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
0017:         * particular file as subject to the "Classpath" exception as provided
0018:         * by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code. If applicable, add the following below the
0020:         * License Header, with the fields enclosed by brackets [] replaced by
0021:         * your own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         *
0024:         * Contributor(s):
0025:         *
0026:         * The Original Software is NetBeans. The Initial Developer of the Original
0027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
0028:         * Microsystems, Inc. All Rights Reserved.
0029:         *
0030:         * If you wish your version of this file to be governed by only the CDDL
0031:         * or only the GPL Version 2, indicate your decision by adding
0032:         * "[Contributor] elects to include this software in this distribution
0033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034:         * single choice of license, a recipient has the option to distribute
0035:         * your version of this file under either the CDDL, the GPL Version 2 or
0036:         * to extend the choice of license to its licensees as provided above.
0037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0038:         * Version 2 license, then the option applies only if the new code is
0039:         * made subject to such option by the copyright holder.
0040:         */
0041:        package org.openide.explorer.view;
0042:
0043:        import javax.swing.table.TableColumnModel;
0044:        import org.openide.awt.MouseUtils;
0045:        import org.openide.explorer.propertysheet.PropertyPanel;
0046:        import org.openide.nodes.Node;
0047:        import org.openide.nodes.Node.Property;
0048:        import org.openide.util.NbBundle;
0049:        import org.openide.util.Utilities;
0050:
0051:        import java.awt.*;
0052:        import java.awt.event.ActionEvent;
0053:        import java.awt.event.ActionListener;
0054:        import java.awt.event.FocusEvent;
0055:        import java.awt.event.FocusListener;
0056:        import java.awt.event.KeyEvent;
0057:        import java.awt.event.MouseEvent;
0058:
0059:        import java.beans.PropertyEditor;
0060:
0061:        import java.util.ArrayList;
0062:        import java.util.Collections;
0063:        import java.util.EventObject;
0064:        import java.util.List;
0065:        import java.util.logging.Level;
0066:        import java.util.logging.Logger;
0067:
0068:        import javax.swing.*;
0069:        import javax.swing.event.*;
0070:        import javax.swing.plaf.basic.BasicTableUI;
0071:        import javax.swing.plaf.basic.BasicTreeUI;
0072:        import javax.swing.table.JTableHeader;
0073:        import javax.swing.table.TableCellEditor;
0074:        import javax.swing.table.TableCellRenderer;
0075:        import javax.swing.table.TableColumn;
0076:        import javax.swing.tree.*;
0077:        import org.openide.util.Exceptions;
0078:
0079:        /**
0080:         * TreeTable implementation.
0081:         *
0082:         * @author Jan Rojcek
0083:         */
0084:        class TreeTable extends JTable implements  Runnable {
0085:            /** Action key for up/down focus action */
0086:            private static final String ACTION_FOCUS_NEXT = "focusNext"; //NOI18N
0087:            private static Color unfocusedSelBg = null;
0088:            private static Color unfocusedSelFg = null;
0089:
0090:            /** A subclass of JTree. */
0091:            private TreeTableCellRenderer tree;
0092:            private NodeTableModel tableModel;
0093:            private int treeColumnIndex = -1;
0094:
0095:            /** Tree editor stuff. */
0096:            private int lastRow = -1;
0097:            private boolean canEdit;
0098:            private boolean ignoreScrolling = false;
0099:
0100:            /** Flag to ignore clearSelection() called from super.tableChanged(). */
0101:            private boolean ignoreClearSelection = false;
0102:
0103:            /** Position of tree renderer, used for horizontal scrolling. */
0104:            private int positionX;
0105:
0106:            /** If true, horizontal scrolling of tree column is enabled in TreeTableView */
0107:            private boolean treeHScrollingEnabled = true;
0108:            private final ListToTreeSelectionModelWrapper selectionWrapper;
0109:            private boolean edCreated = false;
0110:            boolean inSelectAll = false;
0111:            private boolean needCalcRowHeight = true;
0112:            boolean inEditRequest = false;
0113:            boolean inEditorChangeRequest = false;
0114:            int editRow = -1;
0115:            private boolean inRemoveRequest = false;
0116:
0117:            private TableSheetCell tableCell;
0118:
0119:            public TreeTable(NodeTreeModel treeModel, NodeTableModel tableModel) {
0120:                super ();
0121:
0122:                setSurrendersFocusOnKeystroke(true);
0123:
0124:                this .tree = new TreeTableCellRenderer(treeModel);
0125:                this .tableModel = new TreeTableModelAdapter(tree, tableModel);
0126:
0127:                tree.setCellRenderer(new NodeRenderer());
0128:
0129:                // Install a tableModel representing the visible rows in the tree. 
0130:                setModel(this .tableModel);
0131:
0132:                // Force the JTable and JTree to share their row selection models. 
0133:                selectionWrapper = new ListToTreeSelectionModelWrapper();
0134:                tree.setSelectionModel(selectionWrapper);
0135:                setSelectionModel(selectionWrapper.getListSelectionModel());
0136:                getTableHeader().setReorderingAllowed(false);
0137:
0138:                // Install the tree editor renderer and editor. 
0139:                setDefaultRenderer(TreeTableModelAdapter.class, tree);
0140:
0141:                // Install property renderer and editor.
0142:                tableCell = new TableSheetCell(this .tableModel);
0143:                tableCell.setFlat(true);
0144:                setDefaultRenderer(Property.class, tableCell);
0145:                setDefaultEditor(Property.class, tableCell);
0146:                getTableHeader().setDefaultRenderer(tableCell);
0147:                getAccessibleContext().setAccessibleName(
0148:                        NbBundle.getBundle(TreeTable.class).getString(
0149:                                "ACSN_TreeTable")); // NOI18N
0150:                getAccessibleContext().setAccessibleDescription( // NOI18N
0151:                        NbBundle.getBundle(TreeTable.class).getString(
0152:                                "ACSD_TreeTable")); // NOI18N
0153:
0154:                setFocusCycleRoot(true);
0155:                setFocusTraversalPolicy(new STPolicy());
0156:                putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
0157:                putClientProperty("JTable.autoStartsEdit", Boolean.FALSE);
0158:
0159:                initKeysAndActions();
0160:            }
0161:
0162:            private void initKeysAndActions() {
0163:                setFocusTraversalKeys(
0164:                        KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
0165:                        Collections.<AWTKeyStroke> emptySet());
0166:                setFocusTraversalKeys(
0167:                        KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
0168:                        Collections.<AWTKeyStroke> emptySet());
0169:
0170:                //Next two lines do not work using inputmap/actionmap, but do work
0171:                //using the older API.  We will process ENTER to skip to next row,
0172:                //not next cell
0173:                unregisterKeyboardAction(KeyStroke.getKeyStroke(
0174:                        KeyEvent.VK_ENTER, 0));
0175:                unregisterKeyboardAction(KeyStroke.getKeyStroke(
0176:                        KeyEvent.VK_ENTER, Event.SHIFT_MASK));
0177:
0178:                InputMap imp = getInputMap(WHEN_FOCUSED);
0179:                InputMap imp2 = getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
0180:                ActionMap am = getActionMap();
0181:
0182:                // copied from TreeView which tried to fix #18292
0183:                // by doing this
0184:                imp2.put(KeyStroke.getKeyStroke("control C"), "none"); // NOI18N
0185:                imp2.put(KeyStroke.getKeyStroke("control V"), "none"); // NOI18N
0186:                imp2.put(KeyStroke.getKeyStroke("control X"), "none"); // NOI18N
0187:                imp2.put(KeyStroke.getKeyStroke("COPY"), "none"); // NOI18N
0188:                imp2.put(KeyStroke.getKeyStroke("PASTE"), "none"); // NOI18N
0189:                imp2.put(KeyStroke.getKeyStroke("CUT"), "none"); // NOI18N
0190:
0191:                imp.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB,
0192:                        KeyEvent.CTRL_MASK | KeyEvent.SHIFT_MASK, false),
0193:                        ACTION_FOCUS_NEXT);
0194:                imp.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB,
0195:                        KeyEvent.CTRL_MASK, false), ACTION_FOCUS_NEXT);
0196:
0197:                Action ctrlTab = new CTRLTabAction();
0198:                am.put(ACTION_FOCUS_NEXT, ctrlTab);
0199:
0200:                getActionMap().put(
0201:                        "selectNextColumn", // NOI18N
0202:                        new TreeTableAction(tree.getActionMap().get(
0203:                                "selectChild"), // NOI18N
0204:                                getActionMap().get("selectNextColumn"))); // NOI18N
0205:                getActionMap().put(
0206:                        "selectPreviousColumn", // NOI18N
0207:                        new TreeTableAction(tree.getActionMap().get(
0208:                                "selectParent"), // NOI18N
0209:                                getActionMap().get("selectPreviousColumn"))); // NOI18N
0210:
0211:                getAccessibleContext().setAccessibleName(
0212:                        NbBundle.getBundle(TreeTable.class).getString(
0213:                                "ACSN_TreeTable")); // NOI18N
0214:                getAccessibleContext().setAccessibleDescription( // NOI18N
0215:                        NbBundle.getBundle(TreeTable.class).getString(
0216:                                "ACSD_TreeTable")); // NOI18N
0217:
0218:                imp.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, false),
0219:                        "beginEdit");
0220:                getActionMap().put("beginEdit", new EditAction());
0221:
0222:                imp2.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false),
0223:                        "cancelEdit");
0224:                getActionMap().put("cancelEdit", new CancelEditAction());
0225:
0226:                imp.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false),
0227:                        "enter");
0228:                getActionMap().put("enter", new EnterAction());
0229:
0230:                imp.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), "next");
0231:
0232:                imp.put(KeyStroke.getKeyStroke(KeyEvent.VK_TAB,
0233:                        KeyEvent.SHIFT_DOWN_MASK), "previous");
0234:
0235:                am.put("next", new NavigationAction(true));
0236:                am.put("previous", new NavigationAction(false));
0237:            }
0238:
0239:            public TableCellEditor getDefaultEditor(Class columnClass) {
0240:                if (!edCreated && (columnClass == TreeTableModelAdapter.class)) {
0241:                    //Creating this editor in the constructor can take > 100ms even
0242:                    //on a very fast machine, so do it lazily here to improve 
0243:                    //performance of creating a TreeTable
0244:                    setDefaultEditor(TreeTableModelAdapter.class,
0245:                            new TreeTableCellEditor());
0246:                    edCreated = true;
0247:                }
0248:
0249:                return super .getDefaultEditor(columnClass);
0250:            }
0251:
0252:            public void selectAll() {
0253:                //#48242 - select all over 1000 nodes generates 1000 re-sorts
0254:                inSelectAll = true;
0255:
0256:                try {
0257:                    super .selectAll();
0258:                } finally {
0259:                    inSelectAll = false;
0260:                    selectionWrapper.updateSelectedPathsFromSelectedRows();
0261:                }
0262:            }
0263:
0264:            /*
0265:             * Overridden to message super and forward the method to the tree.
0266:             */
0267:            public void updateUI() {
0268:                super .updateUI();
0269:
0270:                if (tree != null) {
0271:                    tree.updateUI();
0272:                }
0273:
0274:                if (null != tableCell) {
0275:                    tableCell.updateUI();
0276:                }
0277:
0278:                // Use the tree's default foreground and background colors in the
0279:                // table. 
0280:                LookAndFeel.installColorsAndFont(this , "Tree.background", // NOI18N
0281:                        "Tree.foreground", "Tree.font"); // NOI18N
0282:
0283:                if (UIManager.getColor("Table.selectionBackground") == null) { // NOI18N
0284:                    UIManager.put("Table.selectionBackground", new JTable()
0285:                            .getSelectionBackground()); // NOI18N
0286:                }
0287:
0288:                if (UIManager.getColor("Table.selectionForeground") == null) { // NOI18N
0289:                    UIManager.put("Table.selectionForeground", new JTable()
0290:                            .getSelectionForeground()); // NOI18N
0291:                }
0292:
0293:                if (UIManager.getColor("Table.gridColor") == null) { // NOI18N
0294:                    UIManager.put("Table.gridColor", new JTable()
0295:                            .getGridColor()); // NOI18N
0296:                }
0297:
0298:                setUI(new TreeTableUI());
0299:                needCalcRowHeight = true;
0300:            }
0301:
0302:            /* Workaround for BasicTableUI anomaly. Make sure the UI never tries to
0303:             * paint the editor. The UI currently uses different techniques to
0304:             * paint the renderers and editors and overriding setBounds() below
0305:             * is not the right thing to do for an editor. Returning -1 for the
0306:             * editing row in this case, ensures the editor is never painted.
0307:             */
0308:            public int getEditingRow() {
0309:                return (getColumnClass(editingColumn) == TreeTableModelAdapter.class) ? (-1)
0310:                        : editingRow;
0311:            }
0312:
0313:            /** Overridden - JTable's implementation of the method will
0314:             *  actually attach (and leave behind) a gratuitous border
0315:             *  on the enclosing scroll pane. */
0316:            protected final void configureEnclosingScrollPane() {
0317:                Container p = getParent();
0318:
0319:                if (p instanceof  JViewport) {
0320:                    Container gp = p.getParent();
0321:
0322:                    if (gp instanceof  JScrollPane) {
0323:                        JScrollPane scrollPane = (JScrollPane) gp;
0324:                        JViewport viewport = scrollPane.getViewport();
0325:
0326:                        if ((viewport == null) || (viewport.getView() != this )) {
0327:                            return;
0328:                        }
0329:
0330:                        JTableHeader jth = getTableHeader();
0331:
0332:                        if (jth != null) {
0333:                            jth.setBorder(null);
0334:                        }
0335:
0336:                        scrollPane.setColumnHeaderView(jth);
0337:                    }
0338:                }
0339:            }
0340:
0341:            public void paint(Graphics g) {
0342:                if (needCalcRowHeight) {
0343:                    calcRowHeight(g);
0344:
0345:                    return;
0346:                }
0347:
0348:                /*
0349:                long time = perf.highResCounter();
0350:                 */
0351:                super .paint(g);
0352:
0353:                /*
0354:                double dur = perf.highResCounter()-time;
0355:
0356:                total += dur;
0357:                System.err.println("Paint time: " + total + " ticks = " + (total / perf.highResFrequency()) + " ms. ");
0358:                 */
0359:            }
0360:
0361:            //   private static final sun.misc.Perf perf = sun.misc.Perf.getPerf();
0362:            //   private static double total = 0; 
0363:
0364:            /** Calculate the height of rows based on the current font.  This is
0365:             *  done when the first paint occurs, to ensure that a valid Graphics
0366:             *  object is available.
0367:             *  @since 1.25   */
0368:            private void calcRowHeight(Graphics g) {
0369:                Font f = getFont();
0370:                FontMetrics fm = g.getFontMetrics(f);
0371:                int rowHeight = fm.getHeight() + fm.getMaxDescent();
0372:                needCalcRowHeight = false;
0373:                rowHeight = Math.max(20, rowHeight);
0374:                tree.setRowHeight(rowHeight);
0375:                setRowHeight(rowHeight);
0376:            }
0377:
0378:            /**
0379:             * Returns the tree that is being shared between the model.
0380:             */
0381:            JTree getTree() {
0382:                return tree;
0383:            }
0384:
0385:            /**
0386:             * Returns table column index of the column displaying the tree.
0387:             */
0388:            int getTreeColumnIndex() {
0389:                return treeColumnIndex;
0390:            }
0391:
0392:            /**
0393:             * Sets tree column index and fires property change.
0394:             */
0395:            void setTreeColumnIndex(int index) {
0396:                if (treeColumnIndex == index) {
0397:                    return;
0398:                }
0399:
0400:                int old = treeColumnIndex;
0401:                treeColumnIndex = index;
0402:                firePropertyChange("treeColumnIndex", old, treeColumnIndex);
0403:            }
0404:
0405:            /* Overriden to do not clear a selection upon model changes.
0406:             */
0407:            public void clearSelection() {
0408:                if (!ignoreClearSelection) {
0409:                    super .clearSelection();
0410:                }
0411:            }
0412:
0413:            /* Updates tree column name and sets ignoreClearSelection flag.
0414:             */
0415:            public void tableChanged(TableModelEvent e) {
0416:                // update tree column name
0417:                int modelColumn = getTreeColumnIndex();
0418:
0419:                if ((e.getFirstRow() <= 0) && (modelColumn != -1)
0420:                        && (getColumnCount() > 0)) {
0421:                    String columnName = getModel().getColumnName(modelColumn);
0422:                    TableColumn aColumn = getColumnModel().getColumn(
0423:                            modelColumn);
0424:                    aColumn.setHeaderValue(columnName);
0425:                }
0426:
0427:                ignoreClearSelection = true;
0428:
0429:                try {
0430:                    super .tableChanged(e);
0431:                    //#61728 - force update of tree's horizontal scrollbar
0432:                    if (null != getTree()) {
0433:                        firePropertyChange("positionX", -1, getPositionX());
0434:                    }
0435:                } finally {
0436:                    ignoreClearSelection = false;
0437:                }
0438:            }
0439:
0440:            public void processKeyEvent(KeyEvent e) {
0441:                //Manually hook in the bindings for tab - does not seem to get called
0442:                //automatically
0443:                if (isEditing()
0444:                        && ((e.getKeyCode() == e.VK_DOWN) || (e.getKeyCode() == e.VK_UP))) {
0445:                    return; //XXX
0446:                }
0447:
0448:                //Bypass standard tab and escape handling, and use our registered
0449:                //actions instead
0450:                if (!isEditing()
0451:                        || (((e.getKeyCode() != e.VK_TAB) && (e.getKeyCode() != e.VK_ESCAPE)) || ((e
0452:                                .getModifiers() & e.CTRL_MASK) != 0))) {
0453:                    super .processKeyEvent(e);
0454:                } else {
0455:                    processKeyBinding(KeyStroke.getKeyStroke(e.getKeyCode(), e
0456:                            .getModifiersEx(), e.getID() == e.KEY_RELEASED), e,
0457:                            JComponent.WHEN_FOCUSED, e.getID() == e.KEY_PRESSED);
0458:                }
0459:            }
0460:
0461:            /* Performs horizontal scrolling of the tree when editing is started.
0462:             */
0463:            public boolean editCellAt(int row, int column, EventObject e) {
0464:                if (e instanceof  MouseEvent && (column != 0)) {
0465:                    MouseEvent me = (MouseEvent) e;
0466:
0467:                    if (!SwingUtilities.isLeftMouseButton(me)
0468:                            || (me.getID() != me.MOUSE_PRESSED)) {
0469:                        return false;
0470:                    }
0471:                }
0472:
0473:                if ((row >= getRowCount()) || (row < 0)
0474:                        || (column > getColumnCount()) || (column < 0)) {
0475:                    //I don't want to know why this happens, but it does.
0476:                    return false;
0477:                }
0478:
0479:                inEditRequest = true;
0480:                editRow = row;
0481:
0482:                if ((editingRow == row) && (editingColumn == column)
0483:                        && isEditing()) {
0484:                    //discard edit requests if we're already editing that cell
0485:                    inEditRequest = false;
0486:
0487:                    return false;
0488:                }
0489:
0490:                if (isEditing()) {
0491:                    inEditorChangeRequest = true;
0492:
0493:                    try {
0494:                        removeEditor();
0495:                        changeSelection(row, column, false, false);
0496:                    } finally {
0497:                        inEditorChangeRequest = false;
0498:                    }
0499:                }
0500:
0501:                //Treat a keyEvent request to edit on a non-editable
0502:                //column as a request to edit the nearest column that is
0503:                //editable
0504:                boolean editable = getModel().isCellEditable(row, column);
0505:
0506:                //We never want to invoke node name editing from the keyboard,
0507:                //it doesn't work anyway - better to look for an editable property
0508:                if (editable && ((e == null) || e instanceof  KeyEvent)
0509:                        && (column == 0)) {
0510:                    editable = false;
0511:                    column = 1;
0512:                }
0513:
0514:                boolean columnShifted = false;
0515:
0516:                if (!editable && (e instanceof  KeyEvent || (e == null))) {
0517:                    for (int i = column; i < getColumnCount(); i++) {
0518:                        if (getModel().isCellEditable(row, i)) {
0519:                            columnShifted = i != column;
0520:                            column = i;
0521:                            changeSelection(row, column, false, false);
0522:
0523:                            break;
0524:                        }
0525:                    }
0526:                }
0527:
0528:                final Rectangle r = getCellRect(row, column, true);
0529:
0530:                //#44226 - Provide a way to invoke the custom editor on disabled cells
0531:                boolean canTryCustomEditor = (!columnShifted && e instanceof  MouseEvent) ? ((((MouseEvent) e)
0532:                        .getX() > ((r.x + r.width) - 24)) && (((MouseEvent) e)
0533:                        .getX() < (r.x + r.width)))
0534:                        : true;
0535:
0536:                try {
0537:                    canEdit = (lastRow == row);
0538:
0539:                    Object o = getValueAt(row, column);
0540:
0541:                    if (o instanceof  Property) { // && (e == null || e instanceof KeyEvent)) {
0542:
0543:                        //Toggle booleans without instantiating an editor
0544:                        Property p = (Property) o;
0545:
0546:                        if (p.canWrite()
0547:                                && ((p.getValueType() == Boolean.class) || (p
0548:                                        .getValueType() == Boolean.TYPE))) {
0549:                            try {
0550:                                Boolean val = (Boolean) p.getValue();
0551:
0552:                                if (Boolean.FALSE.equals(val)) {
0553:                                    p.setValue(Boolean.TRUE);
0554:                                } else {
0555:                                    //This covers null multi-selections too
0556:                                    p.setValue(Boolean.FALSE);
0557:                                }
0558:
0559:                                repaint(r.x, r.y, r.width, r.height);
0560:
0561:                                return false;
0562:                            } catch (Exception e1) {
0563:                                Logger.getLogger(TreeTable.class.getName())
0564:                                        .log(Level.WARNING, null, e1);
0565:
0566:                                return false;
0567:                            }
0568:                        } else if (canTryCustomEditor
0569:                                && !Boolean.TRUE.equals(p
0570:                                        .getValue("suppressCustomEditor"))) { //NOI18N
0571:
0572:                            PropertyPanel panel = new PropertyPanel(p);
0573:                            PropertyEditor ed = panel.getPropertyEditor();
0574:
0575:                            if ((ed != null) && ed.supportsCustomEditor()) {
0576:                                Action act = panel.getActionMap().get(
0577:                                        "invokeCustomEditor"); //NOI18N
0578:
0579:                                if (act != null) {
0580:                                    SwingUtilities.invokeLater(new Runnable() {
0581:                                        public void run() {
0582:                                            r.x = 0;
0583:                                            r.width = getWidth();
0584:                                            TreeTable.this .repaint(r);
0585:                                        }
0586:                                    });
0587:                                    act.actionPerformed(null);
0588:
0589:                                    return false;
0590:                                }
0591:                            }
0592:                        }
0593:
0594:                        if (!p.canWrite()) {
0595:                            return false;
0596:                        }
0597:                    }
0598:
0599:                    boolean ret = super .editCellAt(row, column, e);
0600:
0601:                    if (ret) {
0602:                        //InvokeLater to get out of the way of anything the winsys is going to do
0603:                        if (column == getTreeColumnIndex()) {
0604:                            ignoreScrolling = true;
0605:                            tree.scrollRectToVisible(tree.getRowBounds(row));
0606:                            ignoreScrolling = false;
0607:                        } else {
0608:                            SwingUtilities.invokeLater(this );
0609:                        }
0610:                    }
0611:
0612:                    return ret;
0613:                } finally {
0614:                    inEditRequest = false;
0615:                }
0616:            }
0617:
0618:            /**
0619:             *
0620:             */
0621:            public void run() {
0622:                if ((editorComp != null) && editorComp.isShowing()) {
0623:                    editorComp.requestFocus();
0624:                }
0625:            }
0626:
0627:            /*
0628:             */
0629:            public void valueChanged(ListSelectionEvent e) {
0630:                if (getSelectedRowCount() == 1) {
0631:                    lastRow = getSelectedRow();
0632:                } else {
0633:                    lastRow = -1;
0634:                }
0635:
0636:                super .valueChanged(e);
0637:            }
0638:
0639:            /* Updates tree column index
0640:             */
0641:            public void columnAdded(TableColumnModelEvent e) {
0642:                super .columnAdded(e);
0643:                updateTreeColumnIndex();
0644:            }
0645:
0646:            /* Updates tree column index
0647:             */
0648:            public void columnRemoved(TableColumnModelEvent e) {
0649:                super .columnRemoved(e);
0650:                updateTreeColumnIndex();
0651:            }
0652:
0653:            /* Updates tree column index
0654:             */
0655:            public void columnMoved(TableColumnModelEvent e) {
0656:                super .columnMoved(e);
0657:                updateTreeColumnIndex();
0658:
0659:                int from = e.getFromIndex();
0660:                int to = e.getToIndex();
0661:
0662:                if (from != to) {
0663:                    firePropertyChange("column_moved", from, to); // NOI18N
0664:                }
0665:            }
0666:
0667:            /* Updates tree column index
0668:             */
0669:            private void updateTreeColumnIndex() {
0670:                for (int i = getColumnCount() - 1; i >= 0; i--) {
0671:                    if (getColumnClass(i) == TreeTableModelAdapter.class) {
0672:                        setTreeColumnIndex(i);
0673:
0674:                        return;
0675:                    }
0676:                }
0677:
0678:                setTreeColumnIndex(-1);
0679:            }
0680:
0681:            /** Returns x coordinate of tree renderer.
0682:             */
0683:            public int getPositionX() {
0684:                return positionX;
0685:            }
0686:
0687:            /** Sets x position.
0688:             */
0689:            public void setPositionX(int x) {
0690:                if ((x == positionX) || !treeHScrollingEnabled) {
0691:                    return;
0692:                }
0693:
0694:                int old = positionX;
0695:                positionX = x;
0696:
0697:                firePropertyChange("positionX", old, x);
0698:
0699:                if (isEditing() && (getEditingColumn() == getTreeColumnIndex())) {
0700:                    CellEditor editor = getCellEditor();
0701:
0702:                    if (ignoreScrolling
0703:                            && editor instanceof  TreeTableCellEditor) {
0704:                        ((TreeTableCellEditor) editor).revalidateTextField();
0705:                    } else {
0706:                        removeEditor();
0707:                    }
0708:                }
0709:
0710:                repaint();
0711:            }
0712:
0713:            /** Overridden to manually draw the focused rectangle for the tree column */
0714:            public void paintComponent(Graphics g) {
0715:                super .paintComponent(g);
0716:
0717:                if (hasFocus() && (getSelectedColumn() == 0)
0718:                        && (getSelectedRow() > 0)) {
0719:                    Color bdr = UIManager.getColor("Tree.selectionBorderColor"); //NOI18N
0720:
0721:                    if (bdr == null) {
0722:                        //Button focus color doesn't work on win classic - better to
0723:                        //get the color from a value we know will work - Tim
0724:                        if (getForeground().equals(Color.BLACK)) { //typical
0725:                            bdr = getBackground().darker();
0726:                        } else {
0727:                            bdr = getForeground().darker();
0728:                        }
0729:                    }
0730:
0731:                    g.setColor(bdr);
0732:
0733:                    Rectangle r = getCellRect(getSelectedRow(),
0734:                            getSelectedColumn(), false);
0735:                    g.drawRect(r.x + 1, r.y + 1, r.width - 3, r.height - 3);
0736:                }
0737:            }
0738:
0739:            /** Enables horizontal scrolling of tree column */
0740:            void setTreeHScrollingEnabled(boolean enabled) {
0741:                treeHScrollingEnabled = enabled;
0742:            }
0743:
0744:            boolean isKnownComponent(Component c) {
0745:                if (c == null) {
0746:                    return false;
0747:                }
0748:
0749:                if (isAncestorOf(c)) {
0750:                    return true;
0751:                }
0752:
0753:                if (c == editorComp) {
0754:                    return true;
0755:                }
0756:
0757:                if ((editorComp != null) && (editorComp instanceof  Container)
0758:                        && ((Container) editorComp).isAncestorOf(c)) {
0759:                    return true;
0760:                }
0761:
0762:                return false;
0763:            }
0764:
0765:            public boolean isValidationRoot() {
0766:                return true;
0767:            }
0768:
0769:            public void paintImmediately(int x, int y, int w, int h) {
0770:                //Eliminate duplicate repaints in an editor change request
0771:                if (inEditorChangeRequest) {
0772:                    return;
0773:                }
0774:
0775:                super .paintImmediately(x, y, w, h);
0776:            }
0777:
0778:            protected void processFocusEvent(FocusEvent fe) {
0779:                super .processFocusEvent(fe);
0780:
0781:                //Remove the editor here if the new focus owner is not
0782:                //known to the table & the focus event is not temporary
0783:                if ((fe.getID() == fe.FOCUS_LOST) && !fe.isTemporary()
0784:                        && !inRemoveRequest && !inEditRequest) {
0785:                    boolean stopEditing = ((fe.getOppositeComponent() != getParent())
0786:                            && !isKnownComponent(fe.getOppositeComponent()) && (fe
0787:                            .getOppositeComponent() != null));
0788:
0789:                    if (stopEditing) {
0790:                        removeEditor();
0791:                    }
0792:                }
0793:
0794:                //The UI will only repaint the lead selection, but we need to
0795:                //paint all selected rows for the color to change when focus
0796:                //is lost/gained
0797:                if (!inRemoveRequest && !inEditRequest) {
0798:                    repaintSelection(fe.getID() == fe.FOCUS_GAINED);
0799:                }
0800:            }
0801:
0802:            public void removeEditor() {
0803:                inRemoveRequest = true;
0804:
0805:                try {
0806:                    synchronized (getTreeLock()) {
0807:                        super .removeEditor();
0808:                    }
0809:                } finally {
0810:                    inRemoveRequest = false;
0811:                }
0812:            }
0813:
0814:            /** Repaint the selected row */
0815:            private void repaintSelection(boolean focused) {
0816:                int start = getSelectionModel().getMinSelectionIndex();
0817:                int end = getSelectionModel().getMaxSelectionIndex();
0818:
0819:                if (end != -1) {
0820:                    if (end != start) {
0821:                        Rectangle begin = getCellRect(start, 0, false);
0822:                        Rectangle r = getCellRect(end, 0, false);
0823:
0824:                        r.y = begin.y;
0825:                        r.x = 0;
0826:                        r.width = getWidth();
0827:                        r.height = (r.y + r.height) - begin.y;
0828:                        repaint(r.x, r.y, r.width, r.height);
0829:                    } else {
0830:                        Rectangle r = getCellRect(start, 0, false);
0831:                        r.width = getWidth();
0832:                        r.x = 0;
0833:                        repaint(r.x, r.y, r.width, r.height);
0834:                    }
0835:                }
0836:
0837:                if (isEditing() && (editorComp != null)) {
0838:                    editorComp.setBackground(focused ? getSelectionBackground()
0839:                            : getUnfocusedSelectedBackground());
0840:                    editorComp.setForeground(focused ? getSelectionForeground()
0841:                            : getUnfocusedSelectedForeground());
0842:                }
0843:            }
0844:
0845:            /** Get the system-wide unfocused selection background color */
0846:            static Color getUnfocusedSelectedBackground() {
0847:                if (unfocusedSelBg == null) {
0848:                    //allow theme/ui custom definition
0849:                    unfocusedSelBg = UIManager
0850:                            .getColor("nb.explorer.unfocusedSelBg"); //NOI18N
0851:
0852:                    if (unfocusedSelBg == null) {
0853:                        //try to get standard shadow color
0854:                        unfocusedSelBg = UIManager.getColor("controlShadow"); //NOI18N
0855:
0856:                        if (unfocusedSelBg == null) {
0857:                            //Okay, the look and feel doesn't suport it, punt
0858:                            unfocusedSelBg = Color.lightGray;
0859:                        }
0860:
0861:                        //Lighten it a bit because disabled text will use controlShadow/
0862:                        //gray
0863:                        unfocusedSelBg = unfocusedSelBg.brighter();
0864:                    }
0865:                }
0866:
0867:                return unfocusedSelBg;
0868:            }
0869:
0870:            /** Get the system-wide unfocused selection foreground color */
0871:            static Color getUnfocusedSelectedForeground() {
0872:                if (unfocusedSelFg == null) {
0873:                    //allow theme/ui custom definition
0874:                    unfocusedSelFg = UIManager
0875:                            .getColor("nb.explorer.unfocusedSelFg"); //NOI18N
0876:
0877:                    if (unfocusedSelFg == null) {
0878:                        //try to get standard shadow color
0879:                        unfocusedSelFg = UIManager.getColor("textText"); //NOI18N
0880:
0881:                        if (unfocusedSelFg == null) {
0882:                            //Okay, the look and feel doesn't suport it, punt
0883:                            unfocusedSelFg = Color.BLACK;
0884:                        }
0885:                    }
0886:                }
0887:
0888:                return unfocusedSelFg;
0889:            }
0890:
0891:            protected JTableHeader createDefaultTableHeader() {
0892:                return new TreeTableHeader(getColumnModel());
0893:            }
0894:
0895:            /**
0896:             * #53748: Default TableHeader provides wrong preferred height when the first column
0897:             * uses default renderer and has no value.
0898:             */
0899:            private static class TreeTableHeader extends JTableHeader {
0900:                public TreeTableHeader(TableColumnModel columnModel) {
0901:                    super (columnModel);
0902:                }
0903:
0904:                public Dimension getPreferredSize() {
0905:
0906:                    Dimension retValue = super .getPreferredSize();
0907:
0908:                    Component comp = getDefaultRenderer()
0909:                            .getTableCellRendererComponent(getTable(), "X",
0910:                                    false, false, -1, 0);
0911:                    int rendererHeight = comp.getPreferredSize().height;
0912:                    retValue.height = Math.max(retValue.height, rendererHeight);
0913:                    return retValue;
0914:                }
0915:            }
0916:
0917:            /**
0918:             * A TreeCellRenderer that displays a JTree.
0919:             */
0920:            class TreeTableCellRenderer extends JTree implements 
0921:                    TableCellRenderer {
0922:                /** Last table/tree row asked to renderer. */
0923:                protected int visibleRow;
0924:
0925:                /* Last width of the tree.
0926:                 */
0927:                private int oldWidth;
0928:                private int transY = 0;
0929:
0930:                public TreeTableCellRenderer(TreeModel model) {
0931:                    super (model);
0932:                    setToggleClickCount(0);
0933:                    putClientProperty("JTree.lineStyle", "None"); // NOI18N
0934:                }
0935:
0936:                public void validate() {
0937:                    //do nothing
0938:                }
0939:
0940:                public void repaint(long tm, int x, int y, int width, int height) {
0941:                    //do nothing
0942:                }
0943:
0944:                public void addHierarchyListener(
0945:                        java.awt.event.HierarchyListener hl) {
0946:                    //do nothing
0947:                }
0948:
0949:                public void addComponentListener(
0950:                        java.awt.event.ComponentListener cl) {
0951:                    //do nothing
0952:                }
0953:
0954:                /**
0955:                 * Accessor so NodeRenderer can check if the tree table or its child has
0956:                 * focus and paint with the appropriate color.
0957:                 *
0958:                 * @see NodeRenderer#configureFrom
0959:                 * @return The tree table
0960:                 */
0961:                TreeTable getTreeTable() {
0962:                    return TreeTable.this ;
0963:                }
0964:
0965:                /**
0966:                 * Sets the row height of the tree, and forwards the row height to
0967:                 * the table.
0968:                 */
0969:                public void setRowHeight(int rowHeight) {
0970:                    if (rowHeight > 0) {
0971:                        super .setRowHeight(rowHeight);
0972:                        TreeTable.this .setRowHeight(rowHeight);
0973:                    }
0974:                }
0975:
0976:                /**
0977:                 * Overridden to always set the size to the height of the TreeTable
0978:                 * and the width of column 0.  The paint() method will translate the
0979:                 * coordinates to the correct position. */
0980:                public void setBounds(int x, int y, int w, int h) {
0981:                    transY = -y;
0982:                    super .setBounds(0, 0, TreeTable.this .getColumnModel()
0983:                            .getColumn(0).getWidth(), TreeTable.this 
0984:                            .getHeight());
0985:                }
0986:
0987:                /* Fire width property change so that we can revalidate horizontal scrollbar in TreeTableView.
0988:                 */
0989:                @SuppressWarnings("deprecation")
0990:                public void reshape(int x, int y, int w, int h) {
0991:                    int oldWidth = getWidth();
0992:                    super .reshape(x, y, w, h);
0993:
0994:                    if (oldWidth != w) {
0995:                        firePropertyChange("width", oldWidth, w);
0996:                    }
0997:                }
0998:
0999:                public void paint(Graphics g) {
1000:                    g.translate(-getPositionX(), transY);
1001:                    super .paint(g);
1002:                }
1003:
1004:                public Rectangle getVisibleRect() {
1005:                    Rectangle visibleRect = TreeTable.this .getVisibleRect();
1006:                    visibleRect.x = positionX;
1007:                    visibleRect.width = TreeTable.this .getColumnModel()
1008:                            .getColumn(getTreeColumnIndex()).getWidth();
1009:
1010:                    return visibleRect;
1011:                }
1012:
1013:                /* Overriden to use this call for moving tree renderer.
1014:                 */
1015:                public void scrollRectToVisible(Rectangle aRect) {
1016:                    Rectangle rect = getVisibleRect();
1017:                    rect.y = aRect.y;
1018:                    rect.height = aRect.height;
1019:
1020:                    TreeTable.this .scrollRectToVisible(rect);
1021:
1022:                    int x = rect.x;
1023:
1024:                    if (aRect.width > rect.width) {
1025:                        x = aRect.x;
1026:                    } else if (aRect.x < rect.x) {
1027:                        x = aRect.x;
1028:                    } else if ((aRect.x + aRect.width) > (rect.x + rect.width)) {
1029:                        x = (aRect.x + aRect.width) - rect.width;
1030:                    }
1031:
1032:                    TreeTable.this .setPositionX(x);
1033:                }
1034:
1035:                public String getToolTipText(MouseEvent event) {
1036:                    if (event != null) {
1037:                        Point p = event.getPoint();
1038:                        p.translate(positionX, visibleRow * getRowHeight());
1039:
1040:                        int selRow = getRowForLocation(p.x, p.y);
1041:
1042:                        if (selRow != -1) {
1043:                            TreePath path = getPathForRow(selRow);
1044:                            VisualizerNode v = (VisualizerNode) path
1045:                                    .getLastPathComponent();
1046:                            String tooltip = v.getShortDescription();
1047:                            String displayName = v.getDisplayName();
1048:
1049:                            if ((tooltip != null)
1050:                                    && !tooltip.equals(displayName)) {
1051:                                return tooltip;
1052:                            }
1053:                        }
1054:                    }
1055:
1056:                    return null;
1057:                }
1058:
1059:                /**
1060:                 * TreeCellRenderer method. Overridden to update the visible row.
1061:                 */
1062:                public Component getTableCellRendererComponent(JTable table,
1063:                        Object value, boolean isSelected, boolean hasFocus,
1064:                        int row, int column) {
1065:                    if (isSelected) {
1066:                        Component focusOwner = KeyboardFocusManager
1067:                                .getCurrentKeyboardFocusManager()
1068:                                .getFocusOwner();
1069:
1070:                        boolean tableHasFocus = (focusOwner == this )
1071:                                || (focusOwner == TreeTable.this )
1072:                                || TreeTable.this .isAncestorOf(focusOwner)
1073:                                || focusOwner instanceof  JRootPane; //RootPane == popup menu
1074:
1075:                        setBackground(tableHasFocus ? table
1076:                                .getSelectionBackground()
1077:                                : getUnfocusedSelectedBackground());
1078:                        setForeground(tableHasFocus ? table
1079:                                .getSelectionForeground()
1080:                                : getUnfocusedSelectedForeground());
1081:                    } else {
1082:                        setBackground(table.getBackground());
1083:                        setForeground(table.getForeground());
1084:                    }
1085:
1086:                    visibleRow = row;
1087:
1088:                    return this ;
1089:                }
1090:
1091:                protected TreeModelListener createTreeModelListener() {
1092:                    return new JTree.TreeModelHandler() {
1093:                        public void treeNodesRemoved(TreeModelEvent e) {
1094:                            if (tree.getSelectionCount() == 0) {
1095:                                TreePath path = TreeView.findSiblingTreePath(e
1096:                                        .getTreePath(), e.getChildIndices());
1097:
1098:                                if ((path != null) && (path.getPathCount() > 0)) {
1099:                                    tree.setSelectionPath(path);
1100:                                }
1101:                            }
1102:                        }
1103:                    };
1104:                }
1105:
1106:                public void fireTreeCollapsed(TreePath path) {
1107:                    super .fireTreeCollapsed(path);
1108:                    firePropertyChange("width", -1, getWidth());
1109:                }
1110:
1111:                public void fireTreeExpanded(TreePath path) {
1112:                    super .fireTreeExpanded(path);
1113:                    firePropertyChange("width", -1, getWidth());
1114:                }
1115:            }
1116:
1117:            /**
1118:             * TreeTableCellEditor implementation.
1119:             */
1120:            class TreeTableCellEditor extends DefaultCellEditor implements 
1121:                    TreeSelectionListener, ActionListener, FocusListener,
1122:                    CellEditorListener {
1123:                /** Used in editing. Indicates x position to place editingComponent. */
1124:                protected transient int offset;
1125:
1126:                /** Used before starting the editing session. */
1127:                protected transient Timer timer;
1128:
1129:                public TreeTableCellEditor() {
1130:                    super (new TreeTableTextField());
1131:
1132:                    tree.addTreeSelectionListener(this );
1133:                    addCellEditorListener(this );
1134:                    super .getComponent().addFocusListener(this );
1135:                }
1136:
1137:                /**
1138:                 * Overridden to determine an offset that tree would place the
1139:                 * editor at. The offset is determined from the
1140:                 * <code>getRowBounds</code> JTree method, and additionally
1141:                 * from the icon DefaultTreeCellRenderer will use.
1142:                 * <p>The offset is then set on the TreeTableTextField component
1143:                 * created in the constructor, and returned.
1144:                 */
1145:                public Component getTableCellEditorComponent(JTable table,
1146:                        Object value, boolean isSelected, int r, int c) {
1147:                    Component component = super .getTableCellEditorComponent(
1148:                            table, value, isSelected, r, c);
1149:
1150:                    determineOffset(value, isSelected, r);
1151:                    ((TreeTableTextField) getComponent()).offset = offset;
1152:
1153:                    return component;
1154:                }
1155:
1156:                /**
1157:                 * This is overridden to forward the event to the tree and start editor timer.
1158:                 */
1159:                public boolean isCellEditable(EventObject e) {
1160:                    if (lastRow != -1) {
1161:                        org.openide.nodes.Node n = Visualizer.findNode(tree
1162:                                .getPathForRow(lastRow).getLastPathComponent());
1163:
1164:                        if ((n == null) || !n.canRename()) {
1165:                            //return false;
1166:                            canEdit = false;
1167:                        }
1168:                    }
1169:
1170:                    if (canEdit && (e != null)
1171:                            && (e.getSource() instanceof  Timer)) {
1172:                        return true;
1173:                    }
1174:
1175:                    if (canEdit && shouldStartEditingTimer(e)) {
1176:                        startEditingTimer();
1177:                    } else if (shouldStopEditingTimer(e)) {
1178:                        timer.stop();
1179:                    }
1180:
1181:                    if (e instanceof  MouseEvent) {
1182:                        MouseEvent me = (MouseEvent) e;
1183:                        int column = getTreeColumnIndex();
1184:
1185:                        if (MouseUtils.isLeftMouseButton(me)
1186:                                && (me.getClickCount() == 2)) {
1187:                            TreePath path = tree.getPathForRow(TreeTable.this 
1188:                                    .rowAtPoint(me.getPoint()));
1189:                            Rectangle r = tree.getPathBounds(path);
1190:
1191:                            if ((me.getX() < (r.x - positionX))
1192:                                    || (me.getX() > (r.x - positionX + r.width))) {
1193:                                me.translatePoint(r.x - me.getX(), 0);
1194:                            }
1195:                        }
1196:
1197:                        MouseEvent newME = new MouseEvent(TreeTable.this .tree,
1198:                                me.getID(), me.getWhen(), me.getModifiers(), me
1199:                                        .getX()
1200:                                        - getCellRect(0, column, true).x
1201:                                        + positionX, me.getY(), me
1202:                                        .getClickCount(), me.isPopupTrigger());
1203:                        TreeTable.this .tree.dispatchEvent(newME);
1204:                    }
1205:
1206:                    return false;
1207:                }
1208:
1209:                /* Stop timer when selection has been changed.
1210:                 */
1211:                public void valueChanged(TreeSelectionEvent e) {
1212:                    if (timer != null) {
1213:                        timer.stop();
1214:                    }
1215:                }
1216:
1217:                /* Timer performer.
1218:                 */
1219:                public void actionPerformed(java.awt.event.ActionEvent e) {
1220:                    if (lastRow != -1) {
1221:                        editCellAt(lastRow, getTreeColumnIndex(),
1222:                                new EventObject(timer));
1223:                    }
1224:                }
1225:
1226:                /* Start editing timer only on certain conditions.
1227:                 */
1228:                private boolean shouldStartEditingTimer(EventObject event) {
1229:                    if ((event instanceof  MouseEvent)
1230:                            && SwingUtilities
1231:                                    .isLeftMouseButton((MouseEvent) event)) {
1232:                        MouseEvent me = (MouseEvent) event;
1233:
1234:                        return ((me.getID() == me.MOUSE_PRESSED)
1235:                                && (me.getClickCount() == 1) && inHitRegion(me));
1236:                    }
1237:
1238:                    return false;
1239:                }
1240:
1241:                /* Stop editing timer only on certain conditions.
1242:                 */
1243:                private boolean shouldStopEditingTimer(EventObject event) {
1244:                    if (timer == null) {
1245:                        return false;
1246:                    }
1247:
1248:                    if (event instanceof  MouseEvent) {
1249:                        MouseEvent me = (MouseEvent) event;
1250:
1251:                        return (!SwingUtilities.isLeftMouseButton(me) || (me
1252:                                .getClickCount() > 1));
1253:                    }
1254:
1255:                    return false;
1256:                }
1257:
1258:                /**
1259:                 * Starts the editing timer.
1260:                 */
1261:                private void startEditingTimer() {
1262:                    if (timer == null) {
1263:                        timer = new Timer(1200, this );
1264:                        timer.setRepeats(false);
1265:                    }
1266:
1267:                    timer.start();
1268:                }
1269:
1270:                /* Does a click go into node's label?
1271:                 */
1272:                private boolean inHitRegion(MouseEvent me) {
1273:                    determineOffset(me);
1274:
1275:                    if (me.getX() <= offset) {
1276:                        return false;
1277:                    }
1278:
1279:                    return true;
1280:                }
1281:
1282:                /* Determines offset of node's label from left edge of the table.
1283:                 */
1284:                private void determineOffset(MouseEvent me) {
1285:                    int row = TreeTable.this .rowAtPoint(me.getPoint());
1286:
1287:                    if (row == -1) {
1288:                        offset = 0;
1289:
1290:                        return;
1291:                    }
1292:
1293:                    determineOffset(tree.getPathForRow(row)
1294:                            .getLastPathComponent(), TreeTable.this 
1295:                            .isRowSelected(row), row);
1296:                }
1297:
1298:                /* Determines offset of node's label from left edge of the table.
1299:                 */
1300:                private void determineOffset(Object value, boolean isSelected,
1301:                        int row) {
1302:                    JTree t = getTree();
1303:                    boolean rv = t.isRootVisible();
1304:                    int offsetRow = row;
1305:
1306:                    if (!rv && (row > 0)) {
1307:                        offsetRow--;
1308:                    }
1309:
1310:                    Rectangle bounds = t.getRowBounds(offsetRow);
1311:                    offset = bounds.x;
1312:
1313:                    TreeCellRenderer tcr = t.getCellRenderer();
1314:                    Object node = t.getPathForRow(offsetRow)
1315:                            .getLastPathComponent();
1316:                    Component comp = tcr.getTreeCellRendererComponent(t, node,
1317:                            isSelected, t.isExpanded(offsetRow), t.getModel()
1318:                                    .isLeaf(node), offsetRow, false);
1319:
1320:                    if (comp instanceof  JLabel) {
1321:                        Icon icon = ((JLabel) comp).getIcon();
1322:
1323:                        if (icon != null) {
1324:                            offset += (((JLabel) comp).getIconTextGap() + icon
1325:                                    .getIconWidth());
1326:                        }
1327:                    }
1328:
1329:                    offset -= positionX;
1330:                }
1331:
1332:                /* Revalidates text field upon change of x position of renderer
1333:                 */
1334:                private void revalidateTextField() {
1335:                    int row = TreeTable.this .editingRow;
1336:
1337:                    if (row == -1) {
1338:                        offset = 0;
1339:
1340:                        return;
1341:                    }
1342:
1343:                    determineOffset(tree.getPathForRow(row)
1344:                            .getLastPathComponent(), TreeTable.this 
1345:                            .isRowSelected(row), row);
1346:                    ((TreeTableTextField) super .getComponent()).offset = offset;
1347:                    getComponent().setBounds(
1348:                            TreeTable.this .getCellRect(row,
1349:                                    getTreeColumnIndex(), false));
1350:                }
1351:
1352:                // Focus listener
1353:
1354:                /* Cancel editing when text field loses focus
1355:                 */
1356:                public void focusLost(java.awt.event.FocusEvent evt) {
1357:                    /* to allow Escape functionality
1358:                    if (!stopCellEditing())
1359:                      cancelCellEditing();
1360:                     */
1361:                }
1362:
1363:                /* Select a text in text field when it gets focus.
1364:                 */
1365:                public void focusGained(java.awt.event.FocusEvent evt) {
1366:                    ((TreeTableTextField) super .getComponent()).selectAll();
1367:                }
1368:
1369:                // Cell editor listener - copied from TreeViewCellEditor
1370:
1371:                /** Implements <code>CellEditorListener</code> interface method. */
1372:                public void editingStopped(ChangeEvent e) {
1373:                    TreePath lastP = tree.getPathForRow(lastRow);
1374:
1375:                    if (lastP != null) {
1376:                        Node n = Visualizer.findNode(lastP
1377:                                .getLastPathComponent());
1378:
1379:                        if ((n != null) && n.canRename()) {
1380:                            String newStr = (String) getCellEditorValue();
1381:
1382:                            try {
1383:                                // bugfix #21589 don't update name if there is not any change
1384:                                if (!n.getName().equals(newStr)) {
1385:                                    n.setName(newStr);
1386:                                }
1387:                            } catch (IllegalArgumentException exc) {
1388:                                boolean needToAnnotate = Exceptions
1389:                                        .findLocalizedMessage(exc) == null;
1390:
1391:                                // annotate new localized message only if there is no localized message yet
1392:                                if (needToAnnotate) {
1393:                                    String msg = NbBundle
1394:                                            .getMessage(
1395:                                                    TreeViewCellEditor.class,
1396:                                                    "RenameFailed",
1397:                                                    n.getName(), newStr);
1398:                                    Exceptions.attachLocalizedMessage(exc, msg);
1399:                                }
1400:
1401:                                Exceptions.printStackTrace(exc);
1402:                            }
1403:                        }
1404:                    }
1405:                }
1406:
1407:                /** Implements <code>CellEditorListener</code> interface method. */
1408:                public void editingCanceled(ChangeEvent e) {
1409:                }
1410:            }
1411:
1412:            /**
1413:             * Component used by TreeTableCellEditor. The only thing this does
1414:             * is to override the <code>reshape</code> method, and to ALWAYS
1415:             * make the x location be <code>offset</code>.
1416:             */
1417:            static class TreeTableTextField extends JTextField {
1418:                public int offset;
1419:
1420:                @SuppressWarnings("deprecation")
1421:                public void reshape(int x, int y, int w, int h) {
1422:                    int newX = Math.max(x, offset);
1423:                    super .reshape(newX, y, w - (newX - x), h);
1424:                }
1425:
1426:                public void addNotify() {
1427:                    super .addNotify();
1428:
1429:                    //requestFocus();  //no longer necessary, STPolicy will do it - Tim
1430:                }
1431:            }
1432:
1433:            /**
1434:             * ListToTreeSelectionModelWrapper extends DefaultTreeSelectionModel
1435:             * to listen for changes in the ListSelectionModel it maintains. Once
1436:             * a change in the ListSelectionModel happens, the paths are updated
1437:             * in the DefaultTreeSelectionModel.
1438:             */
1439:            class ListToTreeSelectionModelWrapper extends
1440:                    DefaultTreeSelectionModel {
1441:                /** Set to true when we are updating the ListSelectionModel. */
1442:                protected boolean updatingListSelectionModel;
1443:
1444:                public ListToTreeSelectionModelWrapper() {
1445:                    super ();
1446:                    listSelectionModel = new TreeTableSelectionModel();
1447:                    getListSelectionModel().addListSelectionListener(
1448:                            createListSelectionListener());
1449:                }
1450:
1451:                /**
1452:                 * Returns the list selection model. ListToTreeSelectionModelWrapper
1453:                 * listens for changes to this model and updates the selected paths
1454:                 * accordingly.
1455:                 */
1456:                ListSelectionModel getListSelectionModel() {
1457:                    return listSelectionModel;
1458:                }
1459:
1460:                /**
1461:                 * This is overridden to set <code>updatingListSelectionModel</code>
1462:                 * and message super. This is the only place DefaultTreeSelectionModel
1463:                 * alters the ListSelectionModel.
1464:                 */
1465:                public void resetRowSelection() {
1466:                    if (!updatingListSelectionModel) {
1467:                        updatingListSelectionModel = true;
1468:
1469:                        try {
1470:                            super .resetRowSelection();
1471:                        } finally {
1472:                            updatingListSelectionModel = false;
1473:                        }
1474:                    }
1475:
1476:                    // Notice how we don't message super if
1477:                    // updatingListSelectionModel is true. If
1478:                    // updatingListSelectionModel is true, it implies the
1479:                    // ListSelectionModel has already been updated and the
1480:                    // paths are the only thing that needs to be updated.
1481:                }
1482:
1483:                /**
1484:                 * Creates and returns an instance of ListSelectionHandler.
1485:                 */
1486:                protected ListSelectionListener createListSelectionListener() {
1487:                    return new ListSelectionHandler();
1488:                }
1489:
1490:                /**
1491:                 * If <code>updatingListSelectionModel</code> is false, this will
1492:                 * reset the selected paths from the selected rows in the list
1493:                 * selection model.
1494:                 */
1495:                protected void updateSelectedPathsFromSelectedRows() {
1496:                    if (!updatingListSelectionModel) {
1497:                        updatingListSelectionModel = true;
1498:
1499:                        try {
1500:                            int min = listSelectionModel.getMinSelectionIndex();
1501:                            int max = listSelectionModel.getMaxSelectionIndex();
1502:
1503:                            if ((min == 0) && (max == getRowCount())) {
1504:                                //#48242 - optimize the case of select all
1505:                                int[] rows = new int[max];
1506:
1507:                                for (int i = 0; i < rows.length; i++) {
1508:                                    rows[i] = i;
1509:                                }
1510:
1511:                                tree.setSelectionRows(rows);
1512:                            } else {
1513:                                List<Integer> list = new ArrayList<Integer>(11);
1514:
1515:                                for (int i = min; i <= max; i++) {
1516:                                    if (listSelectionModel.isSelectedIndex(i)) {
1517:                                        list.add(Integer.valueOf(i));
1518:                                    }
1519:                                }
1520:
1521:                                if (list.isEmpty()) {
1522:                                    clearSelection();
1523:                                } else {
1524:                                    int[] rows = (int[]) Utilities
1525:                                            .toPrimitiveArray(list
1526:                                                    .toArray(new Integer[list
1527:                                                            .size()]));
1528:                                    tree.setSelectionRows(rows);
1529:                                }
1530:                            }
1531:                        } finally {
1532:                            updatingListSelectionModel = false;
1533:                        }
1534:                    }
1535:                }
1536:
1537:                /**
1538:                 * Class responsible for calling updateSelectedPathsFromSelectedRows
1539:                 * when the selection of the list changes.
1540:                 */
1541:                class ListSelectionHandler implements  ListSelectionListener {
1542:                    public void valueChanged(ListSelectionEvent e) {
1543:                        if (inSelectAll || e.getValueIsAdjusting()) {
1544:                            return;
1545:                        }
1546:
1547:                        updateSelectedPathsFromSelectedRows();
1548:                    }
1549:                }
1550:            }
1551:
1552:            /**
1553:             * #63287 - in JDK1.6 the JTable makes additional changes to the ListSelectionModel
1554:             * when clearing row selection. These events must be ignored the same way as
1555:             * the overridden method TreeTable.clearSelection()
1556:             */
1557:            class TreeTableSelectionModel extends DefaultListSelectionModel {
1558:                public void setAnchorSelectionIndex(int anchorIndex) {
1559:                    if (ignoreClearSelection)
1560:                        return;
1561:                    super .setAnchorSelectionIndex(anchorIndex);
1562:                }
1563:
1564:                public void setLeadSelectionIndex(int leadIndex) {
1565:                    if (ignoreClearSelection)
1566:                        return;
1567:                    super .setLeadSelectionIndex(leadIndex);
1568:                }
1569:            }
1570:
1571:            /* This is overriden to handle mouse events especially. E.g. do not change selection
1572:             * when it was clicked on tree's expand/collapse toggles.
1573:             */
1574:            class TreeTableUI extends BasicTableUI {
1575:                /**
1576:                 * Creates the mouse listener for the JTable.
1577:                 */
1578:                protected MouseInputListener createMouseInputListener() {
1579:                    return new TreeTableMouseInputHandler();
1580:                }
1581:
1582:                public class TreeTableMouseInputHandler extends
1583:                        MouseInputHandler {
1584:                    // Component recieving mouse events during editing. May not be editorComponent.
1585:                    private Component dispatchComponent;
1586:
1587:                    //  The Table's mouse listener methods.
1588:                    public void mouseClicked(MouseEvent e) {
1589:                        processMouseEvent(e);
1590:                    }
1591:
1592:                    public void mousePressed(MouseEvent e) {
1593:                        processMouseEvent(e);
1594:                    }
1595:
1596:                    public void mouseReleased(MouseEvent e) {
1597:                        if (shouldIgnore(e)) {
1598:                            return;
1599:                        }
1600:
1601:                        repostEvent(e);
1602:                        dispatchComponent = null;
1603:                        setValueIsAdjusting(false);
1604:
1605:                        if (!TreeTable.this .isEditing()) {
1606:                            processMouseEvent(e);
1607:                        }
1608:                    }
1609:
1610:                    public void mouseDragged(MouseEvent e) {
1611:                        return;
1612:                    }
1613:
1614:                    private void setDispatchComponent(MouseEvent e) {
1615:                        Component editorComponent = table.getEditorComponent();
1616:                        Point p = e.getPoint();
1617:                        Point p2 = SwingUtilities.convertPoint(table, p,
1618:                                editorComponent);
1619:                        dispatchComponent = SwingUtilities
1620:                                .getDeepestComponentAt(editorComponent, p2.x,
1621:                                        p2.y);
1622:                    }
1623:
1624:                    private boolean repostEvent(MouseEvent e) {
1625:                        if (dispatchComponent == null) {
1626:                            return false;
1627:                        }
1628:
1629:                        MouseEvent e2 = SwingUtilities.convertMouseEvent(table,
1630:                                e, dispatchComponent);
1631:                        dispatchComponent.dispatchEvent(e2);
1632:
1633:                        return true;
1634:                    }
1635:
1636:                    private void setValueIsAdjusting(boolean flag) {
1637:                        table.getSelectionModel().setValueIsAdjusting(flag);
1638:                        table.getColumnModel().getSelectionModel()
1639:                                .setValueIsAdjusting(flag);
1640:                    }
1641:
1642:                    private boolean shouldIgnore(MouseEvent e) {
1643:                        return !table.isEnabled()
1644:                                || ((e.getButton() == MouseEvent.BUTTON3)
1645:                                        && (e.getClickCount() == 1) && !e
1646:                                        .isPopupTrigger());
1647:                    }
1648:
1649:                    private boolean isTreeColumn(int column) {
1650:                        return TreeTable.this .getColumnClass(column) == TreeTableModelAdapter.class;
1651:                    }
1652:
1653:                    /** Forwards mouse events to a renderer (tree).
1654:                     */
1655:                    private void processMouseEvent(MouseEvent e) {
1656:                        if (shouldIgnore(e)) {
1657:                            return;
1658:                        }
1659:
1660:                        Point p = e.getPoint();
1661:                        int row = table.rowAtPoint(p);
1662:                        int column = table.columnAtPoint(p);
1663:
1664:                        // The autoscroller can generate drag events outside the Table's range. 
1665:                        if ((column == -1) || (row == -1)) {
1666:                            return;
1667:                        }
1668:
1669:                        // for automatic jemmy testing purposes
1670:                        if ((getEditingColumn() == column)
1671:                                && (getEditingRow() == row)) {
1672:                            return;
1673:                        }
1674:
1675:                        boolean changeSelection = true;
1676:
1677:                        if (isTreeColumn(column)) {
1678:                            TreePath path = tree.getPathForRow(TreeTable.this 
1679:                                    .rowAtPoint(e.getPoint()));
1680:                            Rectangle r = tree.getPathBounds(path);
1681:
1682:                            if ((e.getX() >= (r.x - positionX))
1683:                                    && (e.getX() <= (r.x - positionX + r.width))
1684:                                    || isLocationInExpandControl(path, p)
1685:                                    || e.getID() == MouseEvent.MOUSE_RELEASED
1686:                                    || e.getID() == MouseEvent.MOUSE_CLICKED) {
1687:                                changeSelection = false;
1688:                            }
1689:                        }
1690:
1691:                        if (table.getSelectionModel().isSelectedIndex(row)
1692:                                && e.isPopupTrigger()) {
1693:                            return;
1694:                        }
1695:
1696:                        if (table.editCellAt(row, column, e)) {
1697:                            setDispatchComponent(e);
1698:                            repostEvent(e);
1699:                        }
1700:
1701:                        if (e.getID() == MouseEvent.MOUSE_PRESSED) {
1702:                            table.requestFocus();
1703:                        }
1704:
1705:                        CellEditor editor = table.getCellEditor();
1706:
1707:                        if (changeSelection
1708:                                && ((editor == null) || editor
1709:                                        .shouldSelectCell(e))) {
1710:                            setValueIsAdjusting(true);
1711:                            table.changeSelection(row, column, Utilities
1712:                                    .isMac() ? e.isMetaDown() : e
1713:                                    .isControlDown(), //use META key on Mac to toggle selection
1714:                                    e.isShiftDown());
1715:                        }
1716:                    }
1717:
1718:                    private boolean isLocationInExpandControl(TreePath path,
1719:                            Point location) {
1720:                        if (tree.getModel().isLeaf(path.getLastPathComponent()))
1721:                            return false;
1722:
1723:                        Rectangle r = tree.getPathBounds(path);
1724:                        int boxWidth = 8;
1725:                        Insets i = tree.getInsets();
1726:                        int indent = 0;
1727:
1728:                        if (tree.getUI() instanceof  BasicTreeUI) {
1729:                            BasicTreeUI ui = (BasicTreeUI) tree.getUI();
1730:                            if (null != ui.getExpandedIcon())
1731:                                boxWidth = ui.getExpandedIcon().getIconWidth();
1732:
1733:                            indent = ui.getLeftChildIndent();
1734:                        }
1735:                        int boxX;
1736:                        if (tree.getComponentOrientation().isLeftToRight()) {
1737:                            boxX = r.x - positionX - indent - boxWidth;
1738:                        } else {
1739:                            boxX = r.x - positionX + indent + r.width;
1740:                        }
1741:                        return location.getX() >= boxX
1742:                                && location.getX() <= (boxX + boxWidth);
1743:                    }
1744:                }
1745:            }
1746:
1747:            /* When selected column is tree column then call tree's action otherwise call table's.
1748:             */
1749:            class TreeTableAction extends AbstractAction {
1750:                Action treeAction;
1751:                Action tableAction;
1752:
1753:                TreeTableAction(Action treeAction, Action tableAction) {
1754:                    this .treeAction = treeAction;
1755:                    this .tableAction = tableAction;
1756:                }
1757:
1758:                public void actionPerformed(ActionEvent e) {
1759:                    if (TreeTable.this .getSelectedColumn() == getTreeColumnIndex()) {
1760:                        //Issue 40075, on JDK 1.5, BasicTreeUI remarkably expects
1761:                        //that action events performed on trees actually come from
1762:                        //trees
1763:                        e.setSource(getTree());
1764:                        treeAction.actionPerformed(e);
1765:                    } else {
1766:                        tableAction.actionPerformed(e);
1767:                    }
1768:                }
1769:            }
1770:
1771:            /** Focus transfer policy that retains focus after closing an editor.
1772:             * Copied wholesale from org.openide.explorer.propertysheet.SheetTable */
1773:            private class STPolicy extends ContainerOrderFocusTraversalPolicy {
1774:                public Component getComponentAfter(Container focusCycleRoot,
1775:                        Component aComponent) {
1776:                    if (inRemoveRequest) {
1777:                        return TreeTable.this ;
1778:                    } else {
1779:                        Component result = super .getComponentAfter(
1780:                                focusCycleRoot, aComponent);
1781:
1782:                        return result;
1783:                    }
1784:                }
1785:
1786:                public Component getComponentBefore(Container focusCycleRoot,
1787:                        Component aComponent) {
1788:                    if (inRemoveRequest) {
1789:                        return TreeTable.this ;
1790:                    } else {
1791:                        return super .getComponentBefore(focusCycleRoot,
1792:                                aComponent);
1793:                    }
1794:                }
1795:
1796:                public Component getFirstComponent(Container focusCycleRoot) {
1797:                    if (!inRemoveRequest && isEditing()) {
1798:                        return editorComp;
1799:                    } else {
1800:                        return TreeTable.this ;
1801:                    }
1802:                }
1803:
1804:                public Component getDefaultComponent(Container focusCycleRoot) {
1805:                    if (inRemoveRequest && isEditing()
1806:                            && editorComp.isShowing()) {
1807:                        return editorComp;
1808:                    } else {
1809:                        return TreeTable.this ;
1810:                    }
1811:                }
1812:
1813:                protected boolean accept(Component aComponent) {
1814:                    //Do not allow focus to go to a child of the editor we're using if
1815:                    //we are in the process of removing the editor
1816:                    if (isEditing() && inEditRequest) {
1817:                        return isKnownComponent(aComponent);
1818:                    }
1819:
1820:                    return super .accept(aComponent) && aComponent.isShowing();
1821:                }
1822:            }
1823:
1824:            /** Enables tab keys to navigate between rows but also exit the table
1825:             * to the next focusable component in either direction */
1826:            private final class NavigationAction extends AbstractAction {
1827:                private boolean direction;
1828:
1829:                public NavigationAction(boolean direction) {
1830:                    this .direction = direction;
1831:                }
1832:
1833:                public void actionPerformed(ActionEvent e) {
1834:                    if (isEditing()) {
1835:                        removeEditor();
1836:                    }
1837:
1838:                    int targetRow;
1839:                    int targetColumn;
1840:
1841:                    if (direction) {
1842:                        if (getSelectedColumn() == (getColumnCount() - 1)) {
1843:                            targetColumn = 0;
1844:                            targetRow = getSelectedRow() + 1;
1845:                        } else {
1846:                            targetColumn = getSelectedColumn() + 1;
1847:                            targetRow = getSelectedRow();
1848:                        }
1849:                    } else {
1850:                        if (getSelectedColumn() <= 0) {
1851:                            targetColumn = getColumnCount() - 1;
1852:                            targetRow = getSelectedRow() - 1;
1853:                        } else {
1854:                            targetRow = getSelectedRow();
1855:                            targetColumn = getSelectedColumn() - 1;
1856:                        }
1857:                    }
1858:
1859:                    //if we're off the end, try to find a sibling component to pass
1860:                    //focus to
1861:                    if ((targetRow >= getRowCount()) || (targetRow < 0)) {
1862:                        //This code is a bit ugly, but works
1863:                        Container ancestor = getFocusCycleRootAncestor();
1864:
1865:                        //Find the next component in our parent's focus cycle
1866:                        Component sibling = direction ? ancestor
1867:                                .getFocusTraversalPolicy().getComponentAfter(
1868:                                        ancestor, TreeTable.this .getParent())
1869:                                : ancestor.getFocusTraversalPolicy()
1870:                                        .getComponentBefore(ancestor,
1871:                                                TreeTable.this );
1872:
1873:                        //Often LayoutFocusTranferPolicy will return ourselves if we're
1874:                        //the last.  First try to find a parent focus cycle root that
1875:                        //will be a little more polite
1876:                        if (sibling == TreeTable.this ) {
1877:                            Container grandcestor = ancestor
1878:                                    .getFocusCycleRootAncestor();
1879:
1880:                            if (grandcestor != null) {
1881:                                sibling = direction ? grandcestor
1882:                                        .getFocusTraversalPolicy()
1883:                                        .getComponentAfter(grandcestor,
1884:                                                ancestor) : grandcestor
1885:                                        .getFocusTraversalPolicy()
1886:                                        .getComponentBefore(grandcestor,
1887:                                                ancestor);
1888:                                ancestor = grandcestor;
1889:                            }
1890:                        }
1891:
1892:                        //Okay, we still ended up with ourselves, or there is only one focus
1893:                        //cycle root ancestor.  Try to find the first component according to
1894:                        //the policy
1895:                        if (sibling == TreeTable.this ) {
1896:                            if (ancestor.getFocusTraversalPolicy()
1897:                                    .getFirstComponent(ancestor) != null) {
1898:                                sibling = ancestor.getFocusTraversalPolicy()
1899:                                        .getFirstComponent(ancestor);
1900:                            }
1901:                        }
1902:
1903:                        //If we're *still* getting ourselves, find the default button and punt
1904:                        if (sibling == TreeTable.this ) {
1905:                            JRootPane rp = getRootPane();
1906:                            JButton jb = rp.getDefaultButton();
1907:
1908:                            if (jb != null) {
1909:                                sibling = jb;
1910:                            }
1911:                        }
1912:
1913:                        //See if it's us, or something we know about, and if so, just
1914:                        //loop around to the top or bottom row - there's noplace
1915:                        //interesting for focus to go to
1916:                        if (sibling != null) {
1917:                            if (sibling == TreeTable.this ) {
1918:                                //set the selection if there's nothing else to do
1919:                                changeSelection(direction ? 0
1920:                                        : (getRowCount() - 1), direction ? 0
1921:                                        : (getColumnCount() - 1), false, false);
1922:                            } else {
1923:                                //Request focus on the sibling
1924:                                sibling.requestFocus();
1925:                            }
1926:
1927:                            return;
1928:                        }
1929:                    }
1930:
1931:                    changeSelection(targetRow, targetColumn, false, false);
1932:                }
1933:            }
1934:
1935:            /** Used to explicitly invoke editing from the keyboard */
1936:            private class EditAction extends AbstractAction {
1937:                public void actionPerformed(ActionEvent e) {
1938:                    int row = getSelectedRow();
1939:                    int col = getSelectedColumn();
1940:
1941:                    if (col == 0) {
1942:                        col = 1;
1943:                    }
1944:
1945:                    editCellAt(row, col, null);
1946:                }
1947:
1948:                public boolean isEnabled() {
1949:                    return (getSelectedRow() != -1)
1950:                            && (getSelectedColumn() != -1) && !isEditing();
1951:                }
1952:            }
1953:
1954:            /** Either cancels an edit, or closes the enclosing dialog if present */
1955:            private class CancelEditAction extends AbstractAction {
1956:                public void actionPerformed(ActionEvent e) {
1957:                    if (isEditing() || (editorComp != null)) {
1958:                        removeEditor();
1959:
1960:                        return;
1961:                    } else {
1962:                        Component c = KeyboardFocusManager
1963:                                .getCurrentKeyboardFocusManager()
1964:                                .getFocusOwner();
1965:
1966:                        InputMap imp = getRootPane().getInputMap(
1967:                                WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
1968:                        ActionMap am = getRootPane().getActionMap();
1969:
1970:                        KeyStroke escape = KeyStroke.getKeyStroke(
1971:                                KeyEvent.VK_ESCAPE, 0, false);
1972:                        Object key = imp.get(escape);
1973:
1974:                        if (key == null) {
1975:                            //Default for NbDialog
1976:                            key = "Cancel";
1977:                        }
1978:
1979:                        if (key != null) {
1980:                            Action a = am.get(key);
1981:
1982:                            if (a != null) {
1983:                                String commandKey = (String) a
1984:                                        .getValue(Action.ACTION_COMMAND_KEY);
1985:
1986:                                if (commandKey == null) {
1987:                                    commandKey = key.toString();
1988:                                }
1989:
1990:                                a.actionPerformed(new ActionEvent(this ,
1991:                                        ActionEvent.ACTION_PERFORMED,
1992:                                        commandKey)); //NOI18N
1993:                            }
1994:                        }
1995:                    }
1996:                }
1997:
1998:                public boolean isEnabled() {
1999:                    return isEditing();
2000:                }
2001:            }
2002:
2003:            private class EnterAction extends AbstractAction {
2004:                public void actionPerformed(ActionEvent e) {
2005:                    JRootPane jrp = getRootPane();
2006:
2007:                    if (jrp != null) {
2008:                        JButton b = getRootPane().getDefaultButton();
2009:
2010:                        if ((b != null) && b.isEnabled()) {
2011:                            b.doClick();
2012:                        }
2013:                    }
2014:                }
2015:
2016:                public boolean isEnabled() {
2017:                    return !isEditing() && !inRemoveRequest;
2018:                }
2019:            }
2020:
2021:            private class CTRLTabAction extends AbstractAction {
2022:                public void actionPerformed(ActionEvent e) {
2023:                    setFocusCycleRoot(false);
2024:
2025:                    try {
2026:                        Container con = TreeTable.this 
2027:                                .getFocusCycleRootAncestor();
2028:
2029:                        if (con != null) {
2030:                            Component target = TreeTable.this ;
2031:
2032:                            if (getParent() instanceof  JViewport) {
2033:                                target = getParent().getParent();
2034:
2035:                                if (target == con) {
2036:                                    target = TreeTable.this ;
2037:                                }
2038:                            }
2039:
2040:                            EventObject eo = EventQueue.getCurrentEvent();
2041:                            boolean backward = false;
2042:
2043:                            if (eo instanceof  KeyEvent) {
2044:                                backward = ((((KeyEvent) eo).getModifiers() & KeyEvent.SHIFT_MASK) != 0)
2045:                                        && ((((KeyEvent) eo).getModifiersEx() & KeyEvent.SHIFT_DOWN_MASK) != 0);
2046:                            }
2047:
2048:                            Component to = backward ? con
2049:                                    .getFocusTraversalPolicy()
2050:                                    .getComponentAfter(con, TreeTable.this )
2051:                                    : con.getFocusTraversalPolicy()
2052:                                            .getComponentAfter(con,
2053:                                                    TreeTable.this );
2054:
2055:                            if (to == TreeTable.this ) {
2056:                                to = backward ? con.getFocusTraversalPolicy()
2057:                                        .getFirstComponent(con) : con
2058:                                        .getFocusTraversalPolicy()
2059:                                        .getLastComponent(con);
2060:                            }
2061:
2062:                            to.requestFocus();
2063:                        }
2064:                    } finally {
2065:                        setFocusCycleRoot(true);
2066:                    }
2067:                }
2068:            }
2069:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.