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: /**
0030: * A superclass for components that can be added to a {@link Form
0031: * Form}. All <code>Item</code> objects have a label field,
0032: * which is a string that is
0033: * attached to the item. The label is typically displayed near the component
0034: * when it is displayed within a screen. The label should be positioned on
0035: * the same horizontal row as the item or
0036: * directly above the item. The implementation should attempt to distinguish
0037: * label strings from other textual content, possibly by displaying the label
0038: * in a different font, aligning it to a different margin, or appending a
0039: * colon to it if it is placed on the same line as other string content.
0040: * If the screen is scrolling, the implementation should try
0041: * to keep the label visible at the same time as the <code>Item</code>.
0042: *
0043: * <p>In some cases,
0044: * when the user attempts to interact with an <code>Item</code>,
0045: * the system will switch to
0046: * a system-generated screen where the actual interaction takes place. If
0047: * this occurs, the label will generally be carried along and displayed within
0048: * this new screen in order to provide the user with some context for the
0049: * operation. For this reason it is recommended that applications supply a
0050: * label to all interactive Item objects. However, this is not required, and
0051: * a <code>null</code> value for a label is legal and specifies
0052: * the absence of a label.
0053: * </p>
0054: *
0055: * <h3>Item Layout</h3>
0056: *
0057: * <p>An <code>Item's</code> layout within its container is
0058: * influenced through layout directives:</p>
0059: *
0060: * <ul>
0061: * <li> <code>LAYOUT_DEFAULT</code> </li>
0062: * <li> <code>LAYOUT_LEFT</code> </li>
0063: * <li> <code>LAYOUT_RIGHT</code> </li>
0064: * <li> <code>LAYOUT_CENTER</code> </li>
0065: * <li> <code>LAYOUT_TOP</code> </li>
0066: * <li> <code>LAYOUT_BOTTOM</code> </li>
0067: * <li> <code>LAYOUT_VCENTER</code> </li>
0068: * <li> <code>LAYOUT_NEWLINE_BEFORE</code> </li>
0069: * <li> <code>LAYOUT_NEWLINE_AFTER</code> </li>
0070: * <li> <code>LAYOUT_SHRINK</code> </li>
0071: * <li> <code>LAYOUT_VSHRINK</code> </li>
0072: * <li> <code>LAYOUT_EXPAND</code> </li>
0073: * <li> <code>LAYOUT_VEXPAND</code> </li>
0074: * <li> <code>LAYOUT_2</code> </li>
0075: * </ul>
0076: *
0077: * <p>The <code>LAYOUT_DEFAULT</code> directive indicates
0078: * that the container's default
0079: * layout policy is to be used for this item.
0080: * <code>LAYOUT_DEFAULT</code> has the value
0081: * zero and has no effect when combined with other layout directives. It is
0082: * useful within programs in order to document the programmer's intent.</p>
0083: *
0084: * <p>The <code>LAYOUT_LEFT</code>, <code>LAYOUT_RIGHT</code>, and
0085: * <code>LAYOUT_CENTER</code> directives indicate
0086: * horizontal alignment and are mutually exclusive. Similarly, the
0087: * <code>LAYOUT_TOP</code>, <code>LAYOUT_BOTTOM</code>, and
0088: * <code>LAYOUT_VCENTER</code> directives indicate vertical
0089: * alignment and are mutually exclusive.</p>
0090: *
0091: * <p>A horizontal alignment directive, a vertical alignment directive, and
0092: * any combination of other layout directives may be combined using the
0093: * bit-wise <code>OR</code> operator (<code>|</code>) to compose a
0094: * layout directive value. Such a value
0095: * is used as the parameter to the {@link #setLayout} method and is the return
0096: * value from the {@link #getLayout} method.</p>
0097: *
0098: * <p>Some directives have no defined behavior in some contexts. A layout
0099: * directive is ignored if its behavior is not defined for the particular
0100: * context within which the <code>Item</code> resides.</p>
0101: *
0102: * <p>A complete specification of the layout of <code>Items</code>
0103: * within a <code>Form</code> is given
0104: * <a href="Form.html#layout">here</a>.</p>
0105: *
0106: * <a name="sizes"></a>
0107: * <h3>Item Sizes</h3>
0108: *
0109: * <p><code>Items</code> have two explicit size concepts: the <em>minimum</em>
0110: * size and the
0111: * <em>preferred</em> size. Both the minimum and the preferred sizes refer to
0112: * the total area of the <code>Item</code>, which includes space for the
0113: * <code>Item's</code> contents,
0114: * the <code>Item's</code> label, as well as other space that is
0115: * significant to the layout
0116: * policy. These sizes do not include space that is not significant for
0117: * layout purposes. For example, if the addition of a label to an
0118: * <code>Item</code> would
0119: * cause other <code>Items</code> to move in order to make room,
0120: * then the space occupied by
0121: * this label is significant to layout and is counted as part of
0122: * the <code>Item's</code>
0123: * minimum and preferred sizes. However, if an implementation were to place
0124: * the label in a margin area reserved exclusively for labels, this would not
0125: * affect the layout of neighboring <code>Items</code>.
0126: * In this case, the space occupied
0127: * by the label would not be considered part of the minimum and preferred
0128: * sizes.</p>
0129: *
0130: * <p>The minimum size is the smallest size at which the
0131: * <code>Item</code> can function and
0132: * display its contents, though perhaps not optimally. The minimum size
0133: * may be recomputed whenever the <code>Item's</code> contents changes.</p>
0134: *
0135: * <p>The preferred size is generally a size based on the
0136: * <code>Item's</code> contents and
0137: * is the smallest size at which no information is clipped and text wrapping
0138: * (if any) is kept to a tolerable minimum. The preferred size may be
0139: * recomputed whenever the <code>Item's</code> contents changes.
0140: * The application can
0141: * <em>lock</em> the preferred width or preferred height (or both) by
0142: * supplying specific values for parameters to the {@link #setPreferredSize
0143: * setPreferredSize} method. The manner in which an
0144: * <code>Item</code> fits its contents
0145: * within an application-specified preferred size is implementation-specific.
0146: * However, it is recommended that textual content be word-wrapped to fit the
0147: * preferred size set by the application. The application can <em>unlock</em>
0148: * either or both dimensions by supplying the value <code>-1</code>
0149: * for parameters to the <code>setPreferredSize</code> method.</p>
0150: *
0151: * <p>When an <code>Item</code> is created, both the preferred width
0152: * and height are
0153: * unlocked. In this state, the implementation computes the preferred width
0154: * and height based on the <code>Item's</code> contents, possibly
0155: * including other relevant
0156: * factors such as the <code>Item's</code> graphic design and the
0157: * screen dimensions.
0158: * After having locked either the preferred width or height, the application
0159: * can restore the initial, unlocked state by calling
0160: * <code>setPreferredSize(-1, -1)</code>.</p>
0161: *
0162: * <p>The application can lock one dimension of the preferred size and leave
0163: * the other unlocked. This causes the system to compute an appropriate value
0164: * for the unlocked dimension based on arranging the contents to fit the
0165: * locked dimension. If the contents changes, the size on the unlocked
0166: * dimension is recomputed to reflect the new contents, but the size on the
0167: * locked dimension remains unchanged. For example, if the application called
0168: * <code>setPreferredSize(50, -1)</code>, the preferred width would be
0169: * locked at <code>50</code> pixels and the preferred height would
0170: * be computed based on the
0171: * <code>Item's</code> contents. Similarly, if the application called
0172: * <code>setPreferredSize(-1, 60)</code>, the preferred height would be
0173: * locked at <code>60</code> pixels and the preferred width would be
0174: * computed based on the
0175: * <code>Item's</code> contents. This feature is particularly useful
0176: * for <code>Items</code> with
0177: * textual content that can be line wrapped.</p>
0178: *
0179: * <p>The application can also lock both the preferred width and height to
0180: * specific values. The <code>Item's</code> contents are truncated or padded
0181: * as necessary to honor this request. For <code>Items</code> containing
0182: * text, the text should be wrapped to the specified width, and any truncation
0183: * should occur at the end of the text.</p>
0184: *
0185: * <p><code>Items</code> also have an implicit maximum size provided by the
0186: * implementation. The maximum width is typically based on the width of the
0187: * screen space available to a <code>Form</code>. Since <code>Forms</code>
0188: * can scroll vertically, the maximum height should typically not be based on
0189: * the height of the available screen space.</p>
0190: *
0191: * <p>If the application attempts to lock a preferred size dimension to a
0192: * value smaller than the minimum or larger than the maximum, the
0193: * implementation may disregard the requested value and instead use either the
0194: * minimum or maximum as appropriate. If this occurs, the actual values used
0195: * must be visible to the application via the values returned from the
0196: * {@link #getPreferredWidth getPreferredWidth} and
0197: * {@link #getPreferredHeight getPreferredHeight} methods.
0198: * </p>
0199: *
0200: * <h3>Commands</h3>
0201: *
0202: * <p>A <code>Command</code> is said to be present on an <code>Item</code>
0203: * if the <code>Command</code> has been
0204: * added to this <code>Item</code> with a prior call to {@link #addCommand}
0205: * or {@link #setDefaultCommand} and if
0206: * the <code>Command</code> has not been removed with a subsequent call to
0207: * {@link #removeCommand}. <code>Commands</code> present on an
0208: * item should have a command
0209: * type of <code>ITEM</code>. However, it is not an error for a
0210: * command whose type is
0211: * other than <code>ITEM</code> to be added to an item.
0212: * For purposes of presentation and
0213: * placement within its user interface, the implementation is allowed to
0214: * treat a command's items as if they were of type <code>ITEM</code>. </p>
0215: *
0216: * <p><code>Items</code> may have a <em>default</em> <code>Command</code>.
0217: * This state is
0218: * controlled by the {@link #setDefaultCommand} method. The default
0219: * <code>Command</code> is eligible to be bound to a special
0220: * platform-dependent user
0221: * gesture. The implementation chooses which gesture is the most
0222: * appropriate to initiate the default command on that particular
0223: * <code>Item</code>.
0224: * For example, on a device that has a dedicated selection key, pressing
0225: * this key might invoke the item's default command. Or, on a
0226: * stylus-based device, tapping on the <code>Item</code> might
0227: * invoke its default
0228: * command. Even if it can be invoked through a special gesture, the
0229: * default command should also be invokable in the same fashion as
0230: * other item commands.</p>
0231: *
0232: * <p>It is possible that on some devices there is no special gesture
0233: * suitable for invoking the default command on an item. In this case
0234: * the default command must be accessible to the user in the same
0235: * fashion as other item commands. The implementation may use the state
0236: * of a command being the default in deciding where to place the command
0237: * in its user interface.</p>
0238: *
0239: * <p>It is possible for an <code>Item</code> not to have a default command.
0240: * In this
0241: * case, the implementation may bind its special user gesture (if any)
0242: * for another purpose, such as for displaying a menu of commands. The
0243: * default state of an <code>Item</code> is not to have a default command.
0244: * An <code>Item</code>
0245: * may be set to have no default <code>Command</code> by removing it from
0246: * the <code>Item</code> or
0247: * by passing <code>null</code> to the <code>setDefaultCommand()</code>
0248: * method.</p>
0249: *
0250: * <p>The same command may occur on more than one
0251: * <code>Item</code> and also on more than
0252: * one <code>Displayable</code>. If this situation occurs, the user
0253: * must be provided with
0254: * distinct gestures to invoke that command on each <code>Item</code> or
0255: * <code>Displayable</code> on
0256: * which it occurs, while those <code>Items</code> or <code>Displayables</code>
0257: * are visible on the
0258: * display. When the user invokes the command, the listener
0259: * (<code>CommandListener</code>
0260: * or <code>ItemCommandListener</code> as appropriate) of just the
0261: * object on which the
0262: * command was invoked will be called.</p>
0263: *
0264: * <p>Adding commands to an <code>Item</code> may affect its appearance, the
0265: * way it is laid out, and the traversal behavior. For example, the presence
0266: * of commands on an <code>Item</code> may cause row breaks to occur, or it
0267: * may cause additional graphical elements (such as a menu icon) to appear.
0268: * In particular, if a <code>StringItem</code> whose appearance mode is
0269: * <code>PLAIN</code> (see below) is given one or more <code>Commands</code>,
0270: * the implementation is allowed to treat it as if it had a different
0271: * appearance mode.</p>
0272: *
0273: * <a name="appearance"></a>
0274: * <h3>Appearance Modes</h3>
0275: *
0276: * <p>The <code>StringItem</code> and <code>ImageItem</code> classes have an
0277: * <em>appearance mode</em> attribute that can be set in their constructors.
0278: * This attribute can have one of the values {@link #PLAIN PLAIN},
0279: * {@link #HYPERLINK HYPERLINK}, or {@link #BUTTON BUTTON}.
0280: * An appearance mode of <code>PLAIN</code> is typically used
0281: * for non-interactive
0282: * display of textual or graphical material. The appearance
0283: * mode values do not have any side effects on the interactivity of the item.
0284: * In order to be interactive, the item must have one or more
0285: * <code>Commands</code>
0286: * (preferably with a default command assigned), and it must have a
0287: * <code>CommandListener</code> that receives notification of
0288: * <code>Command</code> invocations. The
0289: * appearance mode values also do not have any effect on the semantics of
0290: * <code>Command</code> invocation on the item. For example,
0291: * setting the appearance mode
0292: * of a <code>StringItem</code> to be <code>HYPERLINK</code>
0293: * requests that the implementation display
0294: * the string contents as if they were a hyperlink in a browser. It is the
0295: * application's responsibility to attach a <code>Command</code>
0296: * and a listener to the
0297: * <code>StringItem</code> that provide behaviors that the user
0298: * would expect from invoking
0299: * an operation on a hyperlink, such as loading the referent of the link or
0300: * adding the link to the user's set of bookmarks.</p>
0301: *
0302: * <p>Setting the appearance mode of an <code>Item</code> to be other than
0303: * <code>PLAIN</code> may affect its minimum, preferred, and maximum sizes, as
0304: * well as the way it is laid out. For example, a <code>StringItem</code>
0305: * with an appearance mode of <code>BUTTON</code> should not be wrapped across
0306: * rows. (However, a <code>StringItem</code> with an appearance mode of
0307: * <code>HYPERLINK</code> should be wrapped the same way as if its appearance
0308: * mode is <code>PLAIN</code>.)</p>
0309: *
0310: * <p>A <code>StringItem</code> or <code>ImageItem</code>
0311: * in <code>BUTTON</code> mode can be used to create a
0312: * button-based user interface. This can easily lead to applications that are
0313: * inconvenient to use. For example, in a traversal-based system, users must
0314: * navigate to a button before they can invoke any commands on it. If buttons
0315: * are spread across a long <code>Form</code>, users may be required
0316: * to perform a
0317: * considerable amount of navigation in order to discover all the available
0318: * commands. Furthermore, invoking a command from a button at the
0319: * other end of the <code>Form</code> can be quite cumbersome.
0320: * Traversal-based systems
0321: * often provide a means of invoking commands from anywhere (such as from a
0322: * menu), without the need to traverse to a particular item. Instead of
0323: * adding a command to a button and placing that button into a
0324: * <code>Form</code>, it would
0325: * often be more appropriate and convenient for users if that command were
0326: * added directly to the <code>Form</code>. Buttons should be used
0327: * only in cases where
0328: * direct user interaction with the item's string or image contents is
0329: * essential to the user's understanding of the commands that can be invoked
0330: * from that item.</p>
0331: *
0332: * <h3>Default State</h3>
0333: *
0334: * <p>Unless otherwise specified by a subclass, the default state of newly
0335: * created <code>Items</code> is as follows:</p>
0336: *
0337: * <ul>
0338: * <li>the <code>Item</code> is not contained within
0339: * ("owned by") any container;</li>
0340: * <li>there are no <code>Commands</code> present;</li>
0341: * <li>the default <code>Command</code> is <code>null</code>;</li>
0342: * <li>the <code>ItemCommandListener</code> is <code>null</code>;</li>
0343: * <li>the layout directive value is <code>LAYOUT_DEFAULT</code>; and</li>
0344: * <li>both the preferred width and preferred height are unlocked.</li>
0345: * </ul>
0346: *
0347: * @since MIDP 1.0
0348: */
0349:
0350: abstract public class Item {
0351:
0352: // ************************************************************
0353: // public member variables
0354: // ************************************************************
0355:
0356: /**
0357: * A layout directive indicating that this <code>Item</code>
0358: * should follow the default layout policy of its container.
0359: *
0360: * <P>Value <code>0</code> is assigned to <code>LAYOUT_DEFAULT</code>.</P>
0361: *
0362: */
0363: public final static int LAYOUT_DEFAULT = 0;
0364:
0365: /**
0366: * A layout directive indicating that this <code>Item</code> should have a
0367: * left-aligned layout.
0368: *
0369: * <P>Value <code>1</code> is assigned to <code>LAYOUT_LEFT</code>.</P>
0370: */
0371: public final static int LAYOUT_LEFT = 1;
0372:
0373: /**
0374: * A layout directive indicating that this <code>Item</code> should have a
0375: * right-aligned layout.
0376: *
0377: * <P>Value <code>2</code> is assigned to <code>LAYOUT_RIGHT</code>.</P>
0378: */
0379: public final static int LAYOUT_RIGHT = 2;
0380:
0381: /**
0382: * A layout directive indicating that this <code>Item</code> should have a
0383: * horizontally centered layout.
0384: *
0385: * <P>Value <code>3</code> is assigned to <code>LAYOUT_CENTER</code>.</P>
0386: */
0387: public final static int LAYOUT_CENTER = 3;
0388:
0389: /**
0390: * A layout directive indicating that this <code>Item</code> should have a
0391: * top-aligned layout.
0392: *
0393: * <P>Value <code>0x10</code> is assigned to <code>LAYOUT_TOP</code>.</P>
0394: */
0395: public final static int LAYOUT_TOP = 0x10;
0396:
0397: /**
0398: * A layout directive indicating that this <code>Item</code> should have a
0399: * bottom-aligned layout.
0400: *
0401: * <P>Value <code>0x20</code> is assigned to <code>LAYOUT_BOTTOM</code>.</P>
0402: */
0403: public final static int LAYOUT_BOTTOM = 0x20;
0404:
0405: /**
0406: * A layout directive indicating that this <code>Item</code> should have a
0407: * vertically centered layout.
0408: *
0409: * <P>Value <code>0x30</code> is assigned to
0410: * <code>LAYOUT_VCENTER</code>.</P>
0411: */
0412: public final static int LAYOUT_VCENTER = 0x30;
0413:
0414: /**
0415: * A layout directive indicating that this <code>Item</code>
0416: * should be placed at the beginning of a new line or row.
0417: *
0418: * <P>Value <code>0x100</code> is assigned to
0419: * <code>LAYOUT_NEWLINE_BEFORE</code>.</P>
0420: */
0421: public final static int LAYOUT_NEWLINE_BEFORE = 0x100;
0422:
0423: /**
0424: * A layout directive indicating that this <code>Item</code>
0425: * should the last on its line or row, and that the next
0426: * <code>Item</code> (if any) in the container
0427: * should be placed on a new line or row.
0428: *
0429: * <P>Value <code>0x200</code> is assigned to
0430: * <code>LAYOUT_NEWLINE_AFTER</code>.</P>
0431: */
0432: public final static int LAYOUT_NEWLINE_AFTER = 0x200;
0433:
0434: /**
0435: * A layout directive indicating that this <code>Item's</code>
0436: * width may be reduced to its minimum width.
0437: *
0438: *<P>Value <code>0x400</code> is assigned to <code>LAYOUT_SHRINK</code></P>
0439: */
0440: public final static int LAYOUT_SHRINK = 0x400;
0441:
0442: /**
0443: * A layout directive indicating that this <code>Item's</code>
0444: * width may be increased to fill available space.
0445: *
0446: *<P>Value <code>0x800</code> is assigned to <code>LAYOUT_EXPAND</code>.</P>
0447: */
0448: public final static int LAYOUT_EXPAND = 0x800;
0449:
0450: /**
0451: * A layout directive indicating that this <code>Item's</code>
0452: * height may be reduced to its minimum height.
0453: *
0454: * <P>Value <code>0x1000</code> is assigned to
0455: * <code>LAYOUT_VSHRINK</code>.</P>
0456: */
0457: public final static int LAYOUT_VSHRINK = 0x1000;
0458:
0459: /**
0460: * A layout directive indicating that this <code>Item's</code>
0461: * height may be increased to fill available space.
0462: *
0463: * <P>Value <code>0x2000</code> is assigned to
0464: * <code>LAYOUT_VEXPAND</code>.</P>
0465: */
0466: public final static int LAYOUT_VEXPAND = 0x2000;
0467:
0468: /**
0469: * A layout directive indicating that new MIDP layout
0470: * rules are in effect for this <code>Item</code>. If this
0471: * bit is clear, indicates that MIDP 1.0 layout behavior
0472: * applies to this <code>Item</code>.
0473: *
0474: * <P>Value <code>0x4000</code> is assigned to
0475: * <code>LAYOUT_2</code>.</P>
0476: *
0477: */
0478: public static final int LAYOUT_2 = 0x4000;
0479:
0480: /**
0481: * An appearance mode value indicating that the <code>Item</code> is to have
0482: * a normal appearance.
0483: *
0484: * <P>Value <code>0</code> is assigned to <code>PLAIN</code>.</P>
0485: */
0486: public final static int PLAIN = 0;
0487:
0488: /**
0489: * An appearance mode value indicating that the <code>Item</code>
0490: * is to appear as a hyperlink.
0491: * <P>Value <code>1</code> is assigned to <code>HYPERLINK</code>.</P>
0492: */
0493: public final static int HYPERLINK = 1;
0494:
0495: /**
0496: * An appearance mode value indicating that the <code>Item</code>
0497: * is to appear as a button.
0498: * <P>Value <code>2</code> is assigned to <code>BUTTON</code>.</P>
0499: */
0500: public final static int BUTTON = 2;
0501:
0502: // ************************************************************
0503: // Static initializer, constructor
0504: // ************************************************************
0505:
0506: /**
0507: * Creates a new item with a given label.
0508: *
0509: * @param label the label string; null is allowed
0510: */
0511: Item(String label) {
0512: // SYNC NOTE: probably safe, but since subclasses can't lock
0513: // around their call to super(), we'll lock it here
0514: synchronized (Display.LCDUILock) {
0515: this .label = label;
0516: }
0517: }
0518:
0519: // ************************************************************
0520: // public methods
0521: // ************************************************************
0522:
0523: /**
0524: * Sets the label of the <code>Item</code>. If <code>label</code>
0525: * is <code>null</code>, specifies that this item has no label.
0526: *
0527: * <p>It is illegal to call this method if this <code>Item</code>
0528: * is contained within an <code>Alert</code>.</p>
0529: *
0530: * @param label the label string
0531: * @throws IllegalStateException if this <code>Item</code> is contained
0532: * within an <code>Alert</code>
0533: * @see #getLabel
0534: */
0535: public void setLabel(String label) {
0536: synchronized (Display.LCDUILock) {
0537: if (label != this .label
0538: && (label == null || !label.equals(this .label))) {
0539: this .label = label;
0540: itemLF.lSetLabel(label);
0541: }
0542: }
0543: }
0544:
0545: /**
0546: * Gets the label of this <code>Item</code> object.
0547: * @return the label string
0548: * @see #setLabel
0549: */
0550: public String getLabel() {
0551: // SYNC NOTE: return of atomic value, no locking necessary
0552: return label;
0553: }
0554:
0555: /**
0556: * Gets the layout directives used for placing the item.
0557: * @return a combination of layout directive values
0558: * @see #setLayout
0559: */
0560: public int getLayout() {
0561: // SYNC NOTE: return of atomic value, no locking necessary
0562: return layout;
0563: }
0564:
0565: /**
0566: * Sets the layout directives for this item.
0567: *
0568: * <p>It is illegal to call this method if this <code>Item</code>
0569: * is contained within an <code>Alert</code>.</p>
0570: *
0571: * @param layout a combination of layout directive values for this item
0572: * @throws IllegalArgumentException if the value of layout is not a
0573: * bit-wise OR combination of layout directives
0574: * @throws IllegalStateException if this <code>Item</code> is
0575: * contained within an <code>Alert</code>
0576: * @see #getLayout
0577: */
0578: public void setLayout(int layout) {
0579: synchronized (Display.LCDUILock) {
0580: int oldLayout = this .layout;
0581: setLayoutImpl(layout);
0582: if (oldLayout != this .layout) {
0583: itemLF.lSetLayout(layout);
0584: }
0585: }
0586: }
0587:
0588: /**
0589: * Adds a context sensitive <code>Command</code> to the item.
0590: * The semantic type of
0591: * <code>Command</code> should be <code>ITEM</code>. The implementation
0592: * will present the command
0593: * only when the item is active, for example, highlighted.
0594: * <p>
0595: * If the added command is already in the item (tested by comparing the
0596: * object references), the method has no effect. If the item is
0597: * actually visible on the display, and this call affects the set of
0598: * visible commands, the implementation should update the display as soon
0599: * as it is feasible to do so.
0600: *
0601: * <p>It is illegal to call this method if this <code>Item</code>
0602: * is contained within an <code>Alert</code>.</p>
0603: *
0604: * @param cmd the command to be added
0605: * @throws IllegalStateException if this <code>Item</code> is contained
0606: * within an <code>Alert</code>
0607: * @throws NullPointerException if cmd is <code>null</code>
0608: */
0609: public void addCommand(Command cmd) {
0610: synchronized (Display.LCDUILock) {
0611: addCommandImpl(cmd);
0612: }
0613: }
0614:
0615: /**
0616: * Removes the context sensitive command from item. If the command is not
0617: * in the <code>Item</code> (tested by comparing the object references),
0618: * the method has
0619: * no effect. If the <code>Item</code> is actually visible on the display,
0620: * and this call
0621: * affects the set of visible commands, the implementation should update
0622: * the display as soon as it is feasible to do so.
0623: *
0624: *
0625: * If the command to be removed happens to be the default command,
0626: * the command is removed and the default command on this Item is
0627: * set to <code>null</code>.
0628: *
0629: * The following code:
0630: * <CODE> <pre>
0631: * // Command c is the default command on Item item
0632: * item.removeCommand(c);
0633: * </pre> </CODE>
0634: * is equivalent to the following code:
0635: * <CODE> <pre>
0636: * // Command c is the default command on Item item
0637: * item.setDefaultCommand(null);
0638: * item.removeCommand(c);
0639: * </pre> </CODE>
0640: *
0641: *
0642: * @param cmd the command to be removed
0643: */
0644: public void removeCommand(Command cmd) {
0645: synchronized (Display.LCDUILock) {
0646: removeCommandImpl(cmd);
0647: }
0648: }
0649:
0650: /**
0651: * Sets a listener for <code>Commands</code> to this <code>Item</code>,
0652: * replacing any previous
0653: * <code>ItemCommandListener</code>. A <code>null</code> reference
0654: * is allowed and has the effect of
0655: * removing any existing listener.
0656: *
0657: * <p>It is illegal to call this method if this <code>Item</code>
0658: * is contained within an <code>Alert</code>.</p>
0659: *
0660: * @param l the new listener, or <code>null</code>.
0661: * @throws IllegalStateException if this <code>Item</code> is contained
0662: * within an <code>Alert</code>
0663: */
0664: public void setItemCommandListener(ItemCommandListener l) {
0665: synchronized (Display.LCDUILock) {
0666: commandListener = l;
0667: }
0668: }
0669:
0670: /**
0671: * Gets the preferred width of this <code>Item</code>.
0672: * If the application has locked
0673: * the width to a specific value, this method returns that value.
0674: * Otherwise, the return value is computed based on the
0675: * <code>Item's</code> contents,
0676: * possibly with respect to the <code>Item's</code> preferred height
0677: * if it is locked.
0678: * See <a href="#sizes">Item Sizes</a> for a complete discussion.
0679: *
0680: * @return the preferred width of the Item
0681: * @see #getPreferredHeight
0682: * @see #setPreferredSize
0683: */
0684: public int getPreferredWidth() {
0685: synchronized (Display.LCDUILock) {
0686: if (lockedWidth != -1) {
0687: return lockedWidth;
0688: } else {
0689: return itemLF.lGetPreferredWidth(lockedHeight);
0690: }
0691: }
0692: }
0693:
0694: /**
0695: * Gets the preferred height of this <code>Item</code>.
0696: * If the application has locked
0697: * the height to a specific value, this method returns that value.
0698: * Otherwise, the return value is computed based on the
0699: * <code>Item's</code> contents,
0700: * possibly with respect to the <code>Item's</code> preferred
0701: * width if it is locked.
0702: * See <a href="#sizes">Item Sizes</a> for a complete discussion.
0703: *
0704: * @return the preferred height of the <code>Item</code>
0705: * @see #getPreferredWidth
0706: * @see #setPreferredSize
0707: */
0708: public int getPreferredHeight() {
0709: synchronized (Display.LCDUILock) {
0710: if (lockedHeight != -1) {
0711: return lockedHeight;
0712: } else {
0713: return itemLF.lGetPreferredHeight(lockedWidth);
0714: }
0715: }
0716: }
0717:
0718: /**
0719: * Sets the preferred width and height for this <code>Item</code>.
0720: * Values for width and height less than <code>-1</code> are illegal.
0721: * If the width is between zero and the minimum width, inclusive,
0722: * the minimum width is used instead.
0723: * If the height is between zero and the minimum height, inclusive,
0724: * the minimum height is used instead.
0725: *
0726: * <p>Supplying a width or height value greater than the minimum width or
0727: * height <em>locks</em> that dimension to the supplied
0728: * value. The implementation may silently enforce a maximum dimension for
0729: * an <code>Item</code> based on factors such as the screen size.
0730: * Supplying a value of
0731: * <code>-1</code> for the width or height unlocks that dimension.
0732: * See <a href="#sizes">Item Sizes</a> for a complete discussion.</p>
0733: *
0734: * <p>It is illegal to call this method if this <code>Item</code>
0735: * is contained within an <code>Alert</code>.</p>
0736: *
0737: * @param width the value to which the width should be locked, or
0738: * <code>-1</code> to unlock
0739: * @param height the value to which the height should be locked, or
0740: * <code>-1</code> to unlock
0741: * @throws IllegalArgumentException if width or height is less than
0742: * <code>-1</code>
0743: * @throws IllegalStateException if this <code>Item</code> is contained
0744: * within an <code>Alert</code>
0745: * @see #getPreferredHeight
0746: * @see #getPreferredWidth
0747: */
0748: public void setPreferredSize(int width, int height) {
0749: if (width < -1 || height < -1) {
0750: throw new IllegalArgumentException();
0751: }
0752:
0753: synchronized (Display.LCDUILock) {
0754:
0755: if (owner != null && owner instanceof Alert) {
0756: throw new IllegalStateException();
0757: }
0758:
0759: userPreferredWidth = width;
0760: userPreferredHeight = height;
0761:
0762: lUpdateLockedSize();
0763:
0764: } // synchronized
0765: }
0766:
0767: /**
0768: * Re-calculate the locked width and height using the current values
0769: * of preferred and minimum width and height.
0770: */
0771: void lUpdateLockedSize() {
0772: // Collect minimum size information
0773: int minWidth = itemLF.lGetMinimumWidth();
0774: int minHeight = itemLF.lGetMinimumHeight();
0775:
0776: int newLockedWidth = (userPreferredWidth != -1 && userPreferredWidth < minWidth) ? minWidth
0777: : userPreferredWidth;
0778:
0779: int newLockedHeight = (userPreferredHeight != -1 && userPreferredHeight < minHeight) ? minHeight
0780: : userPreferredHeight;
0781: if (newLockedWidth != lockedWidth
0782: || newLockedHeight != lockedHeight) {
0783: lockedWidth = newLockedWidth;
0784: lockedHeight = newLockedHeight;
0785: itemLF.lSetPreferredSize(lockedWidth, lockedHeight);
0786: }
0787: }
0788:
0789: /**
0790: * Gets the minimum width for this <code>Item</code>. This is a width
0791: * at which the item can function and display its contents,
0792: * though perhaps not optimally.
0793: * See <a href="#sizes">Item Sizes</a> for a complete discussion.
0794: *
0795: * @return the minimum width of the item
0796: */
0797: public int getMinimumWidth() {
0798: synchronized (Display.LCDUILock) {
0799: return itemLF.lGetMinimumWidth();
0800: }
0801: }
0802:
0803: /**
0804: * Gets the minimum height for this <code>Item</code>. This is a height
0805: * at which the item can function and display its contents,
0806: * though perhaps not optimally.
0807: * See <a href="#sizes">Item Sizes</a> for a complete discussion.
0808: *
0809: * @return the minimum height of the item
0810: */
0811: public int getMinimumHeight() {
0812: synchronized (Display.LCDUILock) {
0813: return itemLF.lGetMinimumHeight();
0814: }
0815: }
0816:
0817: /**
0818: * Sets default <code>Command</code> for this <code>Item</code>.
0819: * If the <code>Item</code> previously had a
0820: * default <code>Command</code>, that <code>Command</code>
0821: * is no longer the default, but it
0822: * remains present on the <code>Item</code>.
0823: *
0824: * <p>If not <code>null</code>, the <code>Command</code> object
0825: * passed becomes the default <code>Command</code>
0826: * for this <code>Item</code>. If the <code>Command</code> object
0827: * passed is not currently present
0828: * on this <code>Item</code>, it is added as if {@link #addCommand}
0829: * had been called
0830: * before it is made the default <code>Command</code>.</p>
0831: *
0832: * <p>If <code>null</code> is passed, the <code>Item</code> is set to
0833: * have no default <code>Command</code>.
0834: * The previous default <code>Command</code>, if any, remains present
0835: * on the <code>Item</code>.
0836: * </p>
0837: *
0838: * <p>It is illegal to call this method if this <code>Item</code>
0839: * is contained within an <code>Alert</code>.</p>
0840: *
0841: * @param cmd the command to be used as this <code>Item's</code> default
0842: * <code>Command</code>, or <code>null</code> if there is to
0843: * be no default command
0844: *
0845: * @throws IllegalStateException if this <code>Item</code> is contained
0846: * within an <code>Alert</code>
0847: */
0848: public void setDefaultCommand(Command cmd) {
0849: synchronized (Display.LCDUILock) {
0850: if (defaultCommand != cmd) {
0851: // Make sure the command present on the Item
0852: if (cmd != null) {
0853: addCommandImpl(cmd);
0854: }
0855:
0856: // Set it as new default command
0857: defaultCommand = cmd;
0858: itemLF.lSetDefaultCommand(defaultCommand, numCommands);
0859: }
0860: }
0861: }
0862:
0863: /**
0864: * Causes this <code>Item's</code> containing <code>Form</code> to notify
0865: * the <code>Item's</code> {@link ItemStateListener}.
0866: * The application calls this method to inform the
0867: * listener on the <code>Item</code> that the <code>Item's</code>
0868: * state has been changed in
0869: * response to an action. Even though this method simply causes a call
0870: * to another part of the application, this mechanism is useful for
0871: * decoupling the implementation of an <code>Item</code> (in particular, the
0872: * implementation of a <code>CustomItem</code>, though this also applies to
0873: * subclasses of other items) from the consumer of the item.
0874: *
0875: * <p>If an edit was performed by invoking a separate screen, and the
0876: * editor now wishes to "return" to the form which contained the
0877: * selected <code>Item</code>, the preferred method is
0878: * <code>Display.setCurrent(Item)</code>
0879: * instead of <code>Display.setCurrent(Displayable)</code>,
0880: * because it allows the
0881: * <code>Form</code> to restore focus to the <code>Item</code>
0882: * that initially invoked the editor.</p>
0883: *
0884: * <p>In order to make sure that the documented behavior of
0885: * <code>ItemStateListener</code> is maintained, it is up to the caller
0886: * (application) to guarantee that this function is
0887: * not called unless:</p>
0888: *
0889: * <ul>
0890: * <li>the <code>Item's</code> value has actually been changed, and</li>
0891: * <li>the change was the result of a user action (an "edit")
0892: * and NOT as a result of state change via calls to
0893: * <code>Item's</code> APIs </li>
0894: * </ul>
0895: *
0896: * <p>The call to <code>ItemStateListener.itemStateChanged</code>
0897: * may be delayed in order to be serialized with the event stream.
0898: * The <code>notifyStateChanged</code> method does not block awaiting
0899: * the completion of the <code>itemStateChanged</code> method.</p>
0900: *
0901: * @throws IllegalStateException if the <code>Item</code> is not owned
0902: * by a <code>Form</code>
0903: */
0904: public void notifyStateChanged() {
0905:
0906: synchronized (Display.LCDUILock) {
0907: // Among the public Displayables,
0908: // List, TextBox and Form are legal to own Items.
0909: // Canvas does not accept Item.
0910: // Alert is the only one that we need to prevent.
0911: if (owner == null || owner instanceof Alert) {
0912: throw new IllegalStateException();
0913: }
0914:
0915: // SYNC NOTE: Displayable.itemStateChanged() will
0916: // simply schedule a state change event. So it's
0917: // OK to call it while holding LCDUILock.
0918: owner.itemStateChanged(this );
0919: }
0920: }
0921:
0922: // ************************************************************
0923: // protected methods
0924: // ************************************************************
0925:
0926: // ************************************************************
0927: // package private methods
0928: // ************************************************************
0929:
0930: /**
0931: * Set the Screen owner of this Item
0932: * SYNC NOTE: Caller must hold LCDUILock around this call.
0933: *
0934: * @param owner The Screen containing this Item
0935: */
0936: void lSetOwner(Screen owner) {
0937: if (this .owner != null && owner != null) {
0938: throw new IllegalStateException();
0939: }
0940:
0941: Screen oldOwner = this .owner;
0942: this .owner = owner;
0943:
0944: itemLF.lSetOwner(oldOwner);
0945: }
0946:
0947: /**
0948: * Gets look & feel object associated with this
0949: * Item.
0950: * @return - ItemLF associated with this Item.
0951: */
0952: ItemLF getLF() {
0953: return itemLF;
0954: }
0955:
0956: /**
0957: * Return whether the Item takes user input focus.
0958: *
0959: * @return return <code>true</code> if abstract commands are present
0960: */
0961: boolean acceptFocus() {
0962: // user needs to access abstract commands
0963: return (numCommands > 0);
0964: }
0965:
0966: /**
0967: * Adds a context sensitive Command to the item.
0968: * LCDUI Lock must be acquired prior to calling this method.
0969: *
0970: * @param cmd the command to be added
0971: * @exception NullPointerException if cmd is null
0972: */
0973: private void addCommandImpl(Command cmd) {
0974: if (cmd == null) {
0975: throw new NullPointerException();
0976: }
0977:
0978: for (int i = 0; i < numCommands; ++i) {
0979: if (commands[i] == cmd) {
0980: return;
0981: }
0982: }
0983:
0984: if ((commands == null) || (numCommands == commands.length)) {
0985: Command[] newCommands = new Command[numCommands + 4];
0986: if (commands != null) {
0987: System.arraycopy(commands, 0, newCommands, 0,
0988: numCommands);
0989: }
0990: commands = newCommands;
0991: }
0992:
0993: commands[numCommands] = cmd;
0994: ++numCommands;
0995:
0996: itemLF.lAddCommand(cmd, numCommands);
0997: }
0998:
0999: /**
1000: * Removes the context sensitive command from item.
1001: * @param cmd the command to be removed
1002: */
1003: void removeCommandImpl(Command cmd) {
1004: // LCDUI Lock must be acquired
1005: // prior to calling this method.
1006: for (int i = 0; i < numCommands; ++i) {
1007: if (commands[i] == cmd) {
1008: commands[i] = commands[--numCommands];
1009: commands[numCommands] = null;
1010:
1011: if (cmd == defaultCommand) {
1012: defaultCommand = null;
1013: itemLF.lSetDefaultCommand(null, i);
1014: }
1015:
1016: itemLF.lRemoveCommand(cmd, i);
1017: return;
1018: }
1019: }
1020: }
1021:
1022: /**
1023: * Set the layout type of this Item
1024: *
1025: * @param layout The layout type.
1026: */
1027: void setLayoutImpl(int layout) {
1028: // LCDUI Lock must be acquired
1029: // prior to calling this method.
1030: if ((layout & ~VALID_LAYOUT) != 0) {
1031: throw new IllegalArgumentException();
1032: }
1033:
1034: this .layout = layout;
1035: }
1036:
1037: /**
1038: * Notify the item to the effect that it has been recently deleted
1039: */
1040: void itemDeleted() {
1041: synchronized (Display.LCDUILock) {
1042: lSetOwner(null);
1043: }
1044: }
1045:
1046: // ************************************************************
1047: // protected member variables
1048: // ************************************************************
1049:
1050: // ************************************************************
1051: // package private member variables
1052: // ************************************************************
1053:
1054: /** internal bitmask representing a valid layout mask */
1055: final static int VALID_LAYOUT;
1056:
1057: static {
1058: VALID_LAYOUT = Item.LAYOUT_DEFAULT | Item.LAYOUT_LEFT
1059: | Item.LAYOUT_RIGHT | Item.LAYOUT_CENTER
1060: | Item.LAYOUT_TOP | Item.LAYOUT_BOTTOM
1061: | Item.LAYOUT_VCENTER | Item.LAYOUT_SHRINK
1062: | Item.LAYOUT_EXPAND | Item.LAYOUT_VSHRINK
1063: | Item.LAYOUT_VEXPAND | Item.LAYOUT_NEWLINE_BEFORE
1064: | Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2;
1065: }
1066:
1067: /**
1068: * Item' Look&Feel object associated with this item
1069: * It is set in the subclasses constructors
1070: */
1071: ItemLF itemLF;
1072:
1073: /**
1074: * commandListener that has to be notified of when ITEM command is
1075: * activated
1076: */
1077: ItemCommandListener commandListener; // = null;
1078:
1079: /** The label of this Item */
1080: String label; // = null
1081:
1082: /**
1083: * The owner Screen for this Item
1084: */
1085: Screen owner; // = null
1086:
1087: /**
1088: * The layout type of this Item
1089: */
1090: int layout; // = 0 ; LAYOUT_DEFAULT = 0
1091:
1092: /** An array of Commands added to this Item */
1093: Command commands[];
1094:
1095: /** The number of Commands added to this Item */
1096: int numCommands; // = 0
1097:
1098: /**
1099: * This is a default Command which represents the callback
1100: * to a selection event.
1101: */
1102: Command defaultCommand; // = null
1103:
1104: /** The locked width of this Item, -1 by default.
1105: * If non-default, locked width is the maximum of minimal
1106: * width and the preferred width. */
1107: int lockedWidth = -1;
1108:
1109: /** The preferred width of this Item, specified in the last call
1110: * of setPreferredSize(int width, int height), -1 by default. */
1111: int userPreferredWidth = -1;
1112:
1113: /** The locked height of this Item, -1 by default.
1114: * If non-default, locked height is the maximum of minimal
1115: * height and the preferred height. */
1116: int lockedHeight = -1;
1117:
1118: /** The preferred height of this Item, specified in the last call
1119: * of setPreferredSize(int width, int height), -1 by default. */
1120: int userPreferredHeight = -1;
1121: }
|