FileDocCategorySizeDatePackage
CustomItemLFImpl.javaAPI DocphoneME MR2 API (J2ME)45025Wed May 02 18:00:22 BST 2007javax.microedition.lcdui

CustomItemLFImpl

public class CustomItemLFImpl extends ItemLFImpl implements CustomItemLF
This is the look and feel implementation for CustomItem.

Fields Summary
private CustomItem
customItem
The CustomItem associated with this view.
private static final int
X1
Parameter used by dirtyRegion[].
private static final int
Y1
Parameter used by dirtyRegion[].
private static final int
X2
Parameter used by dirtyRegion[].
private static final int
Y2
Parameter used by dirtyRegion[].
private int[]
dirtyRegion
Represents the dirty region since last repaint. Array of 4 integers, representing the two corners: (x1,y1), (x2,y2)
private static int
ITEM_PAD
Internal spacing between Item's inner components - label and body. This value is taken from native, and cached here, to minimize native calls.
private ImageData
contentImageData
Mutable image that holds CustomItem repaints
private Graphics
contentGraphics
Graphics associated with contentImage
Constructors Summary
CustomItemLFImpl(CustomItem ci)
Creates CustomItemLF associated with the passed in CustomItem.

param
ci the CustomItem associated with this look & feel.

        super(ci);

        dirtyRegion = new int[4];

        resetDirtyRegion();

        customItem = ci;
    
Methods Summary
voidcreateNativeResource(int ownerId)
Create native resource for current CustomItem. Override function in ItemLFImpl.

param
ownerId Owner screen's native resource id.

        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
            Logging.report(Logging.INFORMATION, LogChannels.LC_HIGHUI,
                           "****************************************" +
                           "CustomItem: createNativeResource -- ownerId=" +
                           ownerId + 
                           "bounds are: " + bounds[X] + "," + bounds[Y] +
                           " -- " + bounds[WIDTH] + "x" + bounds[HEIGHT] + 
                           "****************************************");
        }
        nativeId = createNativeResource0(ownerId,
                                         customItem.label,
                                         customItem.layout);
    
private static native intcreateNativeResource0(int ownerId, java.lang.String label, int layout)
KNI function that creates native resource for current CustomItem.

param
ownerId Owner screen's native resource id (MidpDisplayable *)
param
label - label to be used for this Item
param
layout - layout directive associated with this Item
return
native resource id (MidpItem *) of this CustomItem

private intgetItemPad()
Returns item pad used in native. The value is fetched only once and cached in Java.

return
item pad used in native


        if (ITEM_PAD == 0) {
            // query native for real preferred size
            boolean wasNoNative = 
                (nativeId == DisplayableLFImpl.INVALID_NATIVE_ID);
            
            // Native resource not yet created, do it now
            if (wasNoNative) {
                createTempNativeResource();
            }
            
            ITEM_PAD = getItemPad0(nativeId);
                        
            if (wasNoNative) {
                deleteNativeResource();
            }
        }

        return ITEM_PAD;
    
private static native intgetItemPad0(int nativeId)
Returns item pad used in native.

param
nativeId native resource id for this Item
return
item pad used in native

private intgetLabelHeight(int w)
Get label height.

param
w width available for label
return
label height


        // check empty label case:
        if (customItem.label == null || customItem.label.equals("") ||
            (w >= 0 && w <= 2*getItemPad())) {
            return 0;
        }
        
        if (w > 0) {
            w -= 2*getItemPad();
        } else if (w != -1) {
            w = -1;
        }

        // query native for real preferred size
        boolean wasNoNative = 
          (nativeId == DisplayableLFImpl.INVALID_NATIVE_ID);

        // Native resource not yet created, do it now
        if (wasNoNative) {
            createTempNativeResource();
        }

        int h = getLabelHeight0(nativeId, w);

        if (wasNoNative) {
            deleteNativeResource();
        }

        return h;
    
private static native intgetLabelHeight0(int nativeId, int width)
Returns label height in native widget.

param
nativeId native resource id for this Item
param
width tentative width used to calculate the height
return
label height in native widget

private intgetLabelWidth(int w)
Gets label width used in native. If -1 is passed as a width parameter the whole available width should be used. Note that padding will be subtracted from the passed in width.

