JOGL v2.6.0-rc-20250712
JOGL, High-Performance Graphics Binding for Java™ (public API).
DemoBug910ExtendedAWTAppletLifecycleCheck.java
Go to the documentation of this file.
1/**
2 * Copyright 2013 JogAmp Community. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification, are
5 * permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * The views and conclusions contained in the software and documentation are those of the
25 * authors and should not be interpreted as representing official policies, either expressed
26 * or implied, of JogAmp Community.
27 */
28package com.jogamp.opengl.test.bugs;
29
30import java.applet.Applet;
31import java.awt.BorderLayout;
32import java.awt.Canvas;
33import java.awt.Color;
34import java.awt.Component;
35import java.awt.EventQueue;
36import java.awt.Graphics;
37import java.lang.reflect.InvocationTargetException;
38import java.util.concurrent.atomic.AtomicInteger;
39
40@SuppressWarnings("serial")
41public class DemoBug910ExtendedAWTAppletLifecycleCheck extends Applet {
42
43 private static String currentThreadName() { return "["+Thread.currentThread().getName()+", isAWT-EDT "+EventQueue.isDispatchThread()+"]"; }
44
45 private static void invoke(final boolean wait, final Runnable r) {
46 if(EventQueue.isDispatchThread()) {
47 r.run();
48 } else {
49 try {
50 if(wait) {
51 EventQueue.invokeAndWait(r);
52 } else {
53 EventQueue.invokeLater(r);
54 }
55 } catch (final InvocationTargetException e) {
56 throw new RuntimeException(e.getTargetException());
57 } catch (final InterruptedException e) {
58 throw new RuntimeException(e);
59 }
60 }
61 }
62
63 private static final String comp2Str(final Component c) {
64 return c.getClass().getSimpleName()+"[visible "+c.isVisible()+", showing "+c.isShowing()+", valid "+c.isValid()+
65 ", displayable "+c.isDisplayable()+", "+c.getX()+"/"+c.getY()+" "+c.getWidth()+"x"+c.getHeight()+"]";
66 }
67
68 private void println(final String msg) {
69 System.err.println(msg);
70 }
71
72 private final void checkComponentState(final String msg, final boolean expIsContained, final int expAddNotifyCount, final int expRemoveNotifyCount) {
73 final int compCount = getComponentCount();
74 final Component c = 1 <= compCount ? getComponent(0) : null;
75 final String clazzName = null != c ? c.getName() : "n/a";
76 final boolean isContained = c == myCanvas;
77 final String okS = ( expIsContained == isContained &&
78 expAddNotifyCount == myCanvas.addNotifyCount &&
79 expRemoveNotifyCount == myCanvas.removeNotifyCount ) ? "OK" : "ERROR";
80 println("Component-State @ "+msg+": "+okS+
81 ", contained[exp "+expIsContained+", has "+isContained+"]"+(expIsContained!=isContained?"*":"")+
82 ", addNotify[exp "+expAddNotifyCount+", has "+myCanvas.addNotifyCount+"]"+(expAddNotifyCount!=myCanvas.addNotifyCount?"*":"")+
83 ", removeNotify[exp "+expRemoveNotifyCount+", has "+myCanvas.removeNotifyCount+"]"+(expRemoveNotifyCount!=myCanvas.removeNotifyCount?"*":"")+
84 ", compCount "+compCount+", compClazz "+clazzName);
85 }
86
87 AtomicInteger initCount = new AtomicInteger(0);
88 AtomicInteger startCount = new AtomicInteger(0);
89 AtomicInteger stopCount = new AtomicInteger(0);
90 AtomicInteger destroyCount = new AtomicInteger(0);
91
92 private final void checkAppletState(final String msg, final boolean expIsActive,
93 final int expInitCount, final int expStartCount, final int expStopCount, final boolean startStopCountEquals, final int expDestroyCount) {
94 final boolean isActive = this.isActive();
95 final String okS = ( expInitCount == initCount.get() &&
96 expIsActive == isActive &&
97 expStartCount == startCount.get() &&
98 expStopCount == stopCount.get() &&
99 expDestroyCount == destroyCount.get() &&
100 ( !startStopCountEquals || startCount == stopCount ) ) ? "OK" : "ERROR";
101 println("Applet-State @ "+msg+": "+okS+
102 ", active[exp "+expIsActive+", has "+isActive+"]"+(expIsActive!=isActive?"*":"")+
103 ", init[exp "+expInitCount+", has "+initCount+"]"+(expInitCount!=initCount.get()?"*":"")+
104 ", start[exp "+expStartCount+", has "+startCount+"]"+(expStartCount!=startCount.get()?"*":"")+
105 ", stop[exp "+expStopCount+", has "+stopCount+"]"+(expStopCount!=stopCount.get()?"*":"")+
106 ", start==stop[exp "+startStopCountEquals+", start "+startCount+", stop "+stopCount+"]"+(( startStopCountEquals && startCount != stopCount )?"*":"")+
107 ", destroy[exp "+expDestroyCount+", has "+destroyCount+"]"+(expDestroyCount!=destroyCount.get()?"*":""));
108 }
109
110 private class MyCanvas extends Canvas {
111 int addNotifyCount = 0;
112 int removeNotifyCount = 0;
113 int paintCount = 0;
114
115 MyCanvas() {
116 setBackground( new Color( 200, 200, 255 ) );
117 }
118
119 public String toString() {
120 return comp2Str(this)+", add/remove[addNotify "+addNotifyCount+", removeCount "+removeNotifyCount+"]";
121 }
122
123 @Override
124 public void addNotify() {
125 addNotifyCount++;
126 println("Applet.Canvas.addNotify() - "+currentThreadName());
127 if( !EventQueue.isDispatchThread() ) {
128 println("Applet.Canvas.addNotify() ERROR: Not on AWT-EDT");
129 }
130 // Thread.dumpStack();
131 super.addNotify();
132 println("Applet.Canvas.addNotify(): "+this);
133 }
134
135 @Override
136 public void removeNotify() {
137 removeNotifyCount++;
138 println("Applet.Canvas.removeNotify() - "+currentThreadName());
139 println("Applet.Canvas.removeNotify(): "+this);
140 if( !EventQueue.isDispatchThread() ) {
141 println("Applet.Canvas.removeNotify() ERROR: Not on AWT-EDT");
142 }
143 // Thread.dumpStack();
144 super.removeNotify();
145 }
146
147 @Override
148 public void paint(final Graphics g) {
149 super.paint(g);
150 paintCount++;
151 final int width = getWidth();
152 final int height = getHeight();
153 final String msg = "The payload Canvas. Paint "+width+"x"+height+" #"+paintCount;
154 g.setColor(Color.black);
155 g.drawString(msg, 64, 64);
156 }
157 }
158 MyCanvas myCanvas = null;
159
160 @Override
161 public void init() {
162 final java.awt.Dimension aSize = getSize();
163 println("Applet.init() START - applet.size "+aSize+" - "+currentThreadName());
164 initCount.incrementAndGet();
165 checkAppletState("init", false /* expIsActive */, 1 /* expInitCount */,
166 0 /* expStartCount */, 0 /* expStopCount */, true /* startStopCountEquals */,
167 0 /* expDestroyCount */);
168 invoke(true, new Runnable() {
169 public void run() {
170 setLayout(new BorderLayout());
171 myCanvas = new MyCanvas();
172 println("Applet.init(): self "+comp2Str(DemoBug910ExtendedAWTAppletLifecycleCheck.this));
173 println("Applet.init(): canvas "+comp2Str(myCanvas));
174 checkComponentState("init-add.pre", false, 0, 0);
175 add(myCanvas, BorderLayout.CENTER);
176 validate();
177 checkComponentState("init-add.post", true, 1, 0);
178 println("Applet.init(): canvas "+comp2Str(myCanvas));
179 } } );
180 println("Applet.init() END - "+currentThreadName());
181 }
182
183 @Override
184 public void start() {
185 println("Applet.start() START (isVisible "+isVisible()+", isDisplayable "+isDisplayable()+") - "+currentThreadName());
186 startCount.incrementAndGet();
187 checkAppletState("start", true /* expIsActive */, 1 /* expInitCount */,
188 startCount.get() /* expStartCount */, startCount.get()-1 /* expStopCount */, false /* startStopCountEquals */,
189 0 /* expDestroyCount */);
190 invoke(true, new Runnable() {
191 public void run() {
192 checkComponentState("start-visible.pre", true, 1, 0);
193 if( null != myCanvas ) {
194 myCanvas.setFocusable(true);
195 myCanvas.requestFocus();
196 }
197 checkComponentState("start-visible.post", true, 1, 0);
198 println("Applet.start(): self "+comp2Str(DemoBug910ExtendedAWTAppletLifecycleCheck.this));
199 println("Applet.start(): canvas "+comp2Str(myCanvas));
200 }
201 });
202 println("Applet.start() END - "+currentThreadName());
203 }
204
205 @Override
206 public void stop() {
207 println("Applet.stop() START - "+currentThreadName());
208 stopCount.incrementAndGet();
209 checkAppletState("stop", false /* expIsActive */, 1 /* expInitCount */,
210 stopCount.get() /* expStartCount */, stopCount.get() /* expStopCount */, true /* startStopCountEquals */,
211 0 /* expDestroyCount */);
212 invoke(true, new Runnable() {
213 public void run() {
214 checkComponentState("stop", true, 1, 0);
215 } } );
216 println("Applet.stop() END - "+currentThreadName());
217 }
218
219 @Override
220 public void destroy() {
221 println("Applet.destroy() START - "+currentThreadName());
222 destroyCount.incrementAndGet();
223 checkAppletState("destroy", false /* expIsActive */, 1 /* expInitCount */,
224 startCount.get() /* expStartCount */, stopCount.get() /* expStopCount */, true /* startStopCountEquals */,
225 1 /* expDestroyCount */);
226 invoke(true, new Runnable() {
227 public void run() {
228 checkComponentState("destroy-remove.pre", true, 1, 0);
229 remove(myCanvas);
230 checkComponentState("destroy-remove.post", false, 1, 1);
231 } } );
232 println("Applet.destroy() END - "+currentThreadName());
233 }
234}
235