source: josm/trunk/src/org/jdesktop/swinghelper/debug/CheckThreadViolationRepaintManager.java@ 8961

Last change on this file since 8961 was 4728, checked in by jttt, 12 years ago

Fix #7192: compile error

File size: 6.2 KB
Line 
1/*
2 * This library is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2.1 of the License, or (at your option) any later version.
6 *
7 * This library is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with this library; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
15 */
16
17package org.jdesktop.swinghelper.debug;
18
19import java.lang.ref.WeakReference;
20
21import javax.swing.JButton;
22import javax.swing.JComponent;
23import javax.swing.JEditorPane;
24import javax.swing.JFrame;
25import javax.swing.RepaintManager;
26import javax.swing.SwingUtilities;
27
28/**
29 * <p>This class is used to detect Event Dispatch Thread rule violations<br>
30 * See <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html">How to Use Threads</a>
31 * for more info</p>
32 * <p/>
33 * <p>This is a modification of original idea of Scott Delap<br>
34 * Initial version of ThreadCheckingRepaintManager can be found here<br>
35 * <a href="http://www.clientjava.com/blog/2004/08/20/1093059428000.html">Easily Find Swing Threading Mistakes</a>
36 * </p>
37 *
38 * @author Scott Delap
39 * @author Alexander Potochkin
40 *
41 * https://swinghelper.dev.java.net/
42 */
43public class CheckThreadViolationRepaintManager extends RepaintManager {
44 // it is recommended to pass the complete check
45 private boolean completeCheck = true;
46 private WeakReference<JComponent> lastComponent;
47
48 public CheckThreadViolationRepaintManager(boolean completeCheck) {
49 this.completeCheck = completeCheck;
50 }
51
52 public CheckThreadViolationRepaintManager() {
53 this(true);
54 }
55
56 public boolean isCompleteCheck() {
57 return completeCheck;
58 }
59
60 public void setCompleteCheck(boolean completeCheck) {
61 this.completeCheck = completeCheck;
62 }
63
64 @Override
65 public synchronized void addInvalidComponent(JComponent component) {
66 checkThreadViolations(component);
67 super.addInvalidComponent(component);
68 }
69
70 @Override
71 public void addDirtyRegion(JComponent component, int x, int y, int w, int h) {
72 checkThreadViolations(component);
73 super.addDirtyRegion(component, x, y, w, h);
74 }
75
76 private void checkThreadViolations(JComponent c) {
77 if (!SwingUtilities.isEventDispatchThread() && (completeCheck || c.isShowing())) {
78 boolean repaint = false;
79 boolean fromSwing = false;
80 boolean imageUpdate = false;
81 StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
82 for (StackTraceElement st : stackTrace) {
83 if (repaint && st.getClassName().startsWith("javax.swing.") &&
84 // for details see
85 // https://swinghelper.dev.java.net/issues/show_bug.cgi?id=1
86 !st.getClassName().startsWith("javax.swing.SwingWorker")) {
87 fromSwing = true;
88 }
89 if (repaint && "imageUpdate".equals(st.getMethodName())) {
90 imageUpdate = true;
91 }
92 if ("repaint".equals(st.getMethodName())) {
93 repaint = true;
94 fromSwing = false;
95 }
96 }
97 if (imageUpdate)
98 //assuming it is java.awt.image.ImageObserver.imageUpdate(...)
99 //image was asynchronously updated, that's ok
100 return;
101 if (repaint && !fromSwing)
102 //no problems here, since repaint() is thread safe
103 return;
104 //ignore the last processed component
105 if (lastComponent != null && c == lastComponent.get())
106 return;
107 lastComponent = new WeakReference<JComponent>(c);
108 violationFound(c, stackTrace);
109 }
110 }
111
112 protected void violationFound(JComponent c, StackTraceElement[] stackTrace) {
113 System.out.println();
114 System.out.println("EDT violation detected");
115 System.out.println(c);
116 for (StackTraceElement st : stackTrace) {
117 System.out.println("\tat " + st);
118 }
119 }
120
121 public static void main(String[] args) throws Exception {
122 //set CheckThreadViolationRepaintManager
123 RepaintManager.setCurrentManager(new CheckThreadViolationRepaintManager());
124 //Valid code
125 SwingUtilities.invokeAndWait(new Runnable() {
126 public void run() {
127 test();
128 }
129 });
130 System.out.println("Valid code passed...");
131 repaintTest();
132 System.out.println("Repaint test - correct code");
133 //Invalide code (stack trace expected)
134 test();
135 }
136
137 static void test() {
138 JFrame frame = new JFrame("Am I on EDT?");
139 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
140 frame.add(new JButton("JButton"));
141 frame.pack();
142 frame.setVisible(true);
143 frame.dispose();
144 }
145
146 //this test must pass
147 static void imageUpdateTest() {
148 JFrame frame = new JFrame();
149 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
150 JEditorPane editor = new JEditorPane();
151 frame.setContentPane(editor);
152 editor.setContentType("text/html");
153 //it works with no valid image as well
154 editor.setText("<html><img src=\"file:\\lala.png\"></html>");
155 frame.setSize(300, 200);
156 frame.setVisible(true);
157 }
158
159 private static JButton test;
160 static void repaintTest() {
161 try {
162 SwingUtilities.invokeAndWait(new Runnable() {
163 public void run() {
164 test = new JButton();
165 test.setSize(100, 100);
166 }
167 });
168 } catch (Exception e) {
169 e.printStackTrace();
170 }
171 // repaint(Rectangle) should be ok
172 test.repaint(test.getBounds());
173 test.repaint(0, 0, 100, 100);
174 test.repaint();
175 }
176}
Note: See TracBrowser for help on using the repository browser.