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.threads;
0042:
0043: import org.netbeans.lib.profiler.global.CommonConstants;
0044: import org.netbeans.lib.profiler.results.threads.ThreadData;
0045: import org.netbeans.lib.profiler.ui.charts.DynamicPieChartModel;
0046: import org.netbeans.lib.profiler.ui.charts.PieChart;
0047: import java.awt.*;
0048: import java.awt.event.*;
0049: import java.util.ResourceBundle;
0050: import javax.swing.*;
0051: import javax.swing.border.BevelBorder;
0052: import javax.swing.border.CompoundBorder;
0053: import javax.swing.border.EmptyBorder;
0054: import javax.swing.text.DefaultCaret;
0055:
0056: /** A component that shows details for single thread.
0057: *
0058: * @author Jiri Sedlacek
0059: * @author Ian Formanek
0060: */
0061: public class ThreadDetailsComponent extends JPanel {
0062: //~ Inner Classes ------------------------------------------------------------------------------------------------------------
0063:
0064: // ---------------------------------------------------------------------------------------
0065: // Timeline component
0066: private class SingleThreadState extends JPanel implements
0067: MouseListener, MouseMotionListener {
0068: //~ Static fields/initializers -------------------------------------------------------------------------------------------
0069:
0070: private static final int DISPLAY_MARGIN = 20;
0071:
0072: //~ Instance fields ------------------------------------------------------------------------------------------------------
0073:
0074: private final Color SELECTION_BRIGHT = new Color(150, 150, 255);
0075: private final Color SELECTION_DARK = new Color(80, 80, 255);
0076: private ThreadData threadData;
0077: private boolean dragging = false;
0078: private float factor;
0079: private int focusedThreadDataIndex;
0080: private int mouseDraggedX = -1;
0081: private int mousePressedX = -1;
0082: private int width;
0083: private long dataEnd;
0084: private long dataStart;
0085: private long viewEnd;
0086: private long viewStart;
0087:
0088: //~ Constructors ---------------------------------------------------------------------------------------------------------
0089:
0090: public SingleThreadState() {
0091: addMouseListener(this );
0092: addMouseMotionListener(this );
0093: setBackground(TIMELINE_ALIVE_BACKGROUND);
0094: threadData = new ThreadData(null, null);
0095: dataStart = 0;
0096: dataEnd = 0;
0097: focusedThreadDataIndex = -1;
0098: }
0099:
0100: //~ Methods --------------------------------------------------------------------------------------------------------------
0101:
0102: public int getFocusedThreadDataIndex(Point point) {
0103: if (!isFocusedX(point.x)) {
0104: return -1;
0105: }
0106:
0107: if (!isFocusedY(point.y)) {
0108: return -1;
0109: }
0110:
0111: int focused = getFocusedThreadDataIndex(point.x);
0112:
0113: if (focused == threadData.size()) {
0114: return -1;
0115: }
0116:
0117: return focused;
0118: }
0119:
0120: public Dimension getMinimumSize() {
0121: return getPreferredSize();
0122: }
0123:
0124: public Dimension getPreferredSize() {
0125: return new Dimension(super .getPreferredSize().width,
0126: getFont().getSize() + 20);
0127: }
0128:
0129: public void mouseClicked(MouseEvent e) {
0130: int focusedIndex = getFocusedThreadDataIndex(e.getPoint());
0131:
0132: if (focusedIndex == -1) {
0133: detailsArea.setCaretPosition(detailsArea
0134: .getCaretPosition());
0135:
0136: return;
0137: }
0138:
0139: selectDescriptionAreaLines(focusedIndex, focusedIndex);
0140: }
0141:
0142: public void mouseDragged(MouseEvent e) {
0143: if (mousePressedX != -1) {
0144: dragging = true;
0145: mouseDraggedX = e.getX();
0146:
0147: if (mousePressedX == mouseDraggedX) {
0148: return;
0149: }
0150:
0151: int startX = mousePressedX;
0152: int endX = mouseDraggedX;
0153:
0154: if (startX > endX) {
0155: int tmp = endX;
0156: endX = startX;
0157: startX = tmp;
0158: }
0159:
0160: int startIndex = getFocusedThreadDataIndex(startX);
0161: int endIndex = getFocusedThreadDataIndex(endX);
0162:
0163: if ((startIndex == -1) && (endIndex == -1)) {
0164: detailsArea.setCaretPosition(detailsArea
0165: .getCaretPosition());
0166: repaint();
0167:
0168: return;
0169: }
0170:
0171: if ((startIndex >= threadData.size())
0172: && (endIndex >= threadData.size())) {
0173: detailsArea.setCaretPosition(detailsArea
0174: .getCaretPosition());
0175: repaint();
0176:
0177: return;
0178: }
0179:
0180: int offsetStart = (threadData.getFirstState() == CommonConstants.THREAD_STATUS_ZOMBIE) ? 1
0181: : 0;
0182: int offsetEnd = (threadData.getLastState() == CommonConstants.THREAD_STATUS_ZOMBIE) ? 1
0183: : 0;
0184:
0185: startIndex = Math.max(startIndex, offsetStart);
0186: endIndex = Math.min(endIndex, threadData.size() - 1
0187: - offsetEnd);
0188:
0189: selectDescriptionAreaLines(startIndex, endIndex);
0190:
0191: repaint();
0192: } else {
0193: detailsArea.setCaretPosition(detailsArea
0194: .getCaretPosition());
0195: }
0196: }
0197:
0198: public void mouseEntered(MouseEvent e) {
0199: }
0200:
0201: public void mouseExited(MouseEvent e) {
0202: focusedThreadDataIndex = -1;
0203: repaint();
0204: }
0205:
0206: public void mouseMoved(MouseEvent e) {
0207: int currentlyFocused = getFocusedThreadDataIndex(e
0208: .getPoint());
0209:
0210: if (currentlyFocused != focusedThreadDataIndex) {
0211: focusedThreadDataIndex = currentlyFocused;
0212: repaint();
0213: }
0214: }
0215:
0216: public void mousePressed(MouseEvent e) {
0217: if (isFocusedY(e.getY())) {
0218: mousePressedX = e.getX();
0219: } else {
0220: mousePressedX = -1;
0221: }
0222: }
0223:
0224: public void mouseReleased(MouseEvent e) {
0225: dragging = false;
0226: focusedThreadDataIndex = getFocusedThreadDataIndex(e
0227: .getPoint());
0228: repaint();
0229: }
0230:
0231: public void paint(Graphics g) {
0232: super .paint(g);
0233: viewStart = dataStart;
0234: viewEnd = dataEnd;
0235: width = getWidth() - (2 * DISPLAY_MARGIN);
0236: factor = (float) width / (float) (viewEnd - viewStart);
0237:
0238: if ((viewEnd - viewStart) > 0) {
0239: paintTimeMarks(g);
0240: paintThreadData(g);
0241: }
0242: }
0243:
0244: private int getFirstVisibleDataUnit() {
0245: if (threadData.size() > 0) {
0246: return 0;
0247: } else {
0248: return -1;
0249: }
0250: }
0251:
0252: private int getFocusedThreadDataIndex(int xpos) {
0253: if (threadData == null) {
0254: return -1;
0255: }
0256:
0257: if ((viewEnd - viewStart) <= 0) {
0258: return -1;
0259: }
0260:
0261: int index = getFirstVisibleDataUnit();
0262:
0263: if (index != -1) {
0264: int x;
0265: int xx;
0266:
0267: while ((index < threadData.size())
0268: && (threadData.getTimeStampAt(index) <= viewEnd)) {
0269: if (threadData.getStateAt(index) != CommonConstants.THREAD_STATUS_ZOMBIE) {
0270: x = Math
0271: .max(
0272: (int) ((float) (threadData
0273: .getTimeStampAt(index) - viewStart) * factor),
0274: 0)
0275: + DISPLAY_MARGIN;
0276:
0277: if (xpos < x) {
0278: return -1;
0279: }
0280:
0281: if (index < (threadData.size() - 1)) {
0282: xx = Math
0283: .min(
0284: (int) ((float) (threadData
0285: .getTimeStampAt(index + 1) - viewStart) * factor),
0286: width)
0287: + DISPLAY_MARGIN;
0288: } else {
0289: xx = Math
0290: .min(
0291: (int) ((dataEnd - viewStart) * factor),
0292: width + 1)
0293: + DISPLAY_MARGIN;
0294: }
0295:
0296: if ((xpos >= x) && (xpos <= xx)) {
0297: return index;
0298: }
0299: }
0300:
0301: index++;
0302: }
0303: }
0304:
0305: return index;
0306: }
0307:
0308: private boolean isFocusedX(int x) {
0309: return ((x > DISPLAY_MARGIN) && (x < (getWidth() - DISPLAY_MARGIN)));
0310: }
0311:
0312: private boolean isFocusedY(int y) {
0313: return ((y > (7 + getFont().getSize())) && (y <= getHeight()));
0314: }
0315:
0316: private void paintThreadData(Graphics g) {
0317: if (threadData != null) {
0318: int index = getFirstVisibleDataUnit();
0319:
0320: if (index != -1) {
0321: if ((viewEnd - viewStart) > 0) {
0322: while ((index < threadData.size())
0323: && (threadData.getTimeStampAt(index) <= viewEnd)) {
0324: // Thread alive
0325: if (threadData.getStateAt(index) != CommonConstants.THREAD_STATUS_ZOMBIE) {
0326: paintThreadState(g, index, threadData
0327: .getThreadStateColorAt(index));
0328: }
0329:
0330: index++;
0331: }
0332: }
0333: }
0334: }
0335: }
0336:
0337: private void paintThreadState(Graphics g, int index,
0338: Color threadStateColor) {
0339: int x; // Begin of rectangle
0340: int xx; // End of rectangle
0341:
0342: int graphicsFontSize = g.getFont().getSize();
0343:
0344: x = Math.max((int) ((float) (threadData
0345: .getTimeStampAt(index) - viewStart) * factor), 0)
0346: + DISPLAY_MARGIN;
0347:
0348: if (index < (threadData.size() - 1)) {
0349: xx = Math
0350: .min(
0351: (int) ((float) (threadData
0352: .getTimeStampAt(index + 1) - viewStart) * factor),
0353: width)
0354: + DISPLAY_MARGIN;
0355: } else {
0356: xx = Math.min((int) ((dataEnd - viewStart) * factor),
0357: width + 1)
0358: + DISPLAY_MARGIN;
0359: }
0360:
0361: g.setColor(threadStateColor);
0362: g.fillRect(x, 11 + graphicsFontSize, xx - x, getHeight()
0363: - graphicsFontSize - 14);
0364:
0365: if (dragging) {
0366: g.setColor(SELECTION_BRIGHT);
0367: g.drawLine(mousePressedX, (10 + graphicsFontSize) - 2,
0368: mouseDraggedX, (10 + graphicsFontSize) - 2);
0369: g.drawLine(mousePressedX, getHeight() - 1,
0370: mouseDraggedX, getHeight() - 1);
0371: g.setColor(SELECTION_DARK);
0372: g.drawLine(mousePressedX, (11 + graphicsFontSize) - 2,
0373: mouseDraggedX, (11 + graphicsFontSize) - 2);
0374: g.drawLine(mousePressedX, getHeight() - 2,
0375: mouseDraggedX, getHeight() - 2);
0376: } else if (index == focusedThreadDataIndex) {
0377: g.setColor(SELECTION_BRIGHT);
0378: g.drawLine(x, (10 + graphicsFontSize) - 2, xx - 1,
0379: (10 + graphicsFontSize) - 2);
0380: g.drawLine(x, getHeight() - 1, xx - 1, getHeight() - 1);
0381: g.setColor(SELECTION_DARK);
0382: g.drawLine(x, (11 + graphicsFontSize) - 2, xx - 1,
0383: (11 + graphicsFontSize) - 2);
0384: g.drawLine(x, getHeight() - 2, xx - 1, getHeight() - 2);
0385: }
0386: }
0387:
0388: private void paintTimeMarkString(Graphics g, int currentMark,
0389: int optimalUnits, int x, int y) {
0390: int markStringMillisMargin = 0; // space between mark's string without milliseconds and mark's milliseconds string
0391: int markStringMillisReduce = 2; // markStringNoMillis.height - markStringMillisReduce = markStringMillis.height
0392:
0393: Font markStringNoMillisFont = g.getFont();
0394: Font markStringMillisFont = markStringNoMillisFont
0395: .deriveFont((float) (markStringNoMillisFont
0396: .getSize() - 2));
0397:
0398: String markStringNoMillis = TimeLineUtils
0399: .getTimeMarkNoMillisString(currentMark,
0400: optimalUnits);
0401: int wMarkStringNoMillis = g.getFontMetrics().stringWidth(
0402: markStringNoMillis); // width of the mark's string without milliseconds
0403: String markStringMillis = TimeLineUtils
0404: .getTimeMarkMillisString(currentMark, optimalUnits);
0405:
0406: if (!markStringMillis.equals("")) {
0407: markStringMillis = "." + markStringMillis; // NOI18N
0408: }
0409:
0410: int xMarkStringNoMillis = x - (wMarkStringNoMillis / 2) + 1; // x-position of the mark's string without milliseconds
0411: int xMarkStringMillis = xMarkStringNoMillis
0412: + wMarkStringNoMillis + markStringMillisMargin; // x-position of the mark's milliseconds string
0413:
0414: g.setColor(TimeLineUtils.BASE_TIMELINE_COLOR);
0415: g.drawString(markStringNoMillis, xMarkStringNoMillis, y);
0416:
0417: g.setFont(markStringMillisFont);
0418: g.drawString(markStringMillis, xMarkStringMillis, y
0419: - markStringMillisReduce + 1);
0420: g.setFont(markStringNoMillisFont);
0421: }
0422:
0423: private void paintTimeMarks(Graphics g) {
0424: g.setFont(g.getFont().deriveFont(Font.BOLD));
0425:
0426: int firstValue = (int) (viewStart - dataStart);
0427: int lastValue = (int) (viewEnd - dataStart);
0428: int optimalUnits = TimeLineUtils.getOptimalUnits(factor);
0429:
0430: int firstMark = Math
0431: .max((int) (Math.ceil((double) firstValue
0432: / optimalUnits) * optimalUnits), 0);
0433: int currentMark = firstMark - optimalUnits;
0434:
0435: int componentFontSize = getFont().getSize();
0436:
0437: while (currentMark <= (lastValue + optimalUnits)) {
0438: if (currentMark >= 0) {
0439: float currentMarkRel = currentMark - firstValue;
0440: int markPosition = (int) (currentMarkRel * factor)
0441: + DISPLAY_MARGIN;
0442: paintTimeTicks(
0443: g,
0444: (int) (currentMarkRel * factor)
0445: + DISPLAY_MARGIN,
0446: (int) ((currentMarkRel + optimalUnits) * factor)
0447: + DISPLAY_MARGIN, TimeLineUtils
0448: .getTicksCount(optimalUnits));
0449: g.setColor(TimeLineUtils.BASE_TIMELINE_COLOR);
0450: g.drawLine(markPosition, 0, markPosition, 4);
0451: paintTimeMarkString(g, currentMark, optimalUnits,
0452: markPosition, 5 + componentFontSize);
0453: g.setColor(TimeLineUtils.MAIN_TIMELINE_COLOR);
0454: g.drawLine(markPosition, 8 + componentFontSize,
0455: markPosition, getHeight() - 1);
0456: }
0457:
0458: currentMark += optimalUnits;
0459: }
0460:
0461: Font origFont = g.getFont();
0462: Font plainFont = origFont.deriveFont(Font.PLAIN);
0463: String sLegend = TimeLineUtils.getUnitsLegend(lastValue,
0464: optimalUnits);
0465: int wLegend = g.getFontMetrics(plainFont).stringWidth(
0466: sLegend);
0467:
0468: if ((wLegend + 7) <= width) {
0469: g.setFont(plainFont);
0470: g.setColor(getBackground());
0471: //g.fillRect(width - wLegend - 3 + 2 * DISPLAY_MARGIN, 6, wLegend + 1, 3 + plainFont.getSize());
0472: g.fillRect(width - wLegend - 6 + (2 * DISPLAY_MARGIN),
0473: 5, wLegend + 7, 4 + plainFont.getSize());
0474: g.setColor(Color.BLACK);
0475: g
0476: .drawString(sLegend, width - wLegend - 2
0477: + (2 * DISPLAY_MARGIN), 5 + plainFont
0478: .getSize());
0479: g.setFont(origFont);
0480: }
0481: }
0482:
0483: private void paintTimeTicks(Graphics g, int startPos,
0484: int endPos, int count) {
0485: float timeTicksFactor = (float) (endPos - startPos)
0486: / (float) count;
0487:
0488: for (int i = 1; i < count; i++) {
0489: int x = startPos + (int) (i * timeTicksFactor);
0490: g.setColor(TimeLineUtils.BASE_TIMELINE_COLOR);
0491: g.drawLine(x, 0, x, 2);
0492: g.setColor(TimeLineUtils.TICK_TIMELINE_COLOR);
0493: g.drawLine(x, 3, x, getHeight() - 1);
0494: }
0495: }
0496:
0497: private void selectDescriptionAreaLines(int firstLine,
0498: int lastLine) {
0499: if ((firstLine < 0) || (lastLine < 0)) {
0500: return;
0501: }
0502:
0503: if ((firstLine >= threadData.size())
0504: || (lastLine >= threadData.size())) {
0505: return;
0506: }
0507:
0508: int offsetStart = (threadData.getFirstState() == CommonConstants.THREAD_STATUS_ZOMBIE) ? 0
0509: : 1;
0510:
0511: if (jTabbedPane1.getSelectedIndex() != 1) {
0512: jTabbedPane1.setSelectedIndex(1);
0513: }
0514:
0515: try {
0516: detailsArea.scrollRectToVisible(detailsArea
0517: .modelToView(detailsArea
0518: .getLineStartOffset(firstLine
0519: + offsetStart)));
0520: internalAdjustmentEvent = true;
0521: detailsArea.setCaretPosition(detailsArea
0522: .getLineStartOffset(firstLine + offsetStart));
0523: detailsArea.moveCaretPosition(detailsArea
0524: .getLineEndOffset(lastLine + offsetStart));
0525: SwingUtilities.invokeLater(new Runnable() {
0526: public void run() {
0527: detailsArea.requestFocus();
0528: }
0529: });
0530: } catch (Exception ex) {
0531: }
0532:
0533: ;
0534: }
0535:
0536: private void updateData(ThreadData threadData, long dataStart,
0537: long dataEnd) {
0538: if (threadData != null) {
0539: this .threadData = threadData;
0540: } else {
0541: this .threadData = new ThreadData(null, null);
0542: }
0543:
0544: this .dataStart = dataStart;
0545:
0546: // Update dataEnd - for finished threads the timeline stops moving
0547: if ((this .threadData.size() > 0)
0548: && (this .threadData.getLastState() != CommonConstants.THREAD_STATUS_ZOMBIE)) {
0549: this .dataEnd = dataEnd;
0550: } else {
0551: this .dataEnd = this .threadData.getLastTimeStamp();
0552: }
0553:
0554: repaint();
0555: }
0556: }
0557:
0558: //~ Static fields/initializers -----------------------------------------------------------------------------------------------
0559:
0560: // -----
0561: // I18N String constants
0562: private static final ResourceBundle messages = ResourceBundle
0563: .getBundle("org.netbeans.lib.profiler.ui.threads.Bundle"); // NOI18N
0564: private static final String THREAD_ALIVE_STRING = messages
0565: .getString("ThreadDetailsComponent_ThreadAliveString"); // NOI18N
0566: private static final String THREAD_FINISHED_STRING = messages
0567: .getString("ThreadDetailsComponent_ThreadFinishedString"); // NOI18N
0568: private static final String NO_DATA_COLLECTED_STRING = messages
0569: .getString("ThreadDetailsComponent_NoDataCollectedString"); // NOI18N
0570: private static final String THREAD_STATE_UNKNOWN_STRING = messages
0571: .getString("ThreadDetailsComponent_ThreadStateUnknownString"); // NOI18N
0572: private static final String THREAD_STARTED_STRING = messages
0573: .getString("ThreadDetailsComponent_ThreadStartedString"); // NOI18N
0574: private static final String HIDE_BUTTON_NAME = messages
0575: .getString("ThreadDetailsComponent_HideButtonName"); // NOI18N
0576: private static final String TOTAL_LABEL_STRING = messages
0577: .getString("ThreadDetailsComponent_TotalLabelString"); // NOI18N
0578: private static final String GENERAL_TAB_NAME = messages
0579: .getString("ThreadDetailsComponent_GeneralTabName"); // NOI18N
0580: private static final String DETAILS_TAB_NAME = messages
0581: .getString("ThreadDetailsComponent_DetailsTabName"); // NOI18N
0582: private static final String TIMELINE_ACCESS_NAME = messages
0583: .getString("ThreadDetailsComponent_TimeLineAccessName"); // NOI18N
0584: private static final String THREAD_NAME_LABEL_ACCESS_NAME = messages
0585: .getString("ThreadDetailsComponent_ThreadNameLabelAccessName"); // NOI18N
0586: private static final String THREAD_STATE_LABEL_ACCESS_NAME = messages
0587: .getString("ThreadDetailsComponent_ThreadStateLabelAccessName"); // NOI18N
0588: private static final String HIDE_BUTTON_ACCESS_DESCR = messages
0589: .getString("ThreadDetailsComponent_HideButtonAccessDescr"); // NOI18N
0590: private static final String PIECHART_ACCESS_NAME = messages
0591: .getString("ThreadDetailsComponent_PieChartAccessName"); // NOI18N
0592: private static final String TAB_ACCESS_NAME = messages
0593: .getString("ThreadDetailsComponent_TabAccessName"); // NOI18N
0594: // -----
0595: private static final int THREAD_ICON_SIZE = 9;
0596: private static ThreadStateIcon runningIcon = new ThreadStateIcon(
0597: CommonConstants.THREAD_STATUS_RUNNING, THREAD_ICON_SIZE,
0598: THREAD_ICON_SIZE);
0599: private static ThreadStateIcon sleepingIcon = new ThreadStateIcon(
0600: CommonConstants.THREAD_STATUS_SLEEPING, THREAD_ICON_SIZE,
0601: THREAD_ICON_SIZE);
0602: private static ThreadStateIcon monitorIcon = new ThreadStateIcon(
0603: CommonConstants.THREAD_STATUS_MONITOR, THREAD_ICON_SIZE,
0604: THREAD_ICON_SIZE);
0605: private static ThreadStateIcon waitIcon = new ThreadStateIcon(
0606: CommonConstants.THREAD_STATUS_WAIT, THREAD_ICON_SIZE,
0607: THREAD_ICON_SIZE);
0608: private static ThreadStateIcon unknownIcon = new ThreadStateIcon(
0609: CommonConstants.THREAD_STATUS_UNKNOWN, THREAD_ICON_SIZE,
0610: THREAD_ICON_SIZE);
0611: private static ThreadStateIcon zombieIcon = new ThreadStateIcon(
0612: CommonConstants.THREAD_STATUS_ZOMBIE, THREAD_ICON_SIZE,
0613: THREAD_ICON_SIZE);
0614: private static ThreadStateIcon noneIcon = new ThreadStateIcon(
0615: ThreadStateIcon.ICON_NONE, THREAD_ICON_SIZE,
0616: THREAD_ICON_SIZE);
0617: private static final Color TIMELINE_ALIVE_BACKGROUND = Color.WHITE;
0618: private static final Color TIMELINE_FINISHED_BACKGROUND = new Color(
0619: 240, 240, 240);
0620:
0621: //~ Instance fields ----------------------------------------------------------------------------------------------------------
0622:
0623: long monitorTime;
0624: long runningTime;
0625: long sleepingTime;
0626: long unknownTime;
0627: long waitTime;
0628: private DynamicPieChartModel pieChartModel;
0629: private JButton hideButton;
0630: private JLabel monitorTitleLabel;
0631: private JLabel monitorValueLabel;
0632: private JLabel monitorValueRelLabel;
0633: private JLabel runningTitleLabel;
0634: private JLabel runningValueLabel;
0635: private JLabel runningValueRelLabel;
0636: private JLabel sleepingTitleLabel;
0637: private JLabel sleepingValueLabel;
0638: private JLabel sleepingValueRelLabel;
0639: private JLabel threadClassNameLabel;
0640: private JLabel threadNameLabel;
0641: private JLabel threadStateLabel;
0642: private JLabel totalTitleLabel;
0643: private JLabel totalValueLabel;
0644: private JLabel waitTitleLabel;
0645: private JLabel waitValueLabel;
0646: private JLabel waitValueRelLabel;
0647:
0648: // ---------------------------------------------------------------------------------------
0649: // Components declaration & initialization
0650:
0651: // Variables declaration
0652: private JPanel descriptionPanel;
0653: private JPanel jPanel10;
0654: private JPanel jPanel11;
0655: private JPanel jPanel12;
0656: private JPanel jPanel6;
0657: private JPanel jPanel7;
0658: private JPanel jPanel9;
0659: private JPanel tabsPanel;
0660: private JPanel timeLinePanel;
0661: private JPanel titlePanel;
0662: private JScrollPane jScrollPane1;
0663: private JSeparator jSeparator1;
0664: private JSeparator jSeparator2;
0665: private JSeparator jSeparator3;
0666: private JSeparator jSeparator4;
0667: private JTabbedPane jTabbedPane1;
0668: private JTextArea detailsArea;
0669: private JTextArea threadDescriptionArea;
0670: private PieChart pieChart;
0671: private SingleThreadState timeLine;
0672: private ThreadsDetailsPanel viewManager;
0673: private boolean internalAdjustmentEvent; // internal flag indicating that AdjustmentEvent was caused by the Append command while "tracking end" of detailsArea
0674: private boolean supportsSleepingState; // internal flag indicating that threads monitoring engine correctly reports the "sleeping" state
0675: private byte lastThreadState; // last thread state
0676: private int lastStatesCount; // number of collected thread states when the last dataUpdate() was called
0677: private int lastThreadIndex; // index of thread which data were displayed when the last dataUpdate() was called
0678: private int threadIndex;
0679: private long lastThreadDataEnd; // timestamp of last data updateState
0680:
0681: //~ Constructors -------------------------------------------------------------------------------------------------------------
0682:
0683: public ThreadDetailsComponent(ThreadsDetailsPanel viewManager,
0684: boolean supportsSleepingState) {
0685: this (viewManager, -1, supportsSleepingState);
0686: }
0687:
0688: private ThreadDetailsComponent(ThreadsDetailsPanel viewManager,
0689: int index, boolean supportsSleepingState) {
0690: this .viewManager = viewManager;
0691: this .supportsSleepingState = supportsSleepingState;
0692:
0693: initPieChartComponents();
0694: initComponents();
0695: hookDetailsAreaScrollBar();
0696:
0697: resetData();
0698: setIndex(index);
0699: }
0700:
0701: //~ Methods ------------------------------------------------------------------------------------------------------------------
0702:
0703: public void setIndex(int index) {
0704: threadIndex = index;
0705: updateThreadState();
0706: }
0707:
0708: public int getIndex() {
0709: return threadIndex;
0710: }
0711:
0712: public void dataReset() {
0713: resetData();
0714: setIndex(-1);
0715: }
0716:
0717: private String getPercentValue(float value, float basevalue) {
0718: int basis = (int) (value / basevalue * 1000f);
0719: int percent = basis / 10;
0720: int permille = basis % 10;
0721:
0722: return "" + percent + "." + permille; // NOI18N
0723: }
0724:
0725: private String getThreadDetail(long timestamp, String description) {
0726: long relTimeStamp = timestamp - viewManager.getDataStartTime();
0727:
0728: return (" " + TimeLineUtils.getMillisValue(relTimeStamp) + ": "
0729: + description + "\n"); // NOI18N
0730: }
0731:
0732: private long getThreadStateDuration(ThreadData threadData, int index) {
0733: long startTime = threadData.getTimeStampAt(index);
0734: long endTime = viewManager.getDataEndTime();
0735:
0736: if (index < (threadData.size() - 1)) {
0737: endTime = threadData.getTimeStampAt(index + 1);
0738: }
0739:
0740: return endTime - startTime;
0741: }
0742:
0743: // --- Private implementation -----
0744: private void hookDetailsAreaScrollBar() {
0745: jScrollPane1.getVerticalScrollBar().addAdjustmentListener(
0746: new java.awt.event.AdjustmentListener() {
0747: public void adjustmentValueChanged(
0748: java.awt.event.AdjustmentEvent e) {
0749: JScrollBar scrollbar = jScrollPane1
0750: .getVerticalScrollBar();
0751: int value = e.getValue();
0752: int increment = scrollbar.getUnitIncrement(-1);
0753:
0754: if (!internalAdjustmentEvent) { // real AdjustmentEvent from the user
0755:
0756: if (detailsArea.getCaretPosition() == detailsArea
0757: .getText().length()) { // currently "tracking end"
0758:
0759: if ((scrollbar.getValue() + scrollbar
0760: .getVisibleAmount()) < scrollbar
0761: .getMaximum()) { // user scrolls up
0762:
0763: try {
0764: detailsArea
0765: .setCaretPosition(detailsArea
0766: .getLineStartOffset(value
0767: / increment)); // set Caret somewhere in the visible area && not at the end
0768: } catch (Exception ex) {
0769: }
0770:
0771: ;
0772: }
0773: } else {
0774: if ((scrollbar.getValue() + scrollbar
0775: .getVisibleAmount()) >= scrollbar
0776: .getMaximum()) { // user scrolled to the end
0777: detailsArea
0778: .setCaretPosition(detailsArea
0779: .getText().length()); // set Carret at the end => "tracking end"
0780: }
0781: }
0782: }
0783:
0784: internalAdjustmentEvent = false; // reset internal AdjustmentEvent flag
0785: }
0786: });
0787: }
0788:
0789: private void initComponents() {
0790: timeLine = new SingleThreadState();
0791: timeLine.getAccessibleContext().setAccessibleName(
0792: TIMELINE_ACCESS_NAME);
0793:
0794: GridBagConstraints gridBagConstraints;
0795:
0796: titlePanel = new JPanel();
0797: threadNameLabel = new JLabel();
0798: threadClassNameLabel = new JLabel();
0799: threadStateLabel = new JLabel();
0800: jSeparator2 = new JSeparator();
0801: jPanel9 = new JPanel();
0802: hideButton = new JButton();
0803: descriptionPanel = new JPanel();
0804: threadDescriptionArea = new JTextArea();
0805: jSeparator1 = new JSeparator();
0806: tabsPanel = new JPanel();
0807: jTabbedPane1 = new JTabbedPane();
0808: jPanel6 = new JPanel();
0809: jPanel11 = new JPanel();
0810: jPanel10 = new JPanel();
0811: runningTitleLabel = new JLabel();
0812: sleepingTitleLabel = new JLabel();
0813: waitTitleLabel = new JLabel();
0814: monitorTitleLabel = new JLabel();
0815: runningValueLabel = new JLabel();
0816: runningValueRelLabel = new JLabel();
0817: sleepingValueLabel = new JLabel();
0818: sleepingValueRelLabel = new JLabel();
0819: waitValueLabel = new JLabel();
0820: waitValueRelLabel = new JLabel();
0821: monitorValueLabel = new JLabel();
0822: monitorValueRelLabel = new JLabel();
0823: jSeparator4 = new JSeparator();
0824: totalTitleLabel = new JLabel();
0825: totalValueLabel = new JLabel();
0826: jPanel12 = new JPanel();
0827: jPanel7 = new JPanel();
0828: jScrollPane1 = new JScrollPane();
0829: detailsArea = new JTextArea();
0830:
0831: jSeparator3 = new JSeparator();
0832: timeLinePanel = new JPanel();
0833:
0834: setLayout(new GridBagLayout());
0835:
0836: setBorder(new CompoundBorder(
0837: new BevelBorder(BevelBorder.RAISED), new EmptyBorder(
0838: new Insets(5, 5, 5, 5))));
0839: titlePanel.setLayout(new BorderLayout(5, 5));
0840:
0841: JPanel namePanel = new JPanel();
0842: namePanel.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
0843:
0844: threadNameLabel.setFont(getFont().deriveFont(Font.BOLD,
0845: getFont().getSize() + 1));
0846: threadNameLabel.setVerticalAlignment(SwingConstants.CENTER);
0847: threadNameLabel.setIcon(noneIcon);
0848: threadNameLabel.setIconTextGap(7);
0849: threadNameLabel.setBorder(new EmptyBorder(
0850: new Insets(5, 7, 0, 0)));
0851: threadNameLabel.getAccessibleContext().setAccessibleName(
0852: THREAD_NAME_LABEL_ACCESS_NAME);
0853:
0854: threadClassNameLabel.setFont(getFont().deriveFont(
0855: (float) (getFont().getSize() + 1)));
0856: threadClassNameLabel
0857: .setVerticalAlignment(SwingConstants.CENTER);
0858: threadClassNameLabel.setBorder(new EmptyBorder(new Insets(5, 5,
0859: 0, 0)));
0860:
0861: namePanel.add(threadNameLabel);
0862: namePanel.add(threadClassNameLabel);
0863:
0864: titlePanel.add(namePanel, BorderLayout.WEST);
0865:
0866: threadStateLabel.setVerticalAlignment(SwingConstants.CENTER);
0867: threadStateLabel.setBorder(new EmptyBorder(new Insets(5, 0, 0,
0868: 5)));
0869: threadStateLabel.getAccessibleContext().setAccessibleName(
0870: THREAD_STATE_LABEL_ACCESS_NAME);
0871: titlePanel.add(threadStateLabel, BorderLayout.CENTER);
0872:
0873: titlePanel.add(jSeparator2, BorderLayout.SOUTH);
0874:
0875: jPanel9.setLayout(new BorderLayout(5, 0));
0876:
0877: hideButton.setText(HIDE_BUTTON_NAME);
0878: hideButton.setPreferredSize(new Dimension(hideButton
0879: .getPreferredSize().width, hideButton
0880: .getPreferredSize().height - 4));
0881: hideButton.setMaximumSize(new Dimension(hideButton
0882: .getMaximumSize().width,
0883: hideButton.getMaximumSize().height - 4));
0884: hideButton.addActionListener(new ActionListener() {
0885: public void actionPerformed(ActionEvent e) {
0886: viewManager.hideThreadDetails(threadIndex);
0887: };
0888: });
0889: hideButton.getAccessibleContext().setAccessibleDescription(
0890: HIDE_BUTTON_ACCESS_DESCR);
0891: jPanel9.add(hideButton, BorderLayout.WEST);
0892:
0893: titlePanel.add(jPanel9, BorderLayout.EAST);
0894:
0895: gridBagConstraints = new GridBagConstraints();
0896: gridBagConstraints.gridwidth = GridBagConstraints.REMAINDER;
0897: gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
0898: gridBagConstraints.weightx = 1.0;
0899: gridBagConstraints.insets = new Insets(0, 0, 5, 0);
0900: add(titlePanel, gridBagConstraints);
0901:
0902: descriptionPanel.setLayout(new BorderLayout());
0903:
0904: JPanel threadDescriptionIconPanel = new JPanel();
0905: threadDescriptionIconPanel.setLayout(new BorderLayout());
0906: threadDescriptionIconPanel.setBorder(new EmptyBorder(
0907: new Insets(0, 5, 5, 0)));
0908:
0909: JLabel threadDescriptionIcon = new JLabel(
0910: new ImageIcon(
0911: getClass()
0912: .getResource(
0913: "/org/netbeans/lib/profiler/ui/resources/infoIcon.png"))); // NOI18N
0914:
0915: threadDescriptionIconPanel.add(threadDescriptionIcon,
0916: BorderLayout.NORTH);
0917: descriptionPanel.add(threadDescriptionIconPanel,
0918: BorderLayout.WEST);
0919:
0920: threadDescriptionArea.setBorder(new EmptyBorder(new Insets(0,
0921: 5, 5, 5)));
0922: threadDescriptionArea.setBackground(getBackground());
0923: threadDescriptionArea.setOpaque(false);
0924: threadDescriptionArea.setWrapStyleWord(true);
0925: threadDescriptionArea.setLineWrap(true);
0926: threadDescriptionArea.setEnabled(false);
0927: threadDescriptionArea.setFont(UIManager.getFont("Label.font")); // NOI18N
0928: threadDescriptionArea.setDisabledTextColor(UIManager
0929: .getColor("Label.foreground")); // NOI18N
0930: threadDescriptionArea.setCaret(new DefaultCaret() {
0931: protected void adjustVisibility(Rectangle nloc) {
0932: // do nothing to prevent violent scrolling
0933: }
0934: });
0935: descriptionPanel
0936: .add(threadDescriptionArea, BorderLayout.CENTER);
0937:
0938: descriptionPanel.add(jSeparator1, BorderLayout.SOUTH);
0939:
0940: gridBagConstraints = new GridBagConstraints();
0941: gridBagConstraints.gridwidth = GridBagConstraints.REMAINDER;
0942: gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
0943: gridBagConstraints.weightx = 1.0;
0944: gridBagConstraints.insets = new Insets(0, 0, 5, 0);
0945: add(descriptionPanel, gridBagConstraints);
0946:
0947: tabsPanel.setLayout(new BorderLayout());
0948:
0949: jTabbedPane1.setBorder(new EmptyBorder(new Insets(0, 5, 5, 5)));
0950: jTabbedPane1.getAccessibleContext().setAccessibleName(
0951: TAB_ACCESS_NAME);
0952: jPanel6.setLayout(new BorderLayout());
0953:
0954: jPanel11.setLayout(new BorderLayout());
0955:
0956: jPanel10.setLayout(new GridBagLayout());
0957:
0958: runningTitleLabel
0959: .setText(CommonConstants.THREAD_STATUS_RUNNING_STRING);
0960: runningTitleLabel.setIcon(runningIcon);
0961: gridBagConstraints = new GridBagConstraints();
0962: gridBagConstraints.gridx = 0;
0963: gridBagConstraints.gridy = 0;
0964: gridBagConstraints.anchor = GridBagConstraints.WEST;
0965: gridBagConstraints.insets = new Insets(5, 5, 0, 5);
0966: jPanel10.add(runningTitleLabel, gridBagConstraints);
0967:
0968: if (supportsSleepingState) {
0969: sleepingTitleLabel
0970: .setText(CommonConstants.THREAD_STATUS_SLEEPING_STRING);
0971: sleepingTitleLabel.setBorder(new EmptyBorder(new Insets(5,
0972: 5, 0, 5)));
0973: sleepingTitleLabel.setIcon(sleepingIcon);
0974: gridBagConstraints = new GridBagConstraints();
0975: gridBagConstraints.gridx = 0;
0976: gridBagConstraints.gridy = 1;
0977: gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
0978: gridBagConstraints.anchor = GridBagConstraints.WEST;
0979: gridBagConstraints.weightx = 1.0;
0980: gridBagConstraints.weighty = 1.0;
0981: jPanel10.add(sleepingTitleLabel, gridBagConstraints);
0982: }
0983:
0984: waitTitleLabel
0985: .setText(CommonConstants.THREAD_STATUS_WAIT_STRING);
0986: waitTitleLabel.setIcon(waitIcon);
0987: gridBagConstraints = new GridBagConstraints();
0988: gridBagConstraints.gridx = 0;
0989: gridBagConstraints.gridy = 2;
0990: gridBagConstraints.anchor = GridBagConstraints.WEST;
0991: gridBagConstraints.insets = new Insets(5, 5, 0, 5);
0992: jPanel10.add(waitTitleLabel, gridBagConstraints);
0993:
0994: monitorTitleLabel
0995: .setText(CommonConstants.THREAD_STATUS_MONITOR_STRING);
0996: monitorTitleLabel.setIcon(monitorIcon);
0997: gridBagConstraints = new GridBagConstraints();
0998: gridBagConstraints.gridx = 0;
0999: gridBagConstraints.gridy = 3;
1000: gridBagConstraints.anchor = GridBagConstraints.WEST;
1001: gridBagConstraints.insets = new Insets(5, 5, 5, 5);
1002: jPanel10.add(monitorTitleLabel, gridBagConstraints);
1003:
1004: runningValueLabel
1005: .setHorizontalAlignment(SwingConstants.TRAILING);
1006: gridBagConstraints = new GridBagConstraints();
1007: gridBagConstraints.gridx = 1;
1008: gridBagConstraints.gridy = 0;
1009: gridBagConstraints.anchor = GridBagConstraints.WEST;
1010: gridBagConstraints.insets = new Insets(5, 5, 0, 5);
1011: jPanel10.add(runningValueLabel, gridBagConstraints);
1012:
1013: gridBagConstraints = new GridBagConstraints();
1014: gridBagConstraints.gridx = 2;
1015: gridBagConstraints.gridy = 0;
1016: gridBagConstraints.anchor = GridBagConstraints.WEST;
1017: gridBagConstraints.insets = new Insets(5, 0, 0, 10);
1018: jPanel10.add(runningValueRelLabel, gridBagConstraints);
1019:
1020: if (supportsSleepingState) {
1021: sleepingValueLabel
1022: .setHorizontalAlignment(SwingConstants.TRAILING);
1023: gridBagConstraints = new GridBagConstraints();
1024: gridBagConstraints.gridx = 1;
1025: gridBagConstraints.gridy = 1;
1026: gridBagConstraints.anchor = GridBagConstraints.WEST;
1027: gridBagConstraints.insets = new Insets(5, 5, 0, 5);
1028: jPanel10.add(sleepingValueLabel, gridBagConstraints);
1029:
1030: gridBagConstraints = new GridBagConstraints();
1031: gridBagConstraints.gridx = 2;
1032: gridBagConstraints.gridy = 1;
1033: gridBagConstraints.anchor = GridBagConstraints.WEST;
1034: gridBagConstraints.insets = new Insets(5, 0, 0, 10);
1035: jPanel10.add(sleepingValueRelLabel, gridBagConstraints);
1036: }
1037:
1038: waitValueLabel.setHorizontalAlignment(SwingConstants.TRAILING);
1039: gridBagConstraints = new GridBagConstraints();
1040: gridBagConstraints.gridx = 1;
1041: gridBagConstraints.gridy = 2;
1042: gridBagConstraints.anchor = GridBagConstraints.WEST;
1043: gridBagConstraints.insets = new Insets(5, 5, 0, 5);
1044: jPanel10.add(waitValueLabel, gridBagConstraints);
1045:
1046: gridBagConstraints = new GridBagConstraints();
1047: gridBagConstraints.gridx = 2;
1048: gridBagConstraints.gridy = 2;
1049: gridBagConstraints.anchor = GridBagConstraints.WEST;
1050: gridBagConstraints.insets = new Insets(5, 0, 0, 10);
1051: jPanel10.add(waitValueRelLabel, gridBagConstraints);
1052:
1053: monitorValueLabel
1054: .setHorizontalAlignment(SwingConstants.TRAILING);
1055: gridBagConstraints = new GridBagConstraints();
1056: gridBagConstraints.gridx = 1;
1057: gridBagConstraints.gridy = 3;
1058: gridBagConstraints.anchor = GridBagConstraints.WEST;
1059: gridBagConstraints.insets = new Insets(5, 5, 5, 5);
1060: jPanel10.add(monitorValueLabel, gridBagConstraints);
1061:
1062: gridBagConstraints = new GridBagConstraints();
1063: gridBagConstraints.gridx = 2;
1064: gridBagConstraints.gridy = 3;
1065: gridBagConstraints.anchor = GridBagConstraints.WEST;
1066: gridBagConstraints.insets = new Insets(5, 0, 5, 10);
1067: jPanel10.add(monitorValueRelLabel, gridBagConstraints);
1068:
1069: gridBagConstraints = new GridBagConstraints();
1070: gridBagConstraints.gridx = 0;
1071: gridBagConstraints.gridy = 4;
1072: gridBagConstraints.gridwidth = 3;
1073: gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
1074: gridBagConstraints.anchor = GridBagConstraints.WEST;
1075: gridBagConstraints.insets = new Insets(0, 0, 0, 5);
1076: jPanel10.add(jSeparator4, gridBagConstraints);
1077:
1078: totalTitleLabel.setText(TOTAL_LABEL_STRING);
1079: totalTitleLabel.setIcon(noneIcon);
1080: gridBagConstraints = new GridBagConstraints();
1081: gridBagConstraints.gridx = 0;
1082: gridBagConstraints.gridy = 5;
1083: gridBagConstraints.anchor = GridBagConstraints.WEST;
1084: gridBagConstraints.insets = new Insets(5, 5, 5, 5);
1085: jPanel10.add(totalTitleLabel, gridBagConstraints);
1086:
1087: totalValueLabel.setHorizontalAlignment(SwingConstants.TRAILING);
1088: gridBagConstraints = new GridBagConstraints();
1089: gridBagConstraints.gridx = 1;
1090: gridBagConstraints.gridy = 5;
1091: gridBagConstraints.gridwidth = 2;
1092: gridBagConstraints.anchor = GridBagConstraints.WEST;
1093: gridBagConstraints.insets = new Insets(5, 5, 5, 5);
1094: jPanel10.add(totalValueLabel, gridBagConstraints);
1095:
1096: jPanel11.add(jPanel10, BorderLayout.WEST);
1097:
1098: JPanel northPanel = new JPanel();
1099: northPanel.setLayout(new BorderLayout());
1100: northPanel.setBorder(new EmptyBorder(new Insets(10, 0, 0, 0)));
1101: northPanel.add(jPanel11, BorderLayout.NORTH);
1102:
1103: jPanel6.add(northPanel, BorderLayout.CENTER);
1104:
1105: jPanel12.setLayout(new BorderLayout());
1106:
1107: pieChart.setPreferredSize(new Dimension(230, 100));
1108: pieChart.setBorder(BorderFactory.createEmptyBorder(15, 30, 15,
1109: 30));
1110: jPanel12.add(pieChart, BorderLayout.NORTH);
1111: jPanel12.getAccessibleContext().setAccessibleName(
1112: PIECHART_ACCESS_NAME);
1113: pieChart.setAccessibleContext(jPanel12.getAccessibleContext());
1114:
1115: jPanel6.add(jPanel12, BorderLayout.WEST);
1116:
1117: jTabbedPane1.addTab(GENERAL_TAB_NAME, jPanel6);
1118:
1119: jPanel7.setLayout(new BorderLayout());
1120:
1121: detailsArea.setEditable(false);
1122: detailsArea.setRows(1);
1123: jScrollPane1.setViewportView(detailsArea);
1124:
1125: jPanel7.add(jScrollPane1, BorderLayout.CENTER);
1126:
1127: jTabbedPane1.addTab(DETAILS_TAB_NAME, jPanel7);
1128:
1129: tabsPanel.add(jTabbedPane1, BorderLayout.CENTER);
1130:
1131: tabsPanel.add(jSeparator3, BorderLayout.SOUTH);
1132:
1133: gridBagConstraints = new GridBagConstraints();
1134: gridBagConstraints.gridwidth = GridBagConstraints.REMAINDER;
1135: gridBagConstraints.fill = GridBagConstraints.BOTH;
1136: gridBagConstraints.weightx = 1.0;
1137: gridBagConstraints.weighty = 1.0;
1138: gridBagConstraints.insets = new Insets(0, 0, 5, 0);
1139: add(tabsPanel, gridBagConstraints);
1140:
1141: timeLinePanel.setLayout(new BorderLayout());
1142:
1143: JPanel timeLineContainer = new JPanel();
1144: timeLineContainer.setLayout(new BorderLayout());
1145: timeLineContainer
1146: .setBorder(new BevelBorder(BevelBorder.LOWERED));
1147: timeLineContainer.add(timeLine, BorderLayout.CENTER);
1148:
1149: timeLinePanel.add(timeLineContainer, BorderLayout.CENTER);
1150:
1151: gridBagConstraints = new GridBagConstraints();
1152: gridBagConstraints.gridwidth = GridBagConstraints.REMAINDER;
1153: gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
1154: gridBagConstraints.weightx = 1.0;
1155: gridBagConstraints.insets = new Insets(0, 5, 5, 5);
1156: add(timeLinePanel, gridBagConstraints);
1157: }
1158:
1159: private void initPieChartComponents() {
1160: pieChart = new PieChart();
1161: pieChart.setFocusable(false);
1162: pieChartModel = new DynamicPieChartModel();
1163:
1164: if (supportsSleepingState) {
1165: pieChartModel
1166: .setupModel(
1167: new String[] {
1168: CommonConstants.THREAD_STATUS_RUNNING_STRING,
1169: CommonConstants.THREAD_STATUS_SLEEPING_STRING,
1170: CommonConstants.THREAD_STATUS_WAIT_STRING,
1171: CommonConstants.THREAD_STATUS_MONITOR_STRING },
1172: new Color[] {
1173: CommonConstants.THREAD_STATUS_RUNNING_COLOR,
1174: CommonConstants.THREAD_STATUS_SLEEPING_COLOR,
1175: CommonConstants.THREAD_STATUS_WAIT_COLOR,
1176: CommonConstants.THREAD_STATUS_MONITOR_COLOR });
1177: } else {
1178: pieChartModel
1179: .setupModel(
1180: new String[] {
1181: CommonConstants.THREAD_STATUS_RUNNING_STRING,
1182: CommonConstants.THREAD_STATUS_WAIT_STRING,
1183: CommonConstants.THREAD_STATUS_MONITOR_STRING },
1184: new Color[] {
1185: CommonConstants.THREAD_STATUS_RUNNING_COLOR,
1186: CommonConstants.THREAD_STATUS_WAIT_COLOR,
1187: CommonConstants.THREAD_STATUS_MONITOR_COLOR });
1188: }
1189:
1190: pieChart.setModel(pieChartModel);
1191: }
1192:
1193: private void resetData() {
1194: lastThreadIndex = -1;
1195: lastStatesCount = 0;
1196: lastThreadDataEnd = 0;
1197: lastThreadState = -10;
1198: runningTime = 0;
1199: sleepingTime = 0;
1200: waitTime = 0;
1201: monitorTime = 0;
1202: unknownTime = 0;
1203: detailsArea.setText(""); // NOI18N
1204: jTabbedPane1.setSelectedIndex(0);
1205: }
1206:
1207: private void updateThreadState() {
1208: if (threadIndex == -1) {
1209: return;
1210: }
1211:
1212: ThreadData threadData = viewManager.getThreadData(threadIndex);
1213:
1214: // thread name & classname
1215: threadNameLabel.setText(viewManager.getThreadName(threadIndex));
1216:
1217: if (threadIndex != lastThreadIndex) {
1218: threadClassNameLabel
1219: .setText("["
1220: + viewManager
1221: .getThreadClassName(threadIndex)
1222: + "]"); // NOI18N
1223: }
1224:
1225: // thread state
1226: if ((threadData == null) || (threadData.size() == 0)) {
1227: threadNameLabel.setIcon(zombieIcon);
1228: timeLine.setBackground(TIMELINE_FINISHED_BACKGROUND);
1229: threadStateLabel
1230: .setText("(" + THREAD_FINISHED_STRING + ")"); // NOI18N
1231: } else {
1232: if (lastThreadState != threadData.getLastState()) {
1233: switch (threadData.getLastState()) {
1234: case CommonConstants.THREAD_STATUS_UNKNOWN:
1235: threadNameLabel.setIcon(unknownIcon);
1236: timeLine.setBackground(TIMELINE_ALIVE_BACKGROUND);
1237: threadStateLabel.setText("("
1238: + THREAD_STATE_UNKNOWN_STRING + ")"); // NOI18N
1239:
1240: break;
1241: case CommonConstants.THREAD_STATUS_ZOMBIE:
1242: threadNameLabel.setIcon(zombieIcon);
1243: timeLine
1244: .setBackground(TIMELINE_FINISHED_BACKGROUND);
1245: threadStateLabel.setText("("
1246: + THREAD_FINISHED_STRING + ")"); // NOI18N
1247:
1248: break;
1249: case CommonConstants.THREAD_STATUS_SLEEPING:
1250:
1251: if (supportsSleepingState) {
1252: threadNameLabel.setIcon(sleepingIcon);
1253: } else {
1254: threadNameLabel.setIcon(runningIcon);
1255: }
1256:
1257: timeLine.setBackground(TIMELINE_ALIVE_BACKGROUND);
1258: threadStateLabel.setText("(" + THREAD_ALIVE_STRING
1259: + ")"); // NOI18N
1260:
1261: break;
1262: case CommonConstants.THREAD_STATUS_RUNNING:
1263: threadNameLabel.setIcon(runningIcon);
1264: timeLine.setBackground(TIMELINE_ALIVE_BACKGROUND);
1265: threadStateLabel.setText("(" + THREAD_ALIVE_STRING
1266: + ")"); // NOI18N
1267:
1268: break;
1269: case CommonConstants.THREAD_STATUS_WAIT:
1270: threadNameLabel.setIcon(waitIcon);
1271: timeLine.setBackground(TIMELINE_ALIVE_BACKGROUND);
1272: threadStateLabel.setText("(" + THREAD_ALIVE_STRING
1273: + ")"); // NOI18N
1274:
1275: break;
1276: case CommonConstants.THREAD_STATUS_MONITOR:
1277: threadNameLabel.setIcon(monitorIcon);
1278: timeLine.setBackground(TIMELINE_ALIVE_BACKGROUND);
1279: threadStateLabel.setText("(" + THREAD_ALIVE_STRING
1280: + ")"); // NOI18N
1281:
1282: break;
1283: }
1284: }
1285: }
1286:
1287: // thread description
1288: threadDescriptionArea.setText(viewManager
1289: .getThreadDescription(threadIndex));
1290:
1291: if ((threadData == null) || (threadData.size() == 0)) {
1292: resetData();
1293:
1294: runningValueLabel.setText("-"); // NOI18N
1295: runningValueRelLabel.setText("(-%)"); // NOI18N
1296:
1297: if (supportsSleepingState) {
1298: sleepingValueLabel.setText("-"); // NOI18N
1299: sleepingValueRelLabel.setText("(-%)"); // NOI18N
1300: }
1301:
1302: waitValueLabel.setText("-"); // NOI18N
1303: waitValueRelLabel.setText("(-%)"); // NOI18N
1304: monitorValueLabel.setText("-"); // NOI18N
1305: monitorValueRelLabel.setText("(-%)"); // NOI18N
1306: totalValueLabel.setText(NO_DATA_COLLECTED_STRING);
1307:
1308: if (supportsSleepingState) {
1309: pieChartModel.setItemValues(new double[] { 0d, 0d, 0d,
1310: 0d });
1311: } else {
1312: pieChartModel
1313: .setItemValues(new double[] { 0d, 0d, 0d });
1314: }
1315: } else {
1316: // When the threadIndex was changed (component displays data of different thread) details textarea is cleared
1317: if (threadIndex != lastThreadIndex) {
1318: resetData();
1319: }
1320:
1321: StringBuffer detailsToAppend = new StringBuffer();
1322:
1323: for (int i = lastStatesCount; i < threadData.size(); i++) {
1324: long timeStamp = threadData.getTimeStampAt(i);
1325: byte state = threadData.getStateAt(i);
1326:
1327: if (i == 0) {
1328: detailsToAppend.append(getThreadDetail(timeStamp,
1329: THREAD_STARTED_STRING));
1330: }
1331:
1332: switch (state) {
1333: case CommonConstants.THREAD_STATUS_RUNNING:
1334: detailsToAppend
1335: .append(getThreadDetail(
1336: timeStamp,
1337: CommonConstants.THREAD_STATUS_RUNNING_STRING));
1338: runningTime += getThreadStateDuration(threadData, i);
1339:
1340: break;
1341: case CommonConstants.THREAD_STATUS_SLEEPING:
1342:
1343: if (supportsSleepingState) {
1344: detailsToAppend
1345: .append(getThreadDetail(
1346: timeStamp,
1347: CommonConstants.THREAD_STATUS_SLEEPING_STRING));
1348: sleepingTime += getThreadStateDuration(
1349: threadData, i);
1350: } else {
1351: detailsToAppend
1352: .append(getThreadDetail(
1353: timeStamp,
1354: CommonConstants.THREAD_STATUS_RUNNING_STRING));
1355: runningTime += getThreadStateDuration(
1356: threadData, i);
1357: }
1358:
1359: break;
1360: case CommonConstants.THREAD_STATUS_WAIT:
1361: detailsToAppend.append(getThreadDetail(timeStamp,
1362: CommonConstants.THREAD_STATUS_WAIT_STRING));
1363: waitTime += getThreadStateDuration(threadData, i);
1364:
1365: break;
1366: case CommonConstants.THREAD_STATUS_MONITOR:
1367: detailsToAppend
1368: .append(getThreadDetail(
1369: timeStamp,
1370: CommonConstants.THREAD_STATUS_MONITOR_STRING));
1371: monitorTime += getThreadStateDuration(threadData, i);
1372:
1373: break;
1374: case CommonConstants.THREAD_STATUS_ZOMBIE:
1375:
1376: if (i != 0) {
1377: detailsToAppend
1378: .append(getThreadDetail(
1379: timeStamp,
1380: CommonConstants.THREAD_STATUS_ZOMBIE_STRING));
1381: }
1382:
1383: break;
1384: }
1385: }
1386:
1387: // If currentThreadState == lastThreadState then the end time of lastThreadState must be incremented
1388: if (lastStatesCount == threadData.size()) {
1389: if (threadData.size() != 0) {
1390: long timeDiff = viewManager.getDataEndTime()
1391: - lastThreadDataEnd;
1392: byte state = threadData.getLastState();
1393:
1394: switch (state) {
1395: case CommonConstants.THREAD_STATUS_RUNNING:
1396: runningTime += timeDiff;
1397:
1398: break;
1399: case CommonConstants.THREAD_STATUS_SLEEPING:
1400:
1401: if (supportsSleepingState) {
1402: sleepingTime += timeDiff;
1403: } else {
1404: runningTime += timeDiff;
1405: }
1406:
1407: break;
1408: case CommonConstants.THREAD_STATUS_WAIT:
1409: waitTime += timeDiff;
1410:
1411: break;
1412: case CommonConstants.THREAD_STATUS_MONITOR:
1413: monitorTime += timeDiff;
1414:
1415: break;
1416: }
1417: }
1418: }
1419:
1420: //long totalTime = runningTime + sleepingTime + waitTime + monitorTime + unknownTime;
1421: long totalTime = 0;
1422:
1423: if (supportsSleepingState) {
1424: totalTime = runningTime + sleepingTime + waitTime
1425: + monitorTime;
1426: } else {
1427: totalTime = runningTime + waitTime + monitorTime;
1428: }
1429:
1430: if (supportsSleepingState) {
1431: pieChartModel.setItemValues(new double[] { runningTime,
1432: sleepingTime, waitTime, monitorTime });
1433: } else {
1434: pieChartModel.setItemValues(new double[] { runningTime,
1435: waitTime, monitorTime });
1436: }
1437:
1438: runningValueLabel.setText(TimeLineUtils
1439: .getMillisValue(runningTime));
1440: runningValueRelLabel.setText("("
1441: + ((runningTime == 0) ? "0.0" : getPercentValue(
1442: runningTime, totalTime)) + "%)"); // NOI18N
1443:
1444: if (supportsSleepingState) {
1445: sleepingValueLabel.setText(TimeLineUtils
1446: .getMillisValue(sleepingTime));
1447: sleepingValueRelLabel.setText("("
1448: + ((sleepingTime == 0) ? "0.0"
1449: : getPercentValue(sleepingTime,
1450: totalTime)) + "%)"); // NOI18N
1451: }
1452:
1453: waitValueLabel.setText(TimeLineUtils
1454: .getMillisValue(waitTime));
1455: waitValueRelLabel.setText("("
1456: + ((waitTime == 0) ? "0.0" : getPercentValue(
1457: waitTime, totalTime)) + "%)"); // NOI18N
1458: monitorValueLabel.setText(TimeLineUtils
1459: .getMillisValue(monitorTime));
1460: monitorValueRelLabel.setText("("
1461: + ((monitorTime == 0) ? "0.0" : getPercentValue(
1462: monitorTime, totalTime)) + "%)"); // NOI18N
1463: totalValueLabel.setText(TimeLineUtils
1464: .getMillisValue(totalTime));
1465:
1466: if (detailsToAppend.length() > 0) {
1467: if (detailsArea.getCaretPosition() == detailsArea
1468: .getText().length()) {
1469: internalAdjustmentEvent = true; // if "tracking end" set internal AdjustmentEvent flag
1470: }
1471:
1472: detailsArea.append(detailsToAppend.toString());
1473:
1474: if (lastStatesCount == 0) {
1475: detailsArea.setCaretPosition(1); // First text added, carret position can't be at the end ("tracking end" is not default)
1476: }
1477: }
1478: }
1479:
1480: lastThreadIndex = threadIndex;
1481: lastStatesCount = threadData.size();
1482: lastThreadDataEnd = viewManager.getDataEndTime();
1483: lastThreadState = threadData.getLastState();
1484:
1485: // Timeline
1486: timeLine.updateData(threadData, viewManager.getDataStartTime(),
1487: viewManager.getDataEndTime());
1488: }
1489: }
|