001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package javax.microedition.lcdui;
028:
029: /* import javax.microedition.lcdui.KeyConverter; */
030: import java.util.Vector;
031: import java.util.Enumeration;
032:
033: import com.sun.midp.configurator.Constants;
034:
035: /**
036: * Look and feel implementation of <code>Canvas</code> based on
037: * platform widget.
038: */
039: class CanvasLFImpl extends DisplayableLFImpl implements CanvasLF {
040:
041: /**
042: * LF implementation of <code>Canvas</code>.
043: * @param canvas the <code>Canvas</code> associated with this
044: * <code>CanvasLFImpl</code>
045: */
046: CanvasLFImpl(Canvas canvas) {
047: super (canvas);
048:
049: this .canvas = canvas;
050: }
051:
052: // ************************************************************
053: // public methods - CanvasLF interface implementation
054: // ************************************************************
055:
056: /**
057: * Notifies look & feel object that repaint of a (x, y, width, height)
058: * area is needed.
059: *
060: * SYNC NOTE: The caller of this method handles synchronization.
061: *
062: * @param x The x coordinate of the region to repaint
063: * @param y The y coordinate of the region to repaint
064: * @param width The width of the region to repaint
065: * @param height The height of the region to repaint
066: * @param target an optional paint target to receive the paint request
067: * when it returns via callPaint()
068: */
069: public void lRepaint(int x, int y, int width, int height,
070: Object target) {
071: lRequestPaint(x, y, width, height, target);
072: }
073:
074: /**
075: * Notifies that repaint of the entire <code>Canvas</code> look&feel
076: * is needed.
077: * Repaints the viewport area.
078: *
079: * SYNC NOTE: The caller of this method handles synchronization.
080: */
081: public void lRepaint() {
082: lRequestPaintContents();
083: }
084:
085: /**
086: * Request serviceRepaints from current <code>Display</code>.
087: * SYNC NOTE: Unlike most other LF methods, no locking is held when
088: * this function is called because <code>Display.serviceRepaints()</code>
089: * needs to handle its own locking.
090: */
091: public void uServiceRepaints() {
092: // Avoid locking by making a copy of currentDisplay
093: // -- an atomic operation -- before testing and using it.
094: Display d = currentDisplay;
095:
096: if (d != null) {
097: d.serviceRepaints(this );
098: }
099: }
100:
101: /**
102: * Notify this <code>Canvas</code> that it is being shown on the
103: * given <code>Display</code>.
104: */
105: public void uCallShow() {
106:
107: // Create native resource with title and ticker
108: super .uCallShow();
109:
110: // Notify the canvas subclass before showing native resource
111: synchronized (Display.calloutLock) {
112: try {
113: canvas.showNotify();
114: /* For MMAPI VideoControl in a Canvas */
115: if (mmHelper != null) {
116: for (Enumeration e = embeddedVideos.elements(); e
117: .hasMoreElements();) {
118: mmHelper.showVideo(e.nextElement());
119: }
120: }
121: } catch (Throwable t) {
122: Display.handleThrowable(t);
123: }
124: }
125:
126: }
127:
128: /**
129: * Notify this <code>Canvas</code> that it is being hidden on the
130: * given <code>Display</code>.
131: */
132: public void uCallHide() {
133:
134: int oldState = state;
135:
136: // Delete native resources including title and ticker
137: super .uCallHide();
138:
139: // Notify canvas subclass after hiding the native resource
140: synchronized (Display.calloutLock) {
141: if (oldState == SHOWN) {
142: try {
143: canvas.hideNotify();
144: /* For MMAPI VideoControl in a Canvas */
145: if (mmHelper != null) {
146: for (Enumeration e = embeddedVideos.elements(); e
147: .hasMoreElements();) {
148: mmHelper.hideVideo(e.nextElement());
149: }
150: }
151: } catch (Throwable t) {
152: Display.handleThrowable(t);
153: }
154: }
155: }
156: }
157:
158: /**
159: * Notify this <code>Canvas</code> that it is being frozen on the
160: * given <code>Display</code>.
161: */
162:
163: public void uCallFreeze() {
164:
165: int oldState = state;
166:
167: // Delete native resources including title and ticker
168: super .uCallFreeze();
169:
170: // Notify canvas subclass after hiding the native resource
171: synchronized (Display.calloutLock) {
172: if (oldState == SHOWN) {
173: try {
174: canvas.hideNotify();
175: // For MMAPI VideoControl in a Canvas
176: if (mmHelper != null) {
177: for (Enumeration e = embeddedVideos.elements(); e
178: .hasMoreElements();) {
179: mmHelper.hideVideo(e.nextElement());
180: }
181: }
182: } catch (Throwable t) {
183: Display.handleThrowable(t);
184: }
185: }
186: }
187: }
188:
189: /**
190: * Paint this <code>Canvas</code>.
191: *
192: * @param g the <code>Graphics</code> to paint to
193: * @param target the target Object of this repaint
194: */
195: public void uCallPaint(Graphics g, Object target) {
196: super .uCallPaint(g, target);
197:
198: // We prevent the Canvas from drawing outside of the
199: // allowable viewport.
200: // We also need to preserve the original translation.
201: // g.preserveMIDPRuntimeGC(x, y, WIDTH, HEIGHT);
202:
203: // Reset the graphics context according to the spec. requirement.
204: // This is a must before we call canvas's paint(g) since the
205: // title or ticker drawing routines may change the GC before.
206: g.resetGC();
207:
208: try {
209: synchronized (Display.calloutLock) {
210: canvas.paint(g);
211: }
212: } catch (Throwable t) {
213: Display.handleThrowable(t);
214: }
215:
216: // If there are any video players in this canvas,
217: // let the helper class invoke video rendering
218: // Update frames of any video players displayed on this Canvas
219: if (mmHelper != null) {
220: for (Enumeration e = embeddedVideos.elements(); e
221: .hasMoreElements();) {
222: mmHelper.paintVideo(e.nextElement(), g);
223: }
224: }
225: // g.restoreMIDPRuntimeGC();
226: }
227:
228: // ************************************************************
229: // package private methods
230: // ************************************************************
231:
232: /**
233: * Handle a key press.
234: *
235: * @param keyCode The key that was pressed
236: */
237: void uCallKeyPressed(int keyCode) {
238: if (allowKey(keyCode)) {
239: synchronized (Display.calloutLock) {
240: try {
241: canvas.keyPressed(keyCode);
242: } catch (Throwable t) {
243: Display.handleThrowable(t);
244: }
245: }
246: }
247: }
248:
249: /**
250: * Handle a key release.
251: *
252: * @param keyCode The key that was released
253: */
254: void uCallKeyReleased(int keyCode) {
255: if (allowKey(keyCode)) {
256: synchronized (Display.calloutLock) {
257: try {
258: canvas.keyReleased(keyCode);
259: } catch (Throwable t) {
260: Display.handleThrowable(t);
261: }
262: }
263: }
264: }
265:
266: /**
267: * Handle a repeated key press.
268: *
269: * @param keyCode The key that was pressed
270: */
271: void uCallKeyRepeated(int keyCode) {
272: if (allowKey(keyCode)) {
273: synchronized (Display.calloutLock) {
274: try {
275: canvas.keyRepeated(keyCode);
276: } catch (Throwable t) {
277: Display.handleThrowable(t);
278: }
279: }
280: }
281: }
282:
283: /**
284: * Handle a pointer press event.
285: *
286: * @param x The x coordinate of the press
287: * @param y The y coordinate of the press
288: */
289: void uCallPointerPressed(int x, int y) {
290: synchronized (Display.calloutLock) {
291: try {
292: canvas.pointerPressed(x, y);
293: } catch (Throwable t) {
294: Display.handleThrowable(t);
295: }
296: }
297: }
298:
299: /**
300: * Handle a pointer release event.
301: *
302: * @param x The x coordinate of the release
303: * @param y The y coordinate of the release
304: */
305: void uCallPointerReleased(int x, int y) {
306: synchronized (Display.calloutLock) {
307: try {
308: canvas.pointerReleased(x, y);
309: } catch (Throwable t) {
310: Display.handleThrowable(t);
311: }
312: }
313: }
314:
315: /**
316: * Handle a pointer drag event.
317: *
318: * @param x The x coordinate of the drag
319: * @param y The y coordinate of the drag
320: */
321: void uCallPointerDragged(int x, int y) {
322: synchronized (Display.calloutLock) {
323: try {
324: canvas.pointerDragged(x, y);
325: } catch (Throwable t) {
326: Display.handleThrowable(t);
327: }
328: }
329: }
330:
331: /**
332: * Add embedded video player.
333: * This is called by <code>MMHelperImpl</code>, whenever a video
334: * player joins this canvas.
335: *
336: * @param video The player joining this canvas.
337: */
338: void addEmbeddedVideo(Object video) {
339: embeddedVideos.addElement(video);
340: }
341:
342: /**
343: * Remove embedded video player.
344: * This is called by <code>MMHelperImpl</code>, whenever a video
345: * player leaves this canvas.
346: *
347: * @param video The player leaving this canvas.
348: */
349: void removeEmbeddedVideo(Object video) {
350: embeddedVideos.removeElement(video);
351: }
352:
353: // ************************************************************
354: // private methods
355: // ************************************************************
356:
357: /**
358: * Test to see if the given keyCode should be sent to
359: * the application.
360: *
361: * @param keyCode the key code to pass to the application
362: *
363: * @return true if the key should be allowed
364: */
365: private boolean allowKey(int keyCode) {
366: if (!canvas.suppressKeyEvents) {
367: return true;
368: }
369:
370: switch (KeyConverter.getGameAction(keyCode)) {
371: case -1:
372: // Invalid keycode, don't block this key.
373: return true;
374: case Canvas.UP:
375: case Canvas.DOWN:
376: case Canvas.LEFT:
377: case Canvas.RIGHT:
378: case Canvas.FIRE:
379: case Canvas.GAME_A:
380: case Canvas.GAME_B:
381: case Canvas.GAME_C:
382: case Canvas.GAME_D:
383: // don't generate key events for the defined game keys
384: return false;
385: default:
386: return true;
387: }
388: }
389:
390: /**
391: * Create and show native resource for this <code>Canvas</code>.
392: */
393: void createNativeResource() {
394: nativeId = createNativeResource0(canvas.title,
395: canvas.ticker == null ? null : canvas.ticker
396: .getString());
397: }
398:
399: /**
400: * Create and show native resource for this <code>Canvas</code>.
401: * @param title title of the canvas
402: * @param tickerText text for the ticker
403: * @return native resource ID
404: */
405: private native int createNativeResource0(String title,
406: String tickerText);
407:
408: /**
409: * <code>Canvas</code> being stored in this object.
410: */
411: Canvas canvas;
412:
413: /**
414: * A vector of embedded video players.
415: */
416: private Vector embeddedVideos = new Vector(1);
417:
418: /**
419: * The <code>MMHelperImpl</code> instance.
420: */
421: private static MMHelperImpl mmHelper = MMHelperImpl.getInstance();
422:
423: }
|