FileDocCategorySizeDatePackage
CustomItem.javaAPI DocJ2ME MIDP 2.065834Thu Nov 07 12:02:28 GMT 2002javax.microedition.lcdui

CustomItem.java

/*
 * @(#)CustomItem.java	1.62 02/09/12 @(#)
 *
 * Copyright (c) 2002 Sun Microsystems, Inc.  All rights reserved.
 * PROPRIETARY/CONFIDENTIAL
 * Use is subject to license terms.
 */

package javax.microedition.lcdui;

import java.lang.String;

import com.sun.midp.lcdui.Text;

/**
 * A CustomItem is customizable by subclassing to introduce new visual and
 * interactive elements into <code>Forms</code>. 
 * Subclasses are responsible for their visual
 * appearance including sizing and rendering and choice of colors, fonts and
 * graphics.  Subclasses are responsible for the user interaction mode by
 * responding to events generated by keys, pointer actions, and traversal
 * actions.  Finally, subclasses are responsible for calling {@link
 * Item#notifyStateChanged} to trigger notification of listeners that the
 * <code>CustomItem's</code> value has changed.
 *
 * <p>Like other <code>Items</code>, <code>CustomItems</code>
 * have the concept of <em>minimum</em> and
 * <em>preferred</em> sizes.  These pertain to the total area
 * of the <code>Item</code>,
 * which includes space for the content, label, borders, etc.  See <a
 * href="Item.html#sizes">Item Sizes</a> for a full discussion of the
 * areas and sizes of <code>Items</code>.</p>
 *
 * <p><code>CustomItem</code> subclasses also have the concept
 * of the <em>content</em> size, which is the size of only the
 * content area of the <code>CustomItem</code>.  The
 * content area is a rectangular area inside the total area occupied by the
 * <code>CustomItem</code>.
 * The content area is the area within which the <code>CustomItem</code>
 * subclass paints and receives input events.  It does not include space
 * consumed by labels and borders.  The implementation is responsible for
 * laying out, painting, and handling input events within the area
 * of the <code>Item</code> that is outside the content area.</p>
 *
 * <p>All coordinates passed between the implementation and
 * the <code>CustomItem</code>
 * subclass are relative to the item's content area, with the upper-left
 * corner of this area being located at <code>(0,0)</code>. 
 * Size information passed
 * between the implementation and the <code>CustomItem</code> subclass with the
 * 
 * {@link #getMinContentHeight getMinContentHeight},
 * {@link #getMinContentWidth getMinContentWidth},
 * {@link #getPrefContentHeight getPrefContentHeight},
 * {@link #getPrefContentWidth getPrefContentWidth}, and
 * {@link #sizeChanged sizeChanged}
 * 
 * methods all refer to the size of the content area.  The implementation is
 * responsible for computing and maintaining the difference between the size
 * of the content area and the size of the total area of the
 * <code>Item</code> as reported by the Item size methods
 * 
 * {@link Item#getMinimumHeight Item.getMinimumHeight},
 * {@link Item#getMinimumWidth Item.getMinimumWidth},
 * {@link Item#getPreferredHeight Item.getPreferredHeight}, and
 * {@link Item#getPreferredWidth Item.getPreferredWidth}.</p>
 *
 * <p>The implementation may disregard sizing information returned from a
 * <code>CustomItem</code> if it exceeds limits imposed by the
 * implementation's user interface policy.  In 
 * this case, the implementation must always report the actual size granted to 
 * the <code>CustomItem</code> via the {@link #sizeChanged sizeChanged}
 * and the {@link #paint paint} methods.
 * For example, this situation may occur if the implementation
 * prohibits an <code>Item</code> from becoming wider than the screen.  If the
 * <code>CustomItem</code> subclass code returns a value from
 * <code>getMinContentWidth</code> that would result in the
 * <code>CustomItem</code> being wider than the screen, the implementation may 
 * assign a width smaller than the minimum width returned by
 * <code>getMinContentWidth</code>.</p>
 *
 * <p>The implementation is allowed to call the <code>CustomItem's</code> 
 * content size methods
 * 
 * {@link #getMinContentHeight getMinContentHeight},
 * {@link #getMinContentWidth getMinContentWidth},
 * {@link #getPrefContentHeight getPrefContentHeight}, and
 * {@link #getPrefContentWidth getPrefContentWidth},
 * 
 * in any order with respect to other <code>CustomItem</code> methods.
 * For all of these methods, the <code>CustomItem</code> subclass code must
 * return values that are consistent with the current contents of the
 * <code>CustomItem</code>.  If the contents changes, it is not sufficient for
 * the <code>CustomItem</code> subclass code simply to begin returning
 * different values from the content size methods.  Instead, the subclass code
 * must call the {@link #invalidate invalidate} method whenever its contents
 * changes.  This indicates to the implementation that it may need to perform
 * its layout computation, which will call the content size methods to get new
 * values based on the <code>CustomItem's</code> new contents.</p>
 * 
 * <a name="interaction"></a>
 * <h2>Interaction Modes</h2>
 * <p>The <code>CustomItem</code> class is intended to allow 
 * edit-in-place on many items,
 * but it does not allow every conceivable interaction.  Desire for
 * flexibility has been balanced against a requirement that these APIs be
 * simple enough to master easily, along with a need to allow for
 * platform-specific variations in look-and-feel, all without sacrificing
 * interoperability.</p>
 *
 * <p>The general idea is that there are multiple interaction
 * "modes" and that the <code>Form</code> 
 * implementation can convey which
 * ones it supports.  The <code>CustomItem</code> can then choose to
 * support one or more interaction modes.  There is no requirement for a
 * <code>CustomItem</code> to implement all combinations of
 * all interaction modes.
 * Typically, a <code>CustomItem</code> will implement an 
 * approach (such as the separate
 * editing screen technique discussed below) that works on all platforms,
 * in addition to a highly interactive approach that relies on a particular
 * interaction mode.  At run time, the <code>CustomItem</code>
 * code can query the system
 * to determine whether this interaction mode is supported.  If it is, the
 * <code>CustomItem</code> can use it; otherwise, it will fall
 * back to the approach that works on all platforms. </p>
 *
 * <p><code>CustomItem</code> can always use item commands to invoke
 * a separate editing screen,
 * although components with a small number of discrete
 * states could simply respond by changing the state and
 * then causing an <code>notifyStateChanged</code> notification. 
 * A technique for using a
 * separate editing screen would be to load the value into another
 * <code>Displayable</code> object (such as a List) and then to call
 * {@link Display#setCurrent(Displayable)} on it.
 * When the user
 * issues a command (such as "OK") to indicate that 
 * editing of this value is
 * complete, the listener can retrieve the value from that
 * <code>Displayable</code> object
 * and then call
 * {@link Display#setCurrentItem(Item)} to return to this item.</p>
 *
 * <a name="keypad"></a>
 * <h2>Keypad Input</h2>
 *
 * <p>The implementation may optionally support delivery of keypad events to
 * the <code>CustomItem</code>.  The implementation indicates
 * the level of support by
 * setting the <code>KEY_PRESS</code>, <code>KEY_RELEASE</code>, and
 * <code>KEY_REPEAT</code> bits in the value
 * returned by <code>getInteractionModes</code>.  
 * Events corresponding to these bits are
 * delivered through calls to the <code>keyPressed()</code>,
 * <code>keyReleased()</code>, and
 * <code>keyRepeated()</code> methods, respectively.  
 * If an implementation supports
 * <code>KEY_RELEASE</code> events, it must also support 
 * <code>KEY_PRESS</code> events.  If an
 * implementation supports <code>KEY_REPEAT</code> events, it must also 
 * support <code>KEY_PRESS</code>
 * and <code>KEY_RELEASE</code> events.  If supported, 
 * <code>KEY_RELEASE</code> events will generally
 * occur after a corresponding <code>KEY_PRESS</code> event is 
 * received, and <code>KEY_REPEAT</code>
 * events will generally occur between <code>KEY_PRESS</code> and 
 * <code>KEY_RELEASE</code> events.
 * However, it is possible for the <code>CustomItem</code> to receive
 * <code>KEY_RELEASE</code> or
 * <code>KEY_REPEAT</code> events without a corresponding 
 * <code>KEY_PRESS</code> if a key is down when
 * the <code>CustomItem</code> becomes visible.</p>
 *
 * <p>Key event methods are passed the <code>keyCode</code> 
 * indicating the key on which the
 * event occurred.  Implementations must provide means for the user to
 * generate events with key codes <code>Canvas.KEY_NUM0</code> 
 * through <code>Canvas.KEY_NUM9</code>,
 * <code>Canvas.KEY_STAR</code>, and <code>Canvas.KEY_POUND</code>.
 * Implementations may also deliver
 * key events for other keys, include device-specific keys. 
 * The set of keys
 * available to a <code>CustomItem</code> may differ depending
 * upon whether commands have been added to it.</p>
 *
 * <p>The application may map key codes to game actions through use of the
 * <code>getGameAction</code> method.  
 * If the implementation supports key events on
 * <code>CustomItems</code>, the implementation must provide a 
 * sufficient set of key codes
 * and a mapping to game actions such that all game actions are available to
 * <code>CustomItems</code>.</p>
 *
 * <p>The set of keys and the key events available to a 
 * <code>CustomItem</code> may differ
 * from what is available on a <code>Canvas</code>.  
 * In particular, on a system that
 * supports traversal, the system might use directional keys for traversal and
 * elect not to deliver these keys to <code>CustomItems</code>. 
 * The mapping between key
 * codes and game actions in a <code>CustomItem</code> may differ
 * from the mapping in a <code>Canvas</code>.  See
 * <a href="Canvas.html#keyevents">Key Events</a>
 * and
 * <a href="Canvas.html#gameactions">Game Actions</a>
 * on class <code>Canvas</code> for further information about key codes and game
 * actions.</p>
 *
 * <a name="pointer"></a>
 * <h2>Pointer Input</h2>
 *
 * <p>The implementation may optionally support delivery of pointer events
 * (such as taps with a stylus) to the <code>CustomItem</code>.  
 * The implementation
 * indicates the level of support by setting the <code>POINTER_PRESS</code>,
 * <code>POINTER_RELEASE</code>, and <code>POINTER_DRAG</code> bits
 * in the value returned by <code>getInteractionModes</code>. 
 * Events corresponding to these bits are delivered
 * through calls to the <code>pointerPressed()</code>, 
 * <code>pointerReleased()</code>, and
 * <code>pointerDragged()</code> methods, respectively.  
 * If an implementation supports
 * <code>POINTER_RELEASE</code> events, it must also support 
 * <code>POINTER_PRESS</code> events.  If an
 * implementation supports <code>POINTER_DRAG</code> events, 
 * it must also support
 * <code>POINTER_PRESS</code> and <code>POINTER_RELEASE</code> events.  
 * If supported, <code>POINTER_RELEASE</code>
 * events will generally occur after a corresponding 
 * <code>POINTER_PRESS</code> event is
 * received, and <code>POINTER_DRAG</code> events will generally occur between
 * <code>POINTER_PRESS</code> and <code>POINTER_RELEASE</code> events.  
 * However, it is possible for the
 * <code>CustomItem</code> to receive <code>POINTER_RELEASE</code> 
 * or <code>POINTER_DRAG</code> events without a
 * corresponding <code>POINTER_PRESS</code> if the pointer is 
 * down when the <code>CustomItem</code> becomes visible.</p>
 *
 * <p>The <code>(x,y)</code> location of the pointer event is 
 * reported with every pointer
 * event.  This location is expressed in the coordinate system of the
 * <code>CustomItem</code>, where <code>(0,0)</code> is the upper-left
 * corner of the <code>CustomItem</code>.  Under
 * certain circumstances, pointer events may occur outside the bounds of the
 * item. </p>
 *
 * <h2>Traversal</h2>
 *
 * <p>An implementation may support traversal <em>internal</em> to a
 * <code>CustomItem</code>, that is, the implementation 
 * may temporarily delegate the
 * responsibility for traversal to the item itself.  Even if there is only one
 * traversal location inside the <code>CustomItem</code>, 
 * the item may want support the
 * internal traversal protocol so that it can perform specialized
 * highlighting, animation, etc. when the user has traversed into it.</p>
 *
 * <p>The implementation indicates its support for traversal internal to a
 * <code>CustomItem</code> by setting one or both of the 
 * <code>TRAVERSE_HORIZONTAL</code> or
 * <code>TRAVERSE_VERTICAL</code> bits in the value returned by
 * <code>getInteractionModes()</code>. If
 * neither of these bits is set, the implementation is unwilling to let
 * <code>CustomItems</code> traverse internally, or the 
 * implementation does not support
 * traversal at all.  If the implementation does support traversal but has
 * declined to permit traversal internal to <code>CustomItems</code>,
 * the implementation
 * will supply its own highlighting outside the 
 * <code>CustomItem's</code> content area.</p>
 *
 * <p>The <code>CustomItem</code> need not support internal
 * traversal at all.  It can do
 * this by returning <code>false</code> to the initial call to the
 * <code>traverse</code> method.  (This is the default behavior if this method
 * hasn't been overridden by the <code>CustomItem</code>.) 
 * If this occurs, the system must
 * arrange for the user to be able to traverse onto and past this item.  The
 * system must also arrange for proper scrolling to take place, particularly
 * if the item exceeds the height of the screen, regardless of whether
 * internal traversal is occurring.</p>
 *
 * <p>An implementation may provide support for delivering keypad or pointer
 * events to <code>CustomItems</code> even if it has declined
 * to support delivering traverse events to <code>CustomItems</code>.  
 * If an implementation provides support for
 * delivering keypad or pointer events to <code>CustomItems</code>,
 * it must provide a means
 * to do so for every <code>CustomItem</code>, even for those
 * that have refused internal
 * traversal by returning <code>false</code> to the initial 
 * <code>traverse()</code> call.  
 * This implies that such implementations must still support some notion
 * of focus for an item, even if that item is not supporting internal
 * traversal.</p>
 *
 * <p>See the documentation for the
 * {@link #traverse traverse} method for a full
 * specification of the behavior and responsibilities required for the item to
 * perform internal traversal.</p>
 *
 * <h2>Item Appearance</h2>
 *
 * <p>The visual appearance of each item consists of a
 * label (handled by the implementation)
 * and its contents (handled by the subclass).</p>
 *
 * <p>Labels are the responsibility of the implementation, not the item.  The
 * screen area that is allocated to the <code>CustomItem</code>
 * for its contents is
 * separate from the area that the implementation uses to display the
 * <code>CustomItem's</code> label. 
 * The implementation controls the rendering of the label
 * and its layout with respect to the content area.</p>
 *
 * <p>The <code>CustomItem</code> is responsible for 
 * painting its contents whenever
 * the <code>paint</code> method is called.</p>
 *
 * <p>The colors for foreground, background, highlighted foreground,
 * highlighted background, border, and highlighted border should be
 * retrieved from {@link Display#getColor}.  
 * This will allow <code>CustomItems</code> to
 * match the color scheme of other items provided with the device.
 * The <code>CustomItem</code> is responsible for keeping 
 * track of its own highlighted and
 * unhighlighted state.</p>
 *
 * <p>The fonts used should be retrieved from {@link Font#getFont}.
 * This will allow them to match the fonts used by other items
 * on the device for a consistent visual appearance. </p>
 *
 * @since MIDP 2.0
 */
