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

DEPopupLayer

public class DEPopupLayer extends com.sun.midp.chameleon.layers.ScrollablePopupLayer
This is a popup layer that handles a sub-popup within the date editor, which is also a popup layer.

Fields Summary
DateEditor
editor
The DateEditor that triggered this popup layer.
private int[]
viewport
The viewport setting inside this popup (X, Y, W, H). It is set in this layer's coordinate system.
boolean
open
Indicates if this popup layer is shown (true) or hidden (false).
private int
numElements
Number of elements (list of choices) that constitute this popup layer.
private String[]
elements
The list of choices in this popup layer.
private int
elementWidth
The width of an element.
private int
elementHeight
The height of an element.
private int
elementsToFit
Number of elements that can be shown within the viewport.
private boolean
sbVisible
Indicates whether we do/do not need to draw a scrollbar in this popup layer.
private int
startIndex
The start index of the chosen list of choices from the complete list, to be displayed within the viewport.
private int
endIndex
The end index of the chosen list of choices from the complete list, to be displayed within the viewport.
private int
hilightedIndex
The index that is currently highlighted, is taken as the selected index when popup closes.
private int
selectedIndex
Selected index. Index accepted by pressing set or fire key
private boolean
circularTraversal
True if traversal past the last item in the popup should jump to the beginning and false if attempts to traverse past the last or the first items will have no effect.
private ScreenLFImpl
sLF
static final int
PRESS_OUT_OF_BOUNDS
private int
itemIndexWhenPressed
Constructors Summary
DEPopupLayer(DateEditor editor, String[] elements, int selectedIndex, boolean circularTraversal)
Constructs a date editor sub-popup layer, which behaves like a popup-choicegroup, given a string array of elements that constitute the available list of choices to select from.

param
editor The DateEditor that triggered this popup layer.
param
elements String array holding the list of choices.
param
selectedIndex the index to place the initial highlight on.
param
circularTraversal true if traversal past the last item should jump to the beginning

        super((Image)null, DateEditorSkin.COLOR_POPUPS_BG);
        this.editor = editor;
        
        setContent(elements, selectedIndex);
        this.circularTraversal = circularTraversal;
    
Methods Summary
intgetSelectedIndex()
Gets currently selected index.

return
currently selected index

        return hilightedIndex;
    
public voidhide()
hide current popup

        if (scrollInd != null) {
            scrollInd.setVisible(false);
            sbVisible = false;
            updateScrollIndicator();
            setScrollInd(null);
        }
        if (this.sLF != null) {
            sLF.lGetCurrentDisplay().hidePopup(this);
        }
        editor.requestRepaint();
        // it is necessary, to make sure correctly showing the space occupied by this popup
        this.sLF = null;
        this.open = false;
    
protected voidinitialize()
Initializes the popup layer.

        super.initialize();
        viewport = new int[4];
    
private intitemIndexAtPointerPosition(int x, int y)
Helper function to determine the itemIndex at the x,y position

param
x,y pointer coordinates
return
item's index since 0, or PRESS_OUT_OF_BOUNDS.

        int id = PRESS_OUT_OF_BOUNDS; 
        if (containsPoint(x + bounds[X], y + bounds[Y])) {
            id = (int)(y / elementHeight);
        }
        return id;
    
public booleankeyInput(int type, int code)
Handles key event in the open popup.

param
type - The type of this key event (pressed, released)
param
code - The code of this key event
return
true always, since popupLayers swallow all key events

        if ((type == EventConstants.PRESSED ||
             type == EventConstants.REPEATED) && editor != null) 
        {
            switch (code) {
                case Constants.KEYCODE_SELECT:
                    editor.keyInput(type, code);
                    break;
                case Constants.KEYCODE_UP:
                case Constants.KEYCODE_DOWN:
                case Constants.KEYCODE_LEFT:
                case Constants.KEYCODE_RIGHT:
                    traverseInPopup(code);
                    break;
            }
        }
        // PopupLayers always swallow all key events
        return true;
    
public voidpaintBackground(Graphics g)
Paints popup background (including borders) and scrollbar if it is present.

param
g - The graphics object to paint background on

        super.paintBackground(g);
        g.setColor(DateEditorSkin.COLOR_BORDER);
        g.drawRect(0, -1, bounds[W] - 1, bounds[H]);
        
        
        if (sbVisible && ScrollIndSkin.MODE == 
                ScrollIndResourcesConstants.MODE_ARROWS) {
            int sbX = bounds[W] - 6;
            int sbY = 5;
            int sbH = bounds[H] - 12;
            int thumbY = sbY - 4 + 
                ((((hilightedIndex + 1) * 100) / numElements) * sbH) / 100;
            g.setColor(DateEditorSkin.COLOR_BORDER);

            // draw scrollbar
            g.drawLine(sbX, sbY, sbX, sbY + sbH - 1);
            
            // draw scrollbar thumb
            g.fillRect(sbX - (3 / 2), thumbY, 3, 4);
        }
    
