001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: * The Original Software is NetBeans. The Initial Developer of the Original
026: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
027: * Microsystems, Inc. All Rights Reserved.
028: *
029: * If you wish your version of this file to be governed by only the CDDL
030: * or only the GPL Version 2, indicate your decision by adding
031: * "[Contributor] elects to include this software in this distribution
032: * under the [CDDL or GPL Version 2] license." If you do not indicate a
033: * single choice of license, a recipient has the option to distribute
034: * your version of this file under either the CDDL, the GPL Version 2 or
035: * to extend the choice of license to its licensees as provided above.
036: * However, if you add GPL Version 2 code and therefore, elected the GPL
037: * Version 2 license, then the option applies only if the new code is
038: * made subject to such option by the copyright holder.
039: */
040:
041: package org.netbeans.lib.profiler.ui.cpu;
042:
043: import org.netbeans.lib.profiler.global.CommonConstants;
044: import org.netbeans.lib.profiler.results.cpu.CPUResultsSnapshot;
045: import org.netbeans.lib.profiler.results.cpu.PrestimeCPUCCTNode;
046: import org.netbeans.lib.profiler.ui.UIConstants;
047: import org.netbeans.lib.profiler.ui.UIUtils;
048: import org.netbeans.lib.profiler.ui.components.JTreeTable;
049: import org.netbeans.lib.profiler.ui.components.table.CustomBarCellRenderer;
050: import org.netbeans.lib.profiler.ui.components.table.LabelBracketTableCellRenderer;
051: import org.netbeans.lib.profiler.ui.components.table.LabelTableCellRenderer;
052: import org.netbeans.lib.profiler.ui.components.table.SortableTableModel;
053: import org.netbeans.lib.profiler.ui.components.tree.EnhancedTreeCellRenderer;
054: import org.netbeans.lib.profiler.ui.components.tree.MethodNameTreeCellRenderer;
055: import org.netbeans.lib.profiler.ui.components.treetable.AbstractTreeTableModel;
056: import org.netbeans.lib.profiler.ui.components.treetable.ExtendedTreeTableModel;
057: import org.netbeans.lib.profiler.ui.components.treetable.JTreeTablePanel;
058: import org.netbeans.lib.profiler.ui.components.treetable.TreeTableModel;
059: import org.netbeans.lib.profiler.utils.StringUtils;
060: import java.awt.KeyboardFocusManager;
061: import java.awt.Rectangle;
062: import java.awt.event.ActionEvent;
063: import java.awt.event.FocusListener;
064: import java.awt.event.InputEvent;
065: import java.awt.event.KeyAdapter;
066: import java.awt.event.KeyEvent;
067: import java.awt.event.MouseAdapter;
068: import java.awt.event.MouseEvent;
069: import java.awt.image.BufferedImage;
070: import java.util.HashSet;
071: import java.util.ResourceBundle;
072: import java.util.Set;
073: import javax.swing.*;
074: import javax.swing.event.ListSelectionEvent;
075: import javax.swing.event.ListSelectionListener;
076: import javax.swing.table.TableCellRenderer;
077: import javax.swing.table.TableColumnModel;
078:
079: /**
080: * A display containing a CCT (calling context tree). Always appears together with flat profile display.
081: *
082: * @author Misha Dmitriev
083: * @author Jiri Sedlacek
084: * @author Ian Formanek
085: */
086: public class CCTDisplay extends SnapshotCPUResultsPanel implements
087: ScreenshotProvider {
088: //~ Static fields/initializers -----------------------------------------------------------------------------------------------
089:
090: // -----
091: // I18N String constants
092: private static final ResourceBundle messages = ResourceBundle
093: .getBundle("org.netbeans.lib.profiler.ui.cpu.Bundle"); // NOI18N
094: private static final String METHOD_COLUMN_NAME = messages
095: .getString("CCTDisplay_MethodColumnName"); // NOI18N
096: private static final String METHOD_COLUMN_TOOLTIP = messages
097: .getString("CCTDisplay_MethodColumnToolTip"); // NOI18N
098: private static final String CLASS_COLUMN_NAME = messages
099: .getString("CCTDisplay_ClassColumnName"); // NOI18N
100: private static final String CLASS_COLUMN_TOOLTIP = messages
101: .getString("CCTDisplay_ClassColumnToolTip"); // NOI18N
102: private static final String PACKAGE_COLUMN_NAME = messages
103: .getString("CCTDisplay_PackageColumnName"); // NOI18N
104: private static final String PACKAGE_COLUMN_TOOLTIP = messages
105: .getString("CCTDisplay_PackageColumnToolTip"); // NOI18N
106: private static final String TIME_REL_COLUMN_NAME = messages
107: .getString("CCTDisplay_TimeRelColumnName"); // NOI18N
108: private static final String TIME_COLUMN_NAME = messages
109: .getString("CCTDisplay_TimeColumnName"); // NOI18N
110: private static final String TIME_CPU_COLUMN_NAME = messages
111: .getString("CCTDisplay_TimeCpuColumnName"); // NOI18N
112: private static final String INVOCATIONS_COLUMN_NAME = messages
113: .getString("CCTDisplay_InvocationsColumnName"); // NOI18N
114: private static final String TIME_REL_COLUMN_TOOLTIP = messages
115: .getString("CCTDisplay_TimeRelColumnToolTip"); // NOI18N
116: private static final String TIME_COLUMN_TOOLTIP = messages
117: .getString("CCTDisplay_TimeColumnToolTip"); // NOI18N
118: private static final String TIME_CPU_COLUMN_TOOLTIP = messages
119: .getString("CCTDisplay_TimeCpuColumnToolTip"); // NOI18N
120: private static final String INVOCATIONS_COLUMN_TOOLTIP = messages
121: .getString("CCTDisplay_InvocationsColumnToolTip"); // NOI18N
122: private static final String TREETABLE_ACCESS_NAME = messages
123: .getString("CCTDisplay_TreeTableAccessName"); // NOI18N
124: // -----
125: private static final boolean DEBUG = System
126: .getProperty("org.netbeans.lib.profiler.ui.cpu.CCTDisplay") != null; // NOI18N
127:
128: //~ Instance fields ----------------------------------------------------------------------------------------------------------
129:
130: protected JTreeTable treeTable;
131: protected JTreeTablePanel treeTablePanel;
132: protected boolean sortOrder;
133: protected int sortingColumn;
134: private AbstractTreeTableModel abstractTreeTableModel;
135: private CPUSelectionHandler selectionHandler;
136: private EnhancedTreeCellRenderer enhancedTreeCellRenderer = new MethodNameTreeCellRenderer();
137: private ExtendedTreeTableModel treeTableModel;
138: private ImageIcon leafIcon = new ImageIcon(
139: CCTDisplay.class
140: .getResource("/org/netbeans/lib/profiler/ui/resources/leaf.png")); // NOI18N
141: private ImageIcon nodeIcon = new ImageIcon(
142: CCTDisplay.class
143: .getResource("/org/netbeans/lib/profiler/ui/resources/node.png")); // NOI18N
144: private JButton cornerButton;
145: private int minNamesColumnWidth; // minimal width of classnames columns
146:
147: //~ Constructors -------------------------------------------------------------------------------------------------------------
148:
149: public CCTDisplay(CPUResUserActionsHandler actionsHandler) {
150: this (actionsHandler, null);
151: }
152:
153: public CCTDisplay(CPUResUserActionsHandler actionsHandler,
154: CPUSelectionHandler selectionHandler) {
155: super (actionsHandler);
156:
157: this .selectionHandler = selectionHandler;
158:
159: enhancedTreeCellRenderer.setLeafIcon(leafIcon);
160: enhancedTreeCellRenderer.setClosedIcon(nodeIcon);
161: enhancedTreeCellRenderer.setOpenIcon(nodeIcon);
162:
163: minNamesColumnWidth = getFontMetrics(getFont()).charWidth('W') * 30; // NOI18N
164:
165: cornerPopup = new JPopupMenu();
166: cornerButton = createHeaderPopupCornerButton(cornerPopup);
167:
168: setDefaultSorting();
169: }
170:
171: //~ Methods ------------------------------------------------------------------------------------------------------------------
172:
173: public int getCurrentThreadId() {
174: return -10;
175: } // A meaningless value to denote we don't display results for any
176:
177: // single thread in this window
178:
179: public BufferedImage getCurrentViewScreenshot(
180: boolean onlyVisibleArea) {
181: if ((treeTablePanel == null) || (treeTable == null)) {
182: return null;
183: }
184:
185: if (onlyVisibleArea) {
186: return UIUtils.createScreenshot(treeTablePanel
187: .getScrollPane());
188: } else {
189: return UIUtils.createScreenshot(treeTable);
190: }
191: }
192:
193: // NOTE: this method only sets sortingColumn, sortOrder and sortBy, it doesn't refresh UI!
194: public void setDefaultSorting() {
195: setSorting(1, SortableTableModel.SORT_ORDER_DESC);
196: }
197:
198: public String getDefaultViewName() {
199: return "cpu-calltree"; // NOI18N
200: }
201:
202: // --- Find functionality stuff
203: public void setFindString(String findString) {
204: treeTable.setFindParameters(findString, 0);
205: }
206:
207: public String getFindString() {
208: return treeTable.getFindString();
209: }
210:
211: public boolean isFindStringDefined() {
212: return treeTable.isFindStringDefined();
213: }
214:
215: public Object getResultsViewReference() {
216: return treeTable;
217: }
218:
219: // NOTE: this method only sets sortingColumn, sortOrder and sortBy, it doesn't refresh UI!
220: public void setSorting(int sColumn, boolean sOrder) {
221: if (sColumn == CommonConstants.SORTING_COLUMN_DEFAULT) {
222: setDefaultSorting();
223: } else {
224: sortingColumn = sColumn;
225: sortOrder = sOrder;
226:
227: //sortBy = getSortBy(sortingColumn);
228: }
229: }
230:
231: public int getSortingColumn() {
232: if ((treeTable == null) || (treeTableModel == null)) {
233: return CommonConstants.SORTING_COLUMN_DEFAULT;
234: }
235:
236: return treeTableModel.getRealColumn(treeTable
237: .getSortingColumn());
238: }
239:
240: public boolean getSortingOrder() {
241: if (treeTable == null) {
242: return false;
243: }
244:
245: return treeTable.getSortingOrder();
246: }
247:
248: public void addResultsViewFocusListener(FocusListener listener) {
249: treeTable.addFocusListener(listener);
250: }
251:
252: public boolean findFirst() {
253: return treeTable.findFirst();
254: }
255:
256: public boolean findNext() {
257: return treeTable.findNext();
258: }
259:
260: public boolean findPrevious() {
261: return treeTable.findPrevious();
262: }
263:
264: public boolean fitsVisibleArea() {
265: return !treeTablePanel.getScrollPane().getVerticalScrollBar()
266: .isEnabled();
267: }
268:
269: public void prepareResults() {
270: int currentColumnCount = snapshot.isCollectingTwoTimeStamps() ? 5
271: : 4;
272:
273: if (DEBUG) {
274: columnCount++; // one extra column for jMethodID
275: }
276:
277: if (columnCount != currentColumnCount) {
278: initColumnsData();
279: } else {
280: if (treeTable != null) {
281: saveColumnsData();
282: }
283: }
284:
285: if (treeTable != null) {
286: sortingColumn = treeTable.getSortingColumn();
287: }
288:
289: reset();
290: initFirstColumnName();
291:
292: abstractTreeTableModel = new AbstractTreeTableModel(snapshot
293: .getRootNode(currentView), sortingColumn, sortOrder) {
294: public int getColumnCount() {
295: return columnCount;
296: }
297:
298: public String getColumnName(int column) {
299: return columnNames[column];
300: }
301:
302: public Class getColumnClass(int column) {
303: if (column == 0) {
304: return TreeTableModel.class;
305: } else {
306: return Object.class;
307: }
308: }
309:
310: public Object getValueAt(Object node, int column) {
311: if (!snapshot.isCollectingTwoTimeStamps()) {
312: if (column > 2) {
313: column += 1;
314: }
315: }
316:
317: PrestimeCPUCCTNode pNode = (PrestimeCPUCCTNode) node;
318:
319: switch (column) {
320: case 0:
321: return pNode;
322: case 1:
323: return getNodeTimeRel(pNode);
324: case 2:
325: return getNodeTime(pNode);
326: case 3:
327: return getNodeSecondaryTime(pNode);
328: case 4:
329: return getNodeInvocations(pNode);
330: case 5:
331: return getNodeMethodId(pNode);
332: }
333:
334: return null;
335: }
336:
337: public String getColumnToolTipText(int col) {
338: return columnToolTips[col];
339: }
340:
341: private Float getNodeTimeRel(PrestimeCPUCCTNode pNode) {
342: return new Float(pNode.getTotalTime0InPerCent());
343: }
344:
345: private String getNodeTime(PrestimeCPUCCTNode pNode) {
346: return StringUtils.mcsTimeToString(pNode
347: .getTotalTime0())
348: + " ms (" // NOI18N
349: + percentFormat.format(pNode
350: .getTotalTime0InPerCent() / 100) + ")"; // NOI18N
351: }
352:
353: private String getNodeWaitTime(PrestimeCPUCCTNode pNode) {
354: return StringUtils
355: .mcsTimeToString(pNode.getWaitTime0())
356: + " ms"; // NOI18N
357: }
358:
359: private String getNodeSleepTime(PrestimeCPUCCTNode pNode) {
360: return StringUtils.mcsTimeToString(pNode
361: .getSleepTime0())
362: + " ms"; // NOI18N
363: }
364:
365: private String getNodeSecondaryTime(PrestimeCPUCCTNode pNode) {
366: return StringUtils.mcsTimeToString(pNode
367: .getTotalTime1())
368: + " ms"; // NOI18N
369: }
370:
371: private Integer getNodeInvocations(PrestimeCPUCCTNode pNode) {
372: return new Integer(pNode.getNCalls());
373: }
374:
375: private Integer getNodeMethodId(PrestimeCPUCCTNode pNode) {
376: return new Integer(pNode.getMethodId());
377: }
378:
379: public void sortByColumn(int column, boolean order) {
380: sortOrder = order;
381:
382: //sortingColumn = column;
383: if (!snapshot.isCollectingTwoTimeStamps()) {
384: if (column > 2) {
385: column += 1;
386: }
387: }
388:
389: PrestimeCPUCCTNode pRoot = (PrestimeCPUCCTNode) root;
390:
391: //System.err.println(">> CCT: " + CCTDisplay.this.hashCode() + " sortByColumn " + column + ", " + order);
392: switch (column) {
393: case 0:
394: pRoot.sortChildren(PrestimeCPUCCTNode.SORT_BY_NAME,
395: order);
396:
397: break;
398: case 1:
399: pRoot.sortChildren(
400: PrestimeCPUCCTNode.SORT_BY_TIME_0, order);
401:
402: break;
403: case 2:
404: pRoot.sortChildren(
405: PrestimeCPUCCTNode.SORT_BY_TIME_0, order);
406:
407: break;
408: case 3:
409: pRoot.sortChildren(
410: PrestimeCPUCCTNode.SORT_BY_TIME_1, order);
411:
412: break;
413: case 4:
414: pRoot.sortChildren(
415: PrestimeCPUCCTNode.SORT_BY_INVOCATIONS,
416: order);
417:
418: break;
419: }
420: };
421:
422: public boolean getInitialSorting(int column) {
423: return (column == 0);
424: }
425: };
426:
427: treeTableModel = new ExtendedTreeTableModel(
428: abstractTreeTableModel);
429:
430: if (columnsVisibility != null) {
431: treeTableModel.setColumnsVisibility(columnsVisibility);
432: }
433:
434: treeTable = new JTreeTable(treeTableModel) {
435: public void doLayout() {
436: int columnsWidthsSum = 0;
437: int realFirstColumn = -1;
438:
439: int index;
440: TableColumnModel colModel = getColumnModel();
441:
442: for (int i = 0; i < treeTableModel.getColumnCount(); i++) {
443: index = treeTableModel.getRealColumn(i);
444:
445: if (index == 0) {
446: realFirstColumn = i;
447: } else {
448: columnsWidthsSum += colModel.getColumn(i)
449: .getPreferredWidth();
450: }
451: }
452:
453: if (realFirstColumn != -1) {
454: colModel.getColumn(realFirstColumn)
455: .setPreferredWidth(
456: Math.max(getWidth()
457: - columnsWidthsSum,
458: minNamesColumnWidth));
459: }
460:
461: super .doLayout();
462: };
463: };
464: treeTable.getAccessibleContext().setAccessibleName(
465: TREETABLE_ACCESS_NAME);
466:
467: treeTable.setRowSelectionAllowed(true);
468: treeTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
469: treeTable.setGridColor(UIConstants.TABLE_VERTICAL_GRID_COLOR);
470: treeTable
471: .setSelectionBackground(UIConstants.TABLE_SELECTION_BACKGROUND_COLOR);
472: treeTable
473: .setSelectionForeground(UIConstants.TABLE_SELECTION_FOREGROUND_COLOR);
474: treeTable
475: .setShowHorizontalLines(UIConstants.SHOW_TABLE_HORIZONTAL_GRID);
476: treeTable
477: .setShowVerticalLines(UIConstants.SHOW_TABLE_VERTICAL_GRID);
478: treeTable.setRowMargin(UIConstants.TABLE_ROW_MARGIN);
479: treeTable.setRowHeight(UIUtils.getDefaultRowHeight() + 2);
480: treeTable
481: .getInputMap(JTable.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
482: .put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),
483: "DEFAULT_ACTION"); // NOI18N
484: treeTable.getActionMap().put("DEFAULT_ACTION",
485: new AbstractAction() {
486: public void actionPerformed(ActionEvent e) {
487: performDefaultAction();
488: }
489: }); // NOI18N
490:
491: // Disable traversing table cells using TAB and Shift+TAB
492: Set keys = new HashSet(
493: treeTable
494: .getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS));
495: keys.add(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0));
496: treeTable.setFocusTraversalKeys(
497: KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, keys);
498:
499: keys = new HashSet(
500: treeTable
501: .getFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS));
502: keys.add(KeyStroke.getKeyStroke(KeyEvent.VK_TAB,
503: InputEvent.SHIFT_MASK));
504: treeTable.setFocusTraversalKeys(
505: KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, keys);
506:
507: setColumnsData();
508:
509: UIUtils.autoExpandRoot(treeTable.getTree(), 2);
510: UIUtils.makeTreeAutoExpandable(treeTable.getTree(), 2);
511:
512: treeTable.addKeyListener(new KeyAdapter() {
513: public void keyPressed(KeyEvent e) {
514: if ((e.getKeyCode() == KeyEvent.VK_CONTEXT_MENU)
515: || ((e.getKeyCode() == KeyEvent.VK_F10) && (e
516: .getModifiers() == InputEvent.SHIFT_MASK))) {
517: int selectedRow = treeTable.getSelectedRow();
518:
519: if (selectedRow != -1) {
520: popupPath = treeTable.getTree().getPathForRow(
521: selectedRow);
522:
523: PrestimeCPUCCTNode node = (PrestimeCPUCCTNode) popupPath
524: .getLastPathComponent();
525: enableDisablePopup(node);
526:
527: Rectangle cellRect = treeTable.getCellRect(
528: selectedRow, 0, false);
529: callGraphPopupMenu
530: .show(
531: e.getComponent(),
532: ((cellRect.x + treeTable
533: .getSize().width) > 50) ? 50
534: : 5, cellRect.y);
535: }
536: }
537: }
538: });
539:
540: treeTable.addMouseListener(new MouseAdapter() {
541: public void mousePressed(MouseEvent e) {
542: if (e.getModifiers() == InputEvent.BUTTON3_MASK) {
543: popupPath = treeTable.getTree().getPathForRow(
544: treeTable.rowAtPoint(e.getPoint()));
545:
546: if (popupPath != null) {
547: treeTable.getTree().setSelectionPath(popupPath);
548: }
549: }
550: }
551:
552: public void mouseClicked(MouseEvent e) {
553: popupPath = treeTable.getTree().getPathForRow(
554: treeTable.rowAtPoint(e.getPoint()));
555:
556: if (popupPath == null) {
557: if (e.getModifiers() == InputEvent.BUTTON3_MASK) {
558: treeTable.getTree().clearSelection();
559: }
560: } else {
561: PrestimeCPUCCTNode node = (PrestimeCPUCCTNode) popupPath
562: .getLastPathComponent();
563:
564: enableDisablePopup(node);
565:
566: if (e.getModifiers() == InputEvent.BUTTON3_MASK) {
567: callGraphPopupMenu.show(e.getComponent(), e
568: .getX(), e.getY());
569: } else if ((e.getModifiers() == InputEvent.BUTTON1_MASK)
570: && (e.getClickCount() == 2)) {
571: if (treeTableModel
572: .isLeaf(popupPath.getPath()[popupPath
573: .getPath().length - 1])) {
574: showSourceForMethod(popupPath);
575: }
576: }
577: }
578: }
579: });
580:
581: treeTable.getSelectionModel().addListSelectionListener(
582: new ListSelectionListener() {
583: public void valueChanged(ListSelectionEvent e) {
584: int selectedRow = treeTable.getSelectedRow();
585:
586: if (selectedRow == -1) {
587: return;
588: }
589:
590: popupPath = treeTable.getTree().getPathForRow(
591: selectedRow);
592:
593: PrestimeCPUCCTNode node = (PrestimeCPUCCTNode) popupPath
594: .getLastPathComponent();
595:
596: if (selectionHandler != null) {
597: selectionHandler.methodSelected(node
598: .getThreadId(), node.getMethodId(),
599: currentView);
600: }
601: }
602: });
603:
604: treeTablePanel = new JTreeTablePanel(treeTable);
605: treeTablePanel.setCorner(JScrollPane.UPPER_RIGHT_CORNER,
606: cornerButton);
607: add(treeTablePanel, java.awt.BorderLayout.CENTER);
608: }
609:
610: public void removeResultsViewFocusListener(FocusListener listener) {
611: treeTable.removeFocusListener(listener);
612: }
613:
614: public void requestFocus() {
615: if (treeTable != null) {
616: SwingUtilities.invokeLater(new Runnable() { // must be invoked lazily to override default focus of first component (top-right cornerButton)
617: public void run() {
618: treeTable.requestFocus();
619: }
620: });
621: }
622: }
623:
624: public void reset() {
625: if (treeTablePanel != null) {
626: remove(treeTablePanel);
627: treeTablePanel = null;
628: }
629:
630: treeTable = null;
631: abstractTreeTableModel = null;
632: treeTableModel = null;
633: }
634:
635: public boolean silentlyFindFirst() {
636: return treeTable.silentlyFindFirst();
637: }
638:
639: protected String getSelectedMethodName() {
640: if ((treeTable == null) || (treeTableModel == null)) {
641: return null;
642: }
643:
644: if (treeTable.getSelectedRow() == -1) {
645: return null;
646: }
647:
648: PrestimeCPUCCTNode pNode = (PrestimeCPUCCTNode) treeTable
649: .getTree().getSelectionPath().getLastPathComponent();
650:
651: if (pNode.isSelfTimeNode()) {
652: // Self time represents the same method as its parent Node, and the parent's display name is
653: // the actual method name
654: pNode = (PrestimeCPUCCTNode) pNode.getParent();
655: }
656:
657: if (pNode.isThreadNode()) {
658: // For thread node, the method name is display name of its single child
659: pNode = (PrestimeCPUCCTNode) pNode.getChildren()[0];
660: }
661:
662: return treeTableModel.getValueAt(pNode, 0).toString();
663: }
664:
665: protected void initColumnSelectorItems() {
666: cornerPopup.removeAll();
667:
668: JCheckBoxMenuItem menuItem;
669:
670: for (int i = 0; i < columnCount; i++) {
671: menuItem = new JCheckBoxMenuItem(columnNames[i]);
672: menuItem.setActionCommand(new Integer(i).toString());
673: addMenuItemListener(menuItem);
674:
675: if (treeTable != null) {
676: menuItem
677: .setState(treeTableModel.isRealColumnVisible(i));
678:
679: if (i == 0) {
680: menuItem.setEnabled(false);
681: }
682: } else {
683: menuItem.setState(true);
684: }
685:
686: cornerPopup.add(menuItem);
687: }
688:
689: cornerPopup.pack();
690: }
691:
692: private void setColumnsData() {
693: int index;
694: TableColumnModel colModel = treeTable.getColumnModel();
695:
696: treeTable.setTreeCellRenderer(enhancedTreeCellRenderer);
697: colModel.getColumn(0).setPreferredWidth(minNamesColumnWidth);
698:
699: for (int i = 0; i < treeTableModel.getColumnCount(); i++) {
700: index = treeTableModel.getRealColumn(i);
701:
702: if (index != 0) {
703: colModel.getColumn(i).setPreferredWidth(
704: columnWidths[index - 1]);
705: colModel.getColumn(i).setCellRenderer(
706: columnRenderers[index]);
707: }
708: }
709: }
710:
711: private void addMenuItemListener(JCheckBoxMenuItem menuItem) {
712: menuItem.addActionListener(new java.awt.event.ActionListener() {
713: public void actionPerformed(java.awt.event.ActionEvent e) {
714: boolean sortResults = false;
715: int column = Integer.parseInt(e.getActionCommand());
716: sortingColumn = treeTable.getSortingColumn();
717:
718: int realSortingColumn = treeTableModel
719: .getRealColumn(sortingColumn);
720: boolean isColumnVisible = treeTableModel
721: .isRealColumnVisible(column);
722:
723: // Current sorting column is going to be hidden
724: if ((isColumnVisible) && (column == realSortingColumn)) {
725: // Try to set next column as a sortingColumn. If currentSortingColumn is the last column, set previous
726: // column as a sorting Column (one column is always visible).
727: sortingColumn = ((sortingColumn + 1) == treeTableModel
728: .getColumnCount()) ? (sortingColumn - 1)
729: : (sortingColumn + 1);
730: realSortingColumn = treeTableModel
731: .getRealColumn(sortingColumn);
732: sortResults = true;
733: }
734:
735: treeTableModel.setRealColumnVisibility(column,
736: !isColumnVisible);
737: treeTable.createDefaultColumnsFromModel();
738: treeTable.updateTreeTableHeader();
739: sortingColumn = treeTableModel
740: .getVirtualColumn(realSortingColumn);
741:
742: if (sortResults) {
743: sortOrder = treeTableModel
744: .getInitialSorting(sortingColumn);
745: treeTableModel.sortByColumn(sortingColumn,
746: sortOrder);
747: treeTable.updateTreeTable();
748: }
749:
750: treeTable.setSortingColumn(sortingColumn);
751: treeTable.setSortingOrder(sortOrder);
752: treeTable.getTableHeader().repaint();
753: setColumnsData();
754:
755: // TODO [ui-persistence]
756: }
757: });
758: }
759:
760: private void enableDisablePopup(PrestimeCPUCCTNode node) {
761: popupShowSource
762: .setEnabled(isShowSourceAvailable()
763: && ((node.getThreadId() != -1) && (node
764: .getMethodId() > 0)));
765: popupShowSubtree.setEnabled((node.getThreadId() != -1)
766: && (node.getMethodId() > 0));
767: popupShowReverse.setEnabled((node.getThreadId() != -1)
768: && (node.getMethodId() > 0));
769: popupAddToRoots
770: .setEnabled(isAddToRootsAvailable()
771: && ((node.getThreadId() != -1) && (node
772: .getMethodId() > 0)));
773: popupFind.setEnabled((node.getThreadId() != -1)
774: && (node.getMethodId() > 0));
775: }
776:
777: private void initColumnsData() {
778: columnCount = snapshot.isCollectingTwoTimeStamps() ? 5 : 4;
779:
780: if (DEBUG) {
781: columnCount++; // one extra column for jMethodID
782: }
783:
784: columnWidths = new int[columnCount - 1]; // Width of the first column fits to width
785: columnNames = new String[columnCount];
786: columnRenderers = new TableCellRenderer[columnCount];
787: columnsVisibility = null;
788:
789: int idx = 0;
790: columnNames = new String[columnCount];
791: columnNames[idx++] = ""; // NOI18N
792: columnNames[idx++] = TIME_REL_COLUMN_NAME;
793: columnNames[idx++] = TIME_COLUMN_NAME;
794:
795: if (snapshot.isCollectingTwoTimeStamps()) {
796: columnNames[idx++] = TIME_CPU_COLUMN_NAME;
797: }
798:
799: columnNames[idx++] = INVOCATIONS_COLUMN_NAME;
800:
801: if (DEBUG) {
802: columnNames[idx++] = "JMethodID"; // NOI18N
803: }
804:
805: idx = 0;
806: columnToolTips = new String[columnCount];
807: columnToolTips[idx++] = ""; // NOI18N
808: columnToolTips[idx++] = TIME_REL_COLUMN_TOOLTIP;
809: columnToolTips[idx++] = TIME_COLUMN_TOOLTIP;
810:
811: if (snapshot.isCollectingTwoTimeStamps()) {
812: columnToolTips[idx++] = TIME_CPU_COLUMN_TOOLTIP;
813: }
814:
815: columnToolTips[idx++] = INVOCATIONS_COLUMN_TOOLTIP;
816:
817: if (DEBUG) {
818: columnToolTips[idx++] = "JMethodID for the method"; // NOI18N
819: }
820:
821: int maxWidth = getFontMetrics(getFont()).charWidth('W') * 12; // NOI18N // initial width of data columns
822:
823: CustomBarCellRenderer customBarCellRenderer = new CustomBarCellRenderer(
824: 0, 100);
825: LabelTableCellRenderer labelTableCellRenderer = new LabelTableCellRenderer(
826: JLabel.TRAILING);
827: LabelBracketTableCellRenderer labelBracketTableCellRenderer = new LabelBracketTableCellRenderer(
828: JLabel.TRAILING);
829:
830: columnRenderers[0] = null;
831:
832: // Inclusive (total) time bar
833: columnWidths[1 - 1] = maxWidth;
834: columnRenderers[1] = customBarCellRenderer;
835:
836: // Inclusive (total) time
837: columnWidths[2 - 1] = maxWidth;
838: columnRenderers[2] = labelBracketTableCellRenderer;
839:
840: for (int i = 3; i < columnCount; i++) {
841: columnWidths[i - 1] = maxWidth;
842: columnRenderers[i] = labelTableCellRenderer;
843: }
844: }
845:
846: private void initFirstColumnName() {
847: switch (currentView) {
848: case CPUResultsSnapshot.METHOD_LEVEL_VIEW:
849: columnNames[0] = METHOD_COLUMN_NAME;
850: columnToolTips[0] = METHOD_COLUMN_TOOLTIP;
851:
852: break;
853: case CPUResultsSnapshot.CLASS_LEVEL_VIEW:
854: columnNames[0] = CLASS_COLUMN_NAME;
855: columnToolTips[0] = CLASS_COLUMN_TOOLTIP;
856:
857: break;
858: case CPUResultsSnapshot.PACKAGE_LEVEL_VIEW:
859: columnNames[0] = PACKAGE_COLUMN_NAME;
860: columnToolTips[0] = PACKAGE_COLUMN_TOOLTIP;
861:
862: break;
863: }
864:
865: if (treeTable != null) {
866: treeTable.getTableHeader().repaint();
867: }
868: }
869:
870: private void saveColumnsData() {
871: int index;
872: TableColumnModel colModel = treeTable.getColumnModel();
873:
874: for (int i = 0; i < treeTableModel.getColumnCount(); i++) {
875: index = treeTableModel.getRealColumn(i);
876:
877: if (index != 0) {
878: columnWidths[index - 1] = colModel.getColumn(i)
879: .getPreferredWidth();
880: }
881: }
882:
883: columnsVisibility = null;
884: columnsVisibility = treeTableModel.getColumnsVisibility();
885: }
886:
887: /*
888: public StringBuffer getResultsInCSVFormat(int callChainTypeCode, ExportDataDumper dataDumper) {
889: return snapshot.getResultsInCSVFormat(callChainTypeCode, dataDumper);
890: } */
891: }
|