param
w the width to be used to get label width.
return
actual width of the label.


        // check empty label case:
        if (customItem.label == null || customItem.label.equals("") ||
            (w >= 0 && w <= getItemPad())) {
            return 0;
        }

        if (w > 0) {
            w -= 2*getItemPad();
        } else if (w != -1) {
            w = -1;
        }

        // query native for real preferred size
        boolean wasNoNative = 
          (nativeId == DisplayableLFImpl.INVALID_NATIVE_ID);

        // Native resource not yet created, do it now
        if (wasNoNative) {
            createTempNativeResource();
        }

        int lw = getLabelWidth0(nativeId, w);

        if (wasNoNative) {
            deleteNativeResource();
        }

        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
            Logging.report(Logging.INFORMATION, 
                           LogChannels.LC_HIGHUI_ITEM_REPAINT,
                           "CustomItemLFImpl: getLabelWidth(" + w +
                           ")... nativeId==" + nativeId +
                           " \t returning: " + lw);
        }
        return lw;
    
private static native intgetLabelWidth0(int nativeId, int contentWidth)
Get the actual width required for the label.

param
nativeId native resource id for this Item
param
contentWidth hint for the native widget to decide on label layout
return
actual label width in native widget

voidlCallShowNotify()
Overrides the default method to set dirty region to full size.

        super.lCallShowNotify();
        setDirtyRegionFull();
    
public intlGetInteractionModes()


        // removed support for traversal.
        // (MIDlets should use low level key events instead)

        int result = customItem.TRAVERSE_HORIZONTAL |
                customItem.TRAVERSE_VERTICAL |
                customItem.KEY_PRESS |
                customItem.KEY_RELEASE;
        if (Constants.REPEAT_SUPPORTED) {
            result = result | customItem.KEY_REPEAT;
        }
        if (Constants.POINTER_SUPPORTED) {
            result = result | customItem.POINTER_PRESS |
                customItem.POINTER_RELEASE;
        }
        if (Constants.MOTION_SUPPORTED) {
            result = result | customItem.POINTER_DRAG;
        }
        return result;
    
voidlGetRequestedSizes()
Calculate minimum and preferred width and height of this item and store the result in instance variables minimumWidth, minimumHeight, preferredWidth and preferredHeight. Override the version in ItemLFImpl to do nothing.

        // Even if (isRequestedSizesValid() == false), we won't be able to
        // call into app code for the content sizes since we
        // are holding LCDUILock and may be even on event dispatch thread.
        // Do nothing here so the cached requested sizes will be used.
    
voidlHideNativeResource()
Override ItemLFImpl method to reset the dirty region before hiding the native resource

        resetDirtyRegion();
        super.lHideNativeResource();
    
public voidlInvalidate()
Notifies L&F that CustomItem was invalidated.

        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
            Logging.report(Logging.INFORMATION,
                           LogChannels.LC_HIGHUI_ITEM_LAYOUT,
                           ">>> CustomItemLFImpl -- lInvalidate()");
        }
        setDirtyRegionFull();
        lRequestInvalidate(true, true);
    
public voidlRepaint()
Notifies L&F that repaint of the entire custom item is needed.


        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
            Logging.report(Logging.INFORMATION,
                           LogChannels.LC_HIGHUI_ITEM_REPAINT,
                           ">>> CustomItemLFImpl -- lRepaint()");
        }
        
        // content area is empty no repaint is needed
        if (contentImageData == null) {
            return;
        }

        setDirtyRegionFull();

        try {
            int pad = getItemPad();
            // We prune off the label area when doing a complete repaint
            lRequestPaint(pad,
                          pad + getLabelHeight(bounds[WIDTH]),
                          contentImageData.getWidth(),
                          contentImageData.getHeight());
        } catch (Exception e) {
            Display.handleThrowable(e);
        }
    
public voidlRepaint(int x, int y, int width, int height)
Notifies L&F that repaint of the specified region is needed.