public voidpaintBody(Graphics g)
Paints the body of the popup layer.

param
g The graphics context to paint to

        boolean hilighted = false;
        int translatedY = 0;
        
        int transY = elementHeight;
        g.translate(2, 0);
        
        endIndex = startIndex + (elementsToFit - 1);
        
        if (hilightedIndex > endIndex) {
            endIndex = hilightedIndex;
            startIndex = endIndex - (elementsToFit - 1);
        }
        
        g.setFont(DateEditorSkin.FONT_POPUPS);
        for (int i = startIndex; i <= endIndex; i++) {
            hilighted = (i == hilightedIndex);
        
            if (hilighted) {
                g.setColor(DateEditorSkin.COLOR_TRAVERSE_IND);
                g.fillRect(0, 0, elementWidth - 7, elementHeight);
            }
        
            g.setColor(0);
            g.drawString(elements[i], 2, 0, 0);
            g.translate(0, transY);
            translatedY += transY;
        }
        
        g.translate(-2, -translatedY); 
    
public booleanpointerInput(int type, int x, int y)
Handles pointer event in the open popup.

param
type - The type of this pointer event (pressed, released, dragged)
param
x x coordinate
param
x y coordinate
return
true always, since popupLayers swallow all pointer events

        boolean consume = true;
        switch (type) {
        case EventConstants.PRESSED:
            itemIndexWhenPressed =  itemIndexAtPointerPosition(x, y);
            if (itemIndexWhenPressed == PRESS_OUT_OF_BOUNDS) {
                hide();
                consume = false;
            } else if (itemIndexWhenPressed >= 0 &&
                // press on valid item
                hilightedIndex != itemIndexWhenPressed + startIndex) { 
                hilightedIndex = itemIndexWhenPressed + startIndex;
                requestRepaint();
            } 
            break;
        case EventConstants.RELEASED:
            int itemIndexWhenReleased = itemIndexAtPointerPosition(x,y);
            
            if (itemIndexWhenReleased == itemIndexWhenPressed) {
                if (itemIndexWhenPressed >=0) {
                    keyInput(EventConstants.PRESSED, Constants.KEYCODE_SELECT);
                } else {
                    hide();
                }
            }

            if (itemIndexWhenReleased == PRESS_OUT_OF_BOUNDS) {
                consume = false;
            }            
            //remember to reset the variables
            itemIndexWhenPressed = PRESS_OUT_OF_BOUNDS; 
            break;
        }
        return consume; 
    
public voidscrollContent(int scrollType, int thumbPosition)
Scroll content inside of the DEPopup.

param
scrollType scrollType. Scroll type can be one of the following
see
ScrollIndLayer.SCROLL_NONE
see
ScrollIndLayer.SCROLL_PAGEUP
see
ScrollIndLayer.SCROLL_PAGEDOWN
see
ScrollIndLayer.SCROLL_LINEUP
see
ScrollIndLayer.SCROLL_LINEDOWN or
see
ScrollIndLayer.SCROLL_THUMBTRACK
param
thumbPosition

        switch (scrollType) {
            case ScrollIndLayer.SCROLL_PAGEUP:
                uScrollViewport(Canvas.UP);
                break;
            case ScrollIndLayer.SCROLL_PAGEDOWN:
                uScrollViewport(Canvas.DOWN);
                break;
            case ScrollIndLayer.SCROLL_LINEUP:
                uScrollByLine(Canvas.UP);
                break;
            case ScrollIndLayer.SCROLL_LINEDOWN:
                uScrollByLine(Canvas.DOWN);
                break;
            case ScrollIndLayer.SCROLL_THUMBTRACK:
                uScrollAt(thumbPosition);
                break;
            default:
                break;
        }
    
public voidsetBounds(int x, int y, int w, int h)
Sets the bounds of the popup layer.

param
x the x-coordinate of the popup layer location
param
y the y-coordinate of the popup layer location
param
w the width of this popup layer in open state
param
h the height of this popup layer in open state

        super.setBounds(x, y, w, h);
        transparent = false;
        
            // set viewport in popup's coordinate system
        viewport[X] = 2;
        viewport[Y] = 0;
        viewport[W] = bounds[W] - 3;
        viewport[H] = bounds[H] - 3;

        elementsToFit = viewport[H] / elementHeight;
        if (elementsToFit < numElements) {
            sbVisible = true;
        } else {
            elementsToFit = numElements;
            sbVisible = false;
        }
    
protected voidsetContent(java.lang.String[] newElements, int selectedIndex)
Populates this sub-popup layer with new elements. The number of elements before and after should be the same if the popup already existed.

param
newElements String array holding the list of choices.
param
selectedIndex the index to place the initial highlight on.

        if (newElements != null) {
            numElements = newElements.length;
            elements = new String[numElements];
            System.arraycopy(newElements, 0, elements, 0, numElements);

            this.selectedIndex = selectedIndex;
            hilightedIndex = selectedIndex;
        }
        startIndex = 0;
    
