FileDocCategorySizeDatePackage
Displayable.javaAPI DocJ2ME MIDP 2.037666Thu Nov 07 12:02:26 GMT 2002javax.microedition.lcdui

Displayable

public abstract class Displayable extends Object
An object that has the capability of being placed on the display. A Displayable object may have a title, a ticker, zero or more commands and a listener associated with it. The contents displayed and their interaction with the user are defined by subclasses.

The title string may contain line breaks. The display of the title string must break accordingly. For example, if only a single line is available for a title and the string contains a line break then only the characters up to the line break are displayed.

Unless otherwise specified by a subclass, the default state of newly created Displayable objects is as follows:

  • it is not visible on the Display;
  • there is no Ticker associated with this Displayable;
  • the title is null;
  • there are no Commands present; and
  • there is no CommandListener present.
since
MIDP 1.0

Fields Summary
Display
currentDisplay
The current Display object
Command[]
commands
An array of Commands added to this Displayable
int
numCommands
The number of Commands added to this Displayable
CommandListener
listener
The CommandListener for Commands added to this Displayable
static final int
X
Used as an index into the viewport[], for the x origin
static final int
Y
Used as an index into the viewport[], for the y origin
static final int
WIDTH
Used as an index into the viewport[], for the width
static final int
HEIGHT
Used as an index into the viewport[], for the height
int[]
viewport
The viewport coordinates. Index 0: x origin coordinate (in the Display's coordinate space) Index 1: y origin coordinate (in the DIsplay's coordinate space) Index 2: width Index 3: height
boolean
fullScreenMode
True, if this Displayable is in full screen mode
boolean
sizeChangeOccurred
True, indicates that before being painted, this Displayable should be notified that its size has changed via callSizeChanged()
Displayable
paintDelegate
In some circumstances (such as List), we need to delegate the paint ownership. For example: List uses an internal Form to do its rendering. If the Form requests a repaint, it will get denied because the Form is not actually current - the List is. So, we introduce the delegate, so the List can set the delegate to itself, and its internal Form can schedule repaints.
private static final Font
TITLE_FONT
Special title font
private static final int
TITLE_HEIGHT
Special title height
private String
title
The title for this Displayable
private Ticker
ticker
The ticker that may be set for this Displayable
private static final Timer
tickerTimer
A Timer which will handle firing repaints of the TickerPainter
private TickerPainter
tickerPainter
A TimerTask which will repaint the Ticker on a repeated basis
private int
tickerHeight
Convenience int to avoid garbage during repainting
private int
totalHeight
Convenience int to avoid garbage during repainting
private int
vScrollPosition
The vertical scroll position
private int
vScrollProportion
The vertical scroll proportion
Constructors Summary
Displayable()
Create a new Displayable



// ************************************************************
//  Static initializer, constructor
// ************************************************************

     
    	tickerTimer = new Timer();
    
        setupViewport();
        translateViewport();
        paintDelegate = this;
    
Methods Summary
public voidaddCommand(Command cmd)
Adds a command to the Displayable. The implementation may choose, for example, to add the command to any of the available soft buttons or place it in a menu. If the added command is already in the screen (tested by comparing the object references), the method has no effect. If the Displayable is actually visible on the display, and this call affects the set of visible commands, the implementation should update the display as soon as it is feasible to do so.

param
cmd the command to be added
throws
NullPointerException if cmd is null

        if (cmd == null) {
            throw new NullPointerException();
        }

        synchronized (Display.LCDUILock) {
            addCommandImpl(cmd);
        }
    
voidaddCommandImpl(Command cmd)
Add a Command to this Displayable

param
cmd The Command to add to this Displayable

        for (int i = 0; i < numCommands; ++i) {
            if (commands[i] == cmd) {
                return;
            }
        }

        if ((commands == null) || (numCommands == commands.length)) {
            Command[] newCommands = new Command[numCommands + 4];
            if (commands != null) {
                System.arraycopy(commands, 0, newCommands, 0, numCommands);
            }
            commands = newCommands;
        }

        commands[numCommands] = cmd;
        ++numCommands;
        updateCommandSet();
    
voidcallHideNotify(Display d)
Notify this Displayable it is being hidden on the given Display