param
x the x coordinate of the origin of the dirty region
param
y the y coordinate of the origin of the dirty region
param
width the width of the dirty region
param
height the height of the dirty region


        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
            Logging.report(Logging.INFORMATION,
                           LogChannels.LC_HIGHUI_ITEM_REPAINT,
                           ">>> CustomItemLFImpl -- lRepaint(" + x + 
                           "," + y + "," + width + "," + height + ")");
        }

        try {

            // Content area is empty there is no need to do anything
            if (contentImageData == null) {
                return;
            }

            int pad = getItemPad();
            // int lH = getLabelHeight(bounds[WIDTH]);

            // no need to do anything if the repaint region
            // is complete outside the content area
            
            if (x >= bounds[WIDTH] - 2*pad || 
                y >= bounds[HEIGHT] - 2*pad /* - lH */ ||
                x + width <= 0 || y + height <= 0) {
                return;
            }

            // passed in region is expressed in the same coordinate system
            // as the dirtyRegion; join those 2 regions
            if (x <= 0) {
                dirtyRegion[X1] = 0;
            } else {
                // when dirty region is unset the following will be true
                // and dirtyRegion[X1] will be correctly set
                if (dirtyRegion[X1] > x) {
                    dirtyRegion[X1] = x;
                }
            }

            if (y <= 0) {
                dirtyRegion[Y1] = 0;
            } else {
                // when dirty region is unset the following will be true
                // and dirtyRegion[Y1] will be correctly set
                if (dirtyRegion[Y1] > y) {
                    dirtyRegion[Y1] = y;
                }
            }

            if (x + width >= bounds[WIDTH] - pad) {
                dirtyRegion[X2] = bounds[WIDTH] - pad;
            } else {
                // when dirty region is unset the following will be true
                // and dirtyRegion[X2] will be correctly set
                if (x + width > dirtyRegion[X2]) {
                    dirtyRegion[X2] = x + width;
                }
            }

            if (y + height >= bounds[HEIGHT] - pad) {
                dirtyRegion[Y2] = bounds[HEIGHT] - pad;
            } else {
                // when dirty region is unset the following will be true
                // and dirtyRegion[Y2]  will be correctly set
                if (y + height > dirtyRegion[Y2]) {
                    dirtyRegion[Y2] = y + height;
                }
            }

            if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
                Logging.report(Logging.INFORMATION,
                               LogChannels.LC_HIGHUI_ITEM_REPAINT,
                               "after join ..... \t\t dirtyRegion (" +
                                   dirtyRegion[X1] + "," +
                                   dirtyRegion[Y1] + ") - (" +
                                   dirtyRegion[X2] + "," +
                                   dirtyRegion[Y2] + ")");
            }

            // obsolete - can use any number...
            super.lRequestPaint(0, 0, 0, 0);

            /*
            // repaint should be requested in Item's coordinate
            // system (translate by padding and labelHeight)
            super.lRequestPaint(dirtyRegion[X1] + pad,
                                dirtyRegion[Y1] + pad + lH,
                                dirtyRegion[X2] - dirtyRegion[X1] + 1,
                                dirtyRegion[Y2] - dirtyRegion[Y1] + 1);
            */

        } catch (Exception e) {
            Display.handleThrowable(e);
        }
    
public voidlSetLabel(java.lang.String label)
Overriding ItemLFImpl. Notifies L&F of a label change in the corresponding Item.

param
label the new label string

        super.lSetLabel(label);
    
voidlSetSize(int w, int h)
Sets custom item's size

param
w - the new width of the item
param
h - the new height of the item

        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
            Logging.report(Logging.INFORMATION,
                           LogChannels.LC_HIGHUI_ITEM_LAYOUT,
                           " CustomItemLFImpl  -  setSize: " + w + "x" + h);
        }

        if (w == bounds[WIDTH] && h == bounds[HEIGHT]) {
            return;
        }
        int pad = getItemPad();
        int contentW = w - 2*pad;
        int contentH = h - 2*pad - getLabelHeight(w);

        if (contentImageData == null ||
            contentImageData.getWidth() != contentW || 
            contentImageData.getHeight() != contentH) {
            if (contentW > 0 && contentH > 0) {
                Image contentImage = Image.createImage(contentW, contentH);
                contentImageData = contentImage.getImageData();
                if (nativeId != DisplayableLFImpl.INVALID_NATIVE_ID) {
                    setContentBuffer0(nativeId, contentImageData);
                }
                contentGraphics = contentImage.getGraphics();
                // no need to paint background of the newly created 
                // Mutable image since according to the spec 
                // it will be set to white color
                setDirtyRegionFull();
            }
        }

        super.lSetSize(w, h);
    
