FileDocCategorySizeDatePackage
MIDPWindow.javaAPI DocphoneME MR2 API (J2ME)27150Wed May 02 18:00:20 BST 2007com.sun.midp.chameleon

MIDPWindow

public class MIDPWindow extends CWindow
The MIDPWindow class is a concrete instance of a CWindow which implements the MIDP specification and its graphical elements, such as a title bar, soft buttons, ticker, etc.

Fields Summary
public static final int
ALERT_WASH_LAYER
Id of layer containing the alert wash
public static final int
ALERT_LAYER
Id of layer containing the alert displayable
public static final int
WASH_LAYER
Id of layer containing the mail
public static final int
BTN_LAYER
Id of layer rendering the soft button controls
public static final int
TICKER_LAYER
Id of layer containing the ticker of the current displayable
public static final int
TITLE_LAYER
Id of layer containing the title of the current displayable
public static final int
PTI_LAYER
Id of layer containing the pti contents
public static final int
BODY_LAYER
Id of layer containing the current displayable's contents
public static final int
LAST_LAYER
Number of main layers
ChamDisplayTunnel
tunnel
Used to call back into the Display class from this package
private WashLayer
washLayer
Cached typed references to the namded layers
private WashLayer
alertWashLayer
private AlertLayer
alertLayer
private TitleLayer
titleLayer
private TickerLayer
tickerLayer
private BodyLayer
bodyLayer
private SoftButtonLayer
buttonLayer
private PTILayer
ptiLayer
private static final int
NORMAL_MODE
Normal screen mode
private static final int
FULL_SCR_MODE
Full screen mode when the current displayable is occupying as much screen as possible
int
screenMode
Current screen mode
Command[]
scrCmdCache
Cache of screen commands
int
scrCmdCount
Number of screen commands in the cache
CommandListener
scrCmdListener
Listener to notify when a screen command is selected
Command[]
itemCmdCache
Cache of selected item commands
int
itemCmdCount
Number of item commands in the cache
ItemCommandListener
itemCmdListener
Listener to notify when an item command is selected
CLayer[]
mainLayers
boolean
sizeChangedOccured
Determines whether area of the window has been changed
Constructors Summary
public MIDPWindow(ChamDisplayTunnel tunnel)
Construct a new MIDPWindow given the tunnel to the desired MIDP Display instance

param
tunnel the "tunnel" to make calls from this java package back into the Display object in another package


                                                       
       
        super(ScreenSkin.IMAGE_BG, ScreenSkin.COLOR_BG);

        this.tunnel = tunnel;

        for (int i = LAST_LAYER - 1; i >= 0; i-- ) {
            createLayer(i);
        }
    
Methods Summary
public booleanaddLayer(CLayer layer)
Add the given layer to this window. This method is overridden from CWindow in order to special case popup layers. Popup layers can have their own commands which supercede those of the current displayable.

param
layer the CLayer to add to this window
return
true if new layer was added, false otherwise

        boolean added = super.addLayer(layer);

        if (added && layer instanceof PopupLayer) {
            PopupLayer popup = (PopupLayer)layer;
            popup.setDirty();
            popup.visible = true;

            Command[] cmds = popup.getCommands();
            if (cmds != null) {
                buttonLayer.updateCommandSet(
                    null, 0, null, cmds, cmds.length,
                    popup.getCommandListener());
            }
        }

        if (added && layer instanceof PTILayer) {
            ptiLayer = (PTILayer)layer;
            mainLayers[PTI_LAYER] = layer;
            resize();
        }

        return added;
    
public booleanbelongToCmdLayers(int x, int y)
Returns true if the point lies in the bounds of commnad layer

param
x the "x" coordinate of the point
param
y the "y" coordinate of the point
return
true if the point lies in the bounds of commnad layer

        return buttonLayer.belongToCmdLayers(x,y);
    
public booleanbodyContainsPoint(int x, int y)
Utility method to determine if the given point lies within the bounds of body layer. The point should be in the coordinate space of this layer's containing CWindow.

param
x the "x" coordinate of the point
param
y the "y" coordinate of the point
return
true if the coordinate lies in the bounds of this layer

        return bodyLayer.containsPoint(x, y);
    