abstract public class CustomItem extends Item {

    /**
     * Interaction mode bit indicating support of horizontal traversal
     * internal to the <code>CustomItem</code>.
     *
     * <p><code>TRAVERSE_HORIZONTAL</code> has the value <code>1</code>.</p>
     *
     * @see #getInteractionModes
     * @see #traverse
     */
    protected static final int TRAVERSE_HORIZONTAL = 1;

    /**
     * Interaction mode bit indicating support for vertical traversal
     * internal to the <code>CustomItem</code>.
     *
     * <p><code>TRAVERSE_VERTICAL</code> has the value <code>2</code>.</p>
     *
     * @see #getInteractionModes
     * @see #traverse
     */
    protected static final int TRAVERSE_VERTICAL = 2;

    /**
     * Interaction mode bit indicating support for key pressed events.
     *
     * <p><code>KEY_PRESS</code> has the value <code>4</code>.</p>
     *
     * @see #getInteractionModes
     * @see #keyPressed
     */
    protected static final int KEY_PRESS = 4;

    /**
     * Interaction mode bit indicating support for key released events.
     *
     * <p><code>KEY_RELEASE</code> has the value <code>8</code>.</p>
     *
     * @see #getInteractionModes
     * @see #keyReleased
     */
    protected static final int KEY_RELEASE = 8;