voidlShowNativeResource()
Override ItemLFImpl method to set the dirty region and the content buffer before showing the native resource.

        if (nativeId != DisplayableLFImpl.INVALID_NATIVE_ID) {
            setContentBuffer0(nativeId, contentImageData);
            super.lShowNativeResource();
        }
    
private static native voidrefresh0(int nativeId, int x, int y, int width, int height)
Call to blit the paint result to the CustomItem.

param
nativeId native resource id for this Item
param
x coordinate relative to the widget
param
y coordinate relative to the widget
param
width invalid width to repaint. If < 0 than paint all.
param
height invalid height to repaint. If < 0 than paint all.

private voidresetDirtyRegion()
Reset the values to invalid coordinates.

        dirtyRegion[X1] = 1000;
        dirtyRegion[Y1] = 1000;
        dirtyRegion[X2] =  0;
        dirtyRegion[Y2] =  0;        
    
private voidscrollforInternalTraversal(FormLFImpl ownerLFImpl, int[] vis_Rect)
Called by traverse method to scroll the CustomItem for InternalTraversal.

param
ownerLFImpl FormLFImpl
param
vis_Rect the updated traversal rectangle from the traverse method

        int yOffset = 0;

        // check the returned vis_Rect 
        // to check the validity of x,y,w,h
        // x and y values are relative to item's origin

        if (vis_Rect[X] < 0) {
            vis_Rect[X] = 0;
        }
        if (vis_Rect[WIDTH] < 0) {
            vis_Rect[WIDTH] = 0;
        }
        if (vis_Rect[X] > bounds[WIDTH]) {
            vis_Rect[X] = bounds[WIDTH];
        }
        if (vis_Rect[Y] < 0) {
            vis_Rect[Y] = 0;
        }
        if (vis_Rect[HEIGHT] < 0) {
            vis_Rect[HEIGHT] = 0;
        }
        if (vis_Rect[Y] > bounds[HEIGHT]) {
            vis_Rect[Y] = bounds[HEIGHT];
        }

        // shouldn't exceed viewportHeight
        if (vis_Rect[HEIGHT] > ownerLFImpl.height) {
            vis_Rect[HEIGHT] = ownerLFImpl.height;
        }
        // shouldn't exceed viewportwidth
        if (vis_Rect[WIDTH] > ownerLFImpl.width) {
            vis_Rect[WIDTH] = ownerLFImpl.width;
        }

        // current scroll position
        int vpY1 = ownerLFImpl.getScrollPosition0();
        // vpY2 the y coordinate of bottom left visible pixel
        int vpY2 = vpY1 + ownerLFImpl.height;

        // convert vis_Rect Y into form's co-ordinates
        vis_Rect[Y] += bounds[Y];

        int itemHeight = vis_Rect[HEIGHT];
        int vpHeight = ownerLFImpl.height;

        // make sure that the item is visible
        ItemLFImpl itemLFInFocus = ownerLFImpl.getItemInFocus();
        if ((itemLFInFocus != null)
            && (itemLFInFocus.nativeId 
                != ownerLFImpl.INVALID_NATIVE_ID)) {
            // find the y offset depending on 
            // the vis_Rect returned       

            int vpMidpoint = vpY1 + vpHeight/2;
            int itemMidpoint = vis_Rect[Y] + itemHeight/2;

            if (itemHeight <= vpHeight) { // center it
                // HI DECISION: short circuit scrolling all together
                // if the complete vis_Rect area is in the viewport

                if (itemMidpoint > vpMidpoint) { // lower
                    yOffset = itemMidpoint - vpMidpoint;
                } else if (itemMidpoint < vpMidpoint) { // upper
                    yOffset = vpMidpoint - itemMidpoint;
                }
            } else if (itemHeight > vpHeight) { // top it
                if (itemMidpoint > vpMidpoint) { // lower
                    yOffset = vis_Rect[Y] - vpY1;
                } else if (itemMidpoint < vpMidpoint) { // upper
                    yOffset = vpY1 - vis_Rect[Y];
                }                     
            }
                   
            // QT makes this visible with at least
            // 50 pixel margins (if possible, otherwise centered)
            ownerLFImpl.setCurrentItem0(
                        nativeId, itemLFInFocus.nativeId, yOffset);
        }
    
