FileDocCategorySizeDatePackage
GaugeLFImpl.javaAPI DocphoneME MR2 API (J2ME)53499Wed May 02 18:00:20 BST 2007javax.microedition.lcdui

GaugeLFImpl

public class GaugeLFImpl extends ItemLFImpl implements GaugeLF
This is the look & feel implementation for Gauge.

Fields Summary
Gauge
gauge
Gauge instance associated with this view
static Timer
gaugeUpdateTimer
A Timer which will handle scheduling repaints of an indefinite range gauge when value == Gauge.CONTINUOUS_RUNNING
static final int
I_INC_BTN
Constant representing the increment button. It is an arbitrary integer. The focusBtn attribute is set to this value if, during traversal, the focus is gained by the increment button and later on used to check for focus highlight painting.
static final int
I_DEC_BTN
Constant representing the decrement button. It is an arbitrary integer. The focusBtn attribute is set to this value if, during traversal, the focus is gained by the decrement button and later on used to check for focus highlight painting.
GaugeUpdateTask
updateHelper
A TimerTask which will schedule repaints of an indefinite range gauge when value == Gauge.CONTINUOUS_RUNNING
int
percentWidth
The cached value for the width of the graphical percent sign
int
percentHeight
The cached value for the height of the graphical percent sign
int
focusBtn
Used to remember internally the current button in focus (increment/decrement) when traversal happens and focus is gained by an interactive gauge from another widget, or during internal traversal, between increment and decrement buttons. The constant values it can assume could be: I_INC_BTN: if focus is on increment button I_DEC_BTN: if focus is on decrement button (default initial value) This is later used to check for focus highlight painting.
int[]
percentLoc
An array storing the x,y co-ordinates of the location where the percentage sign should be displayed for a progressbar. This *MUST BE FILLED* inside the drawNumber() method, so that the drawPercentage() method knows where to draw the percentage sign correctly.
int
nextFrame
An index that keeps track of the next image that should be drawn to animate a continuous running gauge, from an array of frames.
boolean
initialTraverse
A flag to mark when the call to a gauge's traverse method is the initial traverse or not. True by default, (reset to true in traverseOut).
boolean
intTraverse
A flag to indicate that internal traversal has occurred within the gauge itself.
private int
pointerArea
the area accepting the pointer event
private static final int
INVALID_AREA
the different areas of an interactive gauge, used for pointer events
private static final int
DEC_BTN_AREA
private static final int
INC_BTN_AREA
private static final int
METER_AREA
Constructors Summary
GaugeLFImpl(Gauge gauge)
Creates GaugeLF for the passed in Gauge.

param
gauge the Gauge object associated with this look&feel.

        
        super(gauge);

        this.gauge = gauge;

        lSetMaxValue(0, gauge.maxValue);
        lSetValue(0, gauge.value);

        // IMPL NOTE: Make this smarter so that only the
        // resources we need load. Also, replicate this
        // code in the set* methods so that a gauge which
        // changes on the fly has the proper resources
        if (gauge.interactive) {
            GaugeResources.load();
        } else {
            ProgressBarResources.load();
            UpdateBarResources.load();
            BusyCursorResources.load();
        }
        
        percentLoc = new int[2];
        drawsTraversalIndicator = false;
    
Methods Summary
voidcancelGaugeUpdateTask()
Stop the GaugeUpdateTask from running.

        if (updateHelper != null) {
            updateHelper.cancel();
            updateHelper = null;
        }
    
voiddrawBusyCursor(Graphics g, int frameToDraw)
Paints the given frame of the continuous running/idle gauge.

param
g the graphics to paint to
param
frameToDraw the frame index of the frame to be drawn from a frame-sequence

        if (BusyCursorSkin.FRAME_SEQUENCE == null ||
            frameToDraw > BusyCursorSkin.FRAME_SEQUENCE.length) 
        {
            return;
        }
        
        frameToDraw = BusyCursorSkin.FRAME_SEQUENCE[frameToDraw];
        
        // draw background, if present
        if (BusyCursorSkin.IMAGE_BG != null) {
            g.drawImage(BusyCursorSkin.IMAGE_BG, 0, 0,
                        Graphics.LEFT | Graphics.TOP);
        } else {
            g.setColor(0xCCCCCC);
            g.fillRect(0, 0, BusyCursorSkin.WIDTH, BusyCursorSkin.HEIGHT);
            g.setColor(0);
        }
        
        if (BusyCursorSkin.IMAGE_FRAME != null &&
            frameToDraw < BusyCursorSkin.IMAGE_FRAME.length) 
        {
            // draw the frame
            g.drawImage(BusyCursorSkin.IMAGE_FRAME[frameToDraw],
                        BusyCursorSkin.FRAME_X,
                        BusyCursorSkin.FRAME_Y,
                        Graphics.LEFT | Graphics.TOP);
        } else {
            switch (frameToDraw % 3) {
                case 0:
                    g.drawString("-", 
                                 (int)(BusyCursorSkin.WIDTH / 2), 
                                 (int)(BusyCursorSkin.HEIGHT / 2),
                                 Graphics.HCENTER | Graphics.BOTTOM);
                    break;
                case 1:
                    g.drawString("\\", 
                                 (int)(BusyCursorSkin.WIDTH / 2), 
                                 (int)(BusyCursorSkin.HEIGHT / 2),
                                 Graphics.HCENTER | Graphics.BOTTOM);
                    break;
                case 2:
                    g.drawString("|", 
                                 (int)(BusyCursorSkin.WIDTH / 2), 
                                 (int)(BusyCursorSkin.HEIGHT / 2),
                                 Graphics.HCENTER | Graphics.BOTTOM);
                    break;
                default:
                    g.drawString("/", 
                                 (int)(BusyCursorSkin.WIDTH / 2), 
                                 (int)(BusyCursorSkin.HEIGHT / 2),
                                 Graphics.HCENTER | Graphics.BOTTOM);
                    break;
            }
        }
    