param
d the Display hiding this Displayable

        synchronized (Display.LCDUILock) {
            currentDisplay = null;
            stopTicker();
        }
    
voidcallInvalidate(Item src)
Called by the event handler to perform an invalidation of this Displayable

param
src The Item who is causing the invalidation. If NULL, all contents should be considered invalid.

    
voidcallItemStateChanged(Item src)
Called by the event handler to notify any ItemStateListener of a change in the given Item

param
src The Item which has changed

    
voidcallKeyPressed(int keyCode)
Handle a key press

param
keyCode The key that was pressed

 
voidcallKeyReleased(int keyCode)
Handle a key release

param
keyCode The key that was released

 
voidcallKeyRepeated(int keyCode)
Handle a repeated key press

param
keyCode The key that was pressed

 
voidcallKeyTyped(char c)
Handle a key that was typed from the keyboard

param
c The char that was typed

voidcallPaint(Graphics g, java.lang.Object target)
Display calls this method on it's current Displayable. Displayable uses this oppportunity to do necessary stuff on the Graphics context, this includes, paint Ticker, paint Title, translate as necessary.

The target Object of this repaint may be some Object initially set by this Displayable when the repaint was requested - allowing this Displayable to know exactly which Object it needs to call to service this repaint, rather than potentially querying all of its Objects to determine the one(s) which need painting. SYNC NOTE: The caller of this method handles synchronization.

param
g the graphics context to paint into.
param
target the target Object of this repaint

        /*
        System.err.println("Displayable:Clip: " +
            g.getClipX() + "," + g.getClipY() + "," +
            g.getClipWidth() + "," + g.getClipHeight());
        */

        synchronized (Display.LCDUILock) {

            if (!(fullScreenMode || (title == null && ticker == null))) {

                if (g.getClipY() < totalHeight) {
                    // We always paint "something" for the ticker, rather
                    // than make the title paint more complicated. If there
                    // is no ticker, we draw the darkgray/white saparator line
                    if (g.getClipY() < tickerHeight) {
                        paintTicker(g);
                    }

                    if (title != null) {
                        if (g.getClipY() + g.getClipHeight() >
                                totalHeight - tickerHeight + 1) {

                            g.translate(0, tickerHeight);
                            paintTitle(g);
                            g.translate(0, -tickerHeight);
                        }
                    }
                }
            } else {
                g.setColor(Item.DARK_GRAY_COLOR);
                g.drawLine(0, 0, Display.WIDTH, 0);
                g.setColor(Display.FG_COLOR);
            }


        } // synchronized
    
voidcallPointerDragged(int x, int y)
Handle a pointer drag event

param
x The x coordinate of the drag
param
y The y coordinate of the drag

 
voidcallPointerPressed(int x, int y)
Handle a pointer press event

param
x The x coordinate of the press
param
y The y coordinate of the press

 
voidcallPointerReleased(int x, int y)
Handle a pointer release event

param
x The x coordinate of the release
param
y The y coordinate of the release

 
final voidcallRepaint(int x, int y, int width, int height, java.lang.Object target)
Repaint this Displayable

param
x The x coordinate of the region to repaint
param
y The y coordinate of the region to repaint
param
width The width of the region to repaint
param
height The height of the region to repaint
param
target an optional paint target to receive the paint request when it returns via callPaint()

        if (currentDisplay != null) {
            // Note: Display will not let anyone but the current
            // Displayable schedule repaints
            currentDisplay.repaintImpl(paintDelegate, x, y, width, height,
                                       target);
        }
    
final voidcallRepaint()
Repaints this Displayable. This is the same as calling callRepaint(0, 0, viewport[X] + viewport[WIDTH], viewport[Y] + viewport[HEIGHT], null)

        callRepaint(0, 0, 
                    viewport[X] + viewport[WIDTH],
                    viewport[Y] + viewport[HEIGHT], null);
    
voidcallShowNotify(Display d)
Notify this Displayable it is being shown on the given Display

param
d the Display showing this Displayable

        synchronized (Display.LCDUILock) {
            currentDisplay = d;

            // call grab full screen to let the native
            // layer know whether to be in 
            // fullscreen or normal mode.
            grabFullScreen(fullScreenMode);

            if (sizeChangeOccurred) {
                callSizeChanged(viewport[WIDTH], viewport[HEIGHT]);
            }
            // display the ticker if we have a visible one.
            startTicker();
        }
    