private static native voidsetContentBuffer0(int nativeId, ImageData imgData)
Sets the content buffer. All paints are done to that buffer. When paint is processed snapshot of the buffer is flushed to the native resource content area.

param
nativeId native resource is for this CustomItem
param
imgData mutable ImageData associated with an Image that serves as an offscreen buffer

private voidsetDirtyRegionFull()
Reset the values to invalid coordinates.

        dirtyRegion[X1] = 0;
        dirtyRegion[Y1] = 0;
        if (contentImageData == null) {
            dirtyRegion[X2] = dirtyRegion[Y2] = 0;
        } else {
            dirtyRegion[X2] = contentImageData.getWidth();
            dirtyRegion[Y2] = contentImageData.getHeight();
        }
    
voiduCallHideNotify()
Overrides the default method in ItemLFImpl. Called by the system to notify this CustomItem that it is being hidden. This method will be called only if this CustomItem was hidden. The default implementation changes the visibleInViewport flag.

        
        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
            Logging.report(Logging.INFORMATION,
                           LogChannels.LC_HIGHUI_ITEM_REPAINT,
                           "CustomItemLFImpl: uCallHideNotify()");
        }

        super.uCallHideNotify();

        try {
            synchronized (Display.calloutLock) {
                customItem.hideNotify();
            }
        } catch (Throwable thr) {
            Display.handleThrowable(thr);
        }
    
voiduCallKeyPressed(int keyCode)
Called by the system to signal a key press.

param
keyCode the key code of the key that has been pressed.
see
#getInteractionModes

        ItemCommandListener cl = null;
        Command defaultCmd = null;
        FormLFImpl ownerLFImpl = null;
        boolean internalTraverse = false;
        int vis_Rect[] = new int[4];
        // vpY1 the y coordinate of the top left visible pixel
        int vpY1 = 0;
        // vpY2 the y coordinate of bottom left visible pixel
        int vpY2 = 0;

        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
            Logging.report(Logging.INFORMATION, LogChannels.LC_HIGHUI,
                           "CustomItemLFImpl: got uCallKeyPressed: " +
                           keyCode);
        }
      
        synchronized (Display.LCDUILock) {
            cl = customItem.commandListener;
            defaultCmd = customItem.defaultCommand;

            if (item.owner != null) {
                ownerLFImpl = 
                    (FormLFImpl)item.owner.getLF();
            }
        } // synchronized


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

        try {
            // SYNC NOTE: We lock on calloutLock around any calls
            // into application code
            synchronized (Display.calloutLock) {
                if ((cl != null)
                    && (defaultCmd != null)
                    && (keyCode == Constants.KEYCODE_SELECT)) {
                    cl.commandAction(defaultCmd, customItem);
                } else {
                        customItem.keyPressed(keyCode);
                }
            } // end synchronized
        } catch (Throwable thr) {
            Display.handleThrowable(thr);
        }

        synchronized (Display.LCDUILock) {
            if (internalTraverse) {
                scrollforInternalTraversal(
                        ownerLFImpl, vis_Rect);
            }
        } // end synchronized
voiduCallKeyReleased(int keyCode)
Called by the system to signal a key release.

param
keyCode the key code of the key that has been released.
see
#getInteractionModes

        try {
            synchronized (Display.calloutLock) {
                customItem.keyReleased(keyCode);
            }
        } catch (Throwable thr) {
            Display.handleThrowable(thr);
        }
    
voiduCallKeyRepeated(int keyCode)
Called by the system to signal a key repeat.

param
keyCode the key code of the key that has been repeated.
see
#getInteractionModes

        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
            Logging.report(Logging.INFORMATION, LogChannels.LC_HIGHUI,
                           "CustomItemLFImpl: uCallKeyRepeated!! " + keyCode);
        }

        try {
            synchronized (Display.calloutLock) {
                customItem.keyRepeated(keyCode);
            }
        } catch (Throwable thr) {
            Display.handleThrowable(thr);
        }
    
private intuCallMinimumHeight()
Get the minimum height of this Item, including the minimum content height and room for the label. This is the callback for Item's public getMinimumHeight() method.

