001: /*
002: * Swing Explorer. Tool for developers exploring Java/Swing-based application internals.
003: * Copyright (C) 2008, Maxim Zakharenkov
004: *
005: * This program is free software; you can redistribute it and/or modify
006: * it under the terms of the GNU General Public License as published by
007: * the Free Software Foundation; either version 2 of the License, or
008: * (at your option) any later version.
009: *
010: * This program is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013: * GNU General Public License for more details.
014: *
015: * You should have received a copy of the GNU General Public License along
016: * with this program; if not, write to the Free Software Foundation, Inc.,
017: * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
018: *
019: * $Header: /cvs/swingexplorer/src/org/swingexplorer/edt_monitor/PNLEDTMonitor.java,v 1.1 2008/03/07 11:46:52 maxz1 Exp $
020: */
021:
022: package org.swingexplorer.edt_monitor;
023:
024: import java.awt.event.ItemEvent;
025: import java.beans.PropertyChangeEvent;
026: import java.beans.PropertyChangeListener;
027: import java.util.Enumeration;
028: import java.util.HashSet;
029:
030: import javax.swing.JFormattedTextField;
031: import javax.swing.JSpinner;
032: import javax.swing.SpinnerNumberModel;
033: import javax.swing.JSpinner.DefaultEditor;
034: import javax.swing.event.ChangeEvent;
035: import javax.swing.event.ChangeListener;
036: import javax.swing.plaf.ButtonUI;
037: import javax.swing.plaf.IconUIResource;
038: import javax.swing.tree.DefaultMutableTreeNode;
039: import javax.swing.tree.DefaultTreeCellEditor;
040: import javax.swing.tree.DefaultTreeCellRenderer;
041: import javax.swing.tree.DefaultTreeModel;
042: import javax.swing.tree.TreeCellRenderer;
043: import javax.swing.tree.TreePath;
044:
045: import org.swingexplorer.GuiUtils;
046: import org.swingexplorer.Icons;
047: import org.swingexplorer.Problem;
048: import org.swingexplorer.ProblemListener;
049: import org.swingexplorer.plaf.CustomButtonUI;
050: import org.swingexplorer.plaf.CustomTreeUI;
051:
052: /**
053: *
054: * @author Maxim Zakharenkov
055: */
056: public class PNLEDTMonitor extends javax.swing.JPanel {
057:
058: /** Creates new form PNLEDTMonitor */
059: public PNLEDTMonitor() {
060: initComponents();
061: setModel(new MdlEDTMonitor());
062:
063: // init spinner
064: spnDelay.setModel(new SpinnerNumberModel(1000, 0, 10000, 100));
065: JSpinner.DefaultEditor editor = (DefaultEditor) spnDelay
066: .getEditor();
067: editor.getTextField().setFocusLostBehavior(
068: JFormattedTextField.COMMIT_OR_REVERT);
069: spnDelay.addChangeListener(new ChangeListener() {
070: public void stateChanged(ChangeEvent e) {
071: mdlMonitor
072: .setMinimalMonitoredHangTime(((Number) spnDelay
073: .getValue()).intValue());
074: }
075: });
076:
077: // init tree
078: treProblems.setRootVisible(false);
079: treProblems.setShowsRootHandles(true);
080: DefaultTreeModel model = (DefaultTreeModel) treProblems
081: .getModel();
082: DefaultMutableTreeNode root = new DefaultMutableTreeNode("root");
083: model.setRoot(root);
084: model.nodeStructureChanged(root);
085:
086: // init tree renderer
087: DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
088: renderer.setOpenIcon(Icons.warning());
089: renderer.setClosedIcon(Icons.warning());
090: renderer.setLeafIcon(Icons.codeLineBall());
091: treProblems.setCellRenderer(renderer);
092: initActions();
093: }
094:
095: /** This method is called from within the constructor to
096: * initialize the form.
097: * WARNING: Do NOT modify this code. The content of this method is
098: * always regenerated by the Form Editor.
099: */
100: // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
101: private void initComponents() {
102:
103: scpProblems = new javax.swing.JScrollPane();
104: treProblems = new javax.swing.JTree();
105: chbEDTViolations = new javax.swing.JCheckBox();
106: chbDelays = new javax.swing.JCheckBox();
107: btnTrace = new javax.swing.JButton();
108: spnDelay = new javax.swing.JSpinner();
109: btnClear = new javax.swing.JButton();
110:
111: scpProblems.setMinimumSize(new java.awt.Dimension(0, 0));
112: scpProblems.setViewportView(treProblems);
113:
114: chbEDTViolations.setText("EDT violations");
115: chbEDTViolations
116: .setToolTipText("Monitor violations of event diapatch thread");
117: chbEDTViolations
118: .addItemListener(new java.awt.event.ItemListener() {
119: public void itemStateChanged(
120: java.awt.event.ItemEvent evt) {
121: chbEDTViolationsItemStateChanged(evt);
122: }
123: });
124:
125: chbDelays.setText("EDT hangs more than (ms):");
126: chbDelays
127: .setToolTipText("Monitor hangs occured in the event dispatch thread more than specified time");
128: chbDelays
129: .setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
130: chbDelays
131: .setHorizontalTextPosition(javax.swing.SwingConstants.RIGHT);
132: chbDelays.addItemListener(new java.awt.event.ItemListener() {
133: public void itemStateChanged(java.awt.event.ItemEvent evt) {
134: chbDelaysItemStateChanged(evt);
135: }
136: });
137:
138: btnTrace.setText("Trace");
139: btnTrace
140: .setToolTipText("Dump selected problem's stack trace to console");
141: btnTrace
142: .setBorder(javax.swing.BorderFactory
143: .createBevelBorder(javax.swing.border.BevelBorder.RAISED));
144:
145: spnDelay
146: .setToolTipText("Minimal delays to monitor (in milliseconds)");
147:
148: btnClear.setText("Clear");
149: btnClear.setToolTipText("Clear problem list");
150: btnClear
151: .setBorder(javax.swing.BorderFactory
152: .createBevelBorder(javax.swing.border.BevelBorder.RAISED));
153:
154: org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(
155: this );
156: this .setLayout(layout);
157: layout
158: .setHorizontalGroup(layout
159: .createParallelGroup(
160: org.jdesktop.layout.GroupLayout.LEADING)
161: .add(
162: layout
163: .createSequentialGroup()
164: .add(chbEDTViolations)
165: .addPreferredGap(
166: org.jdesktop.layout.LayoutStyle.RELATED)
167: .add(chbDelays)
168: .addPreferredGap(
169: org.jdesktop.layout.LayoutStyle.RELATED)
170: .add(
171: spnDelay,
172: org.jdesktop.layout.GroupLayout.PREFERRED_SIZE,
173: 61,
174: org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
175: .addPreferredGap(
176: org.jdesktop.layout.LayoutStyle.RELATED)
177: .add(btnTrace).add(0, 0, 0)
178: .add(btnClear).add(37, 37, 37))
179: .add(
180: scpProblems,
181: org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
182: 480, Short.MAX_VALUE));
183: layout
184: .setVerticalGroup(layout
185: .createParallelGroup(
186: org.jdesktop.layout.GroupLayout.LEADING)
187: .add(
188: layout
189: .createSequentialGroup()
190: .add(
191: layout
192: .createParallelGroup(
193: org.jdesktop.layout.GroupLayout.BASELINE)
194: .add(
195: chbEDTViolations)
196: .add(chbDelays)
197: .add(btnTrace)
198: .add(btnClear)
199: .add(
200: spnDelay,
201: org.jdesktop.layout.GroupLayout.PREFERRED_SIZE,
202: org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
203: org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
204: .add(3, 3, 3)
205: .add(
206: scpProblems,
207: org.jdesktop.layout.GroupLayout.DEFAULT_SIZE,
208: 96, Short.MAX_VALUE)));
209: }// </editor-fold>//GEN-END:initComponents
210:
211: private void initActions() {
212: actClear = new ActClear(this );
213: btnClear.addActionListener(actClear);
214:
215: actTrace = new ActTrace(this );
216: btnTrace.addActionListener(actTrace);
217: }
218:
219: protected void spnDelayStateChanged(ChangeEvent evt) {
220: // TODO Auto-generated method stub
221:
222: }
223:
224: private void chbEDTViolationsItemStateChanged(
225: java.awt.event.ItemEvent evt) {//GEN-FIRST:event_chbEDTViolationsItemStateChanged
226: mdlMonitor
227: .setMonitorViolations(evt.getStateChange() == ItemEvent.SELECTED);
228: }//GEN-LAST:event_chbEDTViolationsItemStateChanged
229:
230: private void chbDelaysItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_chbDelaysItemStateChanged
231: mdlMonitor
232: .setMonitorDelays(evt.getStateChange() == ItemEvent.SELECTED);
233: }//GEN-LAST:event_chbDelaysItemStateChanged
234:
235: // Variables declaration - do not modify//GEN-BEGIN:variables
236: javax.swing.JButton btnClear;
237: javax.swing.JButton btnTrace;
238: javax.swing.JCheckBox chbDelays;
239: javax.swing.JCheckBox chbEDTViolations;
240: javax.swing.JScrollPane scpProblems;
241: javax.swing.JSpinner spnDelay;
242: javax.swing.JTree treProblems;
243: // End of variables declaration//GEN-END:variables
244:
245: ActClear actClear;
246: ActTrace actTrace;
247: MdlEDTMonitor mdlMonitor;
248: ModelPropertyChangeListener modelPropChangeListener = new ModelPropertyChangeListener();
249: ProblemListenerImpl problemListener = new ProblemListenerImpl();
250:
251: public void setModel(MdlEDTMonitor _model) {
252: mdlMonitor = _model;
253: mdlMonitor.addProblemListener(problemListener);
254: mdlMonitor.addPropertyChangeListener(modelPropChangeListener);
255:
256: chbDelays.setSelected(mdlMonitor.isMonitorDelays());
257: chbEDTViolations.setSelected(mdlMonitor.isMonitorViolations());
258: spnDelay.setValue((int) mdlMonitor
259: .getMinimalMonitoredHangTime());
260: spnDelay.setEnabled(mdlMonitor.isMonitorDelays());
261: }
262:
263: public MdlEDTMonitor getModel() {
264: return mdlMonitor;
265: }
266:
267: public void addProblem(Problem problem) {
268: DefaultMutableTreeNode root = (DefaultMutableTreeNode) treProblems
269: .getModel().getRoot();
270:
271: // adding problem
272: DefaultMutableTreeNode problemNode = new DefaultMutableTreeNode(
273: problem);
274:
275: // adding stack trace elements
276: if (problem.getProblemTrace() != null) {
277: for (StackTraceElement elem : problem.getProblemTrace()) {
278: DefaultMutableTreeNode traceNode = new DefaultMutableTreeNode(
279: elem.toString());
280: problemNode.add(traceNode);
281: }
282: }
283: root.add(problemNode);
284: GuiUtils.notifyTreeChanged(treProblems);
285: }
286:
287: public void clearProblems() {
288: DefaultMutableTreeNode root = (DefaultMutableTreeNode) treProblems
289: .getModel().getRoot();
290: root.removeAllChildren();
291: GuiUtils.notifyTreeChanged(treProblems);
292: }
293:
294: /** Returns array of problems selected */
295: public Problem[] getSelectedProblems() {
296: TreePath[] paths = treProblems.getSelectionPaths();
297: if (paths == null) {
298: return null;
299: }
300:
301: // getting only "problem" type nodes without duplications
302: HashSet<DefaultMutableTreeNode> problemNodeSet = new HashSet<DefaultMutableTreeNode>();
303: for (TreePath curPath : paths) {
304: DefaultMutableTreeNode node = (DefaultMutableTreeNode) curPath
305: .getPathComponent(1);
306: problemNodeSet.add(node);
307: }
308:
309: //
310: Problem[] problems = new Problem[problemNodeSet.size()];
311: int i = 0;
312: for (DefaultMutableTreeNode curNode : problemNodeSet) {
313: problems[i++] = (Problem) curNode.getUserObject();
314: }
315:
316: return problems;
317: }
318:
319: class ProblemListenerImpl implements ProblemListener {
320: public void problemOccured(Problem problem) {
321: addProblem(problem);
322: }
323: }
324:
325: class ModelPropertyChangeListener implements PropertyChangeListener {
326: public void propertyChange(PropertyChangeEvent evt) {
327: if ("monitorViolations".equals(evt.getPropertyName())) {
328: chbEDTViolations.setSelected((Boolean) evt
329: .getNewValue());
330: } else if ("minimalMonitoredHangTime".equals(evt
331: .getPropertyName())) {
332: spnDelay.setValue(evt.getNewValue());
333: } else if ("monitorDelays".equals(evt.getPropertyName())) {
334: chbDelays.setSelected((Boolean) evt.getNewValue());
335: spnDelay.setEnabled((Boolean) evt.getNewValue());
336: }
337: }
338: }
339: }
340:
341: /*
342: * $Log: PNLEDTMonitor.java,v $
343: * Revision 1.1 2008/03/07 11:46:52 maxz1
344: * Added thread violation monitor and EDT hang monitor. Changed L & F.
345: *
346: */
|