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.memory;
042:
043: import org.netbeans.lib.profiler.global.CommonConstants;
044: import org.netbeans.lib.profiler.results.memory.PresoObjLivenessCCTNode;
045: import org.netbeans.lib.profiler.ui.UIConstants;
046: import org.netbeans.lib.profiler.ui.UIUtils;
047: import org.netbeans.lib.profiler.ui.components.*;
048: import org.netbeans.lib.profiler.ui.components.JExtendedTable;
049: import org.netbeans.lib.profiler.ui.components.table.ClassNameTableCellRenderer;
050: import org.netbeans.lib.profiler.ui.components.table.CustomBarCellRenderer;
051: import org.netbeans.lib.profiler.ui.components.table.ExtendedTableModel;
052: import org.netbeans.lib.profiler.ui.components.table.LabelBracketTableCellRenderer;
053: import org.netbeans.lib.profiler.ui.components.table.LabelTableCellRenderer;
054: import org.netbeans.lib.profiler.ui.components.table.SortableTableModel;
055: import org.netbeans.lib.profiler.utils.StringUtils;
056: import java.awt.KeyboardFocusManager;
057: import java.awt.event.ActionEvent;
058: import java.awt.event.ActionListener;
059: import java.awt.event.InputEvent;
060: import java.awt.event.KeyEvent;
061: import java.util.HashSet;
062: import java.util.ResourceBundle;
063: import java.util.Set;
064: import javax.swing.*;
065: import javax.swing.table.TableCellRenderer;
066: import javax.swing.table.TableColumnModel;
067:
068: /**
069: * This class implements presentation frames for Object Liveness Profiling.
070: *
071: * @author Misha Dmitriev
072: * @author Ian Formanek
073: * @author Jiri Sedlacek
074: */
075: public abstract class LivenessResultsPanel extends MemoryResultsPanel {
076: //~ Static fields/initializers -----------------------------------------------------------------------------------------------
077:
078: // -----
079: // I18N String constants
080: private static final ResourceBundle messages = ResourceBundle
081: .getBundle("org.netbeans.lib.profiler.ui.memory.Bundle"); // NOI18N
082: private static final String FILTER_MENU_ITEM_NAME = messages
083: .getString("LivenessResultsPanel_FilterMenuItemName"); // NOI18N
084: private static final String CLASS_COLUMN_NAME = messages
085: .getString("LivenessResultsPanel_ClassColumnName"); // NOI18N
086: private static final String LIVE_BYTES_REL_COLUMN_NAME = messages
087: .getString("LivenessResultsPanel_LiveBytesRelColumnName"); // NOI18N
088: private static final String LIVE_BYTES_COLUMN_NAME = messages
089: .getString("LivenessResultsPanel_LiveBytesColumnName"); // NOI18N
090: private static final String LIVE_OBJECTS_COLUMN_NAME = messages
091: .getString("LivenessResultsPanel_LiveObjectsColumnName"); // NOI18N
092: private static final String ALLOC_OBJECTS_COLUMN_NAME = messages
093: .getString("LivenessResultsPanel_AllocObjectsColumnName"); // NOI18N
094: private static final String AVG_AGE_COLUMN_NAME = messages
095: .getString("LivenessResultsPanel_AvgAgeColumnName"); // NOI18N
096: private static final String SURVGEN_COLUMN_NAME = messages
097: .getString("LivenessResultsPanel_SurvGenColumnName"); // NOI18N
098: private static final String TOTAL_ALLOC_OBJECTS_COLUMN_NAME = messages
099: .getString("LivenessResultsPanel_TotalAllocObjectsColumnName"); // NOI18N
100: private static final String CLASS_COLUMN_TOOLTIP = messages
101: .getString("LivenessResultsPanel_ClassColumnToolTip"); // NOI18N
102: private static final String LIVE_BYTES_REL_COLUMN_TOOLTIP = messages
103: .getString("LivenessResultsPanel_LiveBytesRelColumnToolTip"); // NOI18N
104: private static final String LIVE_BYTES_COLUMN_TOOLTIP = messages
105: .getString("LivenessResultsPanel_LiveBytesColumnToolTip"); // NOI18N
106: private static final String LIVE_OBJECTS_COLUMN_TOOLTIP = messages
107: .getString("LivenessResultsPanel_LiveObjectsColumnToolTip"); // NOI18N
108: private static final String ALLOC_OBJECTS_COLUMN_TOOLTIP = messages
109: .getString("LivenessResultsPanel_AllocObjectsColumnToolTip"); // NOI18N
110: private static final String AVG_AGE_COLUMN_TOOLTIP = messages
111: .getString("LivenessResultsPanel_AvgAgeColumnToolTip"); // NOI18N
112: private static final String SURVGEN_COLUMN_TOOLTIP = messages
113: .getString("LivenessResultsPanel_SurvGenColumnToolTip"); // NOI18N
114: private static final String TOTAL_ALLOC_OBJECTS_COLUMN_TOOLTIP = messages
115: .getString("LivenessResultsPanel_TotalAllocObjectsColumnToolTip"); // NOI18N
116: private static final String TABLE_ACCESS_NAME = messages
117: .getString("LivenessResultsPanel_TableAccessName"); // NOI18N
118: // -----
119:
120: //~ Instance fields ----------------------------------------------------------------------------------------------------------
121:
122: protected float[] avgObjectAge;
123: protected int[] maxSurvGen;
124: protected int[] nTotalAllocObjects; // # of allocated objects of each class
125: protected long[] nTrackedAllocObjects; // # of allocated objects of each class (just tracked)
126: protected int[] nTrackedLiveObjects; // # of live objects of each class
127: protected long[] trackedLiveObjectsSize; // Byte side of live objects of each class
128: protected int nInstrClasses;
129: protected int trackedAllocObjects;
130: protected int trackedLiveObjects;
131: protected long nTotalTracked;
132: protected long nTotalTrackedBytes;
133: private int initialSortingColumn;
134: private int minNamesColumnWidth; // minimal width of classnames columns
135:
136: //~ Constructors -------------------------------------------------------------------------------------------------------------
137:
138: public LivenessResultsPanel(
139: MemoryResUserActionsHandler actionsHandler) {
140: super (actionsHandler);
141:
142: setDefaultSorting();
143: }
144:
145: //~ Methods ------------------------------------------------------------------------------------------------------------------
146:
147: /*
148: * @return value 1-100 of percent of objects being tracked - to be used for column name rendering.
149: */
150:
151: // protected abstract int getPercentsTracked ();
152: // NOTE: this method only sets sortBy and sortOrder, it doesn't refresh UI!
153: public void setDefaultSorting() {
154: setSorting(1, SortableTableModel.SORT_ORDER_DESC);
155: }
156:
157: // NOTE: this method only sets sortBy and sortOrder, it doesn't refresh UI!
158: public void setSorting(int sColumn, boolean sOrder) {
159: if (sColumn == CommonConstants.SORTING_COLUMN_DEFAULT) {
160: setDefaultSorting();
161: } else {
162: initialSortingColumn = sColumn;
163: sortBy = getSortBy(initialSortingColumn);
164: sortOrder = sOrder;
165: }
166: }
167:
168: public int getSortingColumn() {
169: if (resTableModel == null) {
170: return CommonConstants.SORTING_COLUMN_DEFAULT;
171: }
172:
173: return resTableModel.getRealColumn(resTableModel
174: .getSortingColumn());
175: }
176:
177: public boolean getSortingOrder() {
178: if (resTableModel == null) {
179: return false;
180: }
181:
182: return resTableModel.getSortingOrder();
183: }
184:
185: protected CustomBarCellRenderer getBarCellRenderer() {
186: return new CustomBarCellRenderer(0, maxValue);
187: }
188:
189: protected void getResultsSortedByAllocObj() {
190: getResultsSortedByClassName(true); // Added because of lines toggling when switching between columns 1 and 2.
191: // At first items must be sorted by class names to get defined initial state for
192: // other sorting.
193:
194: int visibleLines = nInfoLines; // Zero or unprofiled classes are filtered, sorting will be applied only to live
195: // data
196:
197: nInfoLines = sortResults(nTrackedAllocObjects, new int[][] {
198: nTotalAllocObjects, nTrackedLiveObjects, maxSurvGen },
199: new long[][] { trackedLiveObjectsSize },
200: new float[][] { avgObjectAge }, 0, visibleLines, false);
201:
202: totalAllocations = 0;
203: trackedLiveObjects = trackedAllocObjects = 0;
204:
205: for (int i = 0; i < nInfoLines; i++) {
206: trackedLiveObjects += nTrackedLiveObjects[i];
207: trackedAllocObjects += nTrackedAllocObjects[i];
208: totalAllocations += nTotalAllocObjects[i];
209: }
210: }
211:
212: protected void getResultsSortedByAvgAge() {
213: getResultsSortedByClassName(true); // Added because of lines toggling when switching between columns 1 and 2.
214: // At first items must be sorted by class names to get defined initial state for
215: // other sorting.
216:
217: int visibleLines = nInfoLines; // Zero or unprofiled classes are filtered, sorting will be applied only to live
218: // data
219:
220: nInfoLines = sortResults(avgObjectAge, new int[][] {
221: nTotalAllocObjects, nTrackedLiveObjects, maxSurvGen },
222: new long[][] { trackedLiveObjectsSize,
223: nTrackedAllocObjects }, 0, visibleLines, false);
224:
225: totalAllocations = 0;
226: trackedLiveObjects = trackedAllocObjects = 0;
227:
228: for (int i = 0; i < nInfoLines; i++) {
229: trackedLiveObjects += nTrackedLiveObjects[i];
230: trackedAllocObjects += nTrackedAllocObjects[i];
231: totalAllocations += nTotalAllocObjects[i];
232: }
233: }
234:
235: protected void getResultsSortedByClassName(boolean presortOnly) {
236: // Sort classes by name, initially moving to the bottom elements that have zero allocated objects
237: nInfoLines = sortResultsByClassName(new int[][] {
238: nTotalAllocObjects, nTrackedLiveObjects, maxSurvGen },
239: new long[][] { trackedLiveObjectsSize,
240: nTrackedAllocObjects },
241: new float[][] { avgObjectAge }, //nInstrClasses, true);
242: nTrackedItems, truncateZeroItems());
243:
244: if (!presortOnly) {
245: totalAllocations = 0;
246: trackedLiveObjects = trackedAllocObjects = 0;
247:
248: for (int i = 0; i < nInfoLines; i++) {
249: trackedLiveObjects += nTrackedLiveObjects[i];
250: trackedAllocObjects += nTrackedAllocObjects[i];
251: totalAllocations += nTotalAllocObjects[i];
252: }
253: }
254: }
255:
256: protected void getResultsSortedByLiveObjNumber() {
257: getResultsSortedByClassName(true); // Added because of lines toggling when switching between columns 1 and 2.
258: // At first items must be sorted by class names to get defined initial state for
259: // other sorting.
260:
261: int visibleLines = nInfoLines; // Zero or unprofiled classes are filtered, sorting will be applied only to live
262: // data
263:
264: // This will sort nTrackedLiveObjects, align with it the other arrays, and produce sortedClassNames and
265: // sortedClassIds
266: nInfoLines = sortResults(nTrackedLiveObjects, new int[][] {
267: nTotalAllocObjects, maxSurvGen }, new long[][] {
268: trackedLiveObjectsSize, nTrackedAllocObjects },
269: new float[][] { avgObjectAge }, 0, visibleLines, false);
270:
271: totalAllocations = 0;
272: trackedLiveObjects = trackedAllocObjects = 0;
273:
274: for (int i = 0; i < nInfoLines; i++) {
275: trackedLiveObjects += nTrackedLiveObjects[i];
276: trackedAllocObjects += nTrackedAllocObjects[i];
277: totalAllocations += nTotalAllocObjects[i];
278: }
279: }
280:
281: protected void getResultsSortedByLiveObjSize() {
282: getResultsSortedByClassName(true); // Added because of lines toggling when switching between columns 1 and 2.
283: // At first items must be sorted by class names to get defined initial state for
284: // other sorting.
285:
286: int visibleLines = nInfoLines; // Zero or unprofiled classes are filtered, sorting will be applied only to live
287: // data
288:
289: // This will sort trackedLiveObjectsSize, align with it nTrackedLiveObjects and nTotalAllocObjects, and produce
290: // sortedClassNames and sortedClassIds
291: nInfoLines = sortResults(trackedLiveObjectsSize, new int[][] {
292: nTotalAllocObjects, nTrackedLiveObjects, maxSurvGen },
293: new long[][] { nTrackedAllocObjects },
294: new float[][] { avgObjectAge }, 0, visibleLines, false);
295:
296: totalAllocations = 0;
297: trackedLiveObjects = trackedAllocObjects = 0;
298:
299: for (int i = 0; i < nInfoLines; i++) {
300: trackedLiveObjects += nTrackedLiveObjects[i];
301: trackedAllocObjects += nTrackedAllocObjects[i];
302: totalAllocations += nTotalAllocObjects[i];
303: }
304: }
305:
306: protected void getResultsSortedBySurvGen() {
307: getResultsSortedByClassName(true); // Added because of lines toggling when switching between columns 1 and 2.
308: // At first items must be sorted by class names to get defined initial state for
309: // other sorting.
310:
311: int visibleLines = nInfoLines; // Zero or unprofiled classes are filtered, sorting will be applied only to live
312: // data
313:
314: nInfoLines = sortResults(maxSurvGen, new int[][] {
315: nTotalAllocObjects, nTrackedLiveObjects },
316: new long[][] { trackedLiveObjectsSize,
317: nTrackedAllocObjects },
318: new float[][] { avgObjectAge }, 0, visibleLines, false);
319:
320: // Now sort each subgroup where the number of surviving generations is the same and > 0, by the total live obj size
321: int curSurvGen = maxSurvGen[0];
322: int top = 0;
323:
324: while (curSurvGen > 0) {
325: int bottom = top;
326:
327: while ((maxSurvGen[bottom] == curSurvGen)
328: && (bottom < nInfoLines)) {
329: bottom++;
330: }
331:
332: if (bottom > top) {
333: sortResults(trackedLiveObjectsSize, new int[][] {
334: nTrackedLiveObjects, nTotalAllocObjects,
335: maxSurvGen },
336: new long[][] { nTrackedAllocObjects },
337: new float[][] { avgObjectAge }, top, bottom
338: - top, false);
339: top = bottom;
340: curSurvGen = maxSurvGen[bottom];
341: }
342: }
343:
344: totalAllocations = 0;
345: trackedLiveObjects = trackedAllocObjects = 0;
346:
347: for (int i = 0; i < nInfoLines; i++) {
348: trackedLiveObjects += nTrackedLiveObjects[i];
349: trackedAllocObjects += nTrackedAllocObjects[i];
350: totalAllocations += nTotalAllocObjects[i];
351: }
352: }
353:
354: protected void getResultsSortedByTotalAllocObj() {
355: getResultsSortedByClassName(true); // Added because of lines toggling when switching between columns 1 and 2.
356: // At first items must be sorted by class names to get defined initial state for
357: // other sorting.
358:
359: int visibleLines = nInfoLines; // Zero or unprofiled classes are filtered, sorting will be applied only to live
360: // data
361:
362: nInfoLines = sortResults(nTotalAllocObjects, new int[][] {
363: nTrackedLiveObjects, maxSurvGen }, new long[][] {
364: trackedLiveObjectsSize, nTrackedAllocObjects },
365: new float[][] { avgObjectAge }, 0, visibleLines, false);
366:
367: totalAllocations = 0;
368: trackedLiveObjects = trackedAllocObjects = 0;
369:
370: for (int i = 0; i < nInfoLines; i++) {
371: trackedLiveObjects += nTrackedLiveObjects[i];
372: trackedAllocObjects += nTrackedAllocObjects[i];
373: totalAllocations += nTotalAllocObjects[i];
374: }
375: }
376:
377: protected JExtendedTable getResultsTable() {
378: trackedLiveObjects = trackedAllocObjects = 0;
379: totalAllocations = 0;
380:
381: sortResults();
382:
383: if (resTable == null) {
384: resTableModel = new ExtendedTableModel(
385: new SortableTableModel() {
386: public String getColumnName(int col) {
387: return columnNames[col];
388: }
389:
390: public int getRowCount() {
391: return nDisplayedItems;
392: }
393:
394: public int getColumnCount() {
395: return columnNames.length;
396: }
397:
398: public Class getColumnClass(int col) {
399: // The main purpose of this method is to make numeric values aligned properly inside table cells
400: return columnTypes[col];
401: }
402:
403: public Object getValueAt(int row, int col) {
404: return computeValueAt(row, col);
405: }
406:
407: public String getColumnToolTipText(int col) {
408: return columnToolTips[col];
409: }
410:
411: public void sortByColumn(int column,
412: boolean order) {
413: sortBy = getSortBy(column);
414: sortOrder = order;
415:
416: int selectedRow = resTable.getSelectedRow();
417: String selectedRowContents = null;
418:
419: if (selectedRow != -1) {
420: selectedRowContents = (String) resTable
421: .getValueAt(selectedRow, 0);
422: }
423:
424: prepareResults();
425:
426: if (selectedRowContents != null) {
427: resTable.selectRowByContents(
428: selectedRowContents, 0, true);
429: }
430: }
431:
432: /**
433: * @param column The table column index
434: * @return Initial sorting for the specified column - if true, ascending, if false descending
435: */
436: public boolean getInitialSorting(int column) {
437: switch (column) {
438: case 0:
439: return true;
440: default:
441: return false;
442: }
443: }
444: });
445:
446: resTableModel.setRealColumnVisibility(7, false);
447:
448: resTable = new JExtendedTable(resTableModel) {
449: public void doLayout() {
450: int columnsWidthsSum = 0;
451: int realFirstColumn = -1;
452:
453: int index;
454:
455: for (int i = 0; i < resTableModel.getColumnCount(); i++) {
456: index = resTableModel.getRealColumn(i);
457:
458: if (index == 0) {
459: realFirstColumn = i;
460: } else {
461: columnsWidthsSum += getColumnModel()
462: .getColumn(i).getPreferredWidth();
463: }
464: }
465:
466: if (realFirstColumn != -1) {
467: getColumnModel().getColumn(realFirstColumn)
468: .setPreferredWidth(
469: Math.max(getWidth()
470: - columnsWidthsSum,
471: minNamesColumnWidth));
472: }
473:
474: super .doLayout();
475: };
476: };
477: resTable.getAccessibleContext().setAccessibleName(
478: TABLE_ACCESS_NAME);
479:
480: resTableModel.setTable(resTable);
481: resTableModel.setInitialSorting(initialSortingColumn,
482: sortOrder);
483: resTable.setRowSelectionAllowed(true);
484: resTable
485: .setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
486: resTable
487: .setGridColor(UIConstants.TABLE_VERTICAL_GRID_COLOR);
488: resTable
489: .setSelectionBackground(UIConstants.TABLE_SELECTION_BACKGROUND_COLOR);
490: resTable
491: .setSelectionForeground(UIConstants.TABLE_SELECTION_FOREGROUND_COLOR);
492: resTable
493: .setShowHorizontalLines(UIConstants.SHOW_TABLE_HORIZONTAL_GRID);
494: resTable
495: .setShowVerticalLines(UIConstants.SHOW_TABLE_VERTICAL_GRID);
496: resTable.setRowMargin(UIConstants.TABLE_ROW_MARGIN);
497: resTable.setRowHeight(UIUtils.getDefaultRowHeight() + 2);
498:
499: // Disable traversing table cells using TAB and Shift+TAB
500: Set keys = new HashSet(
501: resTable
502: .getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS));
503: keys.add(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0));
504: resTable.setFocusTraversalKeys(
505: KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, keys);
506:
507: keys = new HashSet(
508: resTable
509: .getFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS));
510: keys.add(KeyStroke.getKeyStroke(KeyEvent.VK_TAB,
511: InputEvent.SHIFT_MASK));
512: resTable.setFocusTraversalKeys(
513: KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, keys);
514:
515: setColumnsData();
516: }
517:
518: return resTable;
519: }
520:
521: protected Object computeValueAt(int row, int col) {
522: int index = ((Integer) filteredToFullIndexes.get(row))
523: .intValue();
524:
525: switch (col) {
526: case 0:
527: return sortedClassNames[index];
528: case 1:
529: return new Long(trackedLiveObjectsSize[index]);
530: case 2:
531: return intFormat.format(trackedLiveObjectsSize[index])
532: + " B (" // NOI18N
533: + ((nTotalTrackedBytes == 0) ? "-%" : // NOI18N
534: percentFormat
535: .format((float) trackedLiveObjectsSize[index]
536: / (float) nTotalTrackedBytes))
537: + ")"; // NOI18N
538: case 3:
539: return intFormat.format(nTrackedLiveObjects[index])
540: + " (" // NOI18N
541: + ((nTotalTracked == 0) ? "-%" : // NOI18N
542: percentFormat
543: .format((float) nTrackedLiveObjects[index]
544: / (float) nTotalTracked))
545: + ")"; // NOI18N
546: case 4:
547: return intFormat.format(nTrackedAllocObjects[index]);
548: case 5:
549: return StringUtils
550: .floatPerCentToString(avgObjectAge[index]);
551: case 6:
552: return intFormat.format(maxSurvGen[index]);
553: case 7:
554: return intFormat.format(nTotalAllocObjects[index]);
555: default:
556: return null;
557: }
558: }
559:
560: protected void initColumnSelectorItems() {
561: headerPopup.removeAll();
562:
563: JCheckBoxMenuItem menuItem;
564:
565: for (int i = 0; i < columnNames.length; i++) {
566: menuItem = new JCheckBoxMenuItem(columnNames[i]);
567: menuItem.setActionCommand(new Integer(i).toString());
568: addMenuItemListener(menuItem);
569:
570: if (resTable != null) {
571: menuItem.setState(resTableModel.isRealColumnVisible(i));
572:
573: if (i == 0) {
574: menuItem.setEnabled(false);
575: }
576: } else {
577: menuItem.setState(true);
578: }
579:
580: headerPopup.add(menuItem);
581: }
582:
583: headerPopup.addSeparator();
584:
585: JCheckBoxMenuItem filterMenuItem = new JCheckBoxMenuItem(
586: FILTER_MENU_ITEM_NAME);
587: filterMenuItem.setActionCommand("Filter"); // NOI18N
588: addMenuItemListener(filterMenuItem);
589:
590: if (filterComponent == null) {
591: filterMenuItem.setState(true);
592: } else {
593: filterMenuItem.setState(filterComponent.isVisible());
594: }
595:
596: headerPopup.add(filterMenuItem);
597:
598: headerPopup.pack();
599: }
600:
601: protected void initColumnsData() {
602: int maxWidth = getFontMetrics(getFont()).charWidth('W') * 10; // NOI18N // initial width of data columns
603: minNamesColumnWidth = getFontMetrics(getFont()).charWidth('W') * 30; // NOI18N
604:
605: ClassNameTableCellRenderer classNameTableCellRenderer = new ClassNameTableCellRenderer();
606: LabelTableCellRenderer labelTableCellRenderer = new LabelTableCellRenderer(
607: JLabel.TRAILING);
608: LabelBracketTableCellRenderer labelBracketTableCellRenderer = new LabelBracketTableCellRenderer(
609: JLabel.TRAILING);
610:
611: columnNames = new String[] {
612: CLASS_COLUMN_NAME, // - " + getPercentsTracked() + "% Tracked",
613: LIVE_BYTES_REL_COLUMN_NAME, LIVE_BYTES_COLUMN_NAME,
614: LIVE_OBJECTS_COLUMN_NAME, ALLOC_OBJECTS_COLUMN_NAME,
615: AVG_AGE_COLUMN_NAME, SURVGEN_COLUMN_NAME,
616: TOTAL_ALLOC_OBJECTS_COLUMN_NAME };
617:
618: columnToolTips = new String[] { CLASS_COLUMN_TOOLTIP, // - "+getPercentsTracked()+"% of all allocated objets are displayed\",",
619: LIVE_BYTES_REL_COLUMN_TOOLTIP, // - "+getPercentsTracked()+"% Tracked",
620: LIVE_BYTES_COLUMN_TOOLTIP, // - "+getPercentsTracked()+"% Tracked",
621: LIVE_OBJECTS_COLUMN_TOOLTIP, // - "+getPercentsTracked()+"% Tracked",
622: ALLOC_OBJECTS_COLUMN_TOOLTIP, // - "+getPercentsTracked()+"% Tracked",
623: AVG_AGE_COLUMN_TOOLTIP, // - "+getPercentsTracked()+"% Tracked",
624: SURVGEN_COLUMN_TOOLTIP, // - "+ getPercentsTracked()+"% Tracked",
625: TOTAL_ALLOC_OBJECTS_COLUMN_TOOLTIP };
626: columnTypes = new Class[] { String.class, Number.class,
627: String.class, String.class, String.class, Number.class,
628: Number.class, String.class };
629: columnRenderers = new TableCellRenderer[] {
630: classNameTableCellRenderer, null,
631: labelBracketTableCellRenderer,
632: labelBracketTableCellRenderer, labelTableCellRenderer,
633: labelTableCellRenderer, labelTableCellRenderer,
634: labelTableCellRenderer };
635: columnWidths = new int[] { maxWidth, maxWidth, maxWidth,
636: maxWidth, maxWidth, maxWidth, maxWidth, maxWidth };
637: }
638:
639: protected boolean passesValueFilter(int i) {
640: return ((((double) trackedLiveObjectsSize[i] / (double) nTotalTrackedBytes) * 100f) >= valueFilterValue);
641: }
642:
643: private void setColumnsData() {
644: barRenderer = getBarCellRenderer();
645:
646: TableColumnModel colModel = resTable.getColumnModel();
647: colModel.getColumn(0).setPreferredWidth(minNamesColumnWidth);
648:
649: int index;
650:
651: for (int i = 0; i < colModel.getColumnCount(); i++) {
652: index = resTableModel.getRealColumn(i);
653:
654: if (index == 0) {
655: colModel.getColumn(i).setPreferredWidth(
656: minNamesColumnWidth);
657: } else {
658: colModel.getColumn(i).setPreferredWidth(
659: columnWidths[index - 1]);
660: }
661:
662: if (index == 1) {
663: colModel.getColumn(i).setCellRenderer(barRenderer);
664: } else {
665: colModel.getColumn(i).setCellRenderer(
666: columnRenderers[index]);
667: }
668: }
669: }
670:
671: private int getSortBy(int column) {
672: switch (column) {
673: case 0:
674: return PresoObjLivenessCCTNode.SORT_BY_NAME;
675: case 1:
676: return PresoObjLivenessCCTNode.SORT_BY_LIVE_OBJ_SIZE;
677: case 2:
678: return PresoObjLivenessCCTNode.SORT_BY_LIVE_OBJ_SIZE;
679: case 3:
680: return PresoObjLivenessCCTNode.SORT_BY_LIVE_OBJ_NUMBER;
681: case 4:
682: return PresoObjLivenessCCTNode.SORT_BY_ALLOC_OBJ;
683: case 5:
684: return PresoObjLivenessCCTNode.SORT_BY_AVG_AGE;
685: case 6:
686: return PresoObjLivenessCCTNode.SORT_BY_SURV_GEN;
687: case 7:
688: return PresoObjLivenessCCTNode.SORT_BY_TOTAL_ALLOC_OBJ;
689: }
690:
691: return PresoObjLivenessCCTNode.SORT_BY_LIVE_OBJ_SIZE;
692: }
693:
694: private void addMenuItemListener(JCheckBoxMenuItem menuItem) {
695: menuItem.addActionListener(new ActionListener() {
696: public void actionPerformed(ActionEvent e) {
697: if (e.getActionCommand().equals("Filter")) { // NOI18N
698: filterComponent.setVisible(!filterComponent
699: .isVisible());
700:
701: // TODO [ui-persistence]
702: return;
703: }
704:
705: saveColumnsData();
706:
707: boolean sortResults = false;
708: int column = Integer.parseInt(e.getActionCommand());
709: int sortingColumn = resTableModel.getSortingColumn();
710: int realSortingColumn = resTableModel
711: .getRealColumn(sortingColumn);
712: boolean isColumnVisible = resTableModel
713: .isRealColumnVisible(column);
714:
715: // Current sorting column is going to be hidden
716: if ((isColumnVisible) && (column == realSortingColumn)) {
717: // Try to set next column as a sortingColumn. If currentSortingColumn is the last column, set previous
718: // column as a sorting Column (one column is always visible).
719: sortingColumn = ((sortingColumn + 1) == resTableModel
720: .getColumnCount()) ? (sortingColumn - 1)
721: : (sortingColumn + 1);
722: realSortingColumn = resTableModel
723: .getRealColumn(sortingColumn);
724: sortResults = true;
725: }
726:
727: resTableModel.setRealColumnVisibility(column,
728: !isColumnVisible);
729: resTable.createDefaultColumnsFromModel();
730: resTableModel.setTable(resTable);
731: sortingColumn = resTableModel
732: .getVirtualColumn(realSortingColumn);
733:
734: if (sortResults) {
735: sortOrder = resTableModel
736: .getInitialSorting(sortingColumn);
737: sortBy = getSortBy(realSortingColumn);
738: sortResults();
739: resTable.repaint();
740: }
741:
742: resTableModel.setInitialSorting(sortingColumn,
743: sortOrder);
744: resTable.getTableHeader().repaint();
745:
746: setColumnsData();
747:
748: // TODO [ui-persistence]
749: }
750: });
751: }
752:
753: private void saveColumnsData() {
754: int index;
755: TableColumnModel colModel = resTable.getColumnModel();
756:
757: for (int i = 0; i < resTableModel.getColumnCount(); i++) {
758: index = resTableModel.getRealColumn(i);
759:
760: if (index != 0) {
761: columnWidths[index - 1] = colModel.getColumn(i)
762: .getPreferredWidth();
763: }
764: }
765: }
766:
767: private void sortResults() {
768: switch (sortBy) {
769: case PresoObjLivenessCCTNode.SORT_BY_NAME:
770: getResultsSortedByClassName(false);
771:
772: break;
773: case PresoObjLivenessCCTNode.SORT_BY_LIVE_OBJ_SIZE:
774: getResultsSortedByLiveObjSize();
775:
776: break;
777: case PresoObjLivenessCCTNode.SORT_BY_LIVE_OBJ_NUMBER:
778: getResultsSortedByLiveObjNumber();
779:
780: break;
781: case PresoObjLivenessCCTNode.SORT_BY_ALLOC_OBJ:
782: getResultsSortedByAllocObj();
783:
784: break;
785: case PresoObjLivenessCCTNode.SORT_BY_AVG_AGE:
786: getResultsSortedByAvgAge();
787:
788: break;
789: case PresoObjLivenessCCTNode.SORT_BY_SURV_GEN:
790: getResultsSortedBySurvGen();
791:
792: break;
793: case PresoObjLivenessCCTNode.SORT_BY_TOTAL_ALLOC_OBJ:
794: getResultsSortedByTotalAllocObj();
795:
796: break;
797: }
798:
799: createFilteredIndexes();
800: }
801: }
|