return
the minimum height

        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
            Logging.report(Logging.INFORMATION,
                           LogChannels.LC_HIGHUI_ITEM_LAYOUT,
                           "CustomItemLFImpl -- uCallMinimumHeight");
        }
        // SYNC NOTE: Call into app code. Must not hold LCDUILock.
        int mH = customItem.uGetContentSize(CustomItem.SIZE_MIN_HEIGHT, 0);

        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
            Logging.report(Logging.INFORMATION,
                           LogChannels.LC_HIGHUI_ITEM_LAYOUT,
                           "CustomItem -- uCallMinimumHeight ret: " + mH);
        }
        synchronized (Display.LCDUILock) {
            mH += getLabelHeight(-1);

            if (mH > 0) {
                mH += 2 * getItemPad();
            }
        }

        return mH;
    
private intuCallMinimumWidth()
Get the minimum width of this Item, including the minimum content width and room for the label. This is the callback for Item's public getMinimumWidth() method.

return
the minimum width

        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
            Logging.report(Logging.INFORMATION,
                           LogChannels.LC_HIGHUI_ITEM_LAYOUT,
                           "CustomItemLFImpl -- uCallMinimumWidth");
        }
        // SYNC NOTE: Call into app code. Must not hold LCDUILock.
        int mW = customItem.uGetContentSize(CustomItem.SIZE_MIN_WIDTH, 0);
        
        synchronized (Display.LCDUILock) {
            int lw = getLabelWidth(-1);
            
            // if label is wider than customItem body, we're allowed
            // to make the body wider.
            if (lw > mW) {
                mW = lw;
            }
            
            if (mW > 0) {
                mW += 2 * getItemPad();
            }
        }
        
        return mW;
    
voiduCallPaint(Graphics g, int w, int h)
Called to paint this CustomItem.

param
g the Graphics 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

                
        // ignore passed in graphics and use Custom Item's muttable image
        
        // contentImageData consists only of content so there is
        // no need to do translation by the label height and 
        // around item padding

        int x1, x2, y1, y2;

        boolean visInViewport;

        synchronized (Display.LCDUILock) {

            // spec requires not to call CustomItem's paint
            // if content area width or height is 0 that is why:
            // if content area is empty or dirty region is unset
            // no repaint is needed
            if (contentImageData == null ||
                dirtyRegion[Y2] <= dirtyRegion[Y1] ||
                dirtyRegion[X2] <= dirtyRegion[X1]) {
                return;
            }

            x1 = dirtyRegion[X1];
            x2 = dirtyRegion[X2];
            y1 = dirtyRegion[Y1];
            y2 = dirtyRegion[Y2];
            visInViewport = visibleInViewport;

            if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
                Logging.report(Logging.INFORMATION, 
                               LogChannels.LC_HIGHUI_ITEM_REPAINT, 
                               "<<< \t\t Current clip: (" +
                               g.getClipX() + "," +
                               g.getClipY() + ") - (" +
                               (g.getClipWidth()) + "," +
                               (g.getClipHeight()) + ")" +
                               "<<< \t\t clipping to: (" +
                               dirtyRegion[X1] + "," +
                               dirtyRegion[Y1] + ") - (" +
                               (dirtyRegion[X2] - dirtyRegion[X1] + 1) 
                               + "," +
                               (dirtyRegion[Y2] - dirtyRegion[Y1] + 1) +
                               ")\n\n");
            }
            
            contentGraphics.setClip(x1, y1, x2 - x1 + 1, y2 - y1 +1);
            
            contentGraphics.setColor(
                            Theme.getColor(Display.COLOR_BACKGROUND));
            contentGraphics.fillRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
            
            contentGraphics.setColor(0);
            contentGraphics.setFont(Font.getDefaultFont());
            contentGraphics.setStrokeStyle(Graphics.SOLID);

            resetDirtyRegion();
            
            if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
                contentGraphics.drawLine(dirtyRegion[X1],
                                         dirtyRegion[Y1],
                                         dirtyRegion[X2] - dirtyRegion[X1] + 1,
                                         dirtyRegion[Y2] - dirtyRegion[Y1] + 1);
                Logging.report(Logging.INFORMATION, 
                               LogChannels.LC_HIGHUI_ITEM_REPAINT,
                               "<<< CustomItemLFImpl -- uCallPaint " +
                               nativeId +" / " + w + "x" + h);
            }
        }
         
        // SYNC NOTE: Call into app code. Must not hold LCDUILock.
        try {   
            synchronized (Display.calloutLock) {
                // call to the MIDlet even if it is not visible
                // but do not refresh if it is not visible in viewport
                
                // SYNC NOTE: the change of contentGraphics and use of
                // contentGraphics happen on the event dispatch thread
                // so there is no problem of doing it outside of 
                // the LCDUILock
                customItem.paint(contentGraphics, 
                                 contentImageData.getWidth(),
                                 contentImageData.getHeight());
            }

            // Show the buffer onto screen
            synchronized (Display.LCDUILock) {
                // Need to check nativeId again since it might have been
                // deleted if the CustomItem is removed from the form
                if (nativeId != DisplayableLFImpl.INVALID_NATIVE_ID) {
                    refresh0(nativeId, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
                }
            }
        } catch (Throwable thr) {
            Display.handleThrowable(thr);
        }
    
booleanuCallPeerStateChanged(int hint)
Called by Display to notify an ItemLF in current FormLF of a change in its peer state. Return false since no notification is needed.

param
hint notification sub-type defined as above
return
always false since no internal state changes.

        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
            Logging.report(Logging.INFORMATION, LogChannels.LC_HIGHUI,
                           "-=- CustomItemLFImpl uCallPeerStateChanged " +
                           hint);
        }
        return false;
    