voiddrawNumber(Graphics g, Image valuesImg, int numDigits, int index, int locationX, int locationY, int n)
Accepts a numeric value and draws the number graphically.

param
g the graphics to paint to
param
valuesImg the image to clip from
param
numDigits the number of digits in the image
param
index the index of the digit that needs to be drawn graphically
param
locationX the x co-ordinate of the location to start drawing the digits
param
locationY the y co-ordinate of the location to start drawing the digits
param
n the value as a percentage, equal to (value * 1000) / maxValue

        /*
         * Find the first leftmost, non-zero digit.
         *
         * Keep using a smaller divisor to get to a non-zero
         * digit in n. If the divisor itself becomes zero,
         * this is the case where n = 0. We break out of the
         * loop, in that case.
         *
         * Note that the test for divisor == 0 is done before
         * extracting the next digit in the "while" part, to
         * avoid a divide-by-zero ArithmeticException.
         */
        
        int divisor = 1000;   // assume the max displayed is 4 digit num
        int digit = 0;
        int digitCount = 4;        
        
        int digitWidth = g.getFont().charWidth('9");
        if (valuesImg != null) {
            digitWidth = (int)(valuesImg.getWidth() / numDigits);
        }
                
        // keep whittling down the number until it's in range.
        while (n > 9999) n /= 10;

        // figure out how many digits... adjust divisor accordingly.
        while (divisor != 0 && (digit = n / divisor) == 0) {
            divisor /= 10;
            digitCount--;
        }

        // special case for 0
        if (digitCount == 0) digitCount = 1;

        // position where to start displaying the gauge value
        int start_x = locationX;

        // offset by a digit's width in case of shorter values
        // to make it more presentable
        start_x += (digitCount < 3) ? digitWidth : 0;
        
        // now show the digits
        switch (divisor) {
        case 1000:
            digit = n / 1000;
            n %= divisor;
            divisor /= 10;

            paintDigit(g, valuesImg, numDigits, digit, start_x, locationY);
            start_x += digitWidth;
            // fall through to handle next lower digit.

        case 100:
            digit = n / 100;
            n %= divisor;
            divisor /= 10;

            paintDigit(g, valuesImg, numDigits, digit, start_x, locationY);
            start_x += digitWidth;
            // fall through to handle next lower digit.

        case 10:
            digit = n / 10;
            n %= divisor;
            divisor /= 10;

            paintDigit(g, valuesImg, numDigits, digit, start_x, locationY);
            start_x += digitWidth;
            // fall through to handle next lower digit.

        case 1:
            digit = n;
            paintDigit(g, valuesImg, numDigits, digit, start_x, locationY);
            break;
            
        case 0:  // special case when n = 0
            // paint the non-highlight 0
            paintDigit(g, valuesImg, numDigits, numDigits - 1, 
                       start_x, locationY);
            break;
        default:
            Logging.report(Logging.ERROR, LogChannels.LC_HIGHUI,
                           "GaugeLFImpl: drawNumber," +
                           " divisor=" +divisor);
            break;
        }

        // ASSERT: Make sure this array gets filled with the x,y 
        // co-ordinates where the digits end, so as to facilitate 
        // drawing, say a percentage sign after the value, in some 
        // cases like the progressbar. Removing this notion will
        // cause *malfunction* of the drawPercentage() method, in
        // not being able to locate where to draw the percentage 
        // sign correctly.

        percentLoc[0] = start_x + digitWidth;
        percentLoc[1] = locationY;
    
voiddrawPercentage(Graphics g, Image percentImg, int value)
Draws a percentage sign.

param
g the graphics to paint to
param
percentImg the image to clip from
param
value the value of the gauge


        if (percentImg != null && percentWidth == -1) {
            percentWidth = (int)(percentImg.getWidth() / 2);
            percentHeight = percentImg.getHeight();
        }
        
        if (percentImg != null) {
            // Note: The percentLoc[] array holds the x,y location
            // where the percentage sign should be painted. This is filled
            // by the drawNumber() method after it finishes drawing the
            // numeric value graphically.
    
            g.drawRegion(percentImg, 
                         (value == 0) ? percentWidth : 0, 0, 
                         percentWidth, percentHeight, 
                         Sprite.TRANS_NONE, 
                         percentLoc[0], percentLoc[1], 
                         Graphics.LEFT | Graphics.TOP);
        } else {
            g.drawString("%", percentLoc[0], percentLoc[1], 
                         Graphics.LEFT | Graphics.TOP);
        }
    
voiddrawUpdateBar(Graphics g, int frameToDraw)
Paints the given frame of the incremental updating/idle gauge.

param
g the graphics to paint to
param
frameToDraw the frame index of the frame to be drawn from a frame-sequence

        if (UpdateBarSkin.FRAME_SEQUENCE == null ||
            frameToDraw > UpdateBarSkin.FRAME_SEQUENCE.length) 
        {
            return;
        }
        
        frameToDraw = UpdateBarSkin.FRAME_SEQUENCE[frameToDraw];
        
        // draw background, if present
        if (UpdateBarSkin.IMAGE_BG != null) {
            g.drawImage(UpdateBarSkin.IMAGE_BG, 0, 0,
                        Graphics.LEFT | Graphics.TOP);
        } else {
            g.setColor(0xCCCCCC);
            g.fillRect(0, 0, UpdateBarSkin.WIDTH, UpdateBarSkin.HEIGHT);
            g.setColor(0);
        }
        
        if (UpdateBarSkin.IMAGE_FRAME != null 
            && frameToDraw < UpdateBarSkin.IMAGE_FRAME.length) 
        {
            // draw the frame
            g.drawImage(UpdateBarSkin.IMAGE_FRAME[frameToDraw],
                        UpdateBarSkin.FRAME_X,
                        UpdateBarSkin.FRAME_Y,
                        Graphics.LEFT | Graphics.TOP);
        } else {
            g.fillRect(2, 2, 
                UpdateBarSkin.WIDTH - 4, UpdateBarSkin.HEIGHT - 4);
            int width = 
                (UpdateBarSkin.WIDTH / UpdateBarSkin.FRAME_SEQUENCE.length) *
                frameToDraw;
            if (width < 0) {
                width = 0;
            }
            g.setColor(0xFFFFFF);
            g.fillRect(2, 2, width - 4, UpdateBarSkin.HEIGHT - 4);
            g.setColor(0);
        }
    
booleanequateNLA()
Determine if this Item should have a newline after it

return
true if it should have a newline after

        if (super.equateNLA()) {
            return true;
        }

        return ((gauge.layout & Item.LAYOUT_2) != Item.LAYOUT_2);
    
booleanequateNLB()
Determine if this Item should have a newline before it

return
true if it should have a newline before

        if (super.equateNLB()) {
            return true;
        }

        return ((gauge.layout & Item.LAYOUT_2) != Item.LAYOUT_2);
    
private intgetPointerArea(int x, int y)
Get the area of gauge the pointer cliked in.

param
x x coordinate of pointer
param
y y coordinate of pointer
return
the gauge area is returned. The possible values are
see
#INVALID_AREA if pointer is out of gauge's bounds
see
#INC_BTN_AREA if pointer is on the increment button
see
#DEC_BTN_AREA if pointer is on the decrement button
see
#METER_AREA if pointer is on the meter

        int area = INVALID_AREA;

        x -= contentBounds[X];
        y -= contentBounds[Y];

        if (area == INVALID_AREA &&
            GaugeSkin.IMAGE_DEC_BTN != null &&
            // check coordinates
            x >= GaugeSkin.DEC_BTN_X &&
            y > GaugeSkin.DEC_BTN_Y &&
            x <= (GaugeSkin.DEC_BTN_X +
                  GaugeSkin.IMAGE_DEC_BTN.getWidth()) &&
            y <= (GaugeSkin.DEC_BTN_Y +
                  GaugeSkin.IMAGE_DEC_BTN.getHeight())) {
            
            area = DEC_BTN_AREA;
        }
        if (area == INVALID_AREA &&
            GaugeSkin.IMAGE_INC_BTN != null &&
            // check coordinates
            x >= GaugeSkin.INC_BTN_X &&
            y > GaugeSkin.INC_BTN_Y &&
            x <= (GaugeSkin.INC_BTN_X +
                  GaugeSkin.IMAGE_INC_BTN.getWidth()) &&
            y <= (GaugeSkin.INC_BTN_Y +
                  GaugeSkin.IMAGE_INC_BTN.getHeight())) {
            
            area = INC_BTN_AREA;
        }
        if (area == INVALID_AREA &&
            // check coordinates
            x >= GaugeSkin.METER_X && y > GaugeSkin.METER_Y &&
            x <= (GaugeSkin.METER_X +
                  GaugeSkin.IMAGE_METER_FULL.getWidth()) && 
            y <= (GaugeSkin.METER_Y +
                  GaugeSkin.IMAGE_METER_FULL.getHeight())) {
            
            area = METER_AREA;
        }
        
        return area;
    
voidlCallHideNotify()
Called by the system to notify this Item it is being hidden

The default implementation of this method updates the 'visible' state

        
        super.lCallHideNotify();

        cancelGaugeUpdateTask();
    
voidlCallShowNotify()
Called by the system to notify this Item it is being shown

The default implementation of this method updates the 'visible' state

        
        super.lCallShowNotify();

        // Start update task for CONTINUOUS_RUNNING gauge upon visible
        if (gauge.maxValue == Gauge.INDEFINITE && 
            gauge.value == Gauge.CONTINUOUS_RUNNING) {
            startGaugeUpdateTask();
        }
    
booleanlCallTraverse(int dir, int viewportWidth, int viewportHeight, int[] visRect)
Called by the system to traverse this DateField.

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 passes the visible rectangle into the method, and returns the updated traversal rectangle from the method
return
true if internal traversal had occurred, false if traversal should proceed out

        boolean res = super.lCallTraverse(dir, viewportWidth, viewportHeight, visRect);

        visRect[X] = 0;
        visRect[Y] = 0;
        visRect[HEIGHT] = bounds[HEIGHT];
        visRect[WIDTH] = bounds[WIDTH];
        return res;

    
voidlGetContentSize(int[] size, int availableWidth)
Sets the content size in the passed in array. Content is calculated based on the availableWidth. size[WIDTH] and size[HEIGHT] should be set by this method.

param
size The array that holds Item content size and location in Item internal bounds coordinate system.
param
availableWidth The width available for this Item

        if (gauge.interactive) {
            size[WIDTH] = GaugeSkin.WIDTH;
            size[HEIGHT] = GaugeSkin.HEIGHT;
        } else if (gauge.maxValue != Gauge.INDEFINITE) {
            size[WIDTH] = ProgressBarSkin.WIDTH;
            size[HEIGHT] = ProgressBarSkin.HEIGHT;
        } else if ((gauge.value == Gauge.CONTINUOUS_RUNNING) ||
                   (gauge.value == Gauge.CONTINUOUS_IDLE)) {
           size[WIDTH] = BusyCursorSkin.WIDTH;
           size[HEIGHT] = BusyCursorSkin.HEIGHT;
        } else {
            size[WIDTH] = UpdateBarSkin.WIDTH;
            size[HEIGHT] = UpdateBarSkin.HEIGHT;
        }
    
public intlGetValue()
Gets the current value.

return
the current value

        return gauge.value;
    
voidlPaintContent(Graphics g, int w, int h)
Paints the content area of this Gauge. Graphics is translated to contents origin.

param
g The graphics where Gauge content should be painted
param
w The width available for the Item's content
param
h The height available for the Item's content

     
        if (gauge.interactive) {
            lPaintInteractiveGauge(g, w, h, gauge.maxValue, gauge.value);
        } else if (gauge.maxValue == Gauge.INDEFINITE) {
            lPaintIndefinite(g, w, h, gauge.maxValue, gauge.value);
        } else {
            lPaintProgressBar(g, w, h, gauge.maxValue, gauge.value);
        }
    
voidlPaintIndefinite(Graphics g, int w, int h, int maxValue, int value)

            
        switch (value) {
        case Gauge.CONTINUOUS_RUNNING:
            drawBusyCursor(g, nextFrame);
            
            // increment the frame counter of the incremental gauge
            // and remember to reset it when it hits the total number
            // of frames, so it can start all over again
            if (BusyCursorSkin.FRAME_SEQUENCE != null) {
                nextFrame = ++nextFrame % BusyCursorSkin.FRAME_SEQUENCE.length;
            }
            break;
        case Gauge.CONTINUOUS_IDLE:
            drawBusyCursor(g, 0);
            break;
        case Gauge.INCREMENTAL_UPDATING:
            drawUpdateBar(g, nextFrame);
            
            // increment the frame counter of the incremental gauge
            // and remember to reset it when it hits the total number
            // of frames, so it can start all over again
            if (UpdateBarSkin.FRAME_SEQUENCE != null) {
                nextFrame = ++nextFrame % UpdateBarSkin.FRAME_SEQUENCE.length;
            }
            break;
        case Gauge.INCREMENTAL_IDLE:
            drawUpdateBar(g, 0);
            break;
        default:
            Logging.report(Logging.ERROR, LogChannels.LC_HIGHUI,
                           "GaugeLFImpl: lPaintIndefinite, value=" +value);
            break;
        }
    
voidlPaintInteractiveGauge(Graphics g, int w, int h, int maxValue, int value)

        // case: interactive gauge
        // draw background, if present
        if (GaugeSkin.IMAGE_BG != null) {
            g.drawImage(GaugeSkin.IMAGE_BG, 0, 0,
                        Graphics.LEFT | Graphics.TOP);
        } else {
            g.setColor(0xCCCCCC);
            g.fillRect(0, 0, GaugeSkin.WIDTH, GaugeSkin.HEIGHT);
            g.setColor(0);
            return; 
            // we return early on interactive gauge if there are
            // no images because its rather complicated to draw
            // otherwise, at least right now            
        }

        // computation to decide how much of filled & unfilled
        // portions to be displayed
        int body_full;
        int body_empty;
        if (GaugeSkin.ORIENTATION == Graphics.LEFT ||
            GaugeSkin.ORIENTATION == Graphics.RIGHT)
        {
            body_empty = GaugeSkin.IMAGE_METER_FULL.getWidth();
            body_full = (((value * 100) / maxValue) * body_empty) / 100;
            body_empty -= body_full;
            
            if (GaugeSkin.ORIENTATION == Graphics.RIGHT) {
                g.drawRegion(GaugeSkin.IMAGE_METER_FULL, 0, 0, body_full, 
                             GaugeSkin.IMAGE_METER_FULL.getHeight(), 
                             Sprite.TRANS_NONE, GaugeSkin.METER_X, 
                             GaugeSkin.METER_Y, 
                             Graphics.LEFT | Graphics.TOP);
                             
                g.drawRegion(GaugeSkin.IMAGE_METER_EMPTY, body_full, 0, 
                             body_empty, 
                             GaugeSkin.IMAGE_METER_EMPTY.getHeight(), 
                             Sprite.TRANS_NONE, GaugeSkin.METER_X + 
                             body_full, GaugeSkin.METER_Y, 
                             Graphics.LEFT | Graphics.TOP);
            } else {
                g.drawRegion(GaugeSkin.IMAGE_METER_EMPTY, 0, 0, body_empty, 
                             GaugeSkin.IMAGE_METER_EMPTY.getHeight(), 
                             Sprite.TRANS_NONE, GaugeSkin.METER_X, 
                             GaugeSkin.METER_Y, 
                             Graphics.LEFT | Graphics.TOP);
                             
                g.drawRegion(GaugeSkin.IMAGE_METER_FULL, body_empty, 0, 
                             body_full, 
                             GaugeSkin.IMAGE_METER_FULL.getHeight(), 
                             Sprite.TRANS_NONE, GaugeSkin.METER_X + 
                             body_empty, GaugeSkin.METER_Y, 
                             Graphics.LEFT | Graphics.TOP);
            }                               
                         
        } else {
            body_empty = GaugeSkin.IMAGE_METER_FULL.getHeight();
            body_full = (((value * 100) / maxValue) * body_empty) / 100;
            body_empty -= body_full;
            
            if (GaugeSkin.ORIENTATION == Graphics.TOP) {
                g.drawRegion(GaugeSkin.IMAGE_METER_FULL, 0, body_empty,
                             GaugeSkin.IMAGE_METER_FULL.getWidth(), 
                             body_full, 
                             Sprite.TRANS_NONE, GaugeSkin.METER_X, 
                             GaugeSkin.METER_Y + body_empty, 
                             Graphics.LEFT | Graphics.TOP);
                             
                g.drawRegion(GaugeSkin.IMAGE_METER_EMPTY, 0, 0,
                             GaugeSkin.IMAGE_METER_EMPTY.getWidth(), 
                             body_empty,
                             Sprite.TRANS_NONE, GaugeSkin.METER_X, 
                             GaugeSkin.METER_Y, 
                             Graphics.LEFT | Graphics.TOP);
            } else {
                g.drawRegion(GaugeSkin.IMAGE_METER_EMPTY, 0, body_full,
                             GaugeSkin.IMAGE_METER_EMPTY.getWidth(), 
                             body_empty, 
                             Sprite.TRANS_NONE, GaugeSkin.METER_X, 
                             GaugeSkin.METER_Y + body_full, 
                             Graphics.LEFT | Graphics.TOP);
                             
                g.drawRegion(GaugeSkin.IMAGE_METER_FULL, 0, 0,
                             GaugeSkin.IMAGE_METER_FULL.getWidth(), 
                             body_full,
                             Sprite.TRANS_NONE, GaugeSkin.METER_X, 
                             GaugeSkin.METER_Y, 
                             Graphics.LEFT | Graphics.TOP);
            }                               
            
        }

        // display current value of gauge
        drawNumber(g, GaugeSkin.IMAGE_VALUES, 11, value, 
                   GaugeSkin.VALUE_X, GaugeSkin.VALUE_Y,
                   (value * 100) / maxValue);

        if (GaugeSkin.IMAGE_DEC_BTN != null) {
            // decrease button            
            g.drawImage(GaugeSkin.IMAGE_DEC_BTN,
                        GaugeSkin.DEC_BTN_X,
                        GaugeSkin.DEC_BTN_Y,
                        Graphics.LEFT | Graphics.TOP);
            if (hasFocus && focusBtn == I_DEC_BTN) {
                g.setColor(ScreenSkin.COLOR_TRAVERSE_IND);
                g.drawRect(GaugeSkin.DEC_BTN_X, 
                           GaugeSkin.DEC_BTN_Y, 
                           GaugeSkin.IMAGE_DEC_BTN.getWidth(), 
                           GaugeSkin.IMAGE_DEC_BTN.getHeight());
                g.setColor(0);
            }
        } else {
            g.drawString("-", GaugeSkin.DEC_BTN_X, GaugeSkin.DEC_BTN_Y,
                         Graphics.LEFT | Graphics.TOP);
            if (hasFocus && focusBtn == I_DEC_BTN) {
                g.setColor(ScreenSkin.COLOR_TRAVERSE_IND);
                g.drawRect(GaugeSkin.DEC_BTN_X,
                           GaugeSkin.DEC_BTN_Y,
                           g.getFont().charWidth('-"),
                           g.getFont().charWidth('-"));
                g.setColor(0);
            }
        }
        
        if (GaugeSkin.IMAGE_INC_BTN != null) {
            // increase button
            g.drawImage(GaugeSkin.IMAGE_INC_BTN,
                        GaugeSkin.INC_BTN_X,
                        GaugeSkin.INC_BTN_Y,
                        Graphics.LEFT | Graphics.TOP);
            if (hasFocus && focusBtn == I_INC_BTN) {
                g.setColor(ScreenSkin.COLOR_TRAVERSE_IND);
                g.drawRect(GaugeSkin.INC_BTN_X,
                           GaugeSkin.INC_BTN_Y, 
                           GaugeSkin.IMAGE_INC_BTN.getWidth(), 
                           GaugeSkin.IMAGE_INC_BTN.getHeight());
                g.setColor(0);
            }
        } else {
            g.drawString("+", GaugeSkin.INC_BTN_X, GaugeSkin.INC_BTN_Y,
                         Graphics.LEFT | Graphics.TOP);
            
            if (hasFocus && focusBtn == I_INC_BTN) {
                g.setColor(ScreenSkin.COLOR_TRAVERSE_IND);
                g.drawRect(GaugeSkin.INC_BTN_X,
                           GaugeSkin.INC_BTN_Y,
                           g.getFont().charWidth('+"),
                           g.getFont().charWidth('+"));
                g.setColor(0);
            }
        }
    
voidlPaintProgressBar(Graphics g, int w, int h, int maxValue, int value)

            
        // case: non-interactive definite range gauge/progressbar
        // draw background, if present
        if (ProgressBarSkin.IMAGE_BG != null) {
            g.drawImage(ProgressBarSkin.IMAGE_BG, 0, 0,
                        Graphics.LEFT | Graphics.TOP);
        } else {
            g.setColor(0xCCCCCC);
            g.fillRect(0, 0, ProgressBarSkin.WIDTH, ProgressBarSkin.HEIGHT);
            g.setColor(0);
        }

        // first compute current value of gauge as a percentage
        int n = (value * 100) / maxValue;

        // decide how much of filled & unfilled portions to be shown
        int body_full = 0;
        if (ProgressBarSkin.IMAGE_METER_FULL != null) {
            body_full = 
                (n * ProgressBarSkin.IMAGE_METER_FULL.getWidth()) / 100;
            g.drawRegion(ProgressBarSkin.IMAGE_METER_FULL, 0, 0, 
                         body_full, 
                         ProgressBarSkin.IMAGE_METER_FULL.getHeight(), 
                         Sprite.TRANS_NONE, 
                         ProgressBarSkin.METER_X, 
                         ProgressBarSkin.METER_Y, 
                         Graphics.LEFT | Graphics.TOP);
        } else {
            body_full =
                (n * ProgressBarSkin.WIDTH - ProgressBarSkin.VALUE_WIDTH - 
                    10) / 100;
            g.fillRect(ProgressBarSkin.METER_X, ProgressBarSkin.METER_Y,
                       body_full, ProgressBarSkin.HEIGHT - 
                            (2 * ProgressBarSkin.METER_Y));            
        }
        
        int body_empty = 0;
        if (ProgressBarSkin.IMAGE_METER_FULL != null) {
            body_empty = 
                ProgressBarSkin.IMAGE_METER_FULL.getWidth() - body_full;
                g.drawRegion(ProgressBarSkin.IMAGE_METER_EMPTY, body_full,
                             0, body_empty, 
                             ProgressBarSkin.IMAGE_METER_EMPTY.getHeight(), 
                             Sprite.TRANS_NONE, 
                             ProgressBarSkin.METER_X + body_full, 
                             ProgressBarSkin.METER_Y, 
                             Graphics.LEFT | Graphics.TOP);
        } else {
            body_empty = 
                (ProgressBarSkin.WIDTH - ProgressBarSkin.VALUE_WIDTH -
                    10) - body_full;
            g.setColor(0xFFFFFF);
            g.fillRect(ProgressBarSkin.METER_X + body_full,
                       ProgressBarSkin.METER_Y,
                       body_empty,
                       ProgressBarSkin.HEIGHT -
                        (2 * ProgressBarSkin.METER_Y));
        }

        // current value of gauge as a percentage 
        drawNumber(g, ProgressBarSkin.IMAGE_VALUES, 11, n,
                   ProgressBarSkin.VALUE_X, ProgressBarSkin.VALUE_Y,
                   (value * 100) / maxValue);

        // the percentage symbol
        drawPercentage(g, ProgressBarSkin.IMAGE_PERCENTS, value);           
    
public voidlSetMaxValue(int oldMaxValue, int newMaxValue)
Notifies L&F of a maximum value change in the corresponding Gauge

param
oldMaxValue - the old maximum value set in the Gauge
param
newMaxValue - the new maximum value set in the Gauge

        
        // changing the max value will change the scale of the gauge
        if (oldMaxValue != newMaxValue) {        
            lRequestInvalidate(true, true);
        }
    
public voidlSetValue(int oldValue, int newValue)
Notifies L&F of a value change in the corresponding Gauge.

param
oldValue - the old value set in the Gauge
param
newValue - the new value set in the Gauge

        synchronized (Display.LCDUILock) {
            if (gauge.maxValue == Gauge.INDEFINITE) {
                /**
                 *  -- if there are more than one Gauge, we shouldn't
                 *  stop other continuous gauges until we change Displayable.
                 *  IMPL NOTE: see if this is the only Gauge on the form   -au
                 */
                
                if (newValue == Gauge.CONTINUOUS_RUNNING) {
                    // If this gauge is already visible and its new value
                    // is changed to CONTINUOUS_RUNNING, then start update
                    // task here. 
                    // Otherwise, delay update task creation until it becomes 
                    // visible (I.e. lCallShow is called).
                    if (visible) {
                        startGaugeUpdateTask();
                    }
                } else if (oldValue == Gauge.CONTINUOUS_RUNNING) {
                    cancelGaugeUpdateTask();
                }
                if (oldValue != newValue) 
                    lRequestInvalidate(true, true);
                else
                    lRequestPaint();
            } else if (oldValue != newValue) {
                lRequestPaint();
            }
        } // end sync
    
voidpaintDigit(Graphics g, Image valuesImg, int numDigits, int digitIndex, int x, int y)
Calculates the position of the digit to be clipped from the values image (based on the "digitLocation" parameter passed in) and paints it.

param
g the graphics to paint t
param
valuesImg the image to clip from
param
numDigits the number of digits in the image
param
digitIndex the pixel location of this digit inside the values image, used to extract the digit images from
param
x the x-coordinate where to draw this digit
param
y the y-coordinate where to draw this digit

        if (valuesImg != null) {
            int digitWidth = (int)(valuesImg.getWidth() / numDigits);
            
            g.drawRegion(valuesImg, 
                         digitIndex * digitWidth, 0, 
                         digitWidth,
                         valuesImg.getHeight(), 
                         Sprite.TRANS_NONE, x, y, 
                         Graphics.LEFT | Graphics.TOP);
        } else {
            if (digitIndex == numDigits - 1) {
                digitIndex = 0;
            }
            g.drawString("" + digitIndex, x, y, Graphics.LEFT | Graphics.TOP);
        }
    
booleanshouldSkipTraverse()
Determine if this Gauge should not be traversed to

return
true if this Gauge should not be traversed to

        // Only traverse to gauges which are interactive, or have
        // item-specific commands added to them
        return (gauge.interactive) ? false : super.shouldSkipTraverse(); 
    
voidstartGaugeUpdateTask()
Start the GaugeUpdateTask running

        if (updateHelper == null) {
            updateHelper = new GaugeUpdateTask(this);
            gaugeUpdateTimer.schedule(updateHelper, 100, 100);
        }
    
voiduCallKeyPressed(int keyCode)
Called by the system to signal a key press.

param
keyCode the key code of the key that has been pressed

        if (keyCode != Constants.KEYCODE_SELECT ||
            !gauge.interactive) {
            return;
        }
        
        Form form = null;

        synchronized (Display.LCDUILock) {
            int maxValue = gauge.maxValue;
            int oldValue = gauge.value;
            int value = oldValue;

            switch (focusBtn) {
            case I_INC_BTN:
                value++;
                break;
            case I_DEC_BTN:
                value--;
                break;
            default:
                Logging.report(Logging.ERROR, LogChannels.LC_HIGHUI,
                               "GaugeLFImpl: uCallKeyPressed, focusBtn=" +
                               focusBtn);
                break;
            }
            
            gauge.setValueImpl(value);

            // IMPL NOTE: paint optimization
            lRequestPaint();

            if (value != oldValue) {
                // notify the ItemStateChangedListener
                form = (Form)gauge.owner;
            }
            
        } // end synchronized

        // SYNC NOTE: We make sure we notify the ItemStateChangedListener
        // outside of LCDUILock
        if (form != null) {
            form.uCallItemStateChanged(gauge);
        }
    
voiduCallKeyRepeated(int keyCode)
Called by the system to signal a key repeat

param
keyCode the key code of the key that has been pressed

        uCallKeyPressed(keyCode);
    
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 (gauge.interactive) {
            pointerArea = getPointerArea(x, y);

            switch(pointerArea) {
            case DEC_BTN_AREA:
                focusBtn = I_DEC_BTN;
                uRequestPaint();
                break;
            case INC_BTN_AREA:
                focusBtn = I_INC_BTN;
                uRequestPaint();
                break;
            default:
                break;
            }
        }
    
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

        if (gauge.interactive) {
            int newArea = getPointerArea(x, y);
        
            if (pointerArea == newArea) {
                switch (pointerArea) {
                case DEC_BTN_AREA:
                case INC_BTN_AREA:
                    uCallKeyPressed(Constants.KEYCODE_SELECT);
                    break;
                case METER_AREA:
                    {
                        Form form = null;
                        synchronized (Display.LCDUILock) {
                            int oldValue = gauge.value;
                            int locationOnMeter = x - contentBounds[X] - GaugeSkin.METER_X;
                            float percent = locationOnMeter * 100 / GaugeSkin.IMAGE_METER_FULL.getWidth(); 
                            float value = percent / 100 * gauge.maxValue;
                            /* round the value */
                            int intValue = (int)value;
                            float remainder = value - intValue;
                            if (remainder > 0.5) {
                                intValue++;
                            }
                            
                            gauge.setValueImpl(intValue);
                            lRequestPaint();
                            if (intValue != oldValue) {
                                // notify the ItemStateChangedListener
                                form = (Form)gauge.owner;
                            }
                        }
                        // SYNC NOTE: We make sure we notify the ItemStateChangedListener
                        // outside of LCDUILock
                        if (form != null) {
                            form.uCallItemStateChanged(gauge);
                        }
                    }
                    break;
                default:
                    break;
                } // end of switch 
            } // pointerArea == newArea
        } // interactive gauge
    
booleanuCallTraverse(int dir, int viewportWidth, int viewportHeight, int[] visRect)
Handle traversal within this Gauge

param
dir the direction of traversal
param
viewportWidth the width of the viewport
param
viewportHeight the height of the viewport
param
visRect the in/out rectangle for the internal traversal location
return
True if traversal occurred within this Gauge

        
        super.uCallTraverse(dir, viewportWidth, viewportHeight, visRect);
       
        // If its a non-interactive gauge, there is no internal traversal
        // No need to lock either, we just access the boolean once.
        // (In fact, traverse should never be called on a non-interactive
        // gauge because shouldSkipTraverse() returns true in that case)
        if (!gauge.interactive) {
            return false;
        }
        
        // If it was an invalidate or something, just keep the focus
        // button where it is and reflect there is internal traversal
        if (dir == CustomItem.NONE) {
            intTraverse = true;
        } else {
            // The standard horizontal gauge's orientation is RIGHT, all
            // others accommodate vertical gauges and possible gauges for
            // right-to-left languages (which would be a LEFT orientation)
            
            switch (GaugeSkin.ORIENTATION) {
                // Gauge increases left to right, horizontally
                // (this is the default in chameleon)
            case Graphics.RIGHT:
                switch (dir) {
                case Canvas.LEFT:
                    if (initialTraverse) {
                        intTraverse = true;
                        focusBtn = I_INC_BTN;
                    } else {
                        intTraverse = (focusBtn != I_DEC_BTN);
                        focusBtn = I_DEC_BTN;
                    }
                    break;                        
                case Canvas.RIGHT:
                    if (initialTraverse) {
                        intTraverse = true;
                        focusBtn = I_DEC_BTN;
                    } else {
                        intTraverse = (focusBtn != I_INC_BTN);
                        focusBtn = I_INC_BTN;
                    }
                    break;                        
                case Canvas.UP:
                    intTraverse = initialTraverse;
                    if (initialTraverse) {
                        focusBtn = I_INC_BTN;
                    }
                    break;
                case Canvas.DOWN:
                    intTraverse = initialTraverse;
                    if (initialTraverse) {
                        focusBtn = I_DEC_BTN;
                    }
                    break;
                default:
                    Logging.report(Logging.ERROR, 
                                   LogChannels.LC_HIGHUI,
                                   "GaugeLFImpl: uCallTraverse, dir=" +dir);
                    break;
                }
                break;
                // Gauge increases right to left, horizontally
                // (think of right-to-left languages)
            case Graphics.LEFT:
                switch (dir) {
                case Canvas.LEFT:
                    if (initialTraverse) {
                        intTraverse = true;
                        focusBtn = I_DEC_BTN;
                    } else {
                        intTraverse = (focusBtn != I_INC_BTN);
                        focusBtn = I_INC_BTN;
                    }
                    break;                        
                case Canvas.RIGHT:
                    if (initialTraverse) {
                        intTraverse = true;
                        focusBtn = I_INC_BTN;
                    } else {
                        intTraverse = (focusBtn != I_DEC_BTN);
                        focusBtn = I_DEC_BTN;
                    }
                    break;                        
                case Canvas.UP:
                    intTraverse = initialTraverse;
                    if (initialTraverse) {
                        focusBtn = I_DEC_BTN;
                    }
                    break;
                case Canvas.DOWN:
                    intTraverse = initialTraverse;
                    if (initialTraverse) {
                        focusBtn = I_INC_BTN;
                    }
                    break;
                default:
                    Logging.report(Logging.ERROR, 
                                   LogChannels.LC_HIGHUI,
                                   "GaugeLFImpl: uCallTraverse, dir=" +dir);
                    break;
                }
                break;
                // Gauge increases bottom to top, vertically
            case Graphics.TOP:
                switch (dir) {
                case Canvas.LEFT:
                    intTraverse = initialTraverse;
                    if (initialTraverse) {
                        focusBtn = I_INC_BTN;
                    }
                    break;
                case Canvas.RIGHT:
                    intTraverse = initialTraverse;
                    if (initialTraverse) {
                        focusBtn = I_DEC_BTN;
                    }
                    break;
                case Canvas.UP:
                    if (initialTraverse) {
                        intTraverse = true;
                        focusBtn = I_DEC_BTN;
                    } else {
                        intTraverse = (focusBtn != I_INC_BTN);
                        focusBtn = I_INC_BTN;
                    }
                    break;                        
                case Canvas.DOWN:
                    if (initialTraverse) {
                        intTraverse = true;
                        focusBtn = I_INC_BTN;
                    } else {
                        intTraverse = (focusBtn != I_DEC_BTN);
                        focusBtn = I_DEC_BTN;
                    }
                    break;
                default:
                    Logging.report(Logging.ERROR, 
                                   LogChannels.LC_HIGHUI,
                                   "GaugeLFImpl: uCallTraverse, dir=" +dir);
                    break;                        
                }
                break;
                // Gauge increases top to bottom, vertically
            case Graphics.BOTTOM:
                switch (dir) {
                case Canvas.LEFT:
                    intTraverse = initialTraverse;
                    if (initialTraverse) {
                        focusBtn = I_DEC_BTN;
                    }
                    break;
                case Canvas.RIGHT:
                    intTraverse = initialTraverse;
                    if (initialTraverse) {
                        focusBtn = I_INC_BTN;
                    }
                    break;
                case Canvas.UP:
                    if (initialTraverse) {
                        intTraverse = true;
                        focusBtn = I_INC_BTN;
                    } else {
                        intTraverse = (focusBtn != I_DEC_BTN);
                        focusBtn = I_DEC_BTN;
                    }
                    break;                        
                case Canvas.DOWN:
                    if (initialTraverse) {
                        intTraverse = true;
                        focusBtn = I_DEC_BTN;
                    } else {
                        intTraverse = (focusBtn != I_INC_BTN);
                        focusBtn = I_INC_BTN;
                    }
                    break;
                default:
                    Logging.report(Logging.ERROR, LogChannels.LC_HIGHUI,
                                   "GaugeLFImpl: uCallTraverse, dir=" +dir);
                    break;
                }
                break;
            default:
                Logging.report(Logging.ERROR, LogChannels.LC_HIGHUI,
                               "GaugeLFImpl: uCallTraverse," +
                               "GaugeSkin.ORIENTATION=" +
                               GaugeSkin.ORIENTATION);
                break;
            }
        }
        
        
        switch (focusBtn) {
        case I_INC_BTN:
            visRect[X] = GaugeSkin.INC_BTN_X;
            visRect[Y] = GaugeSkin.INC_BTN_Y;
            if (GaugeSkin.IMAGE_INC_BTN != null) {
                visRect[WIDTH] = GaugeSkin.IMAGE_INC_BTN.getWidth();
                visRect[HEIGHT] = GaugeSkin.IMAGE_INC_BTN.getHeight();
            } else {
                visRect[WIDTH] = 15;
                visRect[HEIGHT] = 15;
            }
            break;
        case I_DEC_BTN:
            visRect[X] = GaugeSkin.DEC_BTN_X;
            visRect[Y] = GaugeSkin.DEC_BTN_Y;
            if (GaugeSkin.IMAGE_DEC_BTN != null) {
                visRect[WIDTH] = GaugeSkin.IMAGE_DEC_BTN.getWidth();
                visRect[HEIGHT] = GaugeSkin.IMAGE_DEC_BTN.getHeight();
            } else {
                visRect[WIDTH] = 15;
                visRect[HEIGHT] = 15;
            }
            break;
        default:
            Logging.report(Logging.ERROR, LogChannels.LC_HIGHUI,
                           "GaugeLFImpl: uCallTraverse, focusBtn=" +focusBtn);
            break;
        }
        
        // Gauge should always return true on at least the initial
        // traverse, or any internal traverse between the two buttons
        if (initialTraverse || intTraverse) {
            initialTraverse = false;
            uRequestPaint();
            return true;
        } 

        return false;
    
voiduCallTraverseOut()
Called by the system to indicate traversal has left this Item.

        super.uCallTraverseOut();
        initialTraverse = true;