voidsetElementSize(int w, int h)
Set the choice element size (width and height).

param
w width of the element
param
h height of the element

        elementWidth = w;
        elementHeight = h;
    
voidsetSelectedIndex(int selId)
Sets currently selected index.

param
selId currently selected index

        selectedIndex = selId;
    
public voidshow(ScreenLFImpl sLF)
show current popup

param
sLF popup owner screen

        this.sLF = sLF;
        sLF.lGetCurrentDisplay().showPopup(this);          
        this.open = true;
        
        // update startIndex to let the selected item shown
        hilightedIndex = selectedIndex;
        startIndex = hilightedIndex;
        if (startIndex > numElements - elementsToFit) {
            // startIndex too bottom, adjust it
            startIndex = numElements - elementsToFit;
        }
        if (startIndex < 0) {
            startIndex = 0;
        }
        
        if (ScrollIndSkin.MODE == ScrollIndResourcesConstants.MODE_BAR) {
            setScrollInd(ScrollIndLayer.getInstance(ScrollIndSkin.MODE));
        }
        
        updateScrollIndicator();
    
booleantraverseInPopup(int code)
Handle traversal in the open popup.

param
code the code of the key event
return
true always, since popupLayers swallow all key events

        boolean updated = true;
        if (code == Constants.KEYCODE_UP) {
            if (hilightedIndex > 0) {
                hilightedIndex--;
                if (hilightedIndex < startIndex) {
                    startIndex--;
                }
            } else if (circularTraversal) {
                // jump to the last element
                hilightedIndex = numElements - 1;
                startIndex = hilightedIndex - elementsToFit + 1;
            } else {
                updated = false;
            }
        } else if (code == Constants.KEYCODE_DOWN) {
            if (hilightedIndex < (numElements - 1)) {
                hilightedIndex++;
                if (hilightedIndex > endIndex) {
                    startIndex++;
                }
            } else if (circularTraversal) {
                // jump to the first element
                hilightedIndex = 0;
                startIndex = 0;
            } else {
                updated = false;
            }
        }
        if (updated) {
            updateScrollIndicator();
            requestRepaint();
        }

        return true;
    
private voiduScrollAt(int position)
Perform a scrolling at the given position.

param
context position

        startIndex = (numElements - elementsToFit) * position / 100;
        if (startIndex < 0) {
            startIndex = 0;
        } else if (startIndex > numElements - elementsToFit) {
            startIndex = numElements - elementsToFit;
        }
        updatePopupLayer();
    
private voiduScrollByLine(int dir)
Perform a line scrolling in the given direction. This method will attempt to scroll the view to show next/previous line.

param
dir the direction of the flip, either DOWN or UP

        switch (dir) {
        case Canvas.UP:
            startIndex--;
            if (startIndex < 0) {
                startIndex = 0;
            }
            break;
        case Canvas.DOWN:
            startIndex++;
            if (startIndex > numElements - elementsToFit) {
                startIndex = numElements - elementsToFit;
            }
            break;
        }
        updatePopupLayer(); 
    
private voiduScrollViewport(int dir)
Perform a page flip in the given direction. This method will attempt to scroll the view to show as much of the next page as possible. It uses the locations and bounds of the items on the page to best determine a new location - taking into account items which may lie on page boundaries as well as items which may span several pages.

param
dir the direction of the flip, either DOWN or UP

        switch (dir) {
        case Canvas.UP:
            startIndex -= elementsToFit - 1; // with top item still visible in new viewport
            if (startIndex < 0) {
                startIndex = 0;
            }
            break;
        case Canvas.DOWN:
            startIndex += elementsToFit - 1; // with bottom item still visible in new viewport
            if (startIndex > numElements - elementsToFit) {
                // startIndex too bottom, adjust it
                startIndex = numElements - elementsToFit;
            }
            break;
        }
        updatePopupLayer();
    
private voidupdatePopupLayer()
This method initiate repaint of the popup layer

        // correct hilighted index depending on new viewport. The hilighted item
        // always has to be visible
        if (hilightedIndex < startIndex) {
            hilightedIndex = startIndex;
        } else if (hilightedIndex >= startIndex + elementsToFit) {
            hilightedIndex = startIndex + elementsToFit - 1;
        }
        updateScrollIndicator();
        addDirtyRegion();
        requestRepaint();
    
public voidupdateScrollIndicator()
Updates the scroll indicator.

        if (scrollInd != null) {
            scrollInd.update(null);
            if (sbVisible) {
                scrollInd.setVerticalScroll(
                                            startIndex * 100 / (numElements - elementsToFit),
                                            elementsToFit * 100 / numElements);                                            
            } else {
                scrollInd.setVerticalScroll(0, 100);
            }
            super.updateScrollIndicator();
        }