voiduCallPointerDragged(int x, int y)
Called by the system to signal a pointer drag.

param
x the x coordinate of the pointer drag
param
y the x coordinate of the pointer drag
see
#getInteractionModes

        try {
            synchronized (Display.calloutLock) {
                customItem.pointerDragged(x, y);
            }
        } catch (Throwable thr) {
            Display.handleThrowable(thr);
        }
    
voiduCallPointerPressed(int x, int y)
Called by the system to signal a pointer press.

param
x the x coordinate of the pointer down
param
y the y coordinate of the pointer down
see
#getInteractionModes

        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
            Logging.report(Logging.INFORMATION, LogChannels.LC_HIGHUI,
                           "*-* CustomItem: uCallPointerPressed *-*");
        }
        try {
            synchronized (Display.calloutLock) {
                customItem.pointerPressed(x, y);
            }
        } catch (Throwable thr) {
            Display.handleThrowable(thr);
        }
    
voiduCallPointerReleased(int x, int y)
Called by the system to signal a pointer release.

param
x the x coordinate of the pointer up
param
y the x coordinate of the pointer up
see
#getInteractionModes

        try {
            synchronized (Display.calloutLock) {
                customItem.pointerReleased(x, y);
            }
        } catch (Throwable thr) {
            Display.handleThrowable(thr);
        }
    
private intuCallPreferredHeight(int w)
Get the preferred height of this Item, including the preferred content height and room for the label. This is the callback for Item's public getPreferredHeight() method.

param
w the width to base the height size on
return
the preferred height


        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
            Logging.report(Logging.INFORMATION,
                           LogChannels.LC_HIGHUI_ITEM_LAYOUT,
                           "CustomItem -- uCallPreferredHeight w=" + w);
        }
        // SYNC NOTE: Call into app code. Must not hold LCDUILock.
        int pH = customItem.uGetContentSize(CustomItem.SIZE_PREF_HEIGHT, w);

        // preferred height should be at least the minimum allowed,
        // this is checked and fixed at Item level

        synchronized (Display.LCDUILock) {
            pH += getLabelHeight(w);

            if (pH > 0) {
                pH += 2 * getItemPad();
            }
        }

        return pH;
    
private intuCallPreferredWidth(int h)
Get the preferred width of this Item, including the preferred content width and room for the label. This is the callback for Item's public getPreferredWidth() method.

param
h the height to base the width size on
return
the preferred width


        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
            Logging.report(Logging.INFORMATION,
                           LogChannels.LC_HIGHUI_ITEM_LAYOUT,
                           "CustomItem -- uCallPreferredWidth h=" + h);
        }

        // SYNC NOTE: Call into app code. Must not hold LCDUILock.
        int pW = customItem.uGetContentSize(CustomItem.SIZE_PREF_WIDTH, h);

        // preferred width should be at least the minimum allowed,
        // this is checked and fixed at Item level

        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
            Logging.report(Logging.INFORMATION,
                           LogChannels.LC_HIGHUI_ITEM_LAYOUT,
                           "\t -- uCallPreferredWidth item returned " +
                           pW);
        }

        synchronized (Display.LCDUILock) {
            // if width is not locked item.lockedWidth will be -1
            // which means that all available width can be used
            int lw = getLabelWidth(item.lockedWidth);

            // if label is wider than customItem body, we're allowed
            // to make the body wider.
            if (lw > pW) {
                pW = lw;
            }

            if (pW > 0) {
                pW += 2 * getItemPad();
            }
        }

        return pW;
    
