Source Code Cross Referenced for JTreeTable.java in  » IDE-Netbeans » cvsclient » org » netbeans » lib » profiler » ui » components » 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 » cvsclient » org.netbeans.lib.profiler.ui.components 
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:         * The Original Software is NetBeans. The Initial Developer of the Original
0026:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
0027:         * Microsystems, Inc. All Rights Reserved.
0028:         *
0029:         * If you wish your version of this file to be governed by only the CDDL
0030:         * or only the GPL Version 2, indicate your decision by adding
0031:         * "[Contributor] elects to include this software in this distribution
0032:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0033:         * single choice of license, a recipient has the option to distribute
0034:         * your version of this file under either the CDDL, the GPL Version 2 or
0035:         * to extend the choice of license to its licensees as provided above.
0036:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0037:         * Version 2 license, then the option applies only if the new code is
0038:         * made subject to such option by the copyright holder.
0039:         */
0040:
0041:        package org.netbeans.lib.profiler.ui.components;
0042:
0043:        import org.netbeans.lib.profiler.results.CCTNode;
0044:        import org.netbeans.lib.profiler.ui.UIUtils;
0045:        import org.netbeans.lib.profiler.ui.components.table.*;
0046:        import org.netbeans.lib.profiler.ui.components.tree.EnhancedTreeCellRenderer;
0047:        import org.netbeans.lib.profiler.ui.components.tree.TreeCellRendererPersistent;
0048:        import org.netbeans.lib.profiler.ui.components.treetable.*;
0049:        import java.awt.*;
0050:        import java.awt.event.*;
0051:        import javax.swing.*;
0052:        import javax.swing.event.ListSelectionEvent;
0053:        import javax.swing.event.ListSelectionListener;
0054:        import javax.swing.plaf.basic.BasicTreeUI;
0055:        import javax.swing.table.JTableHeader;
0056:        import javax.swing.table.TableCellRenderer;
0057:        import javax.swing.table.TableColumnModel;
0058:        import javax.swing.tree.DefaultTreeSelectionModel;
0059:        import javax.swing.tree.TreeCellRenderer;
0060:        import javax.swing.tree.TreeModel;
0061:        import javax.swing.tree.TreePath;
0062:
0063:        /**
0064:         * JTreeTable component implementation
0065:         *
0066:         * @author Jiri Sedlacek
0067:         * @author Ian Formanek
0068:         */
0069:        public class JTreeTable extends JTable implements  CellTipAware,
0070:                MouseListener, MouseMotionListener, MouseWheelListener,
0071:                KeyListener {
0072:            //~ Inner Classes ------------------------------------------------------------------------------------------------------------
0073:
0074:            /**
0075:             * ListToTreeSelectionModelWrapper extends DefaultTreeSelectionModel to
0076:             * listen for changes in the ListSelectionModel it maintains. Once a change
0077:             * in the ListSelectionModel happens, the paths are updated in the
0078:             * DefaultTreeSelectionModel.
0079:             */
0080:            class ListToTreeSelectionModelWrapper extends
0081:                    DefaultTreeSelectionModel {
0082:                //~ Inner Classes --------------------------------------------------------------------------------------------------------
0083:
0084:                /**
0085:                 * Class responsible for calling updateSelectedPathsFromSelectedRows
0086:                 * when the selection of the list changse.
0087:                 */
0088:                class ListSelectionHandler implements  ListSelectionListener {
0089:                    //~ Methods ----------------------------------------------------------------------------------------------------------
0090:
0091:                    public void valueChanged(ListSelectionEvent e) {
0092:                        updateSelectedPathsFromSelectedRows();
0093:                    }
0094:                }
0095:
0096:                //~ Instance fields ------------------------------------------------------------------------------------------------------
0097:
0098:                /**
0099:                 * Set to true when we are updating the ListSelectionModel.
0100:                 */
0101:                protected boolean updatingListSelectionModel;
0102:
0103:                //~ Constructors ---------------------------------------------------------------------------------------------------------
0104:
0105:                public ListToTreeSelectionModelWrapper() {
0106:                    super ();
0107:                    getListSelectionModel().addListSelectionListener(
0108:                            createListSelectionListener());
0109:                }
0110:
0111:                //~ Methods --------------------------------------------------------------------------------------------------------------
0112:
0113:                /**
0114:                 * This is overridden to set <code>updatingListSelectionModel</code>
0115:                 * and message super. This is the only place DefaultTreeSelectionModel
0116:                 * alters the ListSelectionModel.
0117:                 */
0118:                public void resetRowSelection() {
0119:                    if (!updatingListSelectionModel) {
0120:                        updatingListSelectionModel = true;
0121:
0122:                        try {
0123:                            super .resetRowSelection();
0124:                        } finally {
0125:                            updatingListSelectionModel = false;
0126:                        }
0127:                    }
0128:
0129:                    // Notice how we don't message super if
0130:                    // updatingListSelectionModel is true. If
0131:                    // updatingListSelectionModel is true, it implies the
0132:                    // ListSelectionModel has already been updated and the
0133:                    // paths are the only thing that needs to be updated.
0134:                }
0135:
0136:                /**
0137:                 * Creates and returns an instance of ListSelectionHandler.
0138:                 */
0139:                protected ListSelectionListener createListSelectionListener() {
0140:                    return new ListSelectionHandler();
0141:                }
0142:
0143:                /**
0144:                 * If <code>updatingListSelectionModel</code> is false, this will
0145:                 * reset the selected paths from the selected rows in the list
0146:                 * selection model.
0147:                 */
0148:                protected void updateSelectedPathsFromSelectedRows() {
0149:                    if (!updatingListSelectionModel) {
0150:                        updatingListSelectionModel = true;
0151:
0152:                        try {
0153:                            // This is way expensive, ListSelectionModel needs an
0154:                            // enumerator for iterating.
0155:                            int min = listSelectionModel.getMinSelectionIndex();
0156:                            int max = listSelectionModel.getMaxSelectionIndex();
0157:
0158:                            clearSelection();
0159:
0160:                            if ((min != -1) && (max != -1)) {
0161:                                for (int counter = min; counter <= max; counter++) {
0162:                                    if (listSelectionModel
0163:                                            .isSelectedIndex(counter)) {
0164:                                        TreePath selPath = tree
0165:                                                .getPathForRow(counter);
0166:
0167:                                        if (selPath != null) {
0168:                                            addSelectionPath(selPath);
0169:                                        }
0170:                                    }
0171:                                }
0172:                            }
0173:                        } finally {
0174:                            updatingListSelectionModel = false;
0175:                        }
0176:                    }
0177:                }
0178:
0179:                /**
0180:                 * Returns the list selection model. ListToTreeSelectionModelWrapper
0181:                 * listens for changes to this model and updates the selected paths
0182:                 * accordingly.
0183:                 */
0184:                ListSelectionModel getListSelectionModel() {
0185:                    return listSelectionModel;
0186:                }
0187:            }
0188:
0189:            //------------------------------------
0190:
0191:            /**
0192:             * This class is used for listening to the table header mouse events.
0193:             */
0194:            private class TableHeaderListener extends MouseAdapter implements 
0195:                    MouseMotionListener {
0196:                //~ Methods --------------------------------------------------------------------------------------------------------------
0197:
0198:                /*
0199:                 * If the user clicks to the sorting column (column defining the sort criterium and order), the sorting order is reversed.
0200:                 * If new sorting column is selected, the appropriate sorting order for column's datatype is set.
0201:                 */
0202:                public void mouseClicked(MouseEvent e) {
0203:                    if (e.getModifiers() == InputEvent.BUTTON1_MASK) {
0204:                        int column = tableHeader.columnAtPoint(e.getPoint());
0205:                        int sortingColumn = headerRenderer.getSortingColumn();
0206:
0207:                        if (column == sortingColumn) {
0208:                            headerRenderer.reverseSortingOrder();
0209:                        } else {
0210:                            headerRenderer.setSortingColumn(column);
0211:
0212:                            if (treeTableModel.getInitialSorting(column)) {
0213:                                headerRenderer.setSortingOrder(SORT_ORDER_ASC); // Default sort order for strings is Ascending
0214:                            } else {
0215:                                headerRenderer.setSortingOrder(SORT_ORDER_DESC); // Default sort order for numbers is Descending
0216:                            }
0217:                        }
0218:
0219:                        tableHeader.repaint();
0220:
0221:                        treeTableModel.sortByColumn(column, headerRenderer
0222:                                .getSortingOrder());
0223:                        updateTreeTable();
0224:                    }
0225:                }
0226:
0227:                public void mouseDragged(MouseEvent e) {
0228:                }
0229:
0230:                public void mouseMoved(MouseEvent e) {
0231:                    int focusedColumn = tableHeader.columnAtPoint(e.getPoint());
0232:
0233:                    if (focusedColumn != lastFocusedColumn) {
0234:                        if (focusedColumn != -1) {
0235:                            tableHeader.setToolTipText(treeTableModel
0236:                                    .getColumnToolTipText(focusedColumn));
0237:                        } else {
0238:                            tableHeader.setToolTipText(null);
0239:                        }
0240:
0241:                        lastFocusedColumn = focusedColumn;
0242:                    }
0243:                }
0244:
0245:                /*
0246:                 * Here the active header button is programatically pressed
0247:                 */
0248:                public void mousePressed(MouseEvent e) {
0249:                    if ((e.getModifiers() == InputEvent.BUTTON1_MASK)
0250:                            && (tableHeader.getResizingColumn() == null)) {
0251:                        headerRenderer.setPressedColumn(tableHeader
0252:                                .columnAtPoint(e.getPoint()));
0253:                        tableHeader.repaint();
0254:                    }
0255:                }
0256:
0257:                /*
0258:                 * Here the active header button is programatically released
0259:                 */
0260:                public void mouseReleased(MouseEvent e) {
0261:                    if (e.getModifiers() == InputEvent.BUTTON1_MASK) {
0262:                        headerRenderer.setPressedColumn(-1);
0263:                        tableHeader.repaint();
0264:                    }
0265:                }
0266:            }
0267:
0268:            private class TreeTableCellRenderer extends JTree implements 
0269:                    TableCellRenderer {
0270:                //~ Instance fields ------------------------------------------------------------------------------------------------------
0271:
0272:                protected int currentlyPaintedRow;
0273:                private Color darkerUnselectedBackground;
0274:                private Color unselectedBackground;
0275:                private Color unselectedForeground;
0276:                private EnhancedTreeCellRenderer treeCellRenderer;
0277:                private int offsetX; // x-offsed used for scrolling the TreeTable cell
0278:
0279:                //~ Constructors ---------------------------------------------------------------------------------------------------------
0280:
0281:                public TreeTableCellRenderer(TreeModel model) {
0282:                    super (model);
0283:
0284:                    offsetX = 0;
0285:                    setOpaque(false);
0286:                    treeCellRenderer = new EnhancedTreeCellRenderer();
0287:                    setCellRenderer(treeCellRenderer);
0288:                    unselectedBackground = UIUtils
0289:                            .getProfilerResultsBackground();
0290:                    darkerUnselectedBackground = UIUtils
0291:                            .getDarker(unselectedBackground);
0292:                }
0293:
0294:                //~ Methods --------------------------------------------------------------------------------------------------------------
0295:
0296:                public void setBounds(int x, int y, int w, int h) {
0297:                    super .setBounds(x, 0, w, JTreeTable.this .getHeight());
0298:                }
0299:
0300:                public void setOffsetX(int offsetX) {
0301:                    this .offsetX = offsetX;
0302:                }
0303:
0304:                public int getOffsetX() {
0305:                    return offsetX;
0306:                }
0307:
0308:                public void setRowHeight(int rowHeight) {
0309:                    if (rowHeight > 0) {
0310:                        super .setRowHeight(rowHeight);
0311:
0312:                        if ((JTreeTable.this  != null)
0313:                                && (JTreeTable.this .getRowHeight() != rowHeight)) {
0314:                            JTreeTable.this .setRowHeight(getRowHeight());
0315:                        }
0316:                    }
0317:                }
0318:
0319:                public Component getTableCellRendererComponent(JTable table,
0320:                        Object value, boolean isSelected, boolean hasFocus,
0321:                        int row, int column) {
0322:                    if (isSelected) {
0323:                        setRowForeground(table.isFocusOwner() ? table
0324:                                .getSelectionForeground() : UIUtils
0325:                                .getUnfocusedSelectionForeground());
0326:                        setRowBackground(table.isFocusOwner() ? table
0327:                                .getSelectionBackground() : UIUtils
0328:                                .getUnfocusedSelectionBackground());
0329:                    } else {
0330:                        if ((row & 0x1) == 0) { //even row
0331:                            setRowForeground((unselectedForeground != null) ? unselectedForeground
0332:                                    : table.getForeground());
0333:                            setRowBackground((darkerUnselectedBackground != null) ? darkerUnselectedBackground
0334:                                    : UIUtils.getDarker(table.getBackground()));
0335:                        } else {
0336:                            setRowForeground((unselectedForeground != null) ? unselectedForeground
0337:                                    : table.getForeground());
0338:                            setRowBackground((unselectedBackground != null) ? unselectedBackground
0339:                                    : table.getBackground());
0340:                        }
0341:                    }
0342:
0343:                    currentlyPaintedRow = row;
0344:
0345:                    return this ;
0346:                }
0347:
0348:                public void setTreeCellRenderer(
0349:                        EnhancedTreeCellRenderer renderer) {
0350:                    treeCellRenderer = renderer;
0351:                    setCellRenderer(treeCellRenderer);
0352:                }
0353:
0354:                public EnhancedTreeCellRenderer getTreeCellRenderer() {
0355:                    return treeCellRenderer;
0356:                }
0357:
0358:                public void customProcessKeyEvent(KeyEvent e) {
0359:                    processKeyEvent(e);
0360:                }
0361:
0362:                public void paint(Graphics g) {
0363:                    boolean selected;
0364:                    boolean focused;
0365:                    int xpos;
0366:
0367:                    selected = isRowSelected(currentlyPaintedRow);
0368:                    focused = JTreeTable.this .isFocusOwner();
0369:
0370:                    int rHeight = getRowHeight();
0371:
0372:                    // move tree according to offsetX
0373:                    g.translate(-offsetX, -currentlyPaintedRow * rHeight);
0374:
0375:                    if (isGTK) { // Optimized for GTK but doesn't paint selection on the left side of renderer
0376:                        // paint tree row, according to current Clip only one row is painted
0377:                        super .paint(g);
0378:
0379:                        // draw row background
0380:                        Rectangle rowBounds = getRowBounds(currentlyPaintedRow);
0381:                        xpos = rowBounds.x + rowBounds.width;
0382:                        g.setColor(getRowColor(currentlyPaintedRow, selected,
0383:                                focused));
0384:                        g.fillRect(xpos, currentlyPaintedRow * rHeight,
0385:                                getWidth() + offsetX - xpos, rHeight);
0386:                    } else {
0387:                        // draw row background
0388:                        xpos = selected ? 0
0389:                                : getRowBounds(currentlyPaintedRow).x;
0390:                        g.setColor(getRowColor(currentlyPaintedRow, selected,
0391:                                focused));
0392:                        g.fillRect(xpos, currentlyPaintedRow * rHeight,
0393:                                getWidth() + offsetX, rHeight);
0394:
0395:                        // paint tree row, according to current Clip only one row is painted
0396:                        super .paint(g);
0397:                    }
0398:                }
0399:
0400:                protected void setRowBackground(Color c) {
0401:                    //setBackground(c);
0402:                    treeCellRenderer.setBackground(c);
0403:                    treeCellRenderer.setBackgroundNonSelectionColor(c);
0404:                    treeCellRenderer.setBackgroundSelectionColor(c);
0405:                }
0406:
0407:                protected void setRowForeground(Color c) {
0408:                    //setForeground(c);
0409:                    treeCellRenderer.setForeground(c);
0410:                    treeCellRenderer.setTextNonSelectionColor(c);
0411:                    treeCellRenderer.setTextSelectionColor(c);
0412:                }
0413:
0414:                private Color getRowColor(int row, boolean selected,
0415:                        boolean focused) {
0416:                    if (selected) {
0417:                        return focused ? JTreeTable.this 
0418:                                .getSelectionBackground() : UIUtils
0419:                                .getUnfocusedSelectionBackground();
0420:                    } else {
0421:                        Color backgroundColor = UIUtils
0422:                                .getProfilerResultsBackground();
0423:                        if ((row & 0x1) == 0) { //even row
0424:                            return UIUtils.getDarker(backgroundColor);
0425:                        } else {
0426:                            return backgroundColor;
0427:                        }
0428:                    }
0429:                }
0430:            }
0431:
0432:            //~ Static fields/initializers -----------------------------------------------------------------------------------------------
0433:
0434:            public static final boolean SORT_ORDER_DESC = false;
0435:            public static final boolean SORT_ORDER_ASC = true;
0436:
0437:            private static final boolean isGTK = UIUtils.isGTKLookAndFeel();
0438:
0439:            //~ Instance fields ----------------------------------------------------------------------------------------------------------
0440:
0441:            // --- CellTip support declarations -------
0442:            protected JToolTip cellTip;
0443:            protected Rectangle rendererRect;
0444:
0445:            /**
0446:             * A subclass of JTree.
0447:             */
0448:            TreeTableCellRenderer tree;
0449:            protected int lastColumn = -1;
0450:            protected int lastRow = -1;
0451:            private AbstractTreeTableModel treeTableModel;
0452:            private CustomSortableHeaderRenderer headerRenderer;
0453:            private ImageIcon sortAscIcon = new ImageIcon(
0454:                    JTreeTable.class
0455:                            .getResource("/org/netbeans/lib/profiler/ui/resources/sortAsc.png")); //NOI18N
0456:            private ImageIcon sortDescIcon = new ImageIcon(
0457:                    JTreeTable.class
0458:                            .getResource("/org/netbeans/lib/profiler/ui/resources/sortDesc.png")); //NOI18N
0459:            private JTableHeader tableHeader;
0460:            private String internalFindString;
0461:
0462:            //------------------------------------
0463:            // Find functionality stuff
0464:            private String userFindString;
0465:            private TableHeaderListener headerListener;
0466:            private TreeTableModelAdapter treeTableModelAdapter;
0467:            private int lastFocusedColumn = -1;
0468:            private int treeSignExtent; // width/2 of the tree "+"/"-" sign
0469:            private int treeSignRightMargin; // value of BasicTreeUI.getRightChildIndent()
0470:            private int userFindColumn;
0471:
0472:            //~ Constructors -------------------------------------------------------------------------------------------------------------
0473:
0474:            public JTreeTable(AbstractTreeTableModel treeTableModel) {
0475:                super ();
0476:                this .treeTableModel = treeTableModel;
0477:
0478:                int initialSortingColumn = treeTableModel
0479:                        .getInitialSortingColumn();
0480:                boolean initialSortingOrder = treeTableModel
0481:                        .getInitialSortingOrder();
0482:
0483:                if (treeTableModel.supportsSorting()) {
0484:                    treeTableModel.sortByColumn(initialSortingColumn,
0485:                            initialSortingOrder);
0486:                }
0487:
0488:                addKeyListener(this );
0489:                addMouseListener(this );
0490:                addMouseMotionListener(this );
0491:
0492:                // Required for correct updating of focused/unfocused selection
0493:                addFocusListener(new FocusListener() {
0494:                    public void focusGained(FocusEvent e) {
0495:                        if (getSelectedRows().length > 0) {
0496:                            repaint();
0497:                        }
0498:                    }
0499:
0500:                    public void focusLost(FocusEvent e) {
0501:                        if (getSelectedRows().length > 0) {
0502:                            repaint();
0503:                        }
0504:                    }
0505:                });
0506:
0507:                // Create the tree. It will be used as a renderer and editor.
0508:                tree = new TreeTableCellRenderer(treeTableModel);
0509:                setTreeUIVariables();
0510:
0511:                // Install a tableModel representing the visible rows in the tree.
0512:                treeTableModelAdapter = new TreeTableModelAdapter(
0513:                        treeTableModel, this );
0514:                setModel(treeTableModelAdapter);
0515:
0516:                if (treeTableModel.supportsSorting()) {
0517:                    headerListener = new TableHeaderListener();
0518:
0519:                    headerRenderer = new CustomSortableHeaderRenderer(
0520:                            sortAscIcon, sortDescIcon);
0521:                    headerRenderer.setSortingColumn(initialSortingColumn);
0522:                    headerRenderer.setSortingOrder(initialSortingOrder);
0523:
0524:                    updateTreeTableHeader();
0525:                }
0526:
0527:                getTableHeader().setReorderingAllowed(false);
0528:
0529:                // Force the JTable and JTree to share their row selection models.
0530:                ListToTreeSelectionModelWrapper selectionWrapper = new ListToTreeSelectionModelWrapper();
0531:                tree.setSelectionModel(selectionWrapper);
0532:                setSelectionModel(selectionWrapper.getListSelectionModel());
0533:
0534:                // Install the tree editor renderer and editor.
0535:                setDefaultRenderer(TreeTableModel.class, tree);
0536:
0537:                // --- CellTip support ------------------
0538:                cellTip = createCellTip();
0539:                cellTip.setBorder(BorderFactory
0540:                        .createLineBorder(getGridColor()));
0541:                cellTip.setLayout(new BorderLayout());
0542:
0543:                CellTipManager.sharedInstance().registerComponent(this );
0544:            }
0545:
0546:            //~ Methods ------------------------------------------------------------------------------------------------------------------
0547:
0548:            public JToolTip getCellTip() {
0549:                return cellTip;
0550:            }
0551:
0552:            public Point getCellTipLocation() {
0553:                if (rendererRect == null) {
0554:                    return null;
0555:                }
0556:
0557:                return new Point(rendererRect.getLocation().x - 1, rendererRect
0558:                        .getLocation().y - 1);
0559:            }
0560:
0561:            public int getFindColumn() {
0562:                return userFindColumn;
0563:            }
0564:
0565:            public boolean isFindColumnValid() {
0566:                return ((userFindColumn >= 0) && (userFindColumn < getColumnCount()));
0567:            }
0568:
0569:            public void setFindParameters(String findString, int findColumn) {
0570:                userFindString = findString;
0571:                userFindColumn = findColumn;
0572:                internalFindString = getInternalFindString(userFindString);
0573:            }
0574:
0575:            public String getFindString() {
0576:                return userFindString;
0577:            }
0578:
0579:            public boolean isFindStringDefined() {
0580:                return ((userFindString != null) && (userFindString.trim()
0581:                        .length() > 0));
0582:            }
0583:
0584:            //------------------------------------
0585:            // CellTip support
0586:            public void setGridColor(Color gridColor) {
0587:                super .setGridColor(gridColor);
0588:
0589:                if ((gridColor == null) || (cellTip == null)) {
0590:                    return;
0591:                }
0592:
0593:                cellTip.setBorder(BorderFactory.createLineBorder(gridColor));
0594:            }
0595:
0596:            /**
0597:             * Overridden to pass the new rowHeight to the tree.
0598:             */
0599:            public void setRowHeight(int rowHeight) {
0600:                super .setRowHeight(rowHeight);
0601:
0602:                if ((tree != null) && (tree.getRowHeight() != rowHeight)) {
0603:                    tree.setRowHeight(getRowHeight());
0604:                }
0605:            }
0606:
0607:            public void setSortingColumn(int column) {
0608:                headerRenderer.setSortingColumn(column);
0609:            }
0610:
0611:            public int getSortingColumn() {
0612:                return headerRenderer.getSortingColumn();
0613:            }
0614:
0615:            public void setSortingOrder(boolean order) {
0616:                headerRenderer.setSortingOrder(order);
0617:            }
0618:
0619:            public boolean getSortingOrder() {
0620:                return headerRenderer.getSortingOrder();
0621:            }
0622:
0623:            /**
0624:             * Returns the tree that is being shared between the model.
0625:             */
0626:            public JTree getTree() {
0627:                return tree;
0628:            }
0629:
0630:            /** Sets the x-offsed used for scrolling the TreeTable cell */
0631:            public void setTreeCellOffsetX(int offsetX) {
0632:                if (getTreeCellOffsetX() != offsetX) {
0633:                    tree.setOffsetX(offsetX);
0634:                    repaint();
0635:                }
0636:            }
0637:
0638:            /** Gets the x-offsed used for scrolling the TreeTable cell */
0639:            public int getTreeCellOffsetX() {
0640:                return tree.getOffsetX();
0641:            }
0642:
0643:            public void setTreeCellRenderer(EnhancedTreeCellRenderer renderer) {
0644:                tree.setTreeCellRenderer(renderer);
0645:            }
0646:
0647:            public EnhancedTreeCellRenderer getTreeCellRenderer() {
0648:                return tree.getTreeCellRenderer();
0649:            }
0650:
0651:            public boolean canFindBePerformed() {
0652:                return (tree != null) && (treeTableModel.getRoot() != null)
0653:                        && isFindColumnValid() && isFindStringDefined();
0654:            }
0655:
0656:            public boolean findFirst() {
0657:                return findFirst(true);
0658:            }
0659:
0660:            public boolean findNext() {
0661:                if (!canFindBePerformed()) {
0662:                    return false;
0663:                }
0664:
0665:                CCTNode searchRoot = getSearchRoot();
0666:
0667:                // check current search root's subtree
0668:                if (doFindNext(searchRoot, 0, true)) {
0669:                    return true;
0670:                }
0671:
0672:                CCTNode searchRootParent = searchRoot.getParent();
0673:
0674:                // nothing found, process next siblings
0675:                while (searchRootParent != null) {
0676:                    if (doFindNext(searchRootParent, searchRootParent
0677:                            .getIndexOfChild(searchRoot) + 1, true)) {
0678:                        return true;
0679:                    }
0680:
0681:                    searchRoot = searchRootParent;
0682:                    searchRootParent = searchRoot.getParent();
0683:                }
0684:
0685:                return false;
0686:            }
0687:
0688:            public boolean findPrevious() {
0689:                if (!canFindBePerformed()) {
0690:                    return false;
0691:                }
0692:
0693:                // selected/last found node
0694:                CCTNode searchRoot = getSearchRoot();
0695:
0696:                if (!isAnyRowSelected()) {
0697:                    return findFirst();
0698:                }
0699:
0700:                // parent of this node than could contain previous node
0701:                CCTNode searchRootParent = searchRoot.getParent();
0702:
0703:                while (searchRootParent != null) {
0704:                    // if nothing found in previous siblings
0705:                    if (doFindPrevious(searchRootParent, searchRootParent
0706:                            .getIndexOfChild(searchRoot) - 1, true)) {
0707:                        return true;
0708:                    }
0709:
0710:                    // swith one level up
0711:                    searchRoot = searchRootParent;
0712:                    searchRootParent = searchRoot.getParent();
0713:                }
0714:
0715:                return false;
0716:            }
0717:
0718:            //------------------------------------
0719:            // Keyboard processing
0720:            public void keyPressed(KeyEvent e) {
0721:                if (shouldBeForwarded(e)) {
0722:                    dispatchKeyboardEvent(e);
0723:                }
0724:            }
0725:
0726:            public void keyReleased(KeyEvent e) {
0727:                if (shouldBeForwarded(e)) {
0728:                    dispatchKeyboardEvent(e);
0729:                }
0730:            }
0731:
0732:            public void keyTyped(KeyEvent e) {
0733:                if (shouldBeForwarded(e)) {
0734:                    dispatchKeyboardEvent(e);
0735:                }
0736:            }
0737:
0738:            //------------------------------------
0739:            // Mouse processing
0740:            public void mouseClicked(MouseEvent e) {
0741:                dispatchMouseEvent(e);
0742:            }
0743:
0744:            public void mouseDragged(MouseEvent e) {
0745:                dispatchMouseEvent(e);
0746:            }
0747:
0748:            public void mouseEntered(MouseEvent e) {
0749:                //dispatchMouseEvent(e);
0750:
0751:                // --- CellTip support ------------------
0752:                CellTipManager.sharedInstance().setEnabled(false);
0753:            }
0754:
0755:            public void mouseExited(MouseEvent e) {
0756:                //dispatchMouseEvent(e);
0757:
0758:                // --- CellTip support ------------------
0759:                // Return if mouseExit occured because of showing heavyweight celltip
0760:                if (contains(e.getPoint()) && cellTip.isShowing()) {
0761:                    return;
0762:                }
0763:
0764:                CellTipManager.sharedInstance().setEnabled(false);
0765:                lastRow = -1;
0766:                lastColumn = -1;
0767:            }
0768:
0769:            public void mouseMoved(MouseEvent e) {
0770:                //dispatchMouseEvent(e);
0771:
0772:                // --- CellTip support ------------------
0773:
0774:                // Identify treetable row and column at cursor
0775:                int row = rowAtPoint(e.getPoint());
0776:                int column = columnAtPoint(e.getPoint());
0777:
0778:                boolean isForTreeCell = (getColumnClass(column) == TreeTableModel.class);
0779:
0780:                // Return if treetable cell is the same as in previous event
0781:                if (!isForTreeCell && (row == lastRow)
0782:                        && (column == lastColumn)) {
0783:                    return;
0784:                }
0785:
0786:                lastRow = row;
0787:                lastColumn = column;
0788:
0789:                // Return if cursor isn't at any cell
0790:                if ((row < 0) || (column < 0)) {
0791:                    CellTipManager.sharedInstance().setEnabled(false);
0792:
0793:                    return;
0794:                }
0795:
0796:                Component cellRenderer;
0797:                Rectangle cellRect = getCellRect(row, column, false);
0798:
0799:                if (isForTreeCell) {
0800:                    // Cursor at tree cell
0801:                    TreeCellRenderer treeCellRenderer = tree
0802:                            .getTreeCellRenderer();
0803:                    cellRenderer = ((TreeCellRendererPersistent) treeCellRenderer)
0804:                            .getTreeCellRendererComponentPersistent(tree,
0805:                                    treeTableModel.getValueAt(tree
0806:                                            .getPathForRow(row)
0807:                                            .getLastPathComponent(), 0), false,
0808:                                    tree.isExpanded(row), treeTableModel
0809:                                            .isLeaf(tree.getPathForRow(row)
0810:                                                    .getLastPathComponent()),
0811:                                    row, false);
0812:
0813:                    // Return if celltip is not supported for the cell
0814:                    if (cellRenderer == null) {
0815:                        CellTipManager.sharedInstance().setEnabled(false);
0816:
0817:                        return;
0818:                    }
0819:
0820:                    Point treeCellStart = tree.getPathBounds(
0821:                            tree.getPathForRow(row)).getLocation();
0822:                    rendererRect = new Rectangle((cellRect.x + treeCellStart.x)
0823:                            - tree.getOffsetX(), treeCellStart.y, cellRenderer
0824:                            .getPreferredSize().width, cellRenderer
0825:                            .getPreferredSize().height + 2);
0826:                } else {
0827:                    // Cursor at table cell
0828:                    TableCellRenderer tableCellRenderer = getCellRenderer(row,
0829:                            column);
0830:
0831:                    if (!(tableCellRenderer instanceof  TableCellRendererPersistent)) {
0832:                        return;
0833:                    }
0834:
0835:                    cellRenderer = ((TableCellRendererPersistent) tableCellRenderer)
0836:                            .getTableCellRendererComponentPersistent(this ,
0837:                                    getValueAt(row, column), false, false, row,
0838:                                    column);
0839:
0840:                    // Return if celltip is not supported for the cell
0841:                    if (cellRenderer == null) {
0842:                        CellTipManager.sharedInstance().setEnabled(false);
0843:
0844:                        return;
0845:                    }
0846:
0847:                    int horizontalAlignment = ((EnhancedTableCellRenderer) cellRenderer)
0848:                            .getHorizontalAlignment();
0849:
0850:                    if ((horizontalAlignment == SwingConstants.TRAILING)
0851:                            || (horizontalAlignment == SwingConstants.RIGHT)) {
0852:                        rendererRect = new Rectangle(
0853:                                (cellRect.x + cellRect.width)
0854:                                        - cellRenderer.getPreferredSize().width,
0855:                                cellRect.y,
0856:                                cellRenderer.getPreferredSize().width,
0857:                                cellRenderer.getPreferredSize().height);
0858:                    } else {
0859:                        rendererRect = new Rectangle(cellRect.x, cellRect.y,
0860:                                cellRenderer.getPreferredSize().width,
0861:                                cellRenderer.getPreferredSize().height);
0862:                    }
0863:                }
0864:
0865:                if (isForTreeCell && !rendererRect.contains(e.getPoint())) {
0866:                    CellTipManager.sharedInstance().setEnabled(false);
0867:
0868:                    return;
0869:                }
0870:
0871:                // Return if cell contents is fully visible
0872:                if ((rendererRect.x >= cellRect.x)
0873:                        && ((rendererRect.x + rendererRect.width) <= (cellRect.x + cellRect.width))) {
0874:                    CellTipManager.sharedInstance().setEnabled(false);
0875:
0876:                    return;
0877:                }
0878:
0879:                while (cellTip.getComponentCount() > 0) {
0880:                    cellTip.remove(0);
0881:                }
0882:
0883:                cellTip.add(cellRenderer, BorderLayout.CENTER);
0884:                cellTip.setPreferredSize(new Dimension(rendererRect.width + 2,
0885:                        getRowHeight(row) + 2));
0886:
0887:                CellTipManager.sharedInstance().setEnabled(true);
0888:            }
0889:
0890:            public void mousePressed(MouseEvent e) {
0891:                dispatchMouseEvent(e);
0892:            }
0893:
0894:            public void mouseReleased(MouseEvent e) {
0895:                dispatchMouseEvent(e);
0896:            }
0897:
0898:            public void mouseWheelMoved(MouseWheelEvent e) {
0899:                mouseMoved(e);
0900:                CellTipManager.sharedInstance().setEnabled(false);
0901:            }
0902:
0903:            public void processMouseEvent(MouseEvent e) {
0904:                super .processMouseEvent(e);
0905:            }
0906:
0907:            public void resetTreeCellOffsetX() {
0908:                setTreeCellOffsetX(0);
0909:            }
0910:
0911:            //------------------------------------
0912:            public void selectNode(CCTNode node, boolean setVisible) {
0913:                TreePath path = new TreePath(treeTableModel.getPathToRoot(node));
0914:                getTree().setSelectionPath(path);
0915:
0916:                if (setVisible) {
0917:                    scrollRectToVisible(getCellRect(getSelectedRow(), 0, true));
0918:                }
0919:            }
0920:
0921:            public void selectRowByContents(String rowString, int columnIndex,
0922:                    boolean setVisible) {
0923:                for (int i = 0; i < getRowCount(); i++) {
0924:                    if (getValueAt(i, columnIndex).toString().equals(rowString)) {
0925:                        getSelectionModel().setSelectionInterval(i, i);
0926:
0927:                        if (setVisible) {
0928:                            scrollRectToVisible(getCellRect(i, columnIndex,
0929:                                    true));
0930:                        }
0931:
0932:                        return;
0933:                    }
0934:                }
0935:
0936:                getSelectionModel().clearSelection();
0937:            }
0938:
0939:            public boolean silentlyFindFirst() {
0940:                return findFirst(false);
0941:            }
0942:
0943:            public void updateTreeTable() {
0944:                treeTableModelAdapter.updateTreeTable();
0945:            }
0946:
0947:            public void updateTreeTableHeader() {
0948:                TableColumnModel tableColumnModel = getColumnModel();
0949:                int n = tableColumnModel.getColumnCount();
0950:
0951:                for (int i = 0; i < n; i++) {
0952:                    tableColumnModel.getColumn(i).setHeaderRenderer(
0953:                            headerRenderer);
0954:                }
0955:
0956:                if (tableHeader != getTableHeader()) {
0957:                    if (tableHeader != null) {
0958:                        tableHeader.removeMouseListener(headerListener);
0959:                    }
0960:
0961:                    if (tableHeader != null) {
0962:                        tableHeader.removeMouseMotionListener(headerListener);
0963:                    }
0964:
0965:                    tableHeader = getTableHeader();
0966:                    tableHeader.addMouseListener(headerListener);
0967:                    tableHeader.addMouseMotionListener(headerListener);
0968:                    updateTreeTable();
0969:                }
0970:            }
0971:
0972:            /**
0973:             * Overridden to message super and forward the method to the tree. Since
0974:             * the tree is not actually in the component hieachy it will never receive
0975:             * this unless we forward it in this manner.
0976:             */
0977:            public void updateUI() {
0978:                super .updateUI();
0979:
0980:                if (tree != null) {
0981:                    tree.updateUI();
0982:                    setTreeUIVariables();
0983:                }
0984:            }
0985:
0986:            protected JToolTip createCellTip() {
0987:                return new JToolTip();
0988:            }
0989:
0990:            private boolean isAnyRowSelected() {
0991:                TreePath treeSelectionPath = tree.getSelectionPath();
0992:
0993:                return ((treeSelectionPath != null) && (treeSelectionPath
0994:                        .getPathCount() > 0));
0995:            }
0996:
0997:            private String getInternalFindString(String findString) {
0998:                if (findString == null) {
0999:                    return null;
1000:                }
1001:
1002:                return findString.toLowerCase();
1003:            }
1004:
1005:            private CCTNode getSearchRoot() {
1006:                if (!isAnyRowSelected()) {
1007:                    return (CCTNode) treeTableModel.getRoot();
1008:                } else {
1009:                    return (CCTNode) tree.getSelectionPath()
1010:                            .getLastPathComponent();
1011:                }
1012:            }
1013:
1014:            private void setTreeUIVariables() {
1015:                if (tree.getUI() instanceof  BasicTreeUI) {
1016:                    BasicTreeUI treeUI = (BasicTreeUI) tree.getUI();
1017:                    treeSignExtent = treeUI.getExpandedIcon().getIconWidth() / 2;
1018:                    treeSignRightMargin = treeUI.getRightChildIndent();
1019:                }
1020:            }
1021:
1022:            private void dispatchKeyboardEvent(KeyEvent e) {
1023:                JTreeTable.this .tree.customProcessKeyEvent(e);
1024:
1025:                int selectedRow = getSelectedRow();
1026:
1027:                if (selectedRow > -1) {
1028:                    scrollRectToVisible(getCellRect(selectedRow, 0, false));
1029:                }
1030:            }
1031:
1032:            private void dispatchMouseEvent(MouseEvent e) {
1033:                if (e != null) {
1034:                    int row = rowAtPoint(e.getPoint());
1035:                    int column = columnAtPoint(e.getPoint());
1036:
1037:                    Rectangle tableCellRect = getCellRect(row, column, true);
1038:                    Rectangle treeCellRect = tree.getRowBounds(row);
1039:
1040:                    if (treeCellRect != null) {
1041:                        // x-coordinate of the mouseclick must be mapped to the tree coordinate system
1042:                        int xClick;
1043:                        Class columnClass = getColumnClass(column);
1044:
1045:                        if (columnClass == TreeTableModel.class) {
1046:                            // Clicked inside tree cell
1047:                            xClick = e.getX() - tableCellRect.x;
1048:                            xClick += tree.getOffsetX();
1049:
1050:                            if ((xClick < (treeCellRect.x - treeSignExtent - treeSignRightMargin))
1051:                                    || (xClick > ((treeCellRect.x + treeSignExtent)
1052:                                            - treeSignRightMargin + 1))) {
1053:                                // Clicked on "+"/"-" sign
1054:                                xClick = (treeCellRect.x + treeCellRect.width) - 1;
1055:                            }
1056:                        } else {
1057:                            // Clicked outside tree cell
1058:                            xClick = (treeCellRect.x + treeCellRect.width) - 1;
1059:                        }
1060:
1061:                        int clickCount = 2 - (e.getClickCount() % 2);
1062:
1063:                        MouseEvent newEvent = new MouseEvent(
1064:                                JTreeTable.this .tree, e.getID(), e.getWhen(), e
1065:                                        .getModifiers(), xClick, e.getY(),
1066:                                clickCount, e.isPopupTrigger());
1067:                        JTreeTable.this .tree.dispatchEvent(newEvent);
1068:                    }
1069:                }
1070:            }
1071:
1072:            private boolean doFindNext(CCTNode rootForSearch,
1073:                    int childToSearchIndex, boolean requestFocus) {
1074:                int nChildren = rootForSearch.getNChildren();
1075:
1076:                // for all not processed children
1077:                while (childToSearchIndex < nChildren) {
1078:                    CCTNode childToSearch = rootForSearch
1079:                            .getChild(childToSearchIndex);
1080:
1081:                    // check the child itself
1082:                    if (matchesFindCriterion(childToSearch)) {
1083:                        return selectFoundNode(childToSearch, requestFocus);
1084:                    }
1085:                    // and then its subtree
1086:                    else if ((childToSearch.getNChildren() > 0)
1087:                            && doFindNext(childToSearch, 0, requestFocus)) {
1088:                        return true;
1089:                    }
1090:
1091:                    childToSearchIndex++;
1092:                }
1093:
1094:                // nothing found
1095:                return false;
1096:            }
1097:
1098:            private boolean doFindPrevious(CCTNode rootForSearch,
1099:                    int childToSearchIndex, boolean requestFocus) {
1100:                // check all not processed children
1101:                while (childToSearchIndex >= 0) {
1102:                    CCTNode childToSearch = rootForSearch
1103:                            .getChild(childToSearchIndex);
1104:
1105:                    if (doFindPrevious(childToSearch, childToSearch
1106:                            .getNChildren() - 1, requestFocus)) {
1107:                        return true;
1108:                    }
1109:
1110:                    childToSearchIndex--;
1111:                }
1112:
1113:                // check itself
1114:                if (matchesFindCriterion(rootForSearch)) {
1115:                    return selectFoundNode(rootForSearch, requestFocus);
1116:                }
1117:
1118:                // nothing found
1119:                return false;
1120:            }
1121:
1122:            private boolean findFirst(boolean requestFocus) {
1123:                if (!canFindBePerformed()) {
1124:                    return false;
1125:                }
1126:
1127:                CCTNode searchRoot = (CCTNode) treeTableModel.getRoot();
1128:
1129:                if (matchesFindCriterion(searchRoot)) {
1130:                    return selectFoundNode(searchRoot, requestFocus);
1131:                } else {
1132:                    return doFindNext(searchRoot, 0, requestFocus);
1133:                }
1134:            }
1135:
1136:            private boolean matchesFindCriterion(Object node) {
1137:                // find is always performed on values of the first column
1138:                // first column is always visible and has always index=0
1139:                return treeTableModel.getValueAt(node, 0).toString()
1140:                        .toLowerCase().indexOf(internalFindString) != -1;
1141:            }
1142:
1143:            private boolean selectFoundNode(CCTNode nodeToSelect,
1144:                    boolean requestFocus) {
1145:                TreePath nodeToSelectPath = new TreePath(treeTableModel
1146:                        .getPathToRoot(nodeToSelect));
1147:                tree.expandPath(nodeToSelectPath);
1148:                tree.setSelectionPath(nodeToSelectPath);
1149:
1150:                if (requestFocus) {
1151:                    requestFocusInWindow();
1152:                }
1153:
1154:                Rectangle rect = tree.getPathBounds(nodeToSelectPath);
1155:
1156:                if (rect != null) {
1157:                    scrollRectToVisible(rect);
1158:
1159:                    return true;
1160:                } else {
1161:                    return false;
1162:                }
1163:            }
1164:
1165:            // Filters-out actions handled by the JTable itself,
1166:            // see http://www.netbeans.org/issues/show_bug.cgi?id=112848
1167:            private boolean shouldBeForwarded(KeyEvent e) {
1168:                switch (e.getKeyCode()) {
1169:                case KeyEvent.VK_PAGE_UP:
1170:                case KeyEvent.VK_PAGE_DOWN:
1171:                    return false;
1172:                default:
1173:                    return true;
1174:                }
1175:            }
1176:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.