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: package javax.microedition.lcdui;
0027:
0028: import com.sun.midp.log.Logging;
0029: import com.sun.midp.log.LogChannels;
0030: import com.sun.midp.configurator.Constants;
0031:
0032: /**
0033: * Look and feel implementation for <code>Item</code> based on
0034: * platform widgets.
0035: *
0036: * SYNC NOTE: Only functions with prefix 'uCall' handle locking internally.
0037: * Its the caller's responsibility to hold LCDUILock around calls to the
0038: * rest of functions.
0039: */
0040: abstract class ItemLFImpl implements ItemLF {
0041:
0042: /**
0043: * Creates look and feel for the passed in <code>Item</code>.
0044: *
0045: * @param item the <code>Item</code> for which the look & feel
0046: * should be created
0047: */
0048: ItemLFImpl(Item item) {
0049: this .item = item;
0050: actualBoundsInvalid = new boolean[] { true, true, true, true };
0051: bounds = new int[] { 0, 0, 0, 0 };
0052: }
0053:
0054: // *****************************************************
0055: // Public methods - ItemLF interface implementation
0056: // *****************************************************
0057:
0058: /**
0059: * Returns the locked width of the Item, or -1 if it's not locked
0060: * @return locked width plus adornment width, or -1 if it's not locked
0061: */
0062: int lGetLockedWidth() {
0063:
0064: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
0065: Logging.report(Logging.INFORMATION,
0066: LogChannels.LC_HIGHUI_ITEM_LAYOUT,
0067: " ItemLFImpl - lGetLockedWidth: "
0068: + item.lockedWidth);
0069: }
0070: return item.lockedWidth;
0071: }
0072:
0073: /**
0074: * Returns the locked height of the Item, or -1 if it's not locked
0075: * @return locked height plus adornment height, or -1 if it's not locked
0076: */
0077: protected int lGetLockedHeight() {
0078:
0079: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
0080: Logging.report(Logging.INFORMATION,
0081: LogChannels.LC_HIGHUI_ITEM_LAYOUT,
0082: " ItemLFImpl - lGetLockedHeight: "
0083: + item.lockedHeight);
0084: }
0085: return item.lockedHeight;
0086: }
0087:
0088: /**
0089: * PLACE HOLDER
0090: * Used by the Form Layout to set the size of this Item
0091: *
0092: * @param height the tentative content height in pixels
0093: * @return the preferred width
0094: */
0095: int lGetAdornedPreferredWidth(int height) {
0096: return lGetPreferredWidth(height);
0097: }
0098:
0099: /**
0100: * PLACE HOLDER
0101: * Used by the Form Layout to set the size of this Item
0102: *
0103: * @param width the tentative content width in pixels
0104: * @return the preferred height
0105: */
0106: int lGetAdornedPreferredHeight(int width) {
0107: return lGetPreferredHeight(width);
0108: }
0109:
0110: /**
0111: * PLACE HOLDER
0112: * Used by the Form Layout to set the size of this Item
0113: * @return the minimum width that includes cell spacing
0114: */
0115: int lGetAdornedMinimumWidth() {
0116: return lGetMinimumWidth();
0117: }
0118:
0119: /**
0120: * PLACE HOLDER
0121: * Used by the Form Layout to set the size of this Item
0122: * @return the minimum height that includes cell spacing
0123: */
0124: int lGetAdornedMinimumHeight() {
0125: return lGetMinimumHeight();
0126: }
0127:
0128: /**
0129: * Get the preferred width of this <code>Item</code>.
0130: *
0131: * @param h tentative locked height.
0132: * Ignored here and item.lockedHeight is used always.
0133: *
0134: * @return the preferred width
0135: */
0136: public int lGetPreferredWidth(int h) {
0137:
0138: // note: h is not used!
0139:
0140: lGetRequestedSizes();
0141: return preferredWidth;
0142: }
0143:
0144: /**
0145: * Get the preferred height of this <code>Item</code>.
0146: *
0147: * @param w tentative locked width.
0148: * Ignored here and preferred width is used always.
0149: *
0150: * @return the preferred height
0151: */
0152: public int lGetPreferredHeight(int w) {
0153:
0154: // note: w is not used
0155:
0156: lGetRequestedSizes();
0157: return preferredHeight;
0158: }
0159:
0160: /**
0161: * Get the minimum width of this <code>Item</code>.
0162: *
0163: * @return the minimum width
0164: */
0165: public int lGetMinimumWidth() {
0166:
0167: lGetRequestedSizes(); // Make sure cached sizes are up to date
0168: return minimumWidth;
0169: }
0170:
0171: /**
0172: * Get the minimum height of this <code>Item</code>.
0173: *
0174: * @return the minimum height
0175: */
0176: public int lGetMinimumHeight() {
0177: lGetRequestedSizes();
0178: return minimumHeight;
0179: }
0180:
0181: /**
0182: * Notifies L&F of a label change in the corresponding
0183: * <code>Item</code>.
0184: *
0185: * @param label the new label string
0186: */
0187: public void lSetLabel(String label) {
0188: if (nativeId != DisplayableLFImpl.INVALID_NATIVE_ID) {
0189: setLabel0(nativeId, label);
0190: }
0191: lRequestInvalidate(true, true);
0192: }
0193:
0194: /**
0195: * Notifies L&F of a layout change in the corresponding
0196: * <code>Item</code>.
0197: *
0198: * @param layout the new layout descriptor
0199: */
0200: public void lSetLayout(int layout) {
0201: lRequestInvalidate(true, true);
0202: }
0203:
0204: /**
0205: * Notifies L&F of a command addition in the corresponding
0206: * <code>Item</code>.
0207: *
0208: * @param cmd the newly added command
0209: * @param i the index of the added command in the <code>Item</code>'s
0210: * commands[] array
0211: */
0212: public void lAddCommand(Command cmd, int i) {
0213: if (item.owner != null) {
0214: ((DisplayableLFImpl) item.owner.getLF()).updateCommandSet();
0215: }
0216: }
0217:
0218: /**
0219: * Notifies L&F of a command removal in the corresponding
0220: * <code>Item</code>.
0221: *
0222: * @param cmd the newly removed command
0223: * @param i the index of the removed command in the <code>Item</code>'s
0224: * commands[] array
0225: */
0226: public void lRemoveCommand(Command cmd, int i) {
0227: if (item.owner != null) {
0228: ((DisplayableLFImpl) item.owner.getLF()).updateCommandSet();
0229: }
0230: }
0231:
0232: /**
0233: * Notifies L&F of a preferred size change in the corresponding
0234: * <code>Item</code>.
0235: *
0236: * @param width the value to which the width is locked, or
0237: * <code>-1</code> if it is unlocked
0238: * @param height the value to which the height is locked, or
0239: * <code>-1</code> if it is unlocked
0240: */
0241: public void lSetPreferredSize(int width, int height) {
0242: if (width == bounds[WIDTH] && height == bounds[HEIGHT]) {
0243: // no need to invalidate
0244: return;
0245: }
0246: lRequestInvalidate(width != bounds[WIDTH],
0247: height != bounds[HEIGHT]);
0248: }
0249:
0250: /**
0251: * Notifies L&F of the default command change in the corresponding
0252: * <code>Item</code>.
0253: *
0254: * @param cmd the newly set default command
0255: * @param i index of this new command in the <code>ChoiceGroup</code>'s
0256: * commands array
0257: */
0258: public void lSetDefaultCommand(Command cmd, int i) {
0259: }
0260:
0261: /**
0262: * Notify this itemLF that its owner screen has changed.
0263: * Clear internal state if its new owner is <code>null</code>.
0264: *
0265: * @param oldOwner old owner screen before this change. New owner
0266: * can be found in <code>Item</code> model.
0267: */
0268: public void lSetOwner(Screen oldOwner) {
0269:
0270: // Currently Item has no owner
0271: if (item.owner == null) {
0272:
0273: // Hide native resource
0274: lHideNativeResource();
0275:
0276: // Free any native resource
0277: deleteNativeResource();
0278:
0279: // do app notification
0280: if (visibleInViewport) {
0281: uCallHideNotify();
0282: }
0283:
0284: // the deleted item may be added later, so we
0285: // have to invalidate it.
0286: actualBoundsInvalid[X] = true;
0287: actualBoundsInvalid[Y] = true;
0288: actualBoundsInvalid[WIDTH] = true;
0289: actualBoundsInvalid[HEIGHT] = true;
0290: cachedWidth = INVALID_SIZE;
0291: hasFocus = false;
0292: }
0293: }
0294:
0295: /**
0296: * Return whether the cached requested sizes are valid.
0297: *
0298: * @return <code>true</code> if the cached requested sizes are up to date.
0299: * <code>false</code> if they have been invalidated.
0300: */
0301: public final boolean isRequestedSizesValid() {
0302: return (cachedWidth != INVALID_SIZE);
0303: }
0304:
0305: // *****************************************************
0306: // Package private methods
0307: // *****************************************************
0308:
0309: /**
0310: * Create native resource of this <code>Item</code>.
0311: * After this call, <code>Item.nativeId</code> should have had the
0312: * created native resource id.
0313: *
0314: * @param ownerId native <code>MidpDisplayable*</code> of the owner screen
0315: */
0316: abstract void createNativeResource(int ownerId);
0317:
0318: /**
0319: * Delete native resource of this <code>Item</code>.
0320: * After this call, <code>Item.nativeId</code> should have been reset to
0321: * <code>DisplayableLFImpl.INVALID_NATIVE_ID</code>.
0322: */
0323: void deleteNativeResource() {
0324: if (nativeId != DisplayableLFImpl.INVALID_NATIVE_ID) {
0325: delete0(nativeId);
0326: nativeId = DisplayableLFImpl.INVALID_NATIVE_ID;
0327: }
0328: }
0329:
0330: /**
0331: * Create a temporary native resource of this <code>Item</code> whose
0332: * id must be deleted before caller function returns.
0333: */
0334: protected void createTempNativeResource() {
0335:
0336: int ownerId = (item.owner == null) ? DisplayableLFImpl.INVALID_NATIVE_ID
0337: : ((DisplayableLFImpl) item.owner.getLF()).nativeId;
0338:
0339: createNativeResource(ownerId);
0340: }
0341:
0342: /**
0343: * Paint the content of this <code>Item</code>.
0344: * This function simply calls lCallPaint() after obtaining LCDUILock.
0345: *
0346: * @param g the <code>Graphics</code> object to be used for rendering
0347: * the item
0348: * @param w current width of the item in pixels
0349: * @param h current height of the item in pixels
0350: */
0351: void uCallPaint(Graphics g, int w, int h) {
0352: synchronized (Display.LCDUILock) {
0353: lCallPaint(g, w, h);
0354: }
0355: }
0356:
0357: /**
0358: * Paint the content of this <code>Item</code>.
0359: * The default implementation does nothing.
0360: *
0361: * @param g the <code>Graphics</code> object to be used for rendering
0362: * the item
0363: * @param w current width of the item in pixels
0364: * @param h current height of the item in pixels
0365: */
0366: void lCallPaint(Graphics g, int w, int h) {
0367: }
0368:
0369: /**
0370: * Determine if this <code>Item</code> should horizontally shrink.
0371: *
0372: * @return <code>true</code> if it should horizontally shrink
0373: */
0374: boolean shouldHShrink() {
0375: return ((item.layout & Item.LAYOUT_SHRINK) == Item.LAYOUT_SHRINK);
0376: }
0377:
0378: /**
0379: * Determine if this <code>Item</code> should horizontally expand.
0380: *
0381: * @return <code>true</code> if it should horizontally expand
0382: */
0383: boolean shouldHExpand() {
0384: return ((item.layout & Item.LAYOUT_EXPAND) == Item.LAYOUT_EXPAND);
0385: }
0386:
0387: /**
0388: * Determine if this <code>Item</code> should vertically shrink.
0389: *
0390: * @return <code>true</code> if it should vertically shrink
0391: */
0392: boolean shouldVShrink() {
0393: return ((item.layout & Item.LAYOUT_VSHRINK) == Item.LAYOUT_VSHRINK);
0394: }
0395:
0396: /**
0397: * Determine if this <code>Item</code> should vertically expand.
0398: *
0399: * @return <code>true</code> if it should vertically expand
0400: */
0401: boolean shouldVExpand() {
0402: return ((item.layout & Item.LAYOUT_VEXPAND) == Item.LAYOUT_VEXPAND);
0403: }
0404:
0405: /**
0406: * Determine if this <code>Item</code> should have a newline after it.
0407: *
0408: * @return <code>true</code> if it should have a newline after
0409: */
0410: boolean equateNLA() {
0411: return ((item.layout & Item.LAYOUT_NEWLINE_AFTER) == Item.LAYOUT_NEWLINE_AFTER);
0412: }
0413:
0414: /**
0415: * Determine if this <code>Item</code> should have a newline before it.
0416: *
0417: * @return <code>true</code> if it should have a newline before
0418: */
0419: boolean equateNLB() {
0420: return ((item.layout & Item.LAYOUT_NEWLINE_BEFORE) == Item.LAYOUT_NEWLINE_BEFORE);
0421: }
0422:
0423: /**
0424: * Get the effective layout type of this <code>Item</code>.
0425: *
0426: * @return layout The translated layout type.
0427: */
0428: int getLayout() {
0429: int l = item.layout;
0430: if (l == Item.LAYOUT_DEFAULT) {
0431: // the spec requires the default vertical layout to be bottom
0432: return Item.LAYOUT_BOTTOM | Item.LAYOUT_LEFT;
0433: } else {
0434: return l;
0435: }
0436: }
0437:
0438: /**
0439: * Called by the system to notify internal traverse into the item.
0440: * By default, it always returns false and should be overriden for
0441: * items with enabled internal traversal
0442: *
0443: * @param dir the direction of traversal
0444: * @param viewportWidth the width of the container's viewport
0445: * @param viewportHeight the height of the container's viewport
0446: * @param visRect_inout passes the visible rectangle into the method, and
0447: * returns the updated traversal rectangle from the
0448: * method
0449: *
0450: * @return <code>true</code> if focus ius accepted by the item
0451: * <code>false</code> if traversal should proceed out
0452: *
0453: * @see #getInteractionModes
0454: * @see #traverseOut
0455: * @see #TRAVERSE_HORIZONTAL
0456: * @see #TRAVERSE_VERTICAL
0457: */
0458: boolean uCallTraverse(int dir, int viewportWidth,
0459: int viewportHeight, int[] visRect_inout) {
0460: boolean ret = false;
0461: synchronized (Display.LCDUILock) {
0462: if (!hasFocus || dir == CustomItem.NONE) {
0463: if (ret = item.acceptFocus()) {
0464: hasFocus = true;
0465: }
0466: }
0467: }
0468: return ret;
0469: }
0470:
0471: /**
0472: * Called by the system to indicate traversal has left this
0473: * <code>Item</code>.
0474: * This function simply calls lCallTraverseOut after obtaining LCDUILock.
0475: *
0476: * @see #getInteractionModes
0477: * @see #traverse
0478: * @see #TRAVERSE_HORIZONTAL
0479: * @see #TRAVERSE_VERTICAL
0480: */
0481: void uCallTraverseOut() {
0482: synchronized (Display.LCDUILock) {
0483: lCallTraverseOut();
0484: }
0485: }
0486:
0487: /**
0488: * Called by the system to indicate traversal has left this
0489: * <code>Item</code>.
0490: *
0491: * @see #getInteractionModes
0492: * @see #traverse
0493: * @see #TRAVERSE_HORIZONTAL
0494: * @see #TRAVERSE_VERTICAL
0495: */
0496: void lCallTraverseOut() {
0497: hasFocus = false;
0498: }
0499:
0500: /**
0501: * Initialize native resource - size and location.
0502: */
0503: void initNativeResource() {
0504: if (nativeId != DisplayableLFImpl.INVALID_NATIVE_ID) {
0505: if (!actualBoundsInvalid[WIDTH]
0506: && !actualBoundsInvalid[HEIGHT]) {
0507: setSize0(nativeId, bounds[WIDTH], bounds[HEIGHT]);
0508: }
0509: if (!actualBoundsInvalid[X] && !actualBoundsInvalid[Y]) {
0510: setLocation0(nativeId, bounds[X], bounds[Y]);
0511: }
0512: }
0513: }
0514:
0515: /**
0516: * Called by the system to show this <code>Item</code>'s
0517: * native resource.
0518: *
0519: * <p>The default implementation of this method shows
0520: * the native resource corresponding to this <code>Item</code>
0521: *
0522: * <p>SYNC NOTE:
0523: */
0524: void lShowNativeResource() {
0525: if (nativeId != DisplayableLFImpl.INVALID_NATIVE_ID) {
0526: show0(nativeId);
0527: }
0528: }
0529:
0530: /**
0531: * Called by the system to hide this <code>Item</code>'s
0532: * native resource.
0533: *
0534: * <p>The default implementation of this method
0535: * hides native resources corresponding to this <code>Item</code>
0536: */
0537: void lHideNativeResource() {
0538: if (nativeId != DisplayableLFImpl.INVALID_NATIVE_ID) {
0539: hide0(nativeId);
0540: }
0541: }
0542:
0543: /**
0544: * Sets the visibleInViewport flag of this Item to be true.
0545: * Note that this method has no effect on the native resource.
0546: * This function simply calls lCallShowNotify() after obtaining LCDUILock.
0547: */
0548: void uCallShowNotify() {
0549: synchronized (Display.LCDUILock) {
0550: lCallShowNotify();
0551: }
0552: }
0553:
0554: /**
0555: * Sets the visibleInViewport flag of this Item to be true.
0556: * Note that this method has no effect on the native resource.
0557: */
0558: void lCallShowNotify() {
0559: this .visibleInViewport = true;
0560: }
0561:
0562: /**
0563: * Sets the visibleInViewport flag to be false.
0564: * Note the native resource is not hidden, nor deleted.
0565: * This function simply calls lCallShowNotify() after obtaining LCDUILock.
0566: */
0567: void uCallHideNotify() {
0568: synchronized (Display.LCDUILock) {
0569: lCallHideNotify();
0570: }
0571: }
0572:
0573: /**
0574: * Sets the visibleInViewport flag to be false.
0575: * Note the native resource is not hidden, nor deleted.
0576: */
0577: void lCallHideNotify() {
0578: this .visibleInViewport = false;
0579: }
0580:
0581: /**
0582: * Called by event delivery to notify an <code>ItemLF</code> in current
0583: * <code>FormLF</code> of a change in its peer state.
0584: * Subclass should implement this function to sync its state with
0585: * the peer and choose to return proper value to let <code>Form</code> know
0586: * whether the itemStateListener should be notified.
0587: *
0588: * @param hint some value that is interpreted only between the peers
0589: *
0590: * @return <code>true</code> if internal state has changed and
0591: * <code>ItemStateListener</code> should be notified after
0592: * this function returns.
0593: */
0594: abstract boolean uCallPeerStateChanged(int hint);
0595:
0596: /**
0597: * Called by the system to signal a key press.
0598: *
0599: * @param keyCode the key code of the key that has been pressed
0600: *
0601: * @see #getInteractionModes
0602: */
0603: void uCallKeyPressed(int keyCode) {
0604: }
0605:
0606: /**
0607: * Called by the system to signal a key release.
0608: *
0609: * @param keyCode the key code of the key that has been released
0610: *
0611: * @see #getInteractionModes
0612: */
0613: void uCallKeyReleased(int keyCode) {
0614: }
0615:
0616: /**
0617: * Called by the system to signal a key repeat.
0618: *
0619: * @param keyCode the key code of the key that has been repeated
0620: *
0621: * @see #getInteractionModes
0622: */
0623: void uCallKeyRepeated(int keyCode) {
0624: }
0625:
0626: /**
0627: * Called by the system to signal a pointer press.
0628: *
0629: * @param x the x coordinate of the pointer down
0630: * @param y the y coordinate of the pointer down
0631: *
0632: * @see #getInteractionModes
0633: */
0634: void uCallPointerPressed(int x, int y) {
0635: }
0636:
0637: /**
0638: * Called by the system to signal a pointer release.
0639: *
0640: * @param x the x coordinate of the pointer up
0641: * @param y the x coordinate of the pointer up
0642: *
0643: * @see #getInteractionModes
0644: */
0645: void uCallPointerReleased(int x, int y) {
0646: }
0647:
0648: /**
0649: * Called by the system to signal a pointer drag.
0650: *
0651: * @param x the x coordinate of the pointer drag
0652: * @param y the x coordinate of the pointer drag
0653: *
0654: * @see #getInteractionModes
0655: */
0656: void uCallPointerDragged(int x, int y) {
0657: }
0658:
0659: /**
0660: * Called by the system to indicate the size available to this
0661: * <code>Item</code> has changed.
0662: *
0663: * @param w the new width of the item's content area
0664: * @param h the new height of the item's content area
0665: */
0666: void uCallSizeChanged(int w, int h) {
0667: synchronized (Display.LCDUILock) {
0668: item.lUpdateLockedSize();
0669: }
0670: }
0671:
0672: /**
0673: * Called to commit any pending user interaction for the item.
0674: */
0675: public void lCommitPendingInteraction() {
0676: }
0677:
0678: /**
0679: * Sets item's location.
0680: *
0681: * @param x the new x location in form's content coordinate system
0682: * @param y the new y location in form's content coordinate system
0683: */
0684: void lSetLocation(int x, int y) {
0685:
0686: bounds[X] = x;
0687: bounds[Y] = y;
0688:
0689: if (nativeId != DisplayableLFImpl.INVALID_NATIVE_ID) {
0690: setLocation0(nativeId, x, y);
0691: }
0692: }
0693:
0694: /**
0695: * Sets item's size.
0696: *
0697: * @param w the new width of the item
0698: * @param h the new height of the item
0699: */
0700: void lSetSize(int w, int h) {
0701:
0702: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
0703: Logging.report(Logging.INFORMATION,
0704: LogChannels.LC_HIGHUI_ITEM_LAYOUT,
0705: " ItemLFImpl - lSetSize: " + w + "x" + h);
0706: }
0707:
0708: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
0709: if (w < minimumWidth) {
0710: Logging.report(Logging.INFORMATION,
0711: LogChannels.LC_HIGHUI_ITEM_LAYOUT,
0712: " ******* ItemLFImpl - lSetSize: " + w
0713: + " < " + minimumWidth);
0714: }
0715: }
0716: bounds[WIDTH] = w;
0717: bounds[HEIGHT] = h;
0718:
0719: if (nativeId != DisplayableLFImpl.INVALID_NATIVE_ID) {
0720: setSize0(nativeId, w, h);
0721: }
0722: }
0723:
0724: /**
0725: * Moves item's location by delta. Both deltaX and deltaY can be
0726: * positive and negative.
0727: *
0728: * @param deltaX the amount of pixels by which x item's location
0729: * has to be moved
0730: * @param deltaY the amount of pixels by which y item's location
0731: * has to be moved
0732: */
0733: void lMove(int deltaX, int deltaY) {
0734:
0735: bounds[X] += deltaX;
0736: bounds[Y] += deltaY;
0737:
0738: if (nativeId != DisplayableLFImpl.INVALID_NATIVE_ID) {
0739: setLocation0(nativeId, bounds[X], bounds[Y]);
0740: }
0741: }
0742:
0743: /**
0744: * Request the event scheduler to schedule an invalidate event, that
0745: * eventually will call uCallInvalidate(this item) of this item's
0746: * <code>DisplayableLFImpl</code>.
0747: * If caller also needs to call lSetRequestedSizes, then it must be
0748: * called AFTER this function, to have effect.
0749: *
0750: * @param width <code>true</code> if it was changed
0751: * @param height <code>true</code> if it was changed
0752: */
0753: void lRequestInvalidate(boolean width, boolean height) {
0754:
0755: actualBoundsInvalid[WIDTH] = actualBoundsInvalid[WIDTH]
0756: || width;
0757: actualBoundsInvalid[HEIGHT] = actualBoundsInvalid[HEIGHT]
0758: || height;
0759:
0760: if (width || height) {
0761: cachedWidth = INVALID_SIZE;
0762: }
0763:
0764: // if native resource is not visible we still need
0765: // process invalidate to proper set the sizes of this ItemLF
0766: // and of form container as well
0767: if (item.owner != null) {
0768: ((DisplayableLFImpl) item.owner.getLF())
0769: .lRequestInvalidate();
0770: }
0771: }
0772:
0773: /**
0774: * Set minimum and preferred width and height of this item.
0775: * This function should only be called on a <code>CustomItemLFImpl</code>
0776: * or <code>SpacerLFImpl</code>.
0777: * They will collect its own sizing, then call this function to cache them.
0778: *
0779: * @param mw minimum width
0780: * @param mh minimum height
0781: * @param pw preferred width
0782: * @param ph preferred height
0783: */
0784: final void lSetRequestedSizes(int mw, int mh, int pw, int ph) {
0785: // ASSERT (this instanceof CustomItemLFImpl or SpacerLFImpl)
0786: minimumWidth = mw;
0787: minimumHeight = mh;
0788: preferredWidth = pw;
0789: preferredHeight = ph;
0790: cachedWidth = pw;
0791:
0792: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
0793: Logging
0794: .report(Logging.INFORMATION,
0795: LogChannels.LC_HIGHUI_ITEM_LAYOUT,
0796: " lSetRequestedSizes: " + " mw="
0797: + minimumWidth + " mh="
0798: + minimumHeight + " pw="
0799: + preferredWidth + " ph="
0800: + preferredHeight);
0801: }
0802:
0803: }
0804:
0805: /**
0806: * Calculate minimum and preferred width and height of this item and
0807: * store the result in instance variables:
0808: * minimumWidth, minimumHeight, preferredWidth and preferredHeight.
0809: * This function will query native resources for the sizes. For
0810: * <code>Item</code>s like <code>CustomItem</code> and
0811: * <code>Spacer</code>, whose sizes are only calculated in Java, this
0812: * function should be overriden to perform their own calculation.
0813: */
0814: void lGetRequestedSizes() {
0815:
0816: if (cachedWidth != INVALID_SIZE) {
0817: return;
0818: }
0819:
0820: // query native for real preferred sizes
0821: boolean wasNoNative = (nativeId == DisplayableLFImpl.INVALID_NATIVE_ID);
0822:
0823: // Native resource not yet created, create a temporary one
0824: if (wasNoNative) {
0825: createTempNativeResource();
0826: }
0827:
0828: minimumWidth = getMinimumWidth0(nativeId);
0829: // ASSERT (ownerLFImpl.width
0830: // >= minimumWidth >= 0)
0831:
0832: minimumHeight = getMinimumHeight0(nativeId);
0833: // ASSERT (minimumHeight >= 0)
0834:
0835: // NOTE: When the item should shrink, the minimum size is used,
0836: // and the minimum size is calculated with the label
0837: // on the same line
0838: if (shouldHShrink() && item.label != null
0839: && item.label.length() > 0) {
0840: minimumHeight += DEFAULT_LABEL_HEIGHT;
0841: }
0842:
0843: preferredWidth = getPreferredWidth0(nativeId, item.lockedHeight);
0844: if (preferredWidth < minimumWidth) {
0845: preferredWidth = minimumWidth;
0846: }
0847:
0848: // Since we don't support horizontal scrolling,
0849: // we limit the width before using it to query for preferredHeight
0850: if (item.owner != null) {
0851:
0852: DisplayableLFImpl ownerLFImpl = (DisplayableLFImpl) item.owner
0853: .getLF();
0854:
0855: // Right now the space available for items is
0856: // always limited by the scrollbar space (see first
0857: // FormLFImpl constructor)
0858:
0859: // The exception of that rule is List and TextBox
0860: // implementations that use FormLFImpl
0861: // (notice that in the second constructor the width
0862: // is not limited by scrollbar)
0863: // But when a native peer cannot support vertical
0864: // scrolling and has to be longer than the viewport
0865: // FormLFImpl needs to provide its native scrollbar
0866: // To make sure that happens we do the following check.
0867: // That check must be removed if FormLFImpl supports
0868: // dynamic change of the width available for layout.
0869: if (ownerLFImpl.width == Display.WIDTH
0870: && minimumHeight > Display.HEIGHT) {
0871:
0872: ownerLFImpl.width -= Constants.VERT_SCROLLBAR_WIDTH;
0873: }
0874:
0875: if (preferredWidth > ownerLFImpl.width) {
0876: preferredWidth = ownerLFImpl.width;
0877: }
0878:
0879: } else {
0880: if (preferredWidth > Display.WIDTH
0881: - Constants.VERT_SCROLLBAR_WIDTH) {
0882: preferredWidth = Display.WIDTH
0883: - Constants.VERT_SCROLLBAR_WIDTH;
0884: }
0885: }
0886:
0887: preferredHeight = getPreferredHeight0(nativeId,
0888: (item.lockedWidth == -1) ? preferredWidth
0889: : item.lockedWidth);
0890:
0891: if (preferredHeight < minimumHeight) {
0892: preferredHeight = minimumHeight;
0893: }
0894:
0895: // Delete temporary native resource
0896: if (wasNoNative) {
0897: deleteNativeResource();
0898: }
0899:
0900: cachedWidth = preferredWidth;
0901:
0902: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
0903: Logging
0904: .report(Logging.INFORMATION,
0905: LogChannels.LC_HIGHUI_ITEM_LAYOUT,
0906: " lGetRequestedSizes: " + " mw="
0907: + minimumWidth + " mh="
0908: + minimumHeight + " pw="
0909: + preferredWidth + " ph="
0910: + preferredHeight);
0911: }
0912: }
0913:
0914: /**
0915: * Called by subclasses to repaint this entire <code>Item</code>'s bounds.
0916: */
0917: void lRequestPaint() {
0918: if (bounds != null) {
0919: lRequestPaint(0, 0, bounds[WIDTH], bounds[HEIGHT]);
0920: }
0921: }
0922:
0923: /**
0924: * Called by subclasses to repaint a portion of this <code>Item</code>'s
0925: * bounds.
0926: *
0927: * @param x the x coordinate of the origin of the dirty region
0928: * @param y the y coordinate of the origin of the dirty region
0929: * @param w the width of the dirty region
0930: * @param h the height of the dirty region
0931: */
0932: void lRequestPaint(int x, int y, int w, int h) {
0933:
0934: if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
0935: Logging.report(Logging.INFORMATION, LogChannels.LC_HIGHUI,
0936: "repaint " + this + " \t owner =" + item.owner);
0937: }
0938:
0939: if (item.owner != null) {
0940: if (w < 0) {
0941: return;
0942: } else if (w > bounds[WIDTH]) {
0943: w = bounds[WIDTH];
0944: }
0945:
0946: if (h < 0) {
0947: return;
0948: } else if (h > bounds[HEIGHT]) {
0949: h = bounds[HEIGHT];
0950: }
0951:
0952: if (x < 0) {
0953: x = 0;
0954: } else if (x > bounds[WIDTH]) {
0955: return;
0956: }
0957:
0958: if (y < 0) {
0959: y = 0;
0960: } else if (y > bounds[HEIGHT]) {
0961: return;
0962: }
0963:
0964: if (item.owner.getLF() instanceof FormLFImpl) {
0965: ((FormLFImpl) item.owner.getLF()).lRequestPaintItem(
0966: item, x, y, w, h);
0967: } else if (item.owner.getLF() instanceof AlertLFImpl) {
0968: // ((AlertLFImpl)item.owner.getLF()).repaintItem(item,
0969: // x, y, w, h);
0970: ((AlertLFImpl) item.owner.getLF())
0971: .lRequestPaintContents();
0972: }
0973:
0974: }
0975: }
0976:
0977: /**
0978: * Return the current <code>Display</code> instance that this
0979: * <code>Item</code> is displayed in.
0980: *
0981: * @return the <code>Display</code> instance this <code>Item</code>
0982: * is displayed in
0983: */
0984: Display getCurrentDisplay() {
0985: return (item.owner == null) ? null : item.owner.getLF()
0986: .lGetCurrentDisplay();
0987: }
0988:
0989: /**
0990: * Makes native widget that corresponds to this <code>Item</code>
0991: * visible on the screen at the location set earlier.
0992: *
0993: * @param nativeId native resource id of this <code>Item</code>
0994: */
0995: private native void show0(int nativeId);
0996:
0997: /**
0998: * Makes native widget that corresponds to this <code>Item</code>
0999: * invisible and free native resource. After this call, the nativeId
1000: * is no longer valid.
1001: *
1002: * @param nativeId native resource id of this <code>Item</code>
1003: */
1004: private native void hide0(int nativeId);
1005:
1006: /**
1007: * Notify native <code>Item</code> to delete its resource.
1008: *
1009: * @param nativeId native resource id (<code>MidpItem *</code>) of this
1010: * <code>Item</code>
1011: */
1012: private native void delete0(int nativeId);
1013:
1014: /**
1015: * Notifies native widget that <code>Form</code> set location of this
1016: * <code>Item</code> to be at x, y.
1017: *
1018: * @param nativeId native resource id of this <code>Item</code>
1019: * @param x the new x location of the <code>Item</code>
1020: * @param y the new y location of the <code>Item</code>
1021: */
1022: private native void setLocation0(int nativeId, int x, int y);
1023:
1024: /**
1025: * Notifies native widget that <code>Form</code> set size of this
1026: * <code>Item</code> to be at w and h.
1027: *
1028: * @param nativeId native resource id of this <code>Item</code>
1029: * @param w the new width of the <code>Item</code>
1030: * @param h the new height of the <code>Item</code>
1031: */
1032: private native void setSize0(int nativeId, int w, int h);
1033:
1034: /**
1035: * Notifies native width that new label was set on this <code>Item</code>.
1036: *
1037: * @param nativeId native resource id of this <code>Item</code>
1038: * @param label the new label set on this <code>Item</code>
1039: */
1040: native void setLabel0(int nativeId, String label);
1041:
1042: /**
1043: * Gets preferred width from the native resource corresponding to
1044: * this <code>Item</code>.
1045: *
1046: * @param nativeId pointer to the native resource
1047: * @param h the tentative content height in pixels,
1048: * or <code>-1</code> if a tentative height has not been computed
1049: *
1050: * @return preferred width that corresponds to the passed in height
1051: */
1052: native int getPreferredWidth0(int nativeId, int h);
1053:
1054: /**
1055: * Gets preferred height from the native resource corresponding to
1056: * this <code>Item</code>.
1057: *
1058: * @param nativeId pointer to the native resource
1059: * @param w the tentative content width in pixels,
1060: * or <code>-1</code> if a tentative width has not been computed
1061: *
1062: * @return preferred height that corresponds to the passed in width
1063: */
1064: native int getPreferredHeight0(int nativeId, int w);
1065:
1066: /**
1067: * Gets minimum width from the native resource corresponding to
1068: * this <code>Item</code>.
1069: *
1070: * @param nativeId pointer to the native resource
1071: *
1072: * @return minimum width
1073: */
1074: native int getMinimumWidth0(int nativeId);
1075:
1076: /**
1077: * Gets minimum height from the native resource corresponding to
1078: * this <code>Item</code>.
1079: *
1080: * @param nativeId pointer to the native resource
1081: *
1082: * @return minimum height
1083: */
1084: native int getMinimumHeight0(int nativeId);
1085:
1086: /**
1087: * Bounds[] array index to x coordinate.
1088: */
1089: final static int X = FormLFImpl.X;
1090:
1091: /**
1092: * Bounds[] array index to y coordinate.
1093: */
1094: final static int Y = FormLFImpl.Y;
1095:
1096: /**
1097: * Bounds[] array index to width.
1098: */
1099: final static int WIDTH = FormLFImpl.WIDTH;
1100:
1101: /**
1102: * Bounds[] array index to height.
1103: */
1104: final static int HEIGHT = FormLFImpl.HEIGHT;
1105:
1106: /**
1107: * The default label height for an item.
1108: */
1109: static final int DEFAULT_LABEL_HEIGHT = 14;
1110:
1111: /**
1112: * The owner of this view. Set in the constructor.
1113: */
1114: Item item; // = null
1115:
1116: /**
1117: * The native <code>MidpItem*</code> of this view.
1118: * Set by owner screen based on the return value of
1119: * createNativeResource().
1120: */
1121: int nativeId;
1122:
1123: /**
1124: * This is the size <i>granted</i> to this item by the form layout.
1125: * An array of 4 elements, describing the x, y, width, height
1126: * of this <code>Item</code>'s bounds in the viewport coordinate space. If
1127: * it is <code>null</code>, it means the <code>Item</code> is currently
1128: * not in the viewport.
1129: * This array is set by this.lSetLocation() and this.lSetSize(),
1130: * and read by <code>FormLFImpl</code> during layout.
1131: */
1132: int[] bounds;
1133:
1134: /**
1135: * A flag indicating this <code>Item</code> has the input focus. This is
1136: * maintained by the <code>Item</code> superclass for easy use by subclass
1137: * code.
1138: */
1139: boolean hasFocus; // = false
1140:
1141: /**
1142: * A flag indicating the size of this <code>Item</code> has changed in a
1143: * subsequent layout operation.
1144: * This variable is set and read by <code>FormLFImpl</code> during layout.
1145: */
1146: boolean sizeChanged; // = false
1147:
1148: /**
1149: * A flag indicating the native resource of this
1150: * <code>Item</code> is currently (at least
1151: * partially) visible on the <code>Form</code> it is on.
1152: * This is maintained by the <code>Item</code> superclass for easy
1153: * use by subclass code.
1154: */
1155: boolean visibleInViewport; // = false
1156:
1157: /**
1158: * Flags that are set to true when calling invalidate() on this item.
1159: * If it is known that one of the dimensions remains the same, then
1160: * the responding invalid flag will stay <code>false</code>.
1161: * It will turn to <code>false</code> after it gets laid out.
1162: * This is set by <code>Item</code> class and read by
1163: * <code>FormLFImpl</code> during layout.
1164: */
1165: boolean[] actualBoundsInvalid;
1166:
1167: /**
1168: * Cached preferred height when validRequestedSizes is <code>false</code>.
1169: */
1170: private int preferredHeight;
1171:
1172: /**
1173: * Cached preferred width when validRequestedSizes is <code>false</code>.
1174: */
1175: private int preferredWidth;
1176:
1177: /**
1178: * Cached minimum height when validRequestedSizes is <code>false</code>.
1179: */
1180: private int minimumHeight;
1181:
1182: /**
1183: * Cached minimum width when validRequestedSizes is <code>false</code>.
1184: */
1185: private int minimumWidth;
1186:
1187: /**
1188: * If set to true rely on native scrolling mechanism of this item
1189: * and give this item all width and height available.
1190: * (Used for TextBox and List implementation).
1191: */
1192: boolean supportsNativeScrolling; // = false
1193: /**
1194: * This flag marks if the last layout performed placed
1195: * this <code>Item</code> at the beginning of a line.
1196: * This variable is set and read by <code>FormLFImpl</code> during
1197: * layout.
1198: */
1199: boolean isNewLine = false;
1200:
1201: /**
1202: * Marks the height of the row this <code>Item</code> is placed on.
1203: * Note that the <code>Item</code> may be shorter than the height of
1204: * the row.
1205: * This variable is set and read by <code>FormLFImpl</code> during layout.
1206: */
1207: int rowHeight = 0;
1208:
1209: /**
1210: * A constant used to indicate that Item sizes have to be recalculated.
1211: */
1212: static final int INVALID_SIZE = -1;
1213:
1214: /**
1215: * Width used for last calculations. If that indicates if the preferredHeight, preferredWidth,
1216: * minimumHeight, minimumWidth are valid, or need a new query.
1217: */
1218: int cachedWidth = INVALID_SIZE;
1219: }
|