0001: /*
0002: *
0003: *
0004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
0005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
0006: *
0007: * This program is free software; you can redistribute it and/or
0008: * modify it under the terms of the GNU General Public License version
0009: * 2 only, as published by the Free Software Foundation.
0010: *
0011: * This program is distributed in the hope that it will be useful, but
0012: * WITHOUT ANY WARRANTY; without even the implied warranty of
0013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014: * General Public License version 2 for more details (a copy is
0015: * included at /legal/license.txt).
0016: *
0017: * You should have received a copy of the GNU General Public License
0018: * version 2 along with this work; if not, write to the Free Software
0019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
0020: * 02110-1301 USA
0021: *
0022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0023: * Clara, CA 95054 or visit www.sun.com if you need additional
0024: * information or have any questions.
0025: */
0026:
0027: package javax.microedition.lcdui;
0028:
0029: /* import javax.microedition.lcdui.KeyConverter; */
0030:
0031: import javax.microedition.lcdui.game.GameCanvas;
0032: import com.sun.midp.lcdui.EventConstants;
0033: import com.sun.midp.lcdui.GameMap;
0034: import com.sun.midp.lcdui.GameCanvasLFImpl;
0035: import com.sun.midp.log.Logging;
0036: import com.sun.midp.log.LogChannels;
0037: import com.sun.midp.configurator.Constants;
0038:
0039: /**
0040: * The look and feel implementation of <code>Displayable</code> based
0041: * on platform widget.
0042: */
0043: abstract class DisplayableLFImpl implements DisplayableLF {
0044:
0045: /** Static initializer. */
0046: static {
0047: initialize0();
0048: }
0049:
0050: /**
0051: * Native class initializer.
0052: */
0053: private static native void initialize0();
0054:
0055: /**
0056: * Creates <code>DisplayableLF</code> for the passed in
0057: * <code>Displayable</code>.
0058: *
0059: * @param d the <code>Displayable</code> object associated with this
0060: * look & feel.
0061: */
0062: DisplayableLFImpl(Displayable d) {
0063: owner = d;
0064: width = Display.WIDTH;
0065: height = Display.HEIGHT;
0066: }
0067:
0068: /**
0069: * Native finalizer to delete native resources.
0070: */
0071: private native void finalize();
0072:
0073: // ************************************************************
0074: // public methods - DisplayableLF interface implementation
0075: // ************************************************************
0076:
0077: /**
0078: * Implement public API isShown().
0079: *
0080: * @return true if current <code>DisplayableLF</code> is interactive
0081: * with user.
0082: */
0083: public boolean lIsShown() {
0084: return (currentDisplay != null) && currentDisplay.isShown(this );
0085: }
0086:
0087: /**
0088: * Get the width in pixels this <code>Displayable</code> is using.
0089: *
0090: * @return width of the area available to the application
0091: */
0092: public int lGetWidth() {
0093: return width;
0094: }
0095:
0096: /**
0097: * Get the height in pixels this <code>Displayable</code> is using.
0098: *
0099: * @return height of the area available to the application
0100: */
0101: public int lGetHeight() {
0102: return height;
0103: }
0104:
0105: /**
0106: * Notifies <code>Displayable</code>'s look & feel object of
0107: * a title change.
0108: *
0109: * SYNC NOTE: The caller of this method handles synchronization.
0110: *
0111: * @param oldTitle the old title, or <code>null</code> for no title
0112: * @param newTitle the new title, or <code>null</code> for no title
0113: */
0114: public void lSetTitle(String oldTitle, String newTitle) {
0115: // No updates are necessary if we are in a full screen mode
0116: if (owner.isInFullScreenMode) {
0117: return;
0118: }
0119: // No update needed if title string is the same object
0120: if (oldTitle == newTitle) {
0121: return;
0122: }
0123: // No update needed if title strings have same content
0124: if (oldTitle != null && newTitle != null
0125: && oldTitle.equals(newTitle)) {
0126: return;
0127: }
0128: // Update only if we have native resource created
0129: if (nativeId != INVALID_NATIVE_ID) {
0130: setTitle0(nativeId, newTitle);
0131: }
0132: }
0133:
0134: /**
0135: * Notifies <code>Displayable</code>'s look & feel object of
0136: * a ticker change.
0137: *
0138: * SYNC NOTE: The caller of this method handles synchronization.
0139: *
0140: * @param oldTicker the old ticker, or <code>null</code> for no ticker
0141: * @param newTicker the new ticker, or <code>null</code> for no ticker
0142: */
0143: public void lSetTicker(Ticker oldTicker, Ticker newTicker) {
0144:
0145: // This method will not be called if oldTicker and
0146: // newTicker are the same (that includes both being null)
0147:
0148: if (owner.ticker != null) {
0149: owner.ticker.tickerLF.lSetOwner(this );
0150: }
0151:
0152: updateNativeTicker(oldTicker, newTicker);
0153: }
0154:
0155: /**
0156: * Notifies look & feel object of a command addition
0157: * to the <code>Displayable</code>.
0158: *
0159: * SYNC NOTE: The caller of this method handles synchronization.
0160: *
0161: * @param cmd the command that was added
0162: * @param i the index of the added command in
0163: * <code>Displayable.commands[]</code> array
0164: */
0165: public void lAddCommand(Command cmd, int i) {
0166: updateCommandSet();
0167: }
0168:
0169: /**
0170: * Notifies look &s; feel object of a command removal
0171: * from the <code>Displayable</code>.
0172: *
0173: * SYNC NOTE: The caller of this method handles synchronization.
0174: *
0175: * @param cmd the command that was removed
0176: * @param i the index of the removed command in
0177: * <code>Displayable.commands[]</code> array
0178: */
0179: public void lRemoveCommand(Command cmd, int i) {
0180: updateCommandSet();
0181: }
0182:
0183: /**
0184: * Updates command set if this <code>Displayable</code> is visible.
0185: *
0186: * SYNC NOTE: Caller must hold LCDUILock around this call.
0187: */
0188: public void updateCommandSet() {
0189: if (state == SHOWN && currentDisplay != null) {
0190: currentDisplay.updateCommandSet();
0191: }
0192: }
0193:
0194: /**
0195: * Return the <code>Display</code> instance in which the LF is
0196: * currently shown.
0197: *
0198: * @return the <code>Display</code> instance in which the LF is shown.
0199: * <code>Null</code> if not shown.
0200: */
0201: public Display lGetCurrentDisplay() {
0202: return currentDisplay;
0203: }
0204:
0205: /**
0206: * Called to get the key mask of all the keys that were pressed.
0207: * Implement an interface function for <code>CanvasLF</code> only.
0208: *
0209: * @return keyMask The key mask of all the keys that were pressed.
0210: */
0211: public int uGetKeyMask() {
0212: synchronized (Display.LCDUILock) {
0213: // don't release currently pressed keys
0214: int savedMaskCopy = stickyKeyMask | currentKeyMask;
0215: stickyKeyMask = 0;
0216: return savedMaskCopy;
0217: }
0218: }
0219:
0220: /**
0221: * Set the display instance the <code>Displayable</code> is associated
0222: * with.
0223: * Caller should hold LCDUILock around this call.
0224: *
0225: * @param d <code>Display</code> instance in which this
0226: * <code>DisplayableLF</code> is visible.
0227: * <code>null</code> if this <code>DisplayableLF</code> is
0228: * no longer visible.
0229: */
0230: public void lSetDisplay(Display d) {
0231: // ASSERT(d == null || currentDisplay == null)
0232: currentDisplay = d;
0233: }
0234:
0235: /**
0236: * Return the associated Displayable object.
0237: *
0238: * SYNC NOTE: Since the <code>Displayable</code> and
0239: * <code>DisplayableLFImpl</code> has 1-to-1 mapping, this function
0240: * can be called from in or outside of LCDUILock.
0241: *
0242: * @return the public model object this LF is associated with.
0243: */
0244: public Displayable lGetDisplayable() {
0245: return owner;
0246: }
0247:
0248: /**
0249: * Notifies look & feel object of a full screen mode change.
0250: *
0251: * @param mode <code>true</code>, if canvas should be displayed
0252: * without title, ticker, etc.; <code>false</code> otherwise
0253: */
0254: public void uSetFullScreenMode(boolean mode) {
0255:
0256: boolean requestRepaint = false;
0257:
0258: synchronized (Display.LCDUILock) {
0259:
0260: if (lIsShown()) {
0261: // currentDisplay is not null when lIsShown is true
0262: currentDisplay.lSetFullScreen(mode);
0263: if (mode) {
0264: setTicker(null);
0265: } else if (owner.ticker != null) {
0266: setTicker(owner.ticker);
0267: }
0268: updateCommandSet();
0269: requestRepaint = true;
0270: }
0271: }
0272: // This may call into app code, so do it outside LCDUILock
0273: uCallSizeChanged(Display.WIDTH, Display.HEIGHT);
0274:
0275: // app's sizeChanged has to be called before repaint
0276: synchronized (Display.LCDUILock) {
0277: if (requestRepaint) {
0278: lRequestPaint();
0279: }
0280: }
0281: }
0282:
0283: /**
0284: * Prepare to show this LF on physical screen.
0285: * This function will set correct screen mode screen mode
0286: * then call lCallShow.
0287: */
0288: public void uCallShow() {
0289:
0290: boolean copyDefferedSizeChange;
0291:
0292: synchronized (Display.LCDUILock) {
0293: // Assure correct screen mode
0294: currentDisplay.lSetFullScreen(owner.isInFullScreenMode);
0295: // display dimentions may change as the resulr of lSetFullScreen
0296: width = Display.WIDTH;
0297: height = Display.HEIGHT;
0298: if (owner.isInFullScreenMode) {
0299: setTicker(null);
0300: } else if (owner.ticker != null) {
0301: setTicker(owner.ticker);
0302: }
0303: copyDefferedSizeChange = defferedSizeChange;
0304: defferedSizeChange = false;
0305: }
0306:
0307: if (copyDefferedSizeChange) {
0308: synchronized (Display.calloutLock) {
0309: try {
0310: owner.sizeChanged(width, height);
0311: } catch (Throwable t) {
0312: Display.handleThrowable(t);
0313: }
0314: }
0315: }
0316:
0317: synchronized (Display.LCDUILock) {
0318: // Do the internal show preparation
0319: lCallShow();
0320: if (pendingInvalidate || copyDefferedSizeChange) {
0321: lRequestInvalidate();
0322: }
0323: }
0324: }
0325:
0326: /**
0327: * Prepare to show this LF on physical screen. This is the
0328: * internal version of showNotify() function as defined in MIDP spec.
0329: * It is called immediately prior to this LF being made visible
0330: * on the display. The LF should load any resource that is
0331: * needed, layout. App's paint() should NOT be called in this function.
0332: * Instead, it should be in the uCallPaint() that will be called on this
0333: * LF shortly after.
0334: *
0335: * This function sets this DisplayableLF to SHOWN state.
0336: */
0337: void lCallShow() {
0338:
0339: // This will suppress drags, repeats and ups until a
0340: // corresponding down is seen.
0341: sawPointerPress = sawKeyPress = false;
0342:
0343: if (state != SHOWN) {
0344: // Create native resource first
0345: // since the title and ticker may depend on it
0346: createNativeResource();
0347: }
0348:
0349: // Start to paint the ticker
0350: updateNativeTicker(null, owner.ticker);
0351:
0352: // set mapping between GameCanvas and DisplayAccess
0353: // set Game key event flag based on value passed in
0354: // GameCanvas constructor.
0355: if (owner instanceof GameCanvas) {
0356: GameMap.registerDisplayAccess(owner,
0357: currentDisplay.accessor);
0358: stickyKeyMask = currentKeyMask = 0;
0359: } else {
0360: // set the keymask to -1 when
0361: // the displayable is not a GameCanvas.
0362: stickyKeyMask = currentKeyMask = -1;
0363: }
0364:
0365: state = SHOWN;
0366: } // lCallShow()
0367:
0368: /**
0369: * Get the current vertical scroll position.
0370: *
0371: * @return int The vertical scroll position on a scale of 0-100
0372: */
0373: public int getVerticalScrollPosition() {
0374: // SYNC NOTE: return of atomic value
0375: return 0;
0376: }
0377:
0378: /**
0379: * Get the current vertical scroll proportion.
0380: *
0381: * @return ing The vertical scroll proportion on a scale of 0-100
0382: */
0383: public int getVerticalScrollProportion() {
0384: // SYNC NOTE: return of atomic value
0385: return 100;
0386: }
0387:
0388: /**
0389: * Remove this <code>Displayable</code> from physical screen.
0390: * This function calls lCallHide after holding LCDUILock
0391: * and sets this DisplayableLF to HIDDEN state.
0392: */
0393: public void uCallHide() {
0394: synchronized (Display.LCDUILock) {
0395: // Delete native resources and update ticker
0396: lCallHide();
0397: // set state
0398: state = HIDDEN;
0399: }
0400: }
0401:
0402: /**
0403: * Some "system modal dialog" takes over physical screen
0404: * buffer and user input now or foreground is lost.
0405: * This function calls lCallHide after holding LCDUILock
0406: * and sets this DisplayableLF to FROZEN state.
0407: */
0408: public void uCallFreeze() {
0409: synchronized (Display.LCDUILock) {
0410: // Delete native resources and update ticker
0411: lCallHide();
0412: // set state
0413: state = FROZEN;
0414: }
0415: }
0416:
0417: /**
0418: * Remove this <code>Displayable</code> from physical screen.
0419: * The <code>Displayable</code> should unload any resource that
0420: * was allocated. It is not required to clean the physical screen
0421: * before this function returns.
0422: */
0423: void lCallHide() {
0424: if (state == SHOWN) {
0425: updateNativeTicker(owner.ticker, null);
0426: }
0427:
0428: // Delete native resources
0429: deleteNativeResource();
0430:
0431: }
0432:
0433: /**
0434: * Called by the event handler to perform an invalidation of this
0435: * <code>Displayable</code>.
0436: * Subclass should override to perform re-layout.
0437: * Default implementation does nothing.
0438: */
0439: public void uCallInvalidate() {
0440: synchronized (Display.LCDUILock) {
0441: pendingInvalidate = false;
0442: }
0443: }
0444:
0445: /**
0446: * This method is used in repaint, in order to determine the translation
0447: * of the draw coordinates.
0448: *
0449: * @return <code>true</code>, if the scroll responsibility is on
0450: * the native platform.
0451: * <code>false</code>, if the scroll is done at Java level.
0452: */
0453: public boolean uIsScrollNative() {
0454: // only native form overrides this and returns true
0455: return false;
0456: }
0457:
0458: // ************************************************************
0459: // package private methods
0460: // ************************************************************
0461:
0462: /**
0463: * Create native resource.
0464: * Instance variable {@link #nativeId nativeId} must be set
0465: * to the id of the new resource.
0466: */
0467: abstract void createNativeResource();
0468:
0469: /**
0470: * Delete native resource.
0471: * Instance variable {@link #nativeId nativeId} is reset
0472: * to {@link #INVALID_NATIVE_ID INVALID_NATIVE_ID}.
0473: */
0474: void deleteNativeResource() {
0475: if (nativeId != INVALID_NATIVE_ID) {
0476: deleteNativeResource0(nativeId);
0477: nativeId = INVALID_NATIVE_ID;
0478: }
0479: }
0480:
0481: /**
0482: * Package private equivalent of sizeChanged().
0483: *
0484: * @param w the new width
0485: * @param h the new height
0486: *
0487: */
0488: public void uCallSizeChanged(int w, int h) {
0489:
0490: boolean copyDefferedSizeChange;
0491:
0492: synchronized (Display.LCDUILock) {
0493: if (owner instanceof GameCanvas) {
0494: GameCanvasLFImpl gameCanvasLF = GameMap
0495: .getGameCanvasImpl((GameCanvas) owner);
0496: if (gameCanvasLF != null) {
0497: gameCanvasLF.lCallSizeChanged(w, h);
0498: }
0499: }
0500:
0501: // If there is no Display, or if this Displayable is not
0502: // currently visible, we simply record the fact that the
0503: // size has changed
0504: defferedSizeChange = (state != SHOWN);
0505: copyDefferedSizeChange = defferedSizeChange;
0506: /*
0507: * sizeChangeOccurred is a boolean which (when true) indicates
0508: * that sizeChanged() will be called at a later time. So, if it
0509: * is false after calling super(), we go ahead and notify the
0510: * Canvas now, rather than later
0511: */
0512:
0513: width = w;
0514: height = h;
0515: if (!defferedSizeChange) {
0516: lRequestInvalidate();
0517: }
0518:
0519: }
0520: if (!copyDefferedSizeChange) {
0521: synchronized (Display.calloutLock) {
0522: try {
0523: owner.sizeChanged(w, h);
0524: } catch (Throwable t) {
0525: Display.handleThrowable(t);
0526: }
0527: }
0528: }
0529: }
0530:
0531: /**
0532: * This method notify displayable to scroll its content
0533: *
0534: * @param scrollType scrollType
0535: * @param thumbPosition
0536: */
0537: public void uCallScrollContent(int scrollType, int thumbPosition) {
0538: // by default nothing to do
0539: }
0540:
0541: /**
0542: * <code>Display</code> calls this method on it's current
0543: * <code>Displayable</code>.
0544: * <code>Displayable</code> uses this opportunity to do necessary stuff
0545: * on the graphics context, this includes, paint Ticker, paint Title
0546: * and translate as necessary.
0547: *
0548: * <p>The target Object of this repaint may be some Object
0549: * initially set by this <code>Displayable</code> when the repaint was
0550: * requested - allowing this <code>Displayable</code> to know exactly
0551: * which Object it needs to call to service this repaint,
0552: * rather than potentially querying all of its Objects to
0553: * determine the one(s) which need painting.
0554: *
0555: * SYNC NOTE: The caller of this method handles synchronization.
0556: *
0557: * @param g the graphics context to paint into.
0558: * @param target the target Object of this repaint
0559: */
0560: public void uCallPaint(Graphics g, Object target) {
0561: // Made obsolete by dsShow, where native title is shown already
0562: }
0563:
0564: /**
0565: * Handle a raw key event from <code>Display</code>.
0566: *
0567: * @param type type of event, defined in <code>EventConstants</code>
0568: * @param keyCode code of the key event
0569: */
0570: public void uCallKeyEvent(int type, int keyCode) {
0571: int eventType = -1;
0572:
0573: synchronized (Display.LCDUILock) {
0574:
0575: switch (type) {
0576: case EventConstants.PRESSED:
0577: sawKeyPress = true;
0578: eventType = 0;
0579: break;
0580: case EventConstants.RELEASED:
0581: if (sawKeyPress) {
0582: eventType = 1;
0583: }
0584: break;
0585: case EventConstants.REPEATED:
0586: if (sawKeyPress) {
0587: eventType = 2;
0588: }
0589: break;
0590: }
0591: // used later by getKeyMask()
0592: if (currentKeyMask > -1 && eventType != -1) {
0593: if (eventType == 1) {
0594: releaseKeyMask(keyCode);
0595: } else {
0596: // set the mask on key press, repeat or type.
0597: // don't set the mask when a key was released.
0598: setKeyMask(keyCode);
0599: }
0600: }
0601: } // synchronized
0602:
0603: // SYNC NOTE: Since we may call into application code,
0604: // we do so outside of LCDUILock
0605: switch (eventType) {
0606: case -1:
0607: return;
0608: case 0:
0609: uCallKeyPressed(keyCode);
0610: break;
0611: case 1:
0612: uCallKeyReleased(keyCode);
0613: break;
0614: case 2:
0615: uCallKeyRepeated(keyCode);
0616: break;
0617: default:
0618: /*
0619: * TBD:
0620: *
0621: * Originally severity level was "ERROR".
0622: * But it was reduced to INFO because
0623: * a). it do not harm to the system
0624: * b). some cases,
0625: * Displayable processes KEY_PRESS events
0626: * (when in system menu) & cleans all related status flag,
0627: * while following KEY_REPEAT & KEY_RELEASE event pairs
0628: * are not processed in the same way and therefore
0629: * this eror messae was printed or them.
0630: *
0631: * As a temporary solution it was decided to disable messages
0632: * insead of additional event filtering.
0633: */
0634: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
0635: Logging.report(Logging.INFORMATION,
0636: LogChannels.LC_HIGHUI,
0637: "DisplayableLFImpl: uCallKeyEvent," + "type="
0638: + type + " keyCode=" + keyCode);
0639: }
0640: break;
0641: }
0642: } // end of dsKeyEvent()
0643:
0644: /**
0645: * Set status of screen rotation
0646: * @param newStatus
0647: * @return
0648: */
0649: public boolean uSetRotatedStatus(boolean newStatus) {
0650: synchronized (Display.LCDUILock) {
0651: if (newStatus == owner.isRotated) {
0652: return false;
0653: } else {
0654: owner.isRotated = newStatus;
0655: return true;
0656: }
0657: }
0658: }
0659:
0660: /**
0661: * Handle a key press.
0662: *
0663: * @param keyCode The key that was pressed
0664: */
0665: void uCallKeyPressed(int keyCode) {
0666: }
0667:
0668: /**
0669: * Handle a repeated key press.
0670: *
0671: * @param keyCode The key that was pressed
0672: */
0673: void uCallKeyRepeated(int keyCode) {
0674: }
0675:
0676: /**
0677: * Handle a key release.
0678: *
0679: * @param keyCode The key that was released
0680: */
0681: void uCallKeyReleased(int keyCode) {
0682: }
0683:
0684: /**
0685: * Called from the event delivery loop when a pointer event is seen.
0686: *
0687: * @param type kind of pointer event
0688: * @param x x-coordinate of pointer event
0689: * @param y y-coordinate of pointer event
0690: */
0691: public void uCallPointerEvent(int type, int x, int y) {
0692: int eventType = -1;
0693:
0694: synchronized (Display.LCDUILock) {
0695: switch (type) {
0696: case EventConstants.PRESSED:
0697: sawPointerPress = true;
0698: eventType = 0;
0699: break;
0700: case EventConstants.RELEASED:
0701: if (sawPointerPress) {
0702: eventType = 1;
0703: }
0704: break;
0705: case EventConstants.DRAGGED:
0706: if (sawPointerPress) {
0707: eventType = 2;
0708: }
0709: break;
0710: }
0711: } // synchronized
0712:
0713: // SYNC NOTE: Since we may call into application code,
0714: // we do so outside of LCDUILock
0715: switch (eventType) {
0716: case -1:
0717: return;
0718: case 0:
0719: uCallPointerPressed(x, y);
0720: break;
0721: case 1:
0722: uCallPointerReleased(x, y);
0723: break;
0724: case 2:
0725: uCallPointerDragged(x, y);
0726: break;
0727: default:
0728: // this is an error
0729: break;
0730: }
0731: } // uCallPointerEvent()
0732:
0733: /**
0734: * Handle a pointer press event.
0735: *
0736: * @param x The x coordinate of the press
0737: * @param y The y coordinate of the press
0738: */
0739: void uCallPointerPressed(int x, int y) {
0740: }
0741:
0742: /**
0743: * Handle a pointer drag event.
0744: *
0745: * @param x The x coordinate of the drag
0746: * @param y The y coordinate of the drag
0747: */
0748: void uCallPointerDragged(int x, int y) {
0749: }
0750:
0751: /**
0752: * Handle a pointer release event.
0753: *
0754: * @param x The x coordinate of the release
0755: * @param y The y coordinate of the release
0756: */
0757: void uCallPointerReleased(int x, int y) {
0758: }
0759:
0760: /**
0761: * Called to commit any pending user interaction for the current item.
0762: */
0763: public void lCommitPendingInteraction() {
0764: }
0765:
0766: /**
0767: * Repaint this <code>Displayable</code>.
0768: *
0769: * @param x The x coordinate of the region to repaint
0770: * @param y The y coordinate of the region to repaint
0771: * @param width The width of the region to repaint
0772: * @param height The height of the region to repaint
0773: * @param target an optional paint target to receive the paint request
0774: * when it returns via uCallPaint()
0775: */
0776: void lRequestPaint(int x, int y, int width, int height,
0777: Object target) {
0778: if (lIsShown()) {
0779: // Note: Display will not let anyone but the current
0780: // Displayable schedule repaints
0781: currentDisplay.repaintImpl(this , x, y, width, height,
0782: target);
0783: }
0784: }
0785:
0786: /**
0787: * Repaints this <code>Displayable</code>.
0788: * This is the same as calling
0789: * repaint(0, 0, width, height, null)
0790: */
0791: void lRequestPaint() {
0792: lRequestPaint(0, 0, width, height, null);
0793: }
0794:
0795: /**
0796: * Request to paint all of this Displayable (without holding a lock).
0797: */
0798: void uRequestPaint() {
0799: synchronized (Display.LCDUILock) {
0800: lRequestPaint();
0801: }
0802: }
0803:
0804: /**
0805: * Repaint the whole <code>Displayable</code>.
0806: */
0807: void lRequestPaintContents() {
0808: lRequestPaint(0, 0, width, height, null);
0809: }
0810:
0811: /**
0812: * Called to schedule an "invalidate" for this <code>Displayable</code>.
0813: * Invalidation is caused by things like size changes, content changes,
0814: * or spontaneous traversal within the <code>Item</code>.
0815: *
0816: * SYNC NOTE: Caller must hold LCDUILock around this call.
0817: */
0818: void lRequestInvalidate() {
0819: pendingInvalidate = true;
0820: if (state == SHOWN && currentDisplay != null) {
0821: currentDisplay.invalidate();
0822: }
0823: }
0824:
0825: // ************************************************************
0826: // private methods
0827: // ************************************************************
0828:
0829: /**
0830: * Updates the ticker.
0831: *
0832: * @param oldTicker the old ticker, or <code>null</code> for no ticker
0833: * @param newTicker the new ticker, or <code>null</code> for no ticker
0834: */
0835: private void updateNativeTicker(Ticker oldTicker, Ticker newTicker) {
0836:
0837: // CASES:
0838: // 1. Had an invisible non-null ticker, setting a null ticker
0839: // - We need to set the new ticker. There's no need to re-layout
0840: // or start the new ticker
0841: // 2. Had an invisible non-null ticker, setting a non-null ticker
0842: // - We need to set the new ticker. There's no need to re-layout
0843: // or start the new ticker
0844: // 3. Had a visible non-null ticker, setting a null ticker
0845: // - We need to set the new ticker and re-layout. There's no
0846: // need to start the new ticker.
0847: // 4. Had a null ticker, setting a visible non-null ticker
0848: // - We need to set the new ticker, re-layout, and
0849: // start up the new ticker
0850: // 5. Had a visible non-null ticker, setting a non-null ticker
0851: // - We need to set the new ticker. There's no need to re-layout
0852:
0853: if ((owner.isInFullScreenMode)
0854: || ((oldTicker == null) && (newTicker == null))) {
0855: return;
0856: } else {
0857: setTicker(newTicker);
0858: }
0859: }
0860:
0861: /**
0862: * Set the ticker.
0863: *
0864: * @param t the new ticker to be set
0865: */
0866: private void setTicker(Ticker t) {
0867:
0868: if (nativeId != INVALID_NATIVE_ID) {
0869: setTicker0(nativeId, (t == null) ? null
0870: : t.displayedMessage);
0871: }
0872: }
0873:
0874: /**
0875: * Notification that the ticker has changed.
0876: * This method is called from <code>TickerLFImpl</code>.
0877: *
0878: * @param t the ticker associated with the TickerLFImpl
0879: */
0880: void tickerTextChanged(Ticker t) {
0881: if (owner.ticker != t) {
0882: return;
0883: }
0884: setTicker(t);
0885: }
0886:
0887: /**
0888: * Called to set key mask of all the keys that were pressed.
0889: *
0890: * @param keyCode The key code to set the key mask.
0891: */
0892: private void setKeyMask(int keyCode) {
0893: /*
0894: // Shouldn't run into this case.
0895: if (paintSuspended || !hasForeground) {
0896: return;
0897: }
0898: */
0899:
0900: // set the mask of keys pressed
0901: switch (KeyConverter.getGameAction(keyCode)) {
0902: case Canvas.UP:
0903: stickyKeyMask = stickyKeyMask | GameCanvas.UP_PRESSED;
0904: currentKeyMask = currentKeyMask | GameCanvas.UP_PRESSED;
0905: break;
0906: case Canvas.DOWN:
0907: stickyKeyMask = stickyKeyMask | GameCanvas.DOWN_PRESSED;
0908: currentKeyMask = currentKeyMask | GameCanvas.DOWN_PRESSED;
0909: break;
0910: case Canvas.LEFT:
0911: stickyKeyMask = stickyKeyMask | GameCanvas.LEFT_PRESSED;
0912: currentKeyMask = currentKeyMask | GameCanvas.LEFT_PRESSED;
0913: break;
0914: case Canvas.RIGHT:
0915: stickyKeyMask = stickyKeyMask | GameCanvas.RIGHT_PRESSED;
0916: currentKeyMask = currentKeyMask | GameCanvas.RIGHT_PRESSED;
0917: break;
0918: case Canvas.FIRE:
0919: stickyKeyMask = stickyKeyMask | GameCanvas.FIRE_PRESSED;
0920: currentKeyMask = currentKeyMask | GameCanvas.FIRE_PRESSED;
0921: break;
0922: case Canvas.GAME_A:
0923: stickyKeyMask = stickyKeyMask | GameCanvas.GAME_A_PRESSED;
0924: currentKeyMask = currentKeyMask | GameCanvas.GAME_A_PRESSED;
0925: break;
0926: case Canvas.GAME_B:
0927: stickyKeyMask = stickyKeyMask | GameCanvas.GAME_B_PRESSED;
0928: currentKeyMask = currentKeyMask | GameCanvas.GAME_B_PRESSED;
0929: break;
0930: case Canvas.GAME_C:
0931: stickyKeyMask = stickyKeyMask | GameCanvas.GAME_C_PRESSED;
0932: currentKeyMask = currentKeyMask | GameCanvas.GAME_C_PRESSED;
0933: break;
0934: case Canvas.GAME_D:
0935: stickyKeyMask = stickyKeyMask | GameCanvas.GAME_D_PRESSED;
0936: currentKeyMask = currentKeyMask | GameCanvas.GAME_D_PRESSED;
0937: }
0938: }
0939:
0940: /**
0941: * Called to release key mask of all the keys that were release.
0942: *
0943: * @param keyCode The key code to release the key mask.
0944: */
0945: private void releaseKeyMask(int keyCode) {
0946: /*
0947: // Leave this case to dsHide and dsFreeze()
0948: if (paintSuspended || !hasForeground) {
0949: currentKeyMask = 0;
0950: return;
0951: }
0952: */
0953:
0954: // set the mask of keys pressed
0955: switch (KeyConverter.getGameAction(keyCode)) {
0956: case Canvas.UP:
0957: currentKeyMask = currentKeyMask & ~GameCanvas.UP_PRESSED;
0958: break;
0959: case Canvas.DOWN:
0960: currentKeyMask = currentKeyMask & ~GameCanvas.DOWN_PRESSED;
0961: break;
0962: case Canvas.LEFT:
0963: currentKeyMask = currentKeyMask & ~GameCanvas.LEFT_PRESSED;
0964: break;
0965: case Canvas.RIGHT:
0966: currentKeyMask = currentKeyMask & ~GameCanvas.RIGHT_PRESSED;
0967: break;
0968: case Canvas.FIRE:
0969: currentKeyMask = currentKeyMask & ~GameCanvas.FIRE_PRESSED;
0970: break;
0971: case Canvas.GAME_A:
0972: currentKeyMask = currentKeyMask
0973: & ~GameCanvas.GAME_A_PRESSED;
0974: break;
0975: case Canvas.GAME_B:
0976: currentKeyMask = currentKeyMask
0977: & ~GameCanvas.GAME_B_PRESSED;
0978: break;
0979: case Canvas.GAME_C:
0980: currentKeyMask = currentKeyMask
0981: & ~GameCanvas.GAME_C_PRESSED;
0982: break;
0983: case Canvas.GAME_D:
0984: currentKeyMask = currentKeyMask
0985: & ~GameCanvas.GAME_D_PRESSED;
0986: }
0987: }
0988:
0989: // ************************************************************
0990: // public member variables - NOT ALLOWED in this class
0991: // ************************************************************
0992:
0993: // ************************************************************
0994: // protected member variables - NOT ALLOWED in this class
0995: // ************************************************************
0996:
0997: // ************************************************************
0998: // package private member variables
0999: // ************************************************************
1000:
1001: /**
1002: * The current <code>Display</code> object.
1003: */
1004: Display currentDisplay;
1005:
1006: /**
1007: * Width and height available to the <code>Displayable</code>.
1008: */
1009: int width, height;
1010:
1011: /**
1012: * <code>True</code>, indicates that before being painted, this
1013: * <code>Displayable</code> should be notified that its size has
1014: * changed via uCallSizeChanged().
1015: */
1016: boolean defferedSizeChange = true;
1017:
1018: /**
1019: * The owner of this view.
1020: */
1021: Displayable owner;
1022:
1023: /**
1024: * The <code>MidpDisplayable*</code> of this <code>Displayable</code>
1025: * while visible.
1026: * <code>INVALID_NATIVE_ID</code> if no native resource has been created.
1027: */
1028: int nativeId = INVALID_NATIVE_ID;
1029:
1030: /**
1031: * Version number of this LF's data model.
1032: * Should be updated when public data model has changed and
1033: * be passed to native peer if visible. Native peer tags
1034: * all its native events with this version to prevent user
1035: * actions on obsolete copy of the data in native.
1036: */
1037: int modelVersion; // = 0
1038:
1039: // ************************************************************
1040: // private member variables
1041: // ************************************************************
1042:
1043: // No events will be delivered while these are false.
1044: // This is our attempt at avoiding spurious up events.
1045:
1046: /**
1047: * <code>True</code>, if a pointer press is in progress.
1048: */
1049: boolean sawPointerPress;
1050:
1051: /**
1052: * <code>True</code>, if a key press is in progress.
1053: */
1054: boolean sawKeyPress;
1055:
1056: /** current state of DisplayableLF (HIDDEN, SHOWN, or FROZEN) */
1057: int state; // = HIDDEN (0)
1058:
1059: /**
1060: * Stores key code of the current key pressed at least once.
1061: */
1062: // caters to the GameCanvas.getKeyStats() latching behavior.
1063: // This latched state is cleared when getKeyStats() is called.
1064: private int stickyKeyMask;
1065:
1066: /**
1067: * Stores key code of the current key is currently down.
1068: */
1069: // sets the key to 1 when the key is currently down
1070: private int currentKeyMask;
1071:
1072: /**
1073: * Used to indicate the invalidate is needed
1074: */
1075: boolean pendingInvalidate;
1076:
1077: // ************************************************************
1078: // Static initializer, constructor
1079: // ************************************************************
1080:
1081: /**
1082: * Used as an index into the viewport[], for the x origin.
1083: */
1084: final static int X = 0;
1085:
1086: /**
1087: * Used as an index into the viewport[], for the y origin.
1088: */
1089: final static int Y = 1;
1090:
1091: /**
1092: * Used as an index into the viewport[], for the width.
1093: */
1094: final static int WIDTH = 2;
1095:
1096: /**
1097: * Used as an index into the viewport[], for the height.
1098: */
1099: final static int HEIGHT = 3;
1100:
1101: /**
1102: * Uninitialized native resource id value.
1103: */
1104: final static int INVALID_NATIVE_ID = 0;
1105:
1106: /** hidden state of DisplayableLF */
1107: final static int HIDDEN = 0;
1108:
1109: /** shown state of DisplayableLF */
1110: final static int SHOWN = 1;
1111:
1112: /** frozen state of DisplayableLF */
1113: final static int FROZEN = 2;
1114:
1115: // ************************************************************
1116: // Native methods
1117: // ***********************************************************
1118:
1119: /**
1120: * Free the native resource of this <code>Displayable</code> and hide
1121: * it from display.
1122: *
1123: * @param nativeId native resource id
1124: *
1125: * @exception OutOfMemoryException - if out of native resource
1126: */
1127: private native void deleteNativeResource0(int nativeId);
1128:
1129: /**
1130: * Change the title of native resource.
1131: *
1132: * @param nativeId native resource id (<code>MidpDisplayable *</code>)
1133: * @param title New title string. Can be <code>null</code>.
1134: */
1135: private static native void setTitle0(int nativeId, String title);
1136:
1137: /**
1138: * Set text of the native ticker.
1139: *
1140: * @param nativeId native resource id.
1141: * @param text text used. Null if the ticker should stop.
1142: */
1143: private static native void setTicker0(int nativeId, String text);
1144:
1145: } // DisplayableLFImpl
|