voidcallSizeChanged(int w, int h)
Package private equivalent of sizeChanged()

param
w the new width
param
h the new height

        // If there is no Display, or if this Displayable is not
        // currently visible, we simply record the fact that the
        // size has changed
        sizeChangeOccurred =
            (currentDisplay == null) || (!currentDisplay.isShown(this));
    
booleancommandInSetImpl(Command command)
Decide if the given Command has been added to this Displayable's set of abstract commands.

param
command The Command to check. This value should never be null (no checks are made).
return
True if the Command has been previously added via the addCommand() method

        for (int i = 0; i < numCommands; i++) {
            if (commands[i] == command) {
                return true;
            }
        }
        return false;
    
voidcommitPendingInteraction()
Called to commit any pending user interaction

 
voidfullScreenMode(boolean onOff)
Set the full screen mode of this Displayable. If true, this Displayable will take up as much screen real estate as possible

param
onOff true if full screen mode should be turned on

        if (fullScreenMode == onOff) {
            return;
        }

        fullScreenMode = onOff;

        layout();
        updateCommandSet();
        callSizeChanged(viewport[WIDTH], viewport[HEIGHT]);

        callRepaint();

        if (fullScreenMode) {
            stopTicker();
        } else {
            startTicker();
        }
    
intgetCommandCount()
Get the number of commands that have been added to this Displayable

return
int The number of commands that have been added to this Displayable

        return numCommands;
    
CommandListenergetCommandListener()
Get the CommandListener for this Displayable

return
CommandListener The CommandListener listening to Commands on this Displayable

        return listener;
    
Command[]getCommands()
Get the set of Commands that have been added to this Displayable

return
Command[] The array of Commands added to this Displayable

        return commands;
    
ItemgetCurrentItem()
Gets item currently in focus. This is will be only applicable to Form. The rest of the subclasses will return null.

return
Item The item currently in focus in this Displayable; if there are no items in focus, null is returned

        return null;
    
public intgetHeight()
Gets the height in pixels of the displayable area available to the application. The value returned is appropriate for the particular Displayable subclass. This value may depend on how the device uses the display and may be affected by the presence of a title, a ticker, or commands. This method returns the proper result at all times, even if the Displayable object has not yet been shown.

return
height of the area available to the application
since
MIDP 2.0

        // SYNC NOTE: return of atomic value
        return viewport[HEIGHT];
    
public TickergetTicker()
Gets the ticker used by this Displayable.

return
ticker object used, or null if no ticker is present
since
MIDP 2.0
see
#setTicker

        // SYNC NOTE: return of atomic value, no locking necessary
        return ticker;
    
public java.lang.StringgetTitle()
Gets the title of the Displayable. Returns null if there is no title.

return
the title of the instance, or null if no title
since
MIDP 2.0
see
#setTitle

        // SYNC NOTE: return of atomic value, no lock necessary
        return title;
    
intgetVerticalScrollPosition()
Get the current vertical scroll position

return
int The vertical scroll position on a scale of 0-100

        // SYNC NOTE: return of atomic value
        return vScrollPosition;
    
intgetVerticalScrollProportion()
Get the current vertical scroll proportion

return
ing The vertical scroll proportion on a scale of 0-100

        // SYNC NOTE: return of atomic value
        return vScrollProportion;
    
public intgetWidth()
Gets the width in pixels of the displayable area available to the application. The value returned is appropriate for the particular Displayable subclass. This value may depend on how the device uses the display and may be affected by the presence of a title, a ticker, or commands. This method returns the proper result at all times, even if the Displayable object has not yet been shown.

return
width of the area available to the application
since
MIDP 2.0

        // SYNC NOTE: return of atomic value
        return viewport[WIDTH];
    
native voidgrabFullScreen(boolean mode)
Grabs the requested area of the display

param
mode if true, grabs the entire display area for Canvas' display if false, occupies only part of the entire area leaving space for the status and the command labels.

voidinvalidate(Item src)
Called to schedule an "invalidate" for this Displayable. Invalidation is caused by things like size changes, content changes, or spontaneous traversal within the Item