    /**
     * Interaction mode bit indicating support for key repeated events.
     *
     * <p><code>KEY_REPEAT</code> has the value <code>0x10</code>.</p>
     *
     * @see #getInteractionModes
     * @see #keyRepeated
     */
    protected static final int KEY_REPEAT = 0x10;

    /**
     * Interaction mode bit indicating support for point pressed events.
     *
     * <p><code>POINTER_PRESS</code> has the value <code>0x20</code>.</p>
     *
     * @see #getInteractionModes
     * @see #pointerPressed
     */
    protected static final int POINTER_PRESS = 0x20;

    /**
     * Interaction mode bit indicating support for point released events.
     *
     * <p><code>POINTER_RELEASE</code> has the value<code> 0x40</code>.</p>
     *
     * @see #getInteractionModes
     * @see #pointerReleased
     */
    protected static final int POINTER_RELEASE = 0x40;

    /**
     * Interaction mode bit indicating support for point dragged events.
     *
     * <p><code>POINTER_DRAG</code> has the value <code>0x80</code>.</p>
     *
     * @see #getInteractionModes
     * @see #pointerDragged
     */
    protected static final int POINTER_DRAG = 0x80;

    /**
     * A value for traversal direction that indicates that traversal has
     * entered or has changed location within this item, but that no specific
     * direction is associated with this traversal event.
     *
     * <p><code>NONE</code> has the value <code>0</code>.</p>
     *
     * @see #traverse
     */
    protected static final int NONE = 0;

    /**
     * labelHeight caches the height of the label for this CustomItem,
     * as it is not included when reporting dimensions to the subclass
     */
    private int labelHeight = 0;

    /**
     * Superclass constructor, provided so that the
     * <code>CustomItem</code> subclass can specify its label.
     *
     * @param label the <code>CustomItem's</code> label
     */
    protected CustomItem(String label) { 
        super(label);
    }

    /**
     * Gets the game action associated with the given key code of the
     * device.  Returns zero if no game action is associated with this key
     * code.  See the
     * <a href="Canvas.html#gameactions">Game Actions</a>
     * section of class <code>Canvas</code> for further discussion
     * of game actions.
     *
     * <p>The mapping of key codes to game actions may differ between
     * <code>CustomItem</code> and <code>Canvas</code>.</p>
     *
     * @param keyCode the key code
     * @return the game action corresponding to this key, or <code>0</code>
     * if none
     * @throws IllegalArgumentException if <code>keyCode</code> is not
     * a valid key code
     */
    public int getGameAction(int keyCode) {
        int n = Display.getGameAction(keyCode);

        if (n == -1) {
            throw new IllegalArgumentException();
        }

        return n;
    }

    /**
     * Gets the available interaction modes.  This method is intended to be
     * called by <code>CustomItem</code> subclass code in order
     * for it to determine what
     * kinds of input are available from this device.  The modes available may
     * be dependent upon several factors: the hardware keys on the actual
     * device, which of these keys are needed for the system to do proper
     * navigation, the presence of a pointing device, etc.  See <a
     * href="#interaction">Interaction Modes</a> for further discussion.  If
     * this method returns <code>0</code>, the only interaction available 
     * is through item commands.
     *
     * @return a bitmask of the available interaction modes
     */
    protected final int getInteractionModes() { 
        return (TRAVERSE_HORIZONTAL | TRAVERSE_VERTICAL | 
                KEY_PRESS | KEY_RELEASE | KEY_REPEAT |
	        POINTER_PRESS | POINTER_RELEASE | POINTER_DRAG);
    }

    /**
     * Implemented by the subclass to return the minimum width of the content
     * area, in pixels.  This method is called by the implementation as part
     * of its layout algorithm.  The actual width granted is reported in the
     * {@link #sizeChanged sizeChanged} and {@link #paint paint} methods.
     *
     * @return the minimum content width in pixels
     */
    protected abstract int getMinContentWidth();

    /**
     * Implemented by the subclass to return the minimum height of the content
     * area, in pixels.  This method is called by the implementation as part
     * of its layout algorithm.  The actual height granted is reported in the
     * {@link #sizeChanged sizeChanged} and {@link #paint paint} methods.
     *
     * @return the minimum content height in pixels
     */
    protected abstract int getMinContentHeight();

