/*
*
*
* Copyright 1990-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 only, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 2 for more details (a copy is
* included at /legal/license.txt).
*
* You should have received a copy of the GNU General Public License
* version 2 along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 or visit www.sun.com if you need additional
* information or have any questions.
*/
package javax.microedition.lcdui;
/* import javax.microedition.lcdui.KeyConverter; */
/**
* 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>
*
*/
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;
/**
* 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);
synchronized (Display.LCDUILock) {
itemLF = customItemLF = LFFactory.getFactory().getCustomItemLF(this);
}
}
/**
* 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 = KeyConverter.getGameAction(keyCode);
if (n == -1) {
throw new IllegalArgumentException();
}
return n;
}
// JAVADOC COMMENT ELIDED
protected final int getInteractionModes() {
synchronized (Display.LCDUILock) {
return customItemLF.lGetInteractionModes();
}
}
/**
* 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() {
synchronized (Display.LCDUILock) {
customItemLF.lInvalidate();
}
}
/**
* 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() {
synchronized (Display.LCDUILock) {
customItemLF.lRepaint();
}
}
/**
* 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) {
synchronized (Display.LCDUILock) {
customItemLF.lRepaint(x, y, w, h);
}
}
/**
* 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 methods
// ******************************************
/** Size type of minimum width */
final static int SIZE_MIN_WIDTH = 0;
/** Size type of minimum height */
final static int SIZE_MIN_HEIGHT = 1;
/** Size type of preferred width */
final static int SIZE_PREF_WIDTH = 2;
/** Size type of preferred height */
final static int SIZE_PREF_HEIGHT = 3;
/**
* Internal function to query for preferred content size.
* This function will never return negative value.
* SYNC NOTE: This function will internally acquire calloutLock.
* So caller must not hold LCDUILock around this call.
*
* @param type the type of size that is queried.
* @param lockedSize the tentative content size in pixels, or -1 if a
* tentative size has not been computed
* @return the preferred content size in pixels
*/
int uGetContentSize(int type, int lockedSize) {
int result = 0; // default value
try {
synchronized (Display.calloutLock) {
switch (type) {
case SIZE_MIN_WIDTH:
result = getMinContentWidth();
break;
case SIZE_MIN_HEIGHT:
result = getMinContentHeight();
break;
case SIZE_PREF_WIDTH:
result = getPrefContentWidth(lockedSize);
break;
case SIZE_PREF_HEIGHT:
result = getPrefContentHeight(lockedSize);
break;
}
}
} catch (Throwable thr) {
Display.handleThrowable(thr);
}
// If subclass returns negative size, treat it as 0
return (result > 0) ? result : 0;
}
/**
* Return whether the Item takes user input focus.
*
* @return always return <code>true</code>
*/
boolean acceptFocus() {
return true;
}
/**
* The look&feel associated with this CustomItem.
* Set in the constructor.
*/
CustomItemLF customItemLF; // = null
}