param
src The Item who is causing the invalidation. If NULL, all contents should be considered invalid.

        Display d = currentDisplay;
        if (d != null) {
            d.invalidate(src);
        }
    
public booleanisShown()
Checks if the Displayable is actually visible on the display. In order for a Displayable to be visible, all of the following must be true: the Display's MIDlet must be running in the foreground, the Displayable must be the Display's current screen, and the Displayable must not be obscured by a system screen.

return
true if the Displayable is currently visible

        synchronized (Display.LCDUILock) {
            return (currentDisplay == null) ?
                false : currentDisplay.isShown(this);
        }
    
voiditemStateChanged(Item src)
Called to schedule a call to itemStateChanged() due to a change in the given Item.

param
src the Item which has changed

        Display d = currentDisplay;
        if (d != null) {
            d.itemStateChanged(src);
        }
    
voidlayout()
Perform any necessary layout, and update the viewport as necessary

        setupViewport();
        translateViewport();
    
voidpaintTicker(Graphics g)
Paint the ticker if it exists, on this graphics object.

param
g The Graphics object to paint this ticker on.

        // paint the ticker here.
        if (ticker != null) {
            ticker.paintContent(g);
        } else if (title != null) {
            g.setColor(Item.DARK_GRAY_COLOR);
            g.drawLine(0, 0, Display.WIDTH, 0);
            g.setColor(Display.ERASE_COLOR);
            g.drawLine(0, 1, Display.WIDTH, 1);
            g.setColor(Display.FG_COLOR);
        }
    
voidpaintTitle(Graphics g)
Paints the title of this Displayable, including it's border. The graphics context is then translated by the height occupied by the title area.

param
g The graphics object to paint this title on.


        g.setColor(Item.LIGHT_GRAY_COLOR);
        g.fillRect(0, 0, Display.WIDTH, TITLE_HEIGHT - 1);
        g.setColor(Display.FG_COLOR);

        Text.paint(title, TITLE_FONT, g, Display.WIDTH,
                   TITLE_HEIGHT, 1, Text.NORMAL, null);

        g.setColor(Item.DARK_GRAY_COLOR);
        g.drawLine(0, TITLE_HEIGHT - 1, Display.WIDTH, TITLE_HEIGHT - 1);
        g.setColor(Display.FG_COLOR);
    
public voidremoveCommand(Command cmd)
Removes a command from the Displayable. If the command is not in the Displayable (tested by comparing the object references), the method has no effect. If the Displayable is actually visible on the display, and this call affects the set of visible commands, the implementation should update the display as soon as it is feasible to do so. If cmd is null, this method does nothing.

param
cmd the command to be removed

        synchronized (Display.LCDUILock) {
            removeCommandImpl(cmd);
        }
    
voidremoveCommandImpl(Command cmd)
Remove a Command from this Displayable

param
cmd The Command to remove from this Displayable

        for (int i = 0; i < numCommands; ++i) {
            if (commands[i] == cmd) {
                commands[i] = commands[--numCommands];
                commands[numCommands] = null;
                updateCommandSet();
                break;
            }
        }
    
final voidrepaintContents()
Repaint the viewport region of this Displayable

        callRepaint(viewport[X], viewport[Y],
            viewport[WIDTH], viewport[HEIGHT], null);
    
private voidrepaintTickerText()
Paints the ticker's text area.


        if (currentDisplay != null &&
                currentDisplay.isShown(paintDelegate)) {

            currentDisplay.repaintImpl(paintDelegate, 0,
                                       Ticker.DECORATION_HEIGHT,
                                       viewport[WIDTH], Screen.CONTENT_HEIGHT,
                                       ticker);
        }
    
private voidrepaintTitle()
Repaint the title area.

        if (currentDisplay != null) {
            currentDisplay.repaintImpl(paintDelegate, 0,
                (ticker != null) 
                    ? Ticker.PREFERRED_HEIGHT 
                    : 2,
                viewport[WIDTH], TITLE_HEIGHT, title);
	    }
    
public voidsetCommandListener(CommandListener l)
Sets a listener for {@link Command Commands} to this Displayable, replacing any previous CommandListener. A null reference is allowed and has the effect of removing any existing listener.