    /**
     * Implemented by the subclass to return the preferred width of the content
     * area, in pixels.  This method is called by the implementation as part 
     * of its layout algorithm.
     *
     * <p>The <code>height</code> parameter is the tentative height assigned 
     * to the content area.  The subclass code may use this value in its 
     * computation of the preferred width.  The <code>height</code> parameter 
     * will be -1 if the implementation has not assigned a tentative value 
     * for the height.  Otherwise, <code>height</code> will have a specific 
     * value if the application has locked the height of the
     * <code>CustomItem</code> or if the container's layout algorithm has 
     * already computed a tentative height at the time of this call.  The 
     * subclass must not assume that the tentative height passed or the
     * preferred width returned will be granted.
     * The actual size granted is reported in the
     * {@link #sizeChanged sizeChanged} and {@link #paint paint} methods.
     * </p>
     *
     * @param height the tentative content height in pixels, or -1 if a
     * tentative height has not been computed
     * @return the preferred content width in pixels
     */
    protected abstract int getPrefContentWidth(int height);

    /**
     * Implemented by the subclass to return the preferred height of the
     * content area, in pixels.  This method is called by the implementation
     * as part of its layout algorithm.
     *
     * <p>The <code>width</code> parameter is the tentative width assigned 
     * to the content area.  The subclass code may use this value in its 
     * computation of the preferred height.  The <code>width</code> parameter 
     * will be -1 if the implementation has not assigned a tentative value 
     * for the width.  Otherwise, <code>width</code> will have a specific
     * value if the application has locked the width of the
     * <code>CustomItem</code> or if the container's layout algorithm has 
     * already computed a tentative width at the time of this call.  The 
     * subclass must not assume that the tentative width passed or the
     * preferred height returned will be granted.
     * The actual size granted is reported in the
     * {@link #sizeChanged sizeChanged} and {@link #paint paint} methods.
     * </p>
     *
     * @param width the tentative content width in pixels, or -1 if a
     * tentative width has not been computed
     * @return the preferred content height in pixels
     */
    protected abstract int getPrefContentHeight(int width);

    /**
     * Implemented by the subclass in order to handle size change events.
     * This method is called by the system when the size of the content area
     * of this <code>CustomItem</code> has changed.
     *
     * <p>If the size of a <code>CustomItem</code> changes while it is
     * visible on the display, it may trigger an automatic
     * repaint request.  If this occurs, the call to
     * <code>sizeChanged</code> will occur prior to the call to
     * <code>paint</code>.  If the <code>CustomItem</code> has become
     * smaller, the implementation may choose not to trigger a repaint
     * request if the remaining contents of the <code>CustomItem</code>
     * have been preserved.  Similarly, if the <code>CustomItem</code>
     * has become larger, the implementation may choose to trigger a
     * repaint only for the new region.  In both cases, the preserved
     * contents must remain stationary with respect to the origin of the
     * <code>CustomItem</code>.  If the size change is significant to
     * the contents of the <code>CustomItem</code>, the application must
     * explicitly issue a repaint request for the changed areas.  Note
     * that the application's repaint request should not cause multiple
     * repaints, since it can be coalesced with repaint requests that
     * are already pending.</p>
     *
     * <p>If the size of the item's content area
     * changes while it is not visible, calls to this method may be deferred.
     * If the size had changed while the item was not visible,
     * <code>sizeChanged</code> will be called at least once before the item
     * becomes visible once again.</p>
     *
     * <p>The default implementation of this method does
     * nothing.</p>
     *
     * @param w the new width of the item's content area
     * @param h the new height of the item's content area
     */
    protected void sizeChanged(int w, int h) { }

    /**
     * Signals that the <code>CustomItem's</code> size and traversal
     * location need to be updated. 
     * This method is intended to be called by <code>CustomItem</code> 
     * subclass code to inform the implementation that the size of 
     * the <code>CustomItem's</code> content area or the internal
     * traversal location might need to change.  
     * This often occurs if the contents of the <code>CustomItem</code>
     * are modified.  A call to this method will return immediately, and it
     * will cause the container's layout algorithm to run at some point in the
     * future, possibly resulting in calls to
     * 
     * {@link #getMinContentHeight getMinContentHeight},
     * {@link #getMinContentWidth getMinContentWidth},
     * {@link #getPrefContentHeight getPrefContentHeight},
     * {@link #getPrefContentWidth getPrefContentWidth},
     * {@link #sizeChanged sizeChanged}, or
     * {@link #traverse traverse}.
     * 
     * The {@link #paint paint} method may also be called if
     * repainting is necessary as a result of the layout operation.  
     * If the content size is invalidated while the 
     * <code>CustomItem</code> is not visible, the
     * layout operation may be deferred.  The <code>traverse</code> method 
     * will be called if the <code>CustomItem</code> contains the current 
     * traversal location at the time <code>invalidate</code> is called.
     */
    protected final void invalidate() {
        super.invalidate();
    }

    /**
     * Implemented by the subclass to render the item within its container.
     * At the time of the call, the <code>Graphics</code> context's
     * destination is the content area of this <code>CustomItem</code>
     * (or back buffer for it).  The
     * Translation is set so that the upper left corner of the content area is
     * at <code>(0,0)</code>, and the clip is set to the area to be painted.
     * The application must paint every pixel within the given clip area.  The
     * item is allowed to modify the clip area, but the system must not allow
     * any modification to result in drawing outside the bounds of the item's
     * content area.  The <code>w</code> and <code>h</code> passed
     * in are the width and height of the
     * content area of the item.  These values will always be equal to the
     * values passed with the most recent call to <code>sizeChanged()</code>;
     * they are passed here as well for convenience.
     *
     * <p>Other values of the <code>Graphics</code> object are as follows:</p>
     * <UL>
     * <LI>the current color is black;</LI>
     * <LI>the font is the same as the font returned by
     * {@link Font#getDefaultFont() Font.getDefaultFont()};</LI>
     * <LI>the stroke style is {@link Graphics#SOLID SOLID};</LI>
     * </UL>
     *
     * <p>The <code>paint()</code> method will be called only after
     * <code>showNotify()</code> call on this item and before a subsequent
     * <code>hideNotify()</code> call on this item, in other words, only when
     * at least a portion of the item is actually visible on the display.
     * In addition, the <code>paint()</code> method will be called only
     * if the item's width and height are both greater than zero.</p>
     *
     * @param g the <code>Graphics</code> object to be used for
     * rendering the item
     * @param w current width of the item in pixels
     * @param h current height of the item in pixels
     */
    protected abstract void paint(Graphics g, int w, int h);

    /**
     * Called by subclass code to request that the item be repainted.  If this
     * item is visible on the display, this will result in a call to 
     * <code>paint()</code> the next time the <code>CustomItem</code> 
     * is to be displayed.  The <code>CustomItem</code>
     * subclass should call this method when the item's internal state has
     * been updated such that its visual representation needs to be updated.
     */
    protected final void repaint() {
        try {
            // We prune off the label area when doing a complete repaint
            super.repaint(0, labelHeight,
                          bounds[WIDTH], bounds[HEIGHT] - labelHeight);
        } catch (Exception e) {
            Display.handleThrowable(e);
        }
    }

