/* * * * 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 }