param
l the new listener, or null.

        synchronized (Display.LCDUILock) {
            listener = l;
        }
    
public voidsetTicker(Ticker ticker)
Sets a ticker for use with this Displayable, replacing any previous ticker. If null, removes the ticker object from this Displayable. The same ticker may be shared by several Displayable objects within an application. This is done by calling setTicker() with the same Ticker object on several different Displayable objects. If the Displayable is actually visible on the display, the implementation should update the display as soon as it is feasible to do so.

The existence of a ticker may affect the size of the area available for Displayable's contents. Addition, removal, or the setting of the ticker at runtime may dynamically change the size of the content area. This is most important to be aware of when using the Canvas class. If the available area does change, the application will be notified via a call to {@link #sizeChanged(int, int) sizeChanged()}.

param
ticker the ticker object used on this screen
since
MIDP 2.0
see
#getTicker

        synchronized (Display.LCDUILock) {
            setTickerImpl(ticker);
        }
    
voidsetTickerImpl(Ticker t)
Set the ticker for this Displayable

param
t the ticker to set

        // Return early if there's nothing to do
        if (this.ticker == t) {
            return;
        }

        Ticker oldTicker = this.ticker;
        this.ticker = t;

        // CASES:
        // 1. Had an invisible non-null ticker, setting a null ticker
        //    - We need to set the new ticker. There's no need to re-layout
        //      or start the new ticker
        // 2. Had an invisible non-null ticker, setting a non-null ticker
        //    - We need to set the new ticker. There's no need to re-layout
        //      or start the new ticker
        // 3. Had a visible non-null ticker, setting a null ticker
        //    - We need to set the new ticker and re-layout. There's no
        //      need to start the new ticker.
        // 4. Had a null ticker, setting a visible non-null ticker
        //    - We need to set the new ticker, re-layout, and
        //      start up the new ticker
        // 5. Had a visible non-null ticker, setting a non-null ticker
        //    - We need to set the new ticker. There's no need to re-layout

        boolean sizeChange =
            ((oldTicker != null) && (ticker == null)) ||
            ((oldTicker == null) && (ticker != null));

        if (sizeChange) {
            if (ticker != null) {
                ticker.reset();
                startTicker();
            } else {
                stopTicker();
            }
            layout();
            callSizeChanged(viewport[WIDTH], viewport[HEIGHT]);
            callRepaint();
        } else {
            ticker.reset();
        }
    
public voidsetTitle(java.lang.String s)
Sets the title of the Displayable. If null is given, removes the title.

If the Displayable is actually visible on the display, the implementation should update the display as soon as it is feasible to do so.