    /**
     * Called by subclass code to request that the specified rectangular area
     * of the item be repainted.  If that area is visible on the display, this
     * will result in call to <code>paint</code> with graphics set to 
     * include the specified rectangular area.  
     * The area is specified relative to the <code>CustomItem's</code>
     * content area.  
     * The <code>CustomItem</code> should call this method when the item's
     * internal state has been updated and only part of the visual
     * representation needs to be updated.
     *
     * @param x the x coordinate of the rectangular area to be updated
     * @param y the y coordinate of the rectangular area to be updated
     * @param w the width of the rectangular area to be updated
     * @param h the height of the rectangular area to be updated
     */
    protected final void repaint(int x, int y, int w, int h) {
        try {
            // We only allow the CustomItem to repaint within its
            // content area
            if (x > bounds[WIDTH]) {
                return;
            }
            if (x < 0) {
                x = 0;
            }
            if (y < 0) {
                y = 0;
            }
            // We offset the Item's coordinate space by the label
            y += labelHeight;
            if (y > bounds[HEIGHT]) {
                return;
            }
            if (x + w > bounds[WIDTH]) {
                w = bounds[WIDTH] - x;
            }
            if (y + h > bounds[HEIGHT]) {
                h = bounds[HEIGHT] - y;
            }
            super.repaint(x, y, w, h);
        } catch (Exception e) {
            Display.handleThrowable(e);
        }
    }

