Source code: javax/microedition/lcdui/Display.java
1 /*
2 * MicroEmulator
3 * Copyright (C) 2001 Bartek Teodorczyk <barteo@it.pl>
4 *
5 * This library is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU Lesser General Public License as published by the
7 * Free Software Foundation; either version 2.1 of the License, or (at your
8 * option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 * for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this library; if not, write to the Free Software Foundation,
17 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * Contributor(s):
20 * 3GLab
21 */
22
23 package javax.microedition.lcdui;
24
25 import java.util.Enumeration;
26 import java.util.Vector;
27
28 import javax.microedition.midlet.MIDlet;
29
30 import com.barteo.emulator.CommandManager;
31 import com.barteo.emulator.DisplayAccess;
32 import com.barteo.emulator.MIDletBridge;
33 import com.barteo.emulator.device.DeviceFactory;
34
35 public class Display
36 {
37 private static EventDispatcher eventDispatcher = null;
38 private static TickerPaint tickerPaint = null;
39
40 private Displayable current = null;
41 private Displayable nextScreen = null;
42
43 private DisplayAccessor accessor = null;
44
45 private Object paintLock = new Object();
46 private boolean repaintPending = false;
47
48 private class DisplayAccessor implements DisplayAccess
49 {
50 Display display;
51
52 DisplayAccessor(Display d)
53 {
54 display = d;
55 }
56
57 public void commandAction(Command cmd)
58 {
59 if (current == null) {
60 return;
61 }
62 CommandListener listener = current.getCommandListener();
63 if (listener == null) {
64 return;
65 }
66 listener.commandAction(cmd, current);
67 }
68
69 public Display getDisplay()
70 {
71 return display;
72 }
73
74 public void keyPressed(int keyCode)
75 {
76 if (current != null) {
77 current.keyPressed(keyCode);
78 }
79 }
80
81 public void keyReleased(int keyCode)
82 {
83 if (current != null) {
84 current.keyReleased(keyCode);
85 }
86 }
87
88 public void paint(Graphics g)
89 {
90 if (current != null) {
91 current.paint(g);
92 g.translate(-g.getTranslateX(), -g.getTranslateY());
93 synchronized (paintLock) {
94 repaintPending = false;
95 paintLock.notify();
96 }
97 }
98 }
99
100 public Displayable getCurrent()
101 {
102 return getDisplay().getCurrent();
103 }
104
105 public void setCurrent(Displayable d)
106 {
107 getDisplay().setCurrent(d);
108 }
109
110 public void updateCommands()
111 {
112 getDisplay().updateCommands();
113 }
114
115 public void clean()
116 {
117 if (current != null) {
118 current.hideNotify();
119 }
120 }
121 }
122
123 private class AlertTimeout implements Runnable
124 {
125 int time;
126
127 AlertTimeout(int time)
128 {
129 this.time = time;
130 }
131
132 public void run()
133 {
134 try {
135 Thread.sleep(time);
136 } catch (InterruptedException ex) {
137 ex.printStackTrace();
138 }
139
140 setCurrent(nextScreen);
141 }
142 }
143
144 private class TickerPaint implements Runnable
145 {
146 private Display currentDisplay = null;
147
148 public void setCurrentDisplay(Display currentDisplay)
149 {
150 this.currentDisplay = currentDisplay;
151 }
152
153 public void run()
154 {
155 while (true) {
156 if (currentDisplay != null && currentDisplay.current != null && currentDisplay.current instanceof Screen) {
157 Ticker ticker = ((Screen) currentDisplay.current).getTicker();
158 if (ticker != null) {
159 synchronized (ticker) {
160 if (ticker.resetTextPosTo != -1) {
161 ticker.textPos = ticker.resetTextPosTo;
162 ticker.resetTextPosTo = -1;
163 }
164 ticker.textPos -= Ticker.PAINT_MOVE;
165 }
166 currentDisplay.repaint();
167 }
168 }
169 try {
170 Thread.sleep(Ticker.PAINT_TIMEOUT);
171 } catch (InterruptedException ex) {
172 ex.printStackTrace();
173 tickerPaint = null;
174 }
175 }
176 }
177 }
178
179 private class EventDispatcher implements Runnable
180 {
181 private Vector events = new Vector();
182
183 public void add(Runnable r)
184 {
185 synchronized (paintLock) {
186 events.addElement(r);
187 paintLock.notify();
188 }
189 }
190
191 public void run()
192 {
193 Vector jobs;
194
195 while (true) {
196 jobs = null;
197 synchronized (paintLock) {
198 if (!repaintPending) {
199 if (events.size() > 0) {
200 jobs = (Vector) events.clone();
201 events.removeAllElements();
202 }
203 }
204 }
205
206 if (jobs != null) {
207 for (Enumeration en = jobs.elements(); en.hasMoreElements();) {
208 ((Runnable) en.nextElement()).run();
209 }
210 }
211
212 try {
213 synchronized (paintLock) {
214 if (events.size() == 0) {
215 paintLock.wait();
216 }
217 }
218 } catch (InterruptedException ex) {
219 ex.printStackTrace();
220 eventDispatcher = null;
221 }
222 }
223 }
224 }
225
226
227 Display()
228 {
229 accessor = new DisplayAccessor(this);
230
231 if (eventDispatcher == null) {
232 eventDispatcher = new EventDispatcher();
233 new Thread(eventDispatcher, "EventDispatcher").start();
234 }
235 if (tickerPaint == null) {
236 tickerPaint = new TickerPaint();
237 new Thread(tickerPaint, "TickerPaint").start();
238 }
239 }
240
241
242 public void callSerially(Runnable r)
243 {
244 eventDispatcher.add(r);
245 }
246
247
248 public int numColors()
249 {
250 return DeviceFactory.getDevice().getDeviceDisplay().numColors();
251 }
252
253
254 public static Display getDisplay(MIDlet m)
255 {
256 Display result;
257
258 if (MIDletBridge.getMIDletAccess(m).getDisplayAccess() == null) {
259 result = new Display();
260 MIDletBridge.getMIDletAccess(m).setDisplayAccess(result.accessor);
261 } else {
262 result = MIDletBridge.getMIDletAccess(m).getDisplayAccess().getDisplay();
263 }
264
265 tickerPaint.setCurrentDisplay(result);
266
267 return result;
268 }
269
270
271 public Displayable getCurrent()
272 {
273 return current;
274 }
275
276
277 public boolean isColor()
278 {
279 return DeviceFactory.getDevice().getDeviceDisplay().isColor();
280 }
281
282
283 public void setCurrent(Displayable nextDisplayable)
284 {
285 if (nextDisplayable != null) {
286 if (current != null) {
287 current.hideNotify(this);
288 }
289
290 if (nextDisplayable instanceof Alert) {
291 setCurrent((Alert) nextDisplayable, current);
292 return;
293 }
294
295 current = nextDisplayable;
296 current.showNotify(this);
297 setScrollUp(false);
298 setScrollDown(false);
299 updateCommands();
300
301 current.repaint();
302 }
303 }
304
305
306 public void setCurrent(Alert alert, Displayable nextDisplayable)
307 {
308 nextScreen = nextDisplayable;
309
310 current = alert;
311
312 current.showNotify(this);
313 updateCommands();
314 current.repaint();
315
316 if (alert.getTimeout() != Alert.FOREVER) {
317 AlertTimeout at = new AlertTimeout(alert.getTimeout());
318 Thread t = new Thread(at);
319 t.start();
320 }
321 }
322
323
324 void clearAlert()
325 {
326 setCurrent(nextScreen);
327 }
328
329
330 static int getGameAction(int keyCode)
331 {
332 return DeviceFactory.getDevice().getGameAction(keyCode);
333 }
334
335
336 static int getKeyCode(int gameAction)
337 {
338 return DeviceFactory.getDevice().getKeyCode(gameAction);
339 }
340
341
342 boolean isShown(Displayable d)
343 {
344 if (current == null || current != d) {
345 return false;
346 } else {
347 return true;
348 }
349 }
350
351
352 void repaint(Displayable d)
353 {
354 if (current == d) {
355 synchronized (paintLock) {
356 repaintPending = true;
357 }
358 DeviceFactory.getDevice().getDeviceDisplay().repaint();
359 }
360 }
361
362
363 void setScrollDown(boolean state)
364 {
365 DeviceFactory.getDevice().getDeviceDisplay().setScrollDown(state);
366 }
367
368
369 void setScrollUp(boolean state)
370 {
371 DeviceFactory.getDevice().getDeviceDisplay().setScrollUp(state);
372 }
373
374
375 void updateCommands()
376 {
377 if (current == null) {
378 CommandManager.getInstance().updateCommands(null);
379 } else {
380 CommandManager.getInstance().updateCommands(current.getCommands());
381 }
382 /**
383 * updateCommands has changed the softkey labels tell the outside world
384 * it has happened.
385 */
386 MIDletBridge.notifySoftkeyLabelsChanged();
387 repaint();
388 }
389
390
391 private void repaint()
392 {
393 if (current != null) {
394 repaint(current);
395 }
396 }
397
398 }