voiduCallShowNotify()
Overrides the default method in ItemLFImpl. Called by the system to notify this CustomItem that it is being shown. This method will be called only if this CustomItem was made visible. The default implementation changes the visibleInViewport flag.

        
        if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
            Logging.report(Logging.INFORMATION,
                           LogChannels.LC_HIGHUI_ITEM_REPAINT,
                           "CustomItemLFImpl: uCallShowNotify()");
        }

        super.uCallShowNotify();

        try {
            synchronized (Display.calloutLock) {
                customItem.showNotify();
            }

        } catch (Throwable thr) {
            Display.handleThrowable(thr);
        }
    
voiduCallSizeChanged(int w, int h)
Called by the system to indicate the size available to this Item has changed. SYNC NOTE: Caller must not hold LCDUILock.

param
w the new width of the item's content area
param
h the new height of the item's content area

        try {
            synchronized (Display.calloutLock) {
                int pad = getItemPad();
                h -= 2*pad + getLabelHeight(w);
                w -= 2*pad;
                customItem.sizeChanged(w, h);
            }
        } catch (Throwable thr) {
            Display.handleThrowable(thr);
        }
    
public voiduCallSizeRefresh()
Get minimum and preferred sizes from CustomItem subclass and cache the result in super class.


        if (isRequestedSizesValid()) {
            return;
        }

        int mw = uCallMinimumWidth();
        if (mw < 0) mw = 0;

        int mh = uCallMinimumHeight();
        if (mh < 0) mh = 0;
        
        int pw = uCallPreferredWidth(item.lockedHeight);
        if (pw < mw) pw = mw;

        int ph = uCallPreferredHeight(pw);

        synchronized (Display.LCDUILock) {
            // NOTE: When the item should shrink, the minimum size is used,
            // and the minimum size is calculated with the label
            // on the same line
            if (shouldHShrink() &&
                item.label != null &&
                item.label.length() > 0) {
                mh += DEFAULT_LABEL_HEIGHT;
            }
            if (ph < mh) ph = mh;

            // Cache the result in ItemLFImpl
            lSetRequestedSizes(mw, mh, pw, ph);
        }
    
booleanuCallTraverse(int dir, int viewportWidth, int viewportHeight, int[] visRect_inout)
Called by the system to notify internal traverse into the item.

param
dir the direction of traversal
param
viewportWidth the width of the container's viewport
param
viewportHeight the height of the container's viewport
param
visRect_inout passes the visible rectangle into the method, and returns the updated traversal rectangle from the method
return
true if internal traversal had occurred, false if traversal should proceed out
see
#getInteractionModes
see
#traverseOut
see
#TRAVERSE_HORIZONTAL
see
#TRAVERSE_VERTICAL

        // the super implementation has to set the focus to this item

        boolean ret = super.uCallTraverse(dir, viewportWidth,
                                          viewportHeight, visRect_inout);
        try {
            synchronized (Display.calloutLock) {
                if (hasFocus) {
                    int lH = getLabelHeight(bounds[WIDTH]);
                    
                    // We shave off the label height from the overall
                    // item viewport
                    visRect_inout[HEIGHT] -= lH;
                    
                    // NOTE: visRect_inout should reflect native scroll
                    ret |= customItem.traverse(dir, viewportWidth,
                                               viewportHeight - lH,
                                               visRect_inout);
                    // We shift the return value from the item's traverse
                    // by the label height to give the real location
                    visRect_inout[Y] += lH;
                    if (ret) {
                        setDirtyRegionFull();
                    }
                }
            }
        } catch (Throwable thr) {
            Display.handleThrowable(thr);
        }
        return ret;
    
voiduCallTraverseOut()
Called by the system to indicate traversal has left this Item.

see
#getInteractionModes
see
#traverse
see
#TRAVERSE_HORIZONTAL
see
#TRAVERSE_VERTICAL

        super.uCallTraverseOut();

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