    /**
     * Called by the system when traversal has entered the item or has
     * occurred within the item.  The direction of traversal and the item's
     * visible rectangle are passed into the method.  The method must do one
     * of the following: it must either update its state information
     * pertaining to its internal traversal location, set the return rectangle
     * to indicate a region associated with this location, and return
     * <code>true</code>; or, it must return <code>false</code> to indicate
     * that this item does not support internal traversal, or that that
     * internal traversal has reached the edge of the item and that traversal
     * should proceed to the next item if possible.
     *
     * <p>The implementation indicates support for internal traversal within a
     * <code>CustomItem</code> by setting one or both of the
     * <code>TRAVERSE_HORIZONTAL</code> or
     * <code>TRAVERSE_VERTICAL</code> bits in the value returned by the
     * <code>getInteractionModes</code>
     * method.  The <code>dir</code> parameter indicates the direction of
     * traversal by using <code>Canvas</code> game actions 
     * <code>Canvas.UP</code>, <code>Canvas.DOWN</code>,
     * <code>Canvas.LEFT</code>, and <code>Canvas.RIGHT</code>, or the
     * value <code>NONE</code>, which indicates that there is no specific
     * direction associated with this traversal event.
     * If the <code>TRAVERSE_HORIZONTAL</code> bit is set,
     * this indicates that the <code>Canvas.LEFT</code> and 
     * <code>Canvas.RIGHT</code> values will be
     * used to indicate the traversal direction.  
     * If the <code>TRAVERSE_VERTICAL</code> bit
     * is set, this indicates that the <code>Canvas.UP</code> and
     * <code>Canvas.DOWN</code> values will
     * be used to indicate the traversal direction.  If both bits are set, all
     * four direction values may be used for the traversal direction,
     * indicating that the item should perform two-dimensional traversal.  The
     * <code>dir</code> parameter may have the value <code>NONE</code> under
     * any combination of the <code>TRAVERSE_VERTICAL</code> and
     * <code>TRAVERSE_HORIZONTAL</code> bits.
     * </p>
     *
     * <p>Although <code>Canvas</code> game actions are used to indicate the
     * traversal direction, this does not imply that the keys mapped to these
     * game actions are being used for traversal, nor that that keys are being
     * used for traversal at all.</p>
     *
     * <p>The <code>viewportWidth</code> and <code>viewportHeight</code>
     * parameters indicate the size of the viewable area the item's container
     * has granted to its items.  This represents the largest area of the
     * item that is likely to be visible at any given time.</p>
     *
     * <p>The <code>visRect_inout</code> parameter is used both for passing
     * information into this method and for returning information from this
     * method.  It must be an <code>int[4]</code> array.  The information in
     * this array is a rectangle of the form <code>[x,y,w,h]</code>
     * where <code>(x,y)</code> is the
     * location of the upper-left corner of the rectangle relative to the
     * item's origin, and <code>(w,h)</code> are the width and 
     * height of the rectangle.
     * The return values placed into this array are significant only when the
     * <code>traverse()</code> method returns <code>true</code>.  
     * The values are ignored if
     * the <code>traverse()</code> method returns <code>false</code>.</p>
     *
     * <p>When this method is called, the <code>visRect_inout</code> array
     * contains a rectangle representing the region of the item that is
     * currently visible.  This region might have zero area if no part of the
     * item is visible, for example, if it is scrolled offscreen.  The
     * semantics of the rectangle returned are discussed below.</p>
     *
     * <p>The <code>CustomItem</code> must maintain state that tracks 
     * whether traversal is
     * within this item, and if it is, it must also record the current
     * internal location.  Initially, traversal is outside the item.  The
     * first call to the <code>traverse()</code> method indicates 
     * that traversal has
     * entered the item.  Subsequent calls to this method indicate that
     * traversal is occurring within this item.  Traversal remains within the
     * item until the <code>traverseOut</code> method is called.  
     * The <code>CustomItem</code> must keep
     * track of its traversal state so that it can distinguish traversal
     * <em>entering</em> the item from traversal <em>within</em> the item.
     * </p>
     *
     * <p>When traversal enters the item, the traversal code 
     * should initialize its internal traversal
     * location to the "first" location appropriate
     * for the item's structure and the traversal direction.
     * As an example of the latter policy, if
     * the traversal direction is <code>DOWN</code>, the initial 
     * location should be the
     * topmost internal element of the item.  Similarly, if the traversal 
     * direction is <code>UP</code>, the initial location should be the 
     * bottommost element of the item.
     * The <code>CustomItem</code>
     * should still choose the "first" location appropriately
     * even if its primary axis is orthogonal to the
     * axis of traversal.  For example, suppose the traversal 
     * mode supported is <code>TRAVERSE_VERTICAL</code> but the
     * <code>CustomItem</code> is structured as a horizontal row
     * of elements.  If the initial traversal direction is
     * <code>DOWN</code>, the initial location might be the leftmost
     * element, and if the initial traversal direction is
     * <code>UP</code>, the initial location might be the rightmost
     * element.</p>
     *
     * <p>Traversal may enter the item without any specific direction, in
     * which case the traversal direction will be <code>NONE</code>.  This may
     * occur if the user selects the item directly (e.g., with a pointing
     * device), or if the item gains the focus because its containing
     * <code>Form</code> has become current. The <code>CustomItem</code>
     * should choose a default traversal location.  If the
     * <code>CustomItem</code> had been traversed to previously, and if it is
     * appropriate for the user interface of the <code>CustomItem</code>, the
     * previous traversal location should be restored.</p>
     *
     * <p>When traversal occurs within
     * the item, the internal traversal location must be moved to the next
     * appropriate region in the direction of traversal.  The item must report
     * its updated internal traversal location in the
     * <code>visRect_inout</code> return parameter as described below and
     * return <code>true</code>.  The item will typically provide a highlight
     * to display the internal traversal location to the user.  Thus, the item
     * will typically also request repaints of the old and new traversal
     * locations after each traversal event.  There is no requirement that the
     * area the item requests to be repainted is the same as the area returned
     * in the <code>visRect_inout</code> rectangle.  The system will combine
     * any repaint requests with any additional repainting that may occur as a
     * result of scrolling.</p>
     *
     * <p>The <code>traverse()</code> method may be called with a direction of
     * <code>NONE</code> when the traversal is already within the
     * <code>CustomItem</code>.  This will occur in response to the
     * <code>CustomItem</code> subclass code having called the
     * <code>invalidate()</code> method.  In this case, the
     * <code>CustomItem</code> should simply return its current notion of the
     * traversal location.  This mechanism is useful if the
     * <code>CustomItem</code> needs to update the traversal location
     * spontaneously (that is, not in response to a traversal event), for
     * example, because of a change in its contents.</p>
     *
     * <p>If the internal traversal location is such that the traversal event
     * would logically cause traversal to proceed out of the item, the
     * item should return <code>false</code> from the 
     * <code>traverse()</code> method.  For
     * example, if the current traversal location is the bottommost internal
     * element of the item, and the traversal direction is 
     * <code>DOWN</code>, the
     * <code>traverse()</code> method should simply return 
     * <code>false</code>.  In this
     * case the method need not update the values in the
     * <code>visRect_inout</code> array.  The item must leave its internal
     * traversal location unchanged, and it should not request a repaint to
     * update its highlighting.  It should defer these actions until the
     * <code>traverseOut()</code> method is called.  
     * The system will call the <code>traverseOut()</code>
     * method when traversal actually leaves the item.  The system might not
     * call the <code>traverseOut()</code> method, even if 
     * <code>traverse()</code> has returned
     * <code>false</code>, if this item is at the edge of the 
     * <code>Form</code> or there is
     * no other item beyond to accept the traversal. 
     * Even if the <code>traverse()</code>
     * method returns <code>false</code>, the traversal location is still
     * within this item.  
     * It remains within this item until <code>traverseOut()</code> is
     * called.</p>
     *
     * <p>Note the subtle distinction here between the initial
     * <code>traverse()</code> call
     * signifying <em>entry</em> into the item and subsequent calls signifying
     * traversal <em>within</em> the item.  A return value of
     * <code>false</code> to the initial call indicates that this item
     * performs no internal traversal at all, whereas a return of
     * <code>false</code> to subsequent calls indicates that traversal is
     * within this item and may now exit.  </p>
     *
     * <p>The width and height of the rectangle returned in the
     * <code>visRect_inout</code> array are used by the 
     * <code>Form</code> for scrolling
     * and painting purposes.  The <code>Form</code> must always 
     * position the item so that
     * the upper left corner of this rectangle, as specified by
     * the <code>(x,y)</code>
     * position, is visible.  In addition, the item may also specify a width
     * and height, in which case the <code>Form</code> will 
     * attempt to position the item so
     * that as much of this rectangle as possible is visible.  If the width
     * and height are larger than the size of the viewport, the bottom and
     * right portions of this rectangle will most likely not be visible to the
     * user.  The rectangle thus returned will typically denote the size and
     * location of one of the item's internal elements, and it will also
     * typically (though not necessarily) correspond to where the element's
     * highlight will be painted.  Width and height values of zero are legal
     * and are not treated specially.  Negative values of width and height are
     * treated as if they were zero.</p>
     *
     * <p>There is no requirement on the location of the rectangle returned in
     * the <code>visRect_inout</code> array with respect to the traversal 
     * direction.  For example, if the <code>CustomItem</code> implements 
     * internal scrolling, a traversal direction of <code>DOWN</code> may 
     * cause the item's contents to scroll upwards far enough so that the 
     * rectangle returned may be above its old location.
     * <code>CustomItem</code> subclasses must ensure that continued traversal 
     * in one direction will eventually reach the edge of the item and then 
     * traverse out by returning <code>false</code> from this method.
     * <code>CustomItems</code> must not implement "wraparound" 
     * behavior (for example, traversing downwards from the bottommost element 
     * moves the traversal location to the topmost element) because this will 
     * trap the traversal within the item.</p>
     * 
     * <p>If the <code>CustomItem</code> consists of internal 
     * elements that are smaller
     * than the container's viewport, the rectangle returned 
     * should be the
     * same size as one of these elements.  However, the
     * <code>CustomItem</code> might have
     * contents whose elements are larger than the viewport, or it might have
     * contents having no internal structure.  In either of these cases, the
     * item should return a rectangle that best represents its idea of the
     * content area that is important for the user to see.  When traversal
     * occurs, the item should move its traversal location by an amount based
     * on the viewport size.  For example, if the viewport is 
     * <code>80</code> pixels high,
     * and traversal occurs downwards, the item might move its traversal
     * location down by <code>70</code> pixels in order to display 
     * the next screenful of
     * content, with <code>10</code> pixels overlap for context.</p>
     *
     * <p>All internal traversal locations must be reachable regardless of 
     * which traversal modes are provided by the implementation.  This
     * implies that,
     * if the implementation provides one-dimensional traversal, the
     * <code>CustomItem</code> must linearize its internal locations.
     * For example, suppose the traversal mode is
     * <code>TRAVERSE_VERTICAL</code> and the <code>CustomItem</code> consists 
     * of a horizontal row of elements.  If the traversal direction is
     * <code>DOWN</code> the internal traversal location should move to the 
     * right, and if the traversal direction is <code>UP</code> the internal 
     * traversal location should move to the left.  (The foregoing convention 
     * is appropriate for languages that use left-to-right text.  The opposite 
     * convention should be used for languages that use right-to-left text.)
     * Consider a similar example where the traversal mode is
     * <code>TRAVERSE_VERTICAL</code> and the <code>CustomItem</code> consists
     * of a grid of elements.  A traversal direction of <code>DOWN</code> 
     * might proceed leftwards across each row, moving to the next row 
     * downwards when the location reaches the rightmost element in a row.
     * </p>
     * 
     * <p>If the implementation provides two-dimensional traversal but the
     * <code>CustomItem</code> is one-dimensional, a traversal direction
     * along the item's
     * axis should traverse within the item, and a traversal direction
     * orthogonal to the item's axis should cause immediate traversal out of
     * the item by returning <code>false</code> from this method.  For
     * example, suppose a <code>CustomItem</code> is implementing
     * a vertical stack of
     * elements and traversal is already inside the item.  If a traverse event
     * is received with direction <code>UP</code> or <code>DOWN</code>,
     * the <code>traverse()</code> method should
     * move to the next element and return <code>true</code>.  On the other
     * hand, if a traverse event is received with direction 
     * <code>RIGHT</code> or <code>LEFT</code>, the
     * <code>traverse()</code> method should always return 
     * <code>false</code> so that
     * traversal exits the item immediately.  An item that implements internal
     * traversal should always accept entry - that is, the initial call to
     * <code>traverse()</code> should return <code>true</code> - 
     * regardless of the axis of the traversal direction.</p>
     *
     * <p>If the <code>traverse()</code> method returns 
     * <code>false</code> when traversal
     * is entering the item, this indicates to the system that the item does
     * not support internal traversal.  In this case, the item should not
     * perform any of its own highlighting, and the system will perform
     * highlighting appropriate for the platform, external to the item.</p>
     *
     * <p>The default implementation of the <code>traverse()</code> 
     * method always returns <code>false</code>.</p>
     *
     * @param dir the direction of traversal, one of
     * {@link Canvas#UP Canvas.UP}, {@link Canvas#DOWN Canvas.DOWN},
     * {@link Canvas#LEFT Canvas.LEFT}, {@link Canvas#RIGHT Canvas.RIGHT}, or
     * {@link #NONE NONE}.
     * @param viewportWidth the width of the container's viewport
     * @param viewportHeight the height of the container's viewport
     * @param visRect_inout passes the visible rectangle into the method, and
     * returns the updated traversal rectangle from the method
     * @return <code>true</code> if internal traversal had occurred, 
     * <code>false</code> if traversal should proceed out
     *
     * @see #getInteractionModes
     * @see #traverseOut
     * @see #TRAVERSE_HORIZONTAL
     * @see #TRAVERSE_VERTICAL
     */
    protected boolean traverse(int dir,
			       int viewportWidth,
			       int viewportHeight,
			       int visRect_inout[]) {
        return false;
    }