public voidcallPaint(Graphics g, CGraphicsQ refreshQ)
MIDPWindow overrides the parent paint method in order to do special effects such as paint a "wash" over the background when a dialog is up. Also in an effort to call {@link javax.microedition.lcdui.Displayable#sizeChanged } method before painting. This implementation determine whether size has been changed and calls sizeChanged() if it's so. Anyway it invokes the base class's {@link CWindow#paint} method.

param
g The graphics object to use to paint this MIDP window.
param
refreshQ The chameleon graphics queue.

        if (sizeChangedOccured) {
            if (tunnel != null) {
                int w = getBodyWidth();
                int h = getBodyHeight();
                tunnel.callSizeChanged(w, h);
                sizeChangedOccured = false;
            }
        }
        super.paint(g, refreshQ);
    
protected voidclearPopups()
Internal method to clear all current popups. This occurs if a change of displayable occurs, as all popups are treated as belonging to the current displayable.

        synchronized (super.layers) {
            for (CLayerElement le = super.layers.getTop();
                    le != null; le = le.getLower()) {
                CLayer l = le.getLayer();
                if (l instanceof PopupLayer) {
                    removeLayer(l);
                }
            }
        }
    
private voidcreateLayer(int id)
create new layer by id and launch addLayer()

param
id - layer id

        switch (id) {
            case PTI_LAYER:
                break;
            case TITLE_LAYER:
                titleLayer = new TitleLayer();
                mainLayers[id] = titleLayer;
                addLayer(titleLayer);
                break;
            case TICKER_LAYER:
                tickerLayer = new TickerLayer();
                mainLayers[id] = tickerLayer ;
                addLayer(tickerLayer);
                break;
            case BTN_LAYER:
                buttonLayer = new SoftButtonLayer(tunnel);
                mainLayers[id] = buttonLayer;
                addLayer(buttonLayer);
                break;
            case ALERT_LAYER:
                alertLayer = new AlertLayer(tunnel);
                mainLayers[id] = alertLayer;
                break;
            case WASH_LAYER:
                washLayer = new WashLayer();
                mainLayers[id] = washLayer;
                break;
            case ALERT_WASH_LAYER:
                alertWashLayer = new WashLayer();
                mainLayers[id] = alertWashLayer;
                break;
            case BODY_LAYER:
                bodyLayer = new BodyLayer(tunnel);
                mainLayers[id] = bodyLayer;
                addLayer(bodyLayer);
                break;
        }
    
public intgetBodyAnchorX()
Get the current x anchor coordinate for the body layer (the body layer renders the contents of the current displayable).

return
the x anchor coordinate of the body layer

        return bodyLayer.bounds[X];
    
public intgetBodyAnchorY()
Get the current y anchor coordinate for the body layer (the body layer renders the contents of the current displayable).

return
the y anchor coordinate of the body layer

        return bodyLayer.bounds[Y];
    
public intgetBodyHeight()
Get the current height of the body layer (the body layer renders the contents of the current displayable).

return
the height of the body layer

        return bodyLayer.bounds[H];
    
public int[]getBodyLayerBounds()
Return bounds of BodyLayer currently

return
array of bounds

        int[] innerBounds = new int[4];
        System.arraycopy(bodyLayer.bounds,0,innerBounds,0,4);
        return innerBounds;

    
public intgetBodyWidth()
Get the current width of the body layer (the body layer renders the contents of the current displayable).

return
the width of the body layer

        return bodyLayer.bounds[W];
    
public CommandgetSoftOne()
Returns the left soft button (one).

return
the command that's tied to the left soft button

        return buttonLayer.getSoftOne();
    
public Command[]getSoftTwo()
Returns the command array tied to the right soft button (two).

return
the command array that's tied to the right soft button

        return buttonLayer.getSoftTwo();
    
public PopupLayergetTopMostPopup()
Gets the "top" most Popup layer added to this body layer. If there are no popups, this method returns null.

return
the top most popup layer, or null if there are none.

        synchronized (super.layers) {
            for (CLayerElement le = super.layers.getTop();
                    le != null; le = le.getLower()) {
                CLayer l = le.getLayer();
                if (l instanceof PopupLayer) {
                    return (PopupLayer)l;
                }
            }
        }
        return null;
    
public voidhideDisplayable(Displayable displayable)
Alert this MIDPWindow that the given displayable is no longer current and should be removed from the screen. Special circumstances may occur if the displayable is an Alert, such as removing the popup and re-instating the previous displayable which was visible before the Alert popped up.

param
displayable the newly current displayable to show

        if (displayable instanceof Alert) {
            buttonLayer.toggleAlert(false);
            tickerLayer.toggleAlert(false);
            
            alertLayer.setAlert(false, null, 0);
            paintWash(false);
            removeLayer(alertLayer);
        } else {
            bodyLayer.setVisible(false);
        }
        
        buttonLayer.dismissMenu();

        // Make sure that not of the popups are shown
        clearPopups();
    
public booleanisInFullScreenMode()
Determines if window is in full screen mode.

return
true if in full screen mode

        return screenMode == FULL_SCR_MODE;
    
public voidpaintWash(boolean onOff)
Called to paint a wash over the background of this window. Used by SoftButtonLayer when the system menu pops up, and internally when an Alert is shown.

param
onOff A flag indicating if the wash should be on or off

	if (alertLayer.visible) {
            addLayer(washLayer);
            if (onOff) {
                addLayer(alertWashLayer);
            } else {
                removeLayer(alertWashLayer);

                // IMPL_NOTES: interface has to be fixed 
                alertLayer.setScrollInd(
                    ScrollIndLayer.getInstance(ScrollIndSkin.MODE));
                
                // IMPL_NOTES: need to be removed as soon as removeLayer algorithm
                // takes into account layers interaction
                tickerLayer.addDirtyRegion();
                alertLayer.addDirtyRegion();
            }
        } else {
            removeLayer(alertWashLayer);
            if (onOff) {
                addLayer(washLayer);
            } else {
                removeLayer(washLayer);
                
                // IMPL_NOTES: interface has to be fixed 
                bodyLayer.setScrollInd(ScrollIndLayer.getInstance(ScrollIndSkin.MODE));
                
                // IMPL_NOTES: need to be removed as soon as removeLayer algorithm
                // takes into account layers interaction
                tickerLayer.addDirtyRegion();
                titleLayer.addDirtyRegion();

                if (ptiLayer != null) {
                    ptiLayer.addDirtyRegion();
                }
            }
        }
    
public booleanremoveLayer(CLayer layer)
Remove the given layer from this window. This method is overridden from CWindow in order to special case popup layers. Popup layers can have their own commands which supercede those of the current displayable. In this case, the popup is removed and the commands in the soft button bar are restored to either the next top-most popup layer or the current displayable itself.

param
layer the CLayer to remove from this window
return
true if the layer was able to be removed

        if (super.removeLayer(layer)) {
            if (layer instanceof PopupLayer) {
                if (layer == mainLayers[PTI_LAYER]) {
                    ptiLayer = null;
                    mainLayers[PTI_LAYER] = null;
                    resize();
                }

                // Now we update the command set with either the
                // next top most popup or the original cached commands
                PopupLayer p = getTopMostPopup();
                if (p != null && p.getCommands() != null) {
                    Command[] cmds = p.getCommands();
                    buttonLayer.updateCommandSet(
                        null, 0, null, cmds, cmds.length, p.getCommandListener());
                } else {
                    buttonLayer.updateCommandSet(
                        itemCmdCache, itemCmdCount, itemCmdListener,
                        scrCmdCache, scrCmdCount, scrCmdListener);
                }
            } // instanceof
            return true;
        } // removeLayer
        return false;
    
public voidrepaintDisplayable(int x, int y, int w, int h)
Request a repaint of a region of the current displayable. This method specifically marks a region of the body layer (which renders the displayable's contents) as dirty and results in a repaint request being scheduled. The coordinates are in the space of the displayable itself - that is, 0,0 represents the top left corner of the body layer.

param
x the x coordinate of the dirty region
param
y the y coordinate of the dirty region
param
w the width of the dirty region
param
h the height of the dirty region

        // We mark the body layer as dirty
        if (alertLayer.visible) {
            alertLayer.addDirtyRegion(x, y, w, h);
        } else {
            bodyLayer.addDirtyRegion(x, y, w, h);
        }
        requestRepaint();
    
public voidrequestRepaint()
Request a repaint. This method does not require any bounds information as it is contained in each of the Chameleon layers. This method simply results in a repaint event being placed in the event queue for a future callback.

        if (tunnel != null) {
            tunnel.scheduleRepaint();
        }
    
public voidresize()
Internal method to resize window and its content layers according to a size changes in the loaded skins. This is important to re-calculate whenever things such as titles, tickers, fullscreen mode, etc. change state.

        super.resize();

        int oldHeight = bodyLayer.bounds[H];
        int oldWidth = bodyLayer.bounds[W];
        switch (screenMode) {
            case FULL_SCR_MODE:
                // TODO: scroll arrows (bar? ) indicator has to be hidden?
                titleLayer.visible = false;
                tickerLayer.visible = false;
                buttonLayer.visible =
                    buttonLayer.isInteractive();
                break;
            case NORMAL_MODE:
                titleLayer.visible =
                    (titleLayer.getTitle() != null);
                tickerLayer.visible =
                    (tickerLayer.getText() != null);
                buttonLayer.visible = true;
                break;
            default:
                Logging.report(Logging.ERROR, LogChannels.LC_HIGHUI,
                    "MIDPWindow: screenMode=" + screenMode);
                return;
        }

        for (int i = 0; i < LAST_LAYER; i++) {
            CLayer l = mainLayers[i];
            if (l != null && l.visible) {
                l.update(mainLayers);
            }
        }

        if (bodyLayer.bounds[W] != oldWidth ||
                bodyLayer.bounds[H] != oldHeight) {
            setDirty();
            sizeChangedOccured = true;
        }
    
public voidsetFullScreen(boolean onOff)
Set this MIDPWindow's displayable to "fullscreen" mode. This will expand the region occupied by the current displayable to include the area previously occupied by the title and ticker if present

param
onOff true if the displayable should be in fullscreen mode

        if (onOff) {
            setMode(FULL_SCR_MODE);
        } else {
            setMode(NORMAL_MODE);
        }
    
public booleansetGraphicsForCanvas(Graphics g)
This method is an optimization which allows Display to bypass the Chameleon paint engine logic and directly paint an animating canvas. Display will call this method with the graphics context and this method will either return false, indicating the Chameleon paint engine should not be bypassed, or will return true and will setup the graphics context for the canvas to be painted directly.

param
g the graphics context to setup
return
true if Chameleon's paint logic can be bypassed and the canvas can be rendered directly.

        // IMPL_NOTE: Only Canvas painting specially doesn't change
        // dirty state of the owner window, however it is not enough
        // to bypass the Chameleon paint engine. Body layer holding
        // the Canvas should be opaque and be not overlapped with
        // any visible higher layer also. The check for overlapping
        // is to be added later.
        if (super.dirty || !bodyLayer.opaque) {
            return false;
        }

        // NOTE: note the two different orders of clip and translate
        // below. That is because the layer's bounds are stored in
        // the coordinate space of the window. But its internal dirty
        // region is stored in the coordinate space of the layer itself.
        // Thus, for the first one, the clip can be set and then translated,
        // but in the second case, the translate must be done first and then
        // the clip set.
        if (bodyLayer.isDirty()) {
            if (bodyLayer.isEmptyDirtyRegions()) {
                g.setClip(bodyLayer.bounds[X], bodyLayer.bounds[Y],
                          bodyLayer.bounds[W], bodyLayer.bounds[H]);
                g.translate(bodyLayer.bounds[X], bodyLayer.bounds[Y]);

            } else {
                g.translate(bodyLayer.bounds[X], bodyLayer.bounds[Y]);
                g.setClip(bodyLayer.dirtyBounds[X], bodyLayer.dirtyBounds[Y],
                          bodyLayer.dirtyBounds[W], bodyLayer.dirtyBounds[H]);
            }
            bodyLayer.cleanDirty();
        } else {
            // NOTE: the layer can be not dirty, e.g. in the case an empty
            // area was requested for repaint, set empty clip area then.
            g.translate(bodyLayer.bounds[X], bodyLayer.bounds[Y]);
            g.setClip(0, 0, 0, 0);
        }

        return true;
    
private voidsetMode(int mode)
Changes layout mode.

param
mode the mode to be set

        screenMode = mode;
        updateLayout();
    
public voidsetTicker(Ticker ticker)
Set the ticker of this MIDPWindow. This would typically correspond to the ticker of the current displayable, and may result in the ticker layer appearing or disappearing.

param
ticker the current Ticker object. null indicates there is no ticker.

        if (tickerLayer.setText((ticker != null) ? ticker.getString() : null)) {
            resize();
        }
        requestRepaint();
    
public voidsetTitle(java.lang.String title)
Set the title of this MIDPWindow. This would typically correspond to the title of the current displayable, and may result in the title layer appearing or disappearing.

param
title the value of the title. null indicates there is no title.

        if (titleLayer.setTitle(title)) {
            resize();
        }
        requestRepaint();
    
public booleansetVerticalScroll(int scrollPosition, int scrollProportion)
Set the current vertical scroll position and proportion.

param
scrollPosition vertical scroll position.
param
scrollProportion vertical scroll proportion.
return
true if set vertical scroll occues

        if (alertLayer.isVisible()) {
            return alertLayer.setVerticalScroll(
                scrollPosition, scrollProportion);
        }
        if (bodyLayer.setVerticalScroll(
                scrollPosition, scrollProportion)) {
            setDirty();
            sizeChangedOccured = true;
            return true;
        }
        return false;
    
public voidshowDisplayable(Displayable displayable, int height)
Alert this MIDPWindow that the given displayable is now current and should be shown on the screen. This will establish the given displayable on the screen, as well as reflect the displayable's title and ticker (if any). Special circumstances may occur if the displayable is an Alert, such as maintaining the current screen contents and showing the Alert in a popup.

param
displayable the newly current displayable to show
param
height the preferred height of the new displayable

        bodyLayer.opaque =  (displayable instanceof Canvas);

        Ticker t = displayable.getTicker();
        tickerLayer.setText((t != null) ? t.getString() : null);

        if (displayable instanceof Alert) {
            tickerLayer.toggleAlert(true);
            buttonLayer.toggleAlert(true);
            
            alertLayer.setAlert(true, (Alert)displayable, height);
            
            paintWash(false);
            addLayer(alertLayer);
        } else {
            titleLayer.setTitle(displayable.getTitle());
	    bodyLayer.setVisible(true);
        }

        resize();
        requestRepaint();
    
public booleansystemMenuUp()
Determines if the system menu is currently visible. This can be useful in determining the current isShown() status of the displayable.

return
true if the system menu is up

        return buttonLayer.systemMenuUp();
    
public voidupdateCommandSet(Command[] itemCommands, int itemCmdCount, ItemCommandListener itemCmdListener, Command[] scrCommands, int scrCmdCount, CommandListener scrCmdListener)
Update this MIDPWindow's current command set to match the current displayable and possibly item selection.

param
itemCommands the set of item specific commands
param
itemCmdCount the number of item commands
param
itemCmdListener the notification listener for item commands
param
scrCommands the set of screen specific commands
param
scrCmdCount the number of screen commands
param
scrCmdListener the notification listener for screen commands

        // We cache commands to easily reset them when a
        // popup takes precedence and then is dismissed
        this.itemCmdCache = itemCommands;
        this.itemCmdCount = itemCmdCount;
        this.itemCmdListener = itemCmdListener;
        this.scrCmdCache = scrCommands;
        this.scrCmdCount = scrCmdCount;
        this.scrCmdListener = scrCmdListener;

        buttonLayer.updateCommandSet(itemCommands, itemCmdCount,
                                  itemCmdListener,
                                  scrCommands, scrCmdCount,
                                  scrCmdListener);
    
public voidupdateLayout()
Update the current layout

        resize();
        requestRepaint();