The existence of a title may affect the size of the area available for Displayable content. Addition, removal, or the setting of the title text at runtime may dynamically change the size of the content area. This is most important to be aware of when using the Canvas class. If the available area does change, the application will be notified via a call to {@link #sizeChanged(int, int) sizeChanged()}.

param
s the new title, or null for no title
since
MIDP 2.0
see
#getTitle

        synchronized (Display.LCDUILock) {
            setTitleImpl(s);
        }
    
voidsetTitleImpl(java.lang.String s)
Package private unsynchronized version of setTitle(String)

param
s Title to set on this Displayable.

        if (title == s || (title != null && title.equals(s))) {
            return;
        }

        String oldTitle = this.title;
        this.title = s;

        if (fullScreenMode) {
            return;
        }

        boolean sizeChange =
            ((oldTitle != null) && (title == null)) ||
            ((oldTitle == null) && (title != null));

        if (sizeChange) {
            layout();
            callSizeChanged(viewport[WIDTH], viewport[HEIGHT]);
            callRepaint();
        } else {
            repaintTitle();
        }
    
voidsetVerticalScroll(int scrollPosition, int scrollProportion)
Set the vertical scroll position and proportion

param
scrollPosition The vertical scroll position to set on a scale of 0-100
param
scrollProportion The vertical scroll proportion to set on a scale of 0-100. For example, if the viewport is 25 pixels high and the Displayable is 100 pixels high, then the scroll proportion would be 25, since only 25% of the Displayable can be viewed at any one time. This proportion value can be used by implementations which render scrollbars to indicate scrollability to the user.

        synchronized (Display.LCDUILock) {
            this.vScrollPosition = scrollPosition;
            this.vScrollProportion = scrollProportion;

            if (currentDisplay != null) {
                currentDisplay.setVerticalScroll(scrollPosition,
                                                 scrollProportion);
            }
        }
    
private voidsetupViewport()
By default, the viewport array is configured to be at origin 0,0 with width Display.WIDTH and height either Display.HEIGHT or Display.ADORNEDHEIGHT, depending on full screen mode.

        // setup the default viewport, the size of the Display
        if (viewport == null) {
            viewport = new int[4];
        }

        viewport[X] = 
        viewport[Y] = 0;

        viewport[WIDTH]  = Display.WIDTH;
        viewport[HEIGHT] = (fullScreenMode) 
                         ? Display.HEIGHT 
                         : Display.ADORNEDHEIGHT;
    
private booleansizeChangeImpl()
This method is called from showNotify(Display ) It checks if a size change has occurred since the last time a size change occurred or since the object was constructed. If a size change has occurred, it calls callSizeChanged() for package private handling of size change events, and returns true, else returns false.

return
true if a size change has occurred since the last size change or since the construction of this Displayable. false otherwise

        boolean flag = sizeChangeOccurred;
        sizeChangeOccurred = false;

        if (flag) {
            callSizeChanged(viewport[WIDTH], viewport[HEIGHT]);
        }

        return flag;
    
protected voidsizeChanged(int w, int h)
The implementation calls this method when the available area of the Displayable has been changed. The "available area" is the area of the display that may be occupied by the application's contents, such as Items in a Form or graphics within a Canvas. It does not include space occupied by a title, a ticker, command labels, scroll bars, system status area, etc. A size change can occur as a result of the addition, removal, or changed contents of any of these display features.

This method is called at least once before the Displayable is shown for the first time. If the size of a Displayable changes while it is visible, sizeChanged will be called. If the size of a Displayable changes while it is not visible, calls to sizeChanged may be deferred. If the size had changed while the Displayable was not visible, sizeChanged will be called at least once at the time the Displayable becomes visible once again.

The default implementation of this method in Displayable and its subclasses defined in this specification must be empty. This method is intended solely for being overridden by the application. This method is defined on Displayable even though applications are prohibited from creating direct subclasses of Displayable. It is defined here so that applications can override it in subclasses of Canvas and Form. This is useful for Canvas subclasses to tailor their graphics and for Forms to modify Item sizes and layout directives in order to fit their contents within the the available display area.

param
w the new width in pixels of the available area
param
h the new height in pixels of the available area
since
MIDP 2.0

	// this method is intended to be overridden by the application
    
private voidstartTicker()
Starts the "ticking" of the ticker.

        if (ticker == null || fullScreenMode) {
            return;
        }

        stopTicker();
        tickerPainter = new TickerPainter();
        tickerTimer.schedule(tickerPainter, 0, Ticker.TICK_RATE);
    
private voidstopTicker()
Stop the ticking of the ticker.

        if (tickerPainter == null) {
            return;
        }
        tickerPainter.cancel();
        tickerPainter = null;
    
private voidtranslateViewport()
Translate the viewport for any decorations by this Displayable such as a title or ticker


        if (!(fullScreenMode || (title == null && ticker == null))) {

            //
            // determine the right tickerHeight
            //
            if (ticker != null) {
                tickerHeight = Ticker.PREFERRED_HEIGHT;
            } else {
                if (title != null) {
                    tickerHeight = 2;
                } else {
                    tickerHeight = 0;
                }
            }
 
            //
            // add to any title height
            //
            totalHeight = (title != null)
                        ? TITLE_HEIGHT + tickerHeight
                        : tickerHeight;
        } else {
            //
            // in fullscreen, or with no title or ticker we have
            // a single dark line under the status bar
            //
            totalHeight = 1;
        }

        viewport[Y] += totalHeight;
        viewport[HEIGHT] -= totalHeight;
    
voidupdateCommandSet()
Updates command set if this Displayable is visible

        // SYNC NOTE: Display requires calls to updateCommandSet to
        // be synchronized
        synchronized (Display.LCDUILock) {
            if ((currentDisplay != null) && currentDisplay.isShown(this)) {
                currentDisplay.updateCommandSet();
            }
        }