    /**
     * Called by the system when traversal has occurred out of the item.  This
     * may occur in response to the <code>CustomItem</code> having returned
     * <code>false</code> to a previous call to <code>traverse()</code>, if
     * the user has begun interacting with another item, or if 
     * <code>Form</code> containing
     * this item is no longer current.  If the <code>CustomItem</code>
     * is using highlighting to indicate internal traversal,
     * the <code>CustomItem</code>
     * should set its state to be unhighlighted and request a repaint.  (Note
     * that painting will not occur if the item is no longer visible.)
     *
     * @see #getInteractionModes
     * @see #traverse
     * @see #TRAVERSE_HORIZONTAL
     * @see #TRAVERSE_VERTICAL
     */
    protected void traverseOut() { }

    /**
     * Called by the system when a key is pressed.  The implementation
     * indicates support for delivery of key press events by setting the
     * <code>KEY_PRESS</code> bit in the value returned by the 
     * <code>getInteractionModes</code> method.
     *
     * @param keyCode the key code of the key that has been pressed
     * @see #getInteractionModes
     */
    protected void keyPressed(int keyCode) { }

    /**
     * Called by the system when a key is released.  The implementation
     * indicates support for delivery of key release events by setting the
     * <code>KEY_RELEASE</code> bit in the value returned by the 
     * <code>getInteractionModes</code> method.
     *
     * @param keyCode the key code of the key that has been released
     * @see #getInteractionModes
     */
    protected void keyReleased(int keyCode) { }

    /**
     * Called by the system when a key is repeated.  The implementation
     * indicates support for delivery of key repeat events by setting the
     * <code>KEY_REPEAT</code> bit in the value returned by the 
     * <code>getInteractionModes</code> method.
     *
     * @param keyCode the key code of the key that has been repeated
     * @see #getInteractionModes
     */
    protected void keyRepeated(int keyCode) { }

    /**
     * Called by the system when a pointer down action (for example, a pen
     * tap) has occurred within the item.  The <code>(x,y)</code> 
     * coordinates are relative
     * to the origin of the item, and they will always indicate a location
     * within the item.  The implementation indicates support for delivery of
     * pointer press events by setting the <code>POINTER_PRESS</code> 
     * bit in the value
     * returned by the <code>getInteractionModes</code> method.
     *
     * @param x the <code>x</code> coordinate of the pointer down
     * @param y the <code>y</code> coordinate of the pointer down
     *
     * @see #getInteractionModes
     */
    protected void pointerPressed(int x, int y) { }

    /**
     * Called by the system when a pointer up action (for example, a pen lift)
     * has occurred after a pointer down action had occurred within the item.
     * The <code>(x,y)</code> coordinates are relative to the origin
     * of the item.
     * Implementations should deliver a pointer release event to an item even
     * if the pointer has moved outside the item when the release occurs.  In
     * this case the <code>(x,y)</code> coordinates may indicate a
     * location outside the
     * bounds of the item.  The implementation indicates support for delivery
     * of pointer release events by setting the 
     * <code>POINTER_RELEASE</code> bit in the
     * value returned by the <code>getInteractionModes</code> method.
     *
     * @param x the x coordinate of the pointer up
     * @param y the x coordinate of the pointer up
     *
     * @see #getInteractionModes
     */
    protected void pointerReleased(int x, int y) { }

    /**
     * Called by the system when a pointer drag action (for example, pen
     * motion after a press but before a release) has occurred within the item.
     * The <code>(x,y)</code> coordinates are relative to the origin
     * of the item.
     * Implementations should deliver pointer drag events to an item even if
     * the pointer is being moved outside the item.  In this case 
     * the <code>(x,y)</code>
     * coordinates may indicate a location outside the bounds of the item.
     * The implementation indicates support for delivery of pointer release
     * events by setting the <code>POINTER_DRAG</code> bit in the
     * value returned by the
     * <code>getInteractionModes</code> method.
     *
     * @param x the <code>x</code> coordinate of the pointer drag
     * @param y the <code>x</code> coordinate of the pointer drag
     *
     * @see #getInteractionModes
     */
    protected void pointerDragged(int x, int y) { }

    /**
     * Called by the system to notify the item that it is now at least
     * partially visible, when it previously had been completely invisible.
     * The item may receive <code>paint()</code> calls after
     * <code>showNotify()</code> has been called.
     *
     * <p>The default implementation of this method does nothing.</p>
     */
    protected void showNotify() { }

    /**
     * Called by the system to notify the item that it is now completely
     * invisible, when it previously had been at least partially visible.  No
     * further <code>paint()</code> calls will be made on this item
     * until after a <code>showNotify()</code> has been called again.
     *
     * <p>The default implementation of this method does nothing.</p>
     */
    protected void hideNotify() { }

// **************************************************************************
//  Package Private - These are all methods which delegate calls to
//                    CustomItem application code, locking on the calloutLock
//                    before doing so
// **************************************************************************

    /**
     * Called to determine the effective layout directive.
     *
     * @return the CustomItem's layout directive
     */
    int callGetLayout() {
        int l = LAYOUT_TOP | LAYOUT_LEFT;
        try {
            // SYNC NOTE: We lock on calloutLock around any calls
            // into application code
            synchronized (Display.calloutLock) {
                l = this.getLayout();
            }
        } catch (Throwable thr) {
            Display.handleThrowable(thr);
        }
        return l;
    }

    /**
     * Get the preferred width of this Item, including the preferred
     * content width and room for the label. This is the callback
     * for Item's public getPreferredWidth() method.
     *
     * @param h the height to base the width size on
     * @return the preferred width
     */
    int callPreferredWidth(int h) {
        try {
            synchronized (Display.calloutLock) {
                return this.getPrefContentWidth(h);
            }
        } catch (Throwable thr) {
            Display.handleThrowable(thr);
        }
        return -1;
    }

    /**
     * Get the preferred height of this Item, including the preferred
     * content height and room for the label. This is the callback
     * for Item's public getPreferredHeight() method.
     *
     * @param w the width to base the height size on
     * @return the preferred height
     */
    int callPreferredHeight(int w) {
        try {
            synchronized (Display.calloutLock) {
                return this.getPrefContentHeight(w) + getLabelHeight(w);
            }
        } catch (Throwable thr) {
            Display.handleThrowable(thr);
        }
        return -1;
    }

    /**
     * Get the minimum width of this Item, including the minimum
     * content width and room for the label. This is the callback
     * for Item's public getMinimumWidth() method.
     *
     * @return the minimum width
     */
    int callMinimumWidth() {
        try {
            synchronized (Display.calloutLock) {
                return this.getMinContentWidth();
            }
        } catch (Throwable thr) {
            Display.handleThrowable(thr);
        }
        return -1;
    }

    /**
     * Get the minimum height of this Item, including the minimum
     * content height and room for the label. This is the callback
     * for Item's public getMinimumHeight() method.
     *
     * @return the minimum height
     */
    int callMinimumHeight() {
        try {
            synchronized (Display.calloutLock) {
                return this.getMinContentHeight() + getLabelHeight(-1);
            }
        } catch (Throwable thr) {
            Display.handleThrowable(thr);
        }
        return -1;
    }

    /**
     * Called by the system to indicate the size available to this Item
     * has changed
     *
     * @param w the new width of the item's content area
     * @param h the new height of the item's content area
     */
    void callSizeChanged(int w, int h) {
        labelHeight = getLabelHeight(w);
        try {
            synchronized (Display.calloutLock) {
                this.sizeChanged(w, h - labelHeight);
            }
        } catch (Throwable thr) {
            Display.handleThrowable(thr);
        }
    }

    /**
     * Called to paint this CustomItem
     *
     * @param g the <code>Graphics</code> object to be used for
     * rendering the item
     * @param w current width of the item in pixels
     * @param h current height of the item in pixels
     */
    void callPaint(Graphics g, int w, int h) {
        // We need to check the clip to determine if
        // the label needs painting
        super.paintLabel(g, w);
        g.clipRect(0, labelHeight, w, h - labelHeight);
        g.translate(0, labelHeight);

        try {
            synchronized (Display.calloutLock) {
                this.paint(g, w, h - labelHeight);
            }
        } catch (Throwable thr) {
            Display.handleThrowable(thr);
        }

        g.translate(0, -labelHeight);
    }

    /**
     * Traverse this CustomItem
     *
     * @param dir the direction of traversal
     * @param viewportWidth the width of the container's viewport
     * @param viewportHeight the height of the container's viewport
     * @param visRect_inout passes the visible rectangle into the method, and
     * returns the updated traversal rectangle from the method
     * @return true if internal traversal had occurred, false if traversal
     * should proceed out
     */
    boolean callTraverse(int dir, int viewportWidth, int viewportHeight,
                         int[] visRect_inout) {

        super.callTraverse(dir, viewportWidth, viewportHeight, visRect_inout);

        try {
            synchronized (Display.calloutLock) {
                // We shave off the label height from the overall
                // item viewport
                visRect_inout[HEIGHT] -= labelHeight;
                boolean t = this.traverse(dir, viewportWidth,
                                          viewportHeight - labelHeight,
                                          visRect_inout);
                // We shift the return value from the item's traverse
                // by the label height to give the real location
                visRect_inout[Y] += labelHeight;
                return t;
            }
        } catch (Throwable thr) {
            Display.handleThrowable(thr);
        }
        return false;
    }

    /**
     * Called by the system to indicate traversal has left this Item
     *
     * @see #getInteractionModes
     * @see #traverse
     * @see #TRAVERSE_HORIZONTAL
     * @see #TRAVERSE_VERTICAL
     */
    void callTraverseOut() {
        super.callTraverseOut();

        try {
            synchronized (Display.calloutLock) {
                this.traverseOut();
            }
        } catch (Throwable thr) {
            Display.handleThrowable(thr);
        }
    }

    /**
     * Called by the system to signal a key press
     *
     * @param keyCode the key code of the key that has been pressed
     * @see #getInteractionModes
     */
    void callKeyPressed(int keyCode) {

        ItemCommandListener cl = null;
	Command defaultCmd = null;

        synchronized (Display.LCDUILock) {
            cl = commandListener;
	    defaultCmd = defaultCommand;
        } // synchronized


        // SYNC NOTE: The call to the listener must occur outside
        // of the lock

	try {
	    // SYNC NOTE: We lock on calloutLock around any calls
	    // into application code
	    synchronized (Display.calloutLock) {

		if ((cl != null)
                    && (defaultCmd != null)
                    && (keyCode == Display.KEYCODE_SELECT)) {
		    cl.commandAction(defaultCmd, this);
		} else {
		  this.keyPressed(keyCode);
		}
	    }
	} catch (Throwable thr) {
	    Display.handleThrowable(thr);
	}

    }

    /**
     * Called by the system to signal a key release
     *
     * @param keyCode the key code of the key that has been released
     * @see #getInteractionModes
     */
    void callKeyReleased(int keyCode) {
        try {
            synchronized (Display.calloutLock) {
                this.keyReleased(keyCode);
            }
        } catch (Throwable thr) {
            Display.handleThrowable(thr);
        }
    }

    /**
     * Called by the system to signal a key repeat
     *
     * @param keyCode the key code of the key that has been repeated
     * @see #getInteractionModes
     */
    void callKeyRepeated(int keyCode) {
        try {
            synchronized (Display.calloutLock) {
                this.keyRepeated(keyCode);
            }
        } catch (Throwable thr) {
            Display.handleThrowable(thr);
        }
    }

    /**
     * Called by the system to signal a pointer press
     *
     * @param x the x coordinate of the pointer down
     * @param y the y coordinate of the pointer down
     *
     * @see #getInteractionModes
     */
    void callPointerPressed(int x, int y) {
        try {
            synchronized (Display.calloutLock) {
                this.pointerPressed(x, y - labelHeight);
            }
        } catch (Throwable thr) {
            Display.handleThrowable(thr);
        }
    }

    /**
     * Called by the system to signal a pointer release
     *
     * @param x the x coordinate of the pointer up
     * @param y the x coordinate of the pointer up
     *
     * @see #getInteractionModes
     */
    void callPointerReleased(int x, int y) {
        try {
            synchronized (Display.calloutLock) {
                this.pointerReleased(x, y - labelHeight);
            }
        } catch (Throwable thr) {
            Display.handleThrowable(thr);
        }
    }

    /**
     * Called by the system to signal a pointer drag
     *
     * @param x the x coordinate of the pointer drag
     * @param y the x coordinate of the pointer drag
     *
     * @see #getInteractionModes
     */
    void callPointerDragged(int x, int y) {
        try {
            synchronized (Display.calloutLock) {
                this.pointerDragged(x, y - labelHeight);
            }
        } catch (Throwable thr) {
            Display.handleThrowable(thr);
        }
    }

    /**
     * Called by the system to notify this Item it is being shown
     *
     * <p>The default implementation of this method does nothing.</p>
     */
    void callShowNotify() {
        super.callShowNotify();

        try {
            synchronized (Display.calloutLock) {
                this.showNotify();
            }
        } catch (Throwable thr) {
            Display.handleThrowable(thr);
        }
    }

    /**
     * Called by the system to notify this Item it is being hidden
     *
     * <p>The default implementation of this method does nothing.</p>
     */
    void callHideNotify() {
        super.callHideNotify();

        try {
            synchronized (Display.calloutLock) {
                this.hideNotify();
            }
        } catch (Throwable thr) {
            Display.handleThrowable(thr);
        }
    }

}