Just An Application

December 16, 2009

What’s New In MIDP 3.0: Redux – LCDUI – Command Layout

Filed under: JME, Java, LCDUI, MIDP, MIDP3, MIDP3Issues, MIDP3LCDUI — Tags: , , , , , , — Simon Lewis @ 10:49 am

Original Post

Changes Since Proposed Final Draft

javax.microedition.lcdui.Display

The following has been added to the end of the Exact Placement of Commands section
of the Display class documentation.

On each callback of CommandLayoutPolicy.onCommandLayout(Displayable), implementation MUST first disassociate Command and Menu
with their respective previous placements. At the beginning of each callback of CommandLayoutPolicy.onCommandLayout(Displayable) method,
Displayable.getCommand(int) or Displayable.getMenu(int) will return null for every placement.

As I said in my original post

  1. The specification does not contain an explicit definition of the state of a Display’s placements when the onLayout(Displayable)[sic] method is called, that is, whether Commands and/or Menus previously placed on the current Display by the Displayable are still present or whether all Commands and/or Menus must be explicitly placed each time the method is called. This makes implementing the method perhaps more interesting than it ought to be.

Well now it does. Every time you layout a Displayable’s Commands you start with a clean slate.

javax.microedition.lcdui.Displayable

The setCommand(Command,int) method no longer throws an IllegalArgumentException when the placement

is associated with a placement that does not support commands

possibly because it is actually not possible for a placement not to support Commands.

It is hard to be sure because the Item.setCommand(Command,int) method will apparently still throw an IllegalArgumentException when the placement

is associated with a placement that does not support commands

The CommandLayoutPolicy Example

The CommandLayoutPolicy now looks like this. Actually it doesn’t because I have re-formatted it. In Chrome, Firefox and Safari the formatting is all over the place, as it is in the PDF version.


class MyCanvas extends Canvas implements CommandLayoutPolicy {
    MyCanvas() {
        setCommandLayoutPolicy(this);
    }

    void sort(Command[] commands, int[] positions) {
        // sort the commands in the correct order depending on the positions available.
        // Implementation can use Display's getCommandPreferredPlacements to get the recommended
        // placement for each Command.
    }

    public void onCommandLayout(Displayable displayable) {
        Display display = displayable.getCurrentDisplay();

        final int border = Display.SOFTKEY_BOTTOM;

        int[] positions = display.getExactPlacementPositions(border);

        int numOfPositions = positions.length;

        Command[] cmd = displayable.getCommands();

        sort(cmd, positions);

        if (cmd.length <= numOfPositions) {
            for (int i = 0; i < cmd.length; ++i) {
                displayable.setCommand(cmd[i], positions[i]);
            }
        } else {
            for (int i = 0; i < numOfPositions ; ++i) {
                displayable.setCommand(cmd[i], positions[i]);
            }

            int[] menuSupportedPlmts = display.getMenuSupportedPlacements();
            if( menuSupportedPlmts != null ) {
                Menu options = new Menu("More", null, null);
                // first add the remaining commands in the Menu
                for (int i = numOfPositions; i < cmd.length; ++i) {
                    options.append(cmd[i]);
                }
                // Get the first preferred placement of Menu
                int menuPlmt = menuSupportedPlmts[0];
                // check if this placement already occupied by Command
                if( displayable.getCommand(menuPlmt) != null ) {
                    //add the existing Command in Menu, otherwise the existing
                    // Command will be removed from the Displayable according to
                    //setMenu() method
                    //
                    options.append(displayable.getCommand(menuPlmt));
                }
                displayable.setMenu(options, menuPlmt);
            }
        }
    }
 }

This is an improvement on the previous version which was flat-out broken. Note that it still doesn’t check the return value of the call to Display.getExactPlacementPositions(int).

Issues

The changes above are the only ones that I have found. Of the original issues I raised they address two if you are being charitable.

  1. What is the state of the Displayable with respect to Command layout when the CommandLayoutPolicy.onCommandLayout(Displayable) method is invoked ? It is a clean slate

  2. Can there be placements which do not support Commands ? Probably not.

Everything else is still up for grabs. Developers, assuming there are going to be any, are going to have to try it and see what happens, and then hope it happens the same way everywhere, which is the past has not been a guaranteed recipe for success.

Possibly if somebody had attempted to write a real-world example for the specification the Command layout feature itself would have been better specified. The example provided effectively does no more than provide the existing default behaviour.


Copyright (c) 2009 By Simon Lewis. All Rights Reserved.

July 23, 2009

What’s New In MIDP 3.0 ? Part 33: LCDUI – KeyListener

Filed under: JME, Java, LCDUI, MIDP, MIDP3, MIDP3LCDUI — Tags: , , , , , , — Simon Lewis @ 7:19 am

The KeyListener interface enables an object to listen for key events associated with a Canvas, CustomItem, or IdleItem

When a key is pressed, released or repeated the listening object is notified with the key code and modifiers.

The KeyListener of a Canvas or Custom Item can be set using their respective

	public void setKeyListener(KeyListener listener)

methods.

In each case passing null as the listener argument will result in the current KeyListener, if any, being removed.

For both a Canvas and a CustemItem having a KeyListener does not affect the


    protected void keyPressed(int keyCode)

    protected void keyReleased(int keyCode)

    protected void keyRepeated(int keyCode)

and they will continue to be called.


Copyright (c) 2009 By Simon Lewis. All Rights Reserved

What’s New In MIDP 3.0 ? Part 32: LCDUI – TextEditor

Filed under: JME, Java, LCDUI, MIDP, MIDP3, MIDP3LCDUI — Tags: , , , , , , — Simon Lewis @ 7:14 am

1. TextEditor

A TextEditor is a UI element which can be used in conjunction with a Canvas, CustomItem, or IdleItem to display and obtain text input from the user.

A TextEditor is the Canvas/CustomItem equivalent of a TextField and supports the same input constraints and modes as a TextField.

A TextEditor can only be associated with a single Canvas or CustomItem, but a Canvas or CustomItem may have multiple TextEditors associated with it.

The implementation is only responsible for the visual representation of the cursor and text. All other visual aspects of a TextEditor, for example, scroll bars if required, are the responsibility of the MIDlet.

2. TextEditorChangeListener

The TextEditorChangeListener enables an object to listen for the TextEditor events.

The listening object is notified when

  • the caret moves

  • the text changes

  • the current input language changes

  • the current input method changes

  • the direction of the writing language changes

  • the user traverses away from the TextEditor


Copyright (c) 2009 By Simon Lewis. All Rights Reserved

July 22, 2009

What’s New In MIDP 3.0 ? Part 31: LCDUI – Text

Filed under: JME, Java, LCDUI, MIDP, MIDP3, MIDP3LCDUI — Tags: , , , , , , — Simon Lewis @ 8:59 pm

A Text object is a mutable text container with the ability to layout it’s contents.

In addition to the text it contains, it has the following attributes, all of which can be set by a MIDlet as required.

  • the width and height of the rectangle within which to layout it’s contents

  • the initial text layout direction

  • the text alignment

  • the paragraph start indentation level

  • the space in pixels above each line of text

  • the space in pixels below each line of text

  • the background colour

  • the default foreground colour

  • the default Font

  • the position and length of the currently highlighted text, if any

  • the current position, if any, of the caret</p

The colour and Font used to render text can also be set on a section by section basis if required.

The contents of a Text object can be rendered to a Graphics object which means that it can be used in conjunction with a Canvas, CustomItem, IdleItem or mutable Image.


Copyright (c) 2009 By Simon Lewis. All Rights Reserved

What’s New In MIDP 3.0 ? Part 29: LCDUI – AnimatedImage

Filed under: JME, Java, LCDUI, MIDP, MIDP3, MIDP3LCDUI — Tags: , , , , , , — Simon Lewis @ 9:07 am

1. AnimatedImage

The AnimatedImage class is a sub-class of the Image class.

An AnimatedImage is a composite Image which comprises a sequence of Images. It is displayed by displaying the individual Images within the sequence one after another, each Image being replaced by its successor after a specified period of time.

An AnimatedImage may be used anywhere an Image can be used, but an implementation may not necessarily render the AnimatedImage exactly as specified. It may render it statically using the first Image in the sequence, or animate it only for a period of time.

2. Terminology

2.1 Frame

A frame is an individual Image within the sequence of Image’s that comprise the AnimatedImage.

2.2 Frame Count

The frame count is the number of Image’s in the sequence of Image’s that comprise the AnimatedImage.

2.2 Frame Delay

The frame delay is the amount of time, in milliseconds, for which a given frame will be displayed

2.3 Frame Index

The index of a given frame is it’s position within the sequence of Image’s that comprise the AnimatedImage.

Frames are indexed from zero so a valid frame index must be greater than or equal to zero and less than the frame count.

2.3 Loop Count

The loop count is the number of times the AnimatedImage’s frame sequence will be repeated after it has been shown for the first time.

3. Creating An AnimatedImage

An AnimatedImage can be created from data in the GIF89a format using any of the following Image method’s


    public static Image createImage(java.io.InputStream stream)
                        throws
                            java.io.IOException

    public static Image createImage(String name)
                        throws
                            java.io.IOException

    public static Image createImage(byte[] imageData, int imageOffset, int imageLength)

In each case the resulting Image can then be cast to an AnimatedImage.

Whether the resulting Image is in fact an AnimatedImage can be determined by calling the Image’s isAnimated() method.

4. Getting The Frame Count

The frame count of an AnimatedImage can be obtained by calling it’s

    public int getFrameCount()

method.

5. Getting The Loop Count

The loop count of an AnimatedImage can be obtained by calling it’s

	public int getLoopCount()

method.

The method will return -1 if the frame sequence will be repeated indefitely.

6. Getting A Specific Frame

A specific frame of an AnimatedImage can be obtained by calling it’s

    public Image getFrame(int index)

method

It is an error if the index argument does not specify a valid frame index and an IndexOutOfBoundsException will e thrown.

The method will return an immutable Image representing the specified frame.

7. Getting The Delay For A Specific Frame

The delay for a specific Frame of an AnimatedImage by calling it’s

	public int getFrameDelay(int index)

method.

It is an error if the index argument does not specify a valid frame index and an IndexOutOfBoundsException will e thrown.


Copyright (c) 2009 By Simon Lewis. All Rights Reserved.

What’s New In MIDP 3.0 ? Part 28: LCDUI – Images

Filed under: Java, LCDUI, MIDP, MIDP3, MIDP3LCDUI — Tags: , , , , , — Simon Lewis @ 7:31 am

1. Creating Images

1.1 Creating A Mutable Image With An Alpha Channel

A mutable Image with an alpha channel by calling the Image method

    public static Image createImage(
                            int     width,
                            int     height,
                            boolean withAlpha,
                            int     fillColor)

It is an error if either the x or y arguments is less than one and an IllegalArgumentException will be thrown.

The fillColor argument specifies the initial value of each pixel of the created Image.

If the withAlpha argument is true then the fillColor argument is interpreted as a value of the form 0xAARRGGBB, otherwise as a value of the form 0x00RRGGBB

1.2 Creating An Image By Scaling And Transforming An Existing Image

An Image can be created by scaling and transforming all or part of an existing Image by calling the Image method

    public static Image createImage(
                            Image image,
                            int   x,
                            int   y,
                            int   width,
                            int   height,
                            int   transform,
                            int   img_width,
                            int   img_height)

The x, y, width, and height specify the region of the existing Image to use.

It is an error if the specified region is not entirely within the bounds of the source Image, or if the region’s width or height is less than one and an IllegalArgumentException will be thrown.

The transform argument specifies the transform to apply as defined in the Sprite class. It is an error if the specified transform is invalid and an IllegalArgumentException will be thrown.

The img_width and img_height arguments specify the size of the new Image. It is an error if the specified width or height is less than one and an IllegalArgumentException will be thrown.

2. Getting Image Data In 16-bit Formats

A MIDlet can get Image data in 16-bit RGB format by calling the Image’s

    public void getRGB16(
                    short[] rgbData,
                    int     offset,
                    int     scanlength,
                    int     x,
                    int     y,
                    int     width,
                    int     height)

method, and in 16-bit ARGB format by calling the Image’s

    public void getARGB16(
                    short[] rgbData,
                    int     offset,
                    int     scanlength,
                    int     x,
                    int     y,
                    int     width,
                    int     height)

method.

3. Predicate Methods

3.1 Does An Image Have An Alpha Channel ?

A MIDlet can determine whether an Image has an alpha channel by calling it’s

    public boolean hasAlpha()

method.

3.2 Is An Image Animated ?

A MIDlet can determine whether an Image is an instance of the sub-class AnimatedImage by calling the Image’s

    public boolean isAnimated()

method.

3.3 Is An Image Scalable ?

A MIDlet can determine whether an Image is an instance of the sub-class ScalableImage by calling the Image’s

    public boolean isScalable()

method.


Copyright (c) 2009 By Simon Lewis. All Rights Reserved.

July 21, 2009

What’s New In MIDP 3.0 ? Part 27: LCDUI – IdleItem

Filed under: JME, Java, LCDUI, MIDP, MIDP3, MIDP3LCDUI — Tags: , , , , , , — Simon Lewis @ 10:41 pm

1. IdleItem

An IdleItem is a UI element which supports MIDlet access to the ‘idle screen’ associated with a Display on a device.

2. Display Support

A Display may not support the use of IdleItems. This can be determined by calling the Display.getCapabilities() method.

3. Functionality

The UI functionality available via IdleItem is equivalent to that of a CustomItem since the IdleItem is a sub-class of the CustomItem class.

The IdleItem class is abstract and must be sub-classed to be used.

4. Getting IdleItem Related UI Characteristics

4.1 Colours

The foreground, background and highlighted foreground and background colours on an idle screen associated with a given Display can be obtained by calling that Display’s

    public int getColor(int colorSpecifier)

method, passing one of the following Display constants

  • COLOR_IDLE_FOREGROUND

  • COLOR_IDLE_BACKGROUND

  • COLOR_IDLE_HIGHLIGHTED_FOREGROUND

  • COLOR_IDLE_HIGHLIGHTED_BACKGROUND

4.2 Fonts

The Fonts for text and highlighted text on an idle screen can be obtained by calling the Font method

    public static Font getFont(int fontSpecifier)

passing the constant

    Font.FONT_IDLE_TEXT

or

    Font.FONT_IDLE_HIGHLIGHTED_TEXT

respectively.

5. Getting The Current IdleItem On A Given Display

A MIDlet can get the IdleItem, if any, currently associated with a given Display by calling that
Display’s

    public IdleItem getIdleItem()

method.

6. Setting The Current IdleItem On A Given Display

A MIDlet can request that an IdleItem should appear on the idle screen associated with a given
Display by calling that Display’s

    public void setIdleItem(IdleItem idleItem)

method.

If there is an existing associated IdleItem it is removed.

The idleItem argument may be null.

It is an error if the Display does not support IdleItems and a DisplayCapabilityException will be thrown.

It is an error if the specified IdleItem is currently associated with another Display and an IllegalStateException.

Note

  • The method documentation actually says that an IllegalStateException will be thrown if

    If the item is already owned by a Form or Display.

    which seems to indicate that it should be possible to add an IdleItem to a Form and that an IdleItem cannot both be a member of a Form and associated with a Display. Presumably the converse also applies.

7. Notification Methods

If after being passed to the Display.setIdleItem(IdleItem) method of a Display
it is added to the idle screen assciated with that Display, then the IdleItem’s

    protected void addedToDisplay(Display display)

method will be called.

If having been added it is subsequently removed from idle screen associated with the
Display then the IdleItem’s

    protected void removedFromDisplay(Display display)

method will be called.


Copyright (c) 2009 By Simon Lewis. All Rights Reserved.

July 15, 2009

What’s New In MIDP 3.0 ? Part 26: LCDUI – Notification

Filed under: JME, Java, LCDUI, MIDP, MIDP3, MIDP3LCDUI — Tags: , , , , , , — Simon Lewis @ 5:46 pm

1. The Notification Model

  • A Notification is a small piece of information which should be presented to the user independently of any MIDlet specific UI

  • A Notification has an associated type which is an instance of the NotificationType class

    • The type of a Notifiction may be

      • built-in, or

      • MIDlet specific

    • The built-in types are

      • CALL

      • EMAIL

      • IM

      • MMS

      • SMS

      • REMINDER

    • A MIDlet specific Notification type specifies a default label and a default Image

      • If a Notification of a MIDlet specific type does not have a label and/or Image then
        the label and/or Image specified by it’s type will be used

  • A Notification can be in one of two states

    • removed, when it is not accessible by the user, or

    • available, when it is accessible by the user

  • A Notification is created in the removed state

  • A MIDlet can make a Notification available by posting it

  • A MIDlet can remove an available Notification

  • When a Notification is available a user may dismss it

    • If a user dismisses a Notification it’s state changes to removed

  • A MIDet may specify that when a Notification is available it should be possible for the user to select it

    • If a user selects a Notification it’s state changes to removed

  • A MIDet may specify that a Notification should only be available for a maximum period of time

    • If a Notification is not dismissed, or, if possible, selected during the specified period of time, then its state changes to removed

  • The way in which a Notification is displayed and the use made of it’s label and Image are implementation dependent.

  • An implementation can choose to display Notifications differently on the basis of their types

2. NotificationType

2.1 Creating A NotificationType

A MIDlet specific NotificationType can be created using the

	NotificationType(String defaultLabel, Image defaultImage)

constructor.

It is an error if either the defaultLabel or the defaultImage argument is null and a NullPointerException will be thrown.

2.2 NotificationType Constants

The built-in NotificationType’s can be accessed using the following constants defined in the NotificationType class

    public static final NotificationType CALL

    public static final NotificationType IM

    public static final NotificationType EMAIL

    public static final NotificationType MMS

    public static final NotificationType SMS

    public static final NotificationType REMINDER

3. NotificationListener

The NotificationListener interface enables an object which implements it to listen for the following Notification events

  • when a Notification is dismissed

  • when a Notification is selected

  • when a Notification times out

Each event is reported via a call to a corresponding method defined in the interface.

3.1 Notification Dismissed

If an available Notification has been dismissed by the user, then after the Notification has been removed, if it has an associated NotificationListener object then that object’s

    public void notificationDismissed(Notification notification)

method will be called.

3.2 Notification Selected

If a Notification has been posted using the either the Notification.post(boolean) or Notification.post(boolean,int) methods with a selectable argument of true, and it is subsequently selected by the user then after the Notification has been removed, if it has an associated NotificationListener object then that object’s

    public void notificationSelected(Notification notification)

method will be called.

3.3 Notification Timeout

If a Notification has been posted using the Notification.post(boolean,int) method and it subsequently times out, then after the Notification has been removed, if it has an associated NotificationListener object then that object’s

    public void notificationTimeout(Notification notification)

method will be called.

4. Notification Creation

A Notification can be created using one of the following constructors

    public Notification(NotificationType type)
    public Notification(NotificationType type, String label)
    public Notification(NotificationType type, String label, Image image)

In each case it is an error if the type argument is null and a NullPointerException will be thrown.

5. Getting The Type Of A Notification

The type of a Notification can be obtained by calling it’s

    public NotificationType getType()

method.

6. Getting The Timestamp Of A Notification

The time at which a Notification was last posted can be obtained by calling the Notification’s

    public long getTimestamp()

method.

The return value is the same as the result of a call to the System.currentTimeMillis() method made at the time the Notification was last posted.

If the Notification has not been posted the method will return zero.

7. Setting The Label Of A Notification

The label of a Notification can be set by calling it’s

    public void setLabel(String label)

method.

Note

  1. The method documentation does not explicitly state that the label argument may be null. Presumably by analogy with the Image case it can.

  2. Also by an analogy with the Image case, presumably it is necessary for the Notification to be re-posted for this change to have any effect if the Notification is currently available.

8. Setting The Image Of A Notification

The Image of a Notification may be set by calling it’s

    public void setImage(Image image)

method.

The image may specify an immutable or a mutable Image. It may also be null.

If the Image is mutable then a snapshot, created at the point the post() method is called, will be used.

If the Notification is currently available, then it must be re-posted for the change to have an effect.

9. Setting The Listener Of A Notification

The NotificationListener object associated with a Notification can be set by calling the Notification’s

    public void setListener(NotificationListener listener)

method.

The listener argument may be null in which case in addition to removing the currently associated NotificationListener object, if any, if the Notification is currently available it will be removed.

Note

  • The rather suprising side-effect of passing null to this method when the Notification is available does not appear on the state diagram in the class documentation and is not mentioned in the accompanying text which reads

    A Notification can become removed in the following ways :

    • By the implementation, when a Notification is dismissed or selected by the user, before the callbacks
      (notificationSelected() or notificationDismissed()) are triggered.
    • By a MIDlet using the remove() method.
    • By the implementation, due to the duration being passed (see below), which will trigger the notificationTimeout() method.

    A Notification MUST remain available until removed by application or implementation code in the ways defined above.

    and which could be taken to imply that the method should not be doing what it’s documentation says it does.

10. Posting

10.1 Posting A Notification

A Notification can be posted so that it is available to the user by calling the Notification’s

    public void post(boolean selectable)

method.

If the selectable argument is true then the Notification will be selectable by the user.

If it is not possible for the Notification to be posted then a NotificationException will be thrown.

Note

  • NotificationException is an unchecked exception. An IDE or compiler will not issue a warning if this method is called and NotificationException is not explicitly caught.

10.2 Posting A Notification For A Maximum Period Of Time

A Notification can be posted so that it is only available to the user for a maximum period of time by calling the Notification’s

    public void post(boolean selectable, int duration)

method.

If the selectable argument is true then the Notification will be selectable by the user.

The duration argument should specify the maximum period of time in milliseconds the Notification should be available to the user.

It is an error if the duration argument is not a positive integer and an IllegalArgumentException will be thrown.

If it is not possible for the Notification to be posted then a NotificationException will be thrown.

If the Notification is not dismissed or selected by the user first then at the end of specified period of time the Notification is automatically removed. If there is a NotificationListener object associated with the Notification it’s notificationTimeout() method will be called.

Note

  • NotificationException is an unchecked exception. An IDE or compiler will not issue a warning if this method is called and NotificationException is not explicitly caught.

11. Removing A Notification

A Notification can moved into the removed state by callimg it’s

    public void remove()

method.

It is an error if the Notification is already in the removed state and an IllegalStateException will be thrown.

If it is not possible for the Notification to be removed then a NotificationException will be thrown.

Notes

  1. It is not clear under what circumstances a Notification cannot be removed or whether such a situation is recoverable.

  2. NotificationException is an unchecked exception. An IDE or compiler will not issue a warning if this method is called and NotificationException is not explicitly caught.


Copyright (c) 2009 By Simon Lewis. All Rights Reserved.

What’s New In MIDP 3.0 ? Part 25: LCDUI – Fonts

Filed under: JME, Java, LCDUI, MIDP, MIDP3, MIDP3LCDUI — Tags: , , , , , , — Simon Lewis @ 11:49 am

1. Terminology And Definitions

1.1 Font Names

1.1.1 The Family Name

The family name of a Font can be either a foundry or design name, for example, Courier or Geneva, or a logical name.

The logical names are

  • Dialog

  • DialogInput

  • Monospaced

  • Serif

  • SansSerif

1.1.2 The Face Name

The face name specifies the family and style of the font, for example, Arial Narrow Bold or Times Italic.

1.1.3 The Logical Name

The logical name of a Font is the the name that was used to construct the font.

The logical name of a Font that was constructed without a name is “Default”.

1.1.4 The Name Of The Default System Font

The MIDP 3 Font methods which take a Font name can be passed null in which case the method is applied to the default system Font.

1.2 Font Pixel Size

The specification defines the pixel size of a Font to be

the height of the em box – a distance (in pixels) between the baselines of two unadjusted, adjacent lines of text in a single spaced text document.

A pixel size argument of zero is equivalent to a pixel size equal to the value corresponding to the logical size SIZE_MEDIUM.

1.3 Logical Font Attributes

Prior to MIDP 3 Fonts were specified in terms of logical attributes. These continue to be used by some of the new MIDP 3 Font functionality, and the following is included for reference.

1.3.1 Face

There are three logical faces defined by the following Font constants

  • FACE_MONOSPACE

  • FACE_PROPORTIONAL

  • FACE_SYSTEM


1.3.2 Size

There are three logical sizes defined by the following Font constants

  • SIZE_SMALL

  • SIZE_MEDIUM

  • SIZE_PROPORTIONAL


1.3.3 Style

There are four style constants defined in the Font class

  • STYLE_PLAIN

  • STYLE_BOLD

  • STYLE_ITALIC

  • STYLE_UNDERLINED

These are all bit-flags and can be used in the following combinations

  • STYLE_PLAIN

  • STYLE_PLAIN|STYLE_UNDERLINED

  • STYLE_BOLD

  • STYLE_BOLD|STYLE_UNDERLINED

  • STYLE_ITALIC

  • STYLE_ITALIC|STYLE_UNDERLINED

  • STYLE_BOLD|STYLE_ITALIC

  • STYLE_BOLD|STYLE_ITALIC|STYLE_UNDERLINED


2. Font Format Support

The specification requires that when creating Fonts from Font data supplied by a MIDlet Suite, LIBlet, or a MIDlet at runtime, an implementation support OpenType fonts with TrueType outlines of up to 200KB in size.

The specification permits an implementation to discard individual fonts with a file size that exceeds 200KB.

3. Bundled Fonts

Fonts can be bundled with a MIDlet Suite or LIBlet. At runtime they can be used by a MIDlet in exactly the same way as built-in fonts.

Fonts bundled with a MIDlet Suite are specified at installation time using the

    MIDlet-Font

attribute.

The value should be a comma separated list of pathnames which identify files within the MIDlet Suite Jar which contain font data in a supported format.

The equivalent attribute for use in a LIBlet is

    LIBlet-Font

4. New Functionality

4.1 Font Creation

A Font can be created at runtime using the Font method

    public static Font createFont(java.io.InputStream fontData)
                       throws
                           java.io.IOException
	

The fontData should specify an InputStream giving access to Font data in a supported format.

The method will not close the specified InputStream.

If the Font data is invalid or in an unsupported format then a FontFormatException will be thrown.

The style and size of the created Font will be the same as those of a Font created with a style of STYLE_PLAIN and a size of SIZE_MEDIUM.

Note

  • It is not clear what the scope of a Font created is in this way is.

    The method documentation says

    the availability and use of fonts created using createFont method is limited to the execution environment of a MIDlet suite that instantiated the font.

    However, in the Downloadable Fonts section of the javax.microedition.lcdui package documentation
    it says

    Implementations MUST make all individual fonts available (whether downloaded or packaged) to all MIDlets in the MIDlet suite at runtime if the individual font file size does not exceed 200KB.

    and also

    Implementations MUST ensure that the availability and use of fonts packaged with a MIDlet suite in a JAR, packaged with any dependency LIBlets, or downloaded at runtime and created using createFont method are limited to the MIDlet’s runtime execution environment.

    which might just be three ways of saying the same thing. It is difficult to say given the variations in terminology
    being employed.

4.2 Font Discovery

4.2.1 Listing All The Available Fonts

A MIDlet can obtain a list of all the Fonts available to it by calling the Font method.

    public static Font[] getAvailableFonts()

The method result will include all bundled and created fonts.

4.2.2 Listing All The Available Fonts Of A Given Style

A MIDlet can obtain a list of all the Fonts of a given style available to it by calling the Font method.

    public static Font[] getAvailableFonts(int style)

The style argument should be one of

  • STYLE_PLAIN

  • STYLE_BOLD

  • STYLE_ITALIC

  • STYLE_BOLD|STYLE_ITALIC

The method result will include all bundled and created fonts.

Note

  • The behaviour when the style argument is not legal is not specified.

4.2.3 Listing All The Available Fonts Of A Given Face, Style And Size

A MIDlet can obtain a list of all the Fonts of a given style and pixel size available to it by calling the Font method.


    public static Font[] getAvailableFonts(int face, int style, int pixelSize)

The face argument should specify a legal logical Font face.

The style argument should be one of

  • STYLE_PLAIN

  • STYLE_BOLD

  • STYLE_ITALIC

  • STYLE_BOLD|STYLE_ITALIC

The method result will include all bundled and created fonts.

Note

  • The behaviour when the face, style or pixelSize argument is not legal is not specified.

4.3 Accessing Fonts

A named Font with a specific style and pixel size can be obtained by calling the Font method.


    public static Font getFont(String name, int style, int pixelSize)

The name argument can specify either a face name or a family name or null.

It is an error if the Font specified by the name argument cannot be found an IllegalArgumentException.

The style argument should be one of

  • STYLE_PLAIN

  • STYLE_BOLD

  • STYLE_ITALIC

  • STYLE_BOLD|STYLE_ITALIC

If it is not then a value of STYLE_PLAIN is used.

It is an error if the pixelSize argument is less than zero and an IllegalArgumentException will be thrown.

If the name argument specifies a face name which includes style information, then if the specified style argument is the same or contradicts that in the face name it is ignored. Otherwise the style information from the face name and the style argument is combined.

Note

  • The method documentation for the style argument says

    If the style argument does not conform to one of the expected integer bitmasks then the style is set to STYLE_PLAIN.

    It then goes on to say that an IllegalArgumentException will be thrown

    if style or pixelSize are not legal values.

4.4 Font Characteristics

4.4.1 Getting The Pixel Size Of A Named Font

The pixel size of a named font can be obtained by calling the Font method

    public static int getPixelSize(String name)

The name argument can be a font face name or a font family name or null.

If the named Font is scalable then the method will return zero.

It is an error if the named Font cannot be found and an IllegalArgumentException will be thrown

4.4.2 Getting The Style Of A Named Font

The style of a named font can be obtained by calling the Font method

    public static int getStyle(String name)

The name argument can be a font face name or a font family name or null.

It is an error if the named Font cannot be found and an IllegalArgumentException will be thrown

4.5 Deriving A Font Of A Specific Size From An Existing Font

A new Font of a specific pixel size can be derived from an existing Font using that Font’s

    public Font deriveFont(int pixelSize)

method.

It is an error if the pixelSize is less than zero, or if the Font is not scalable, and an IllegalArgumentException will be thrown.

4.6 Deriving A Font Of A Specific Style And Size From An Existing Font

A new Font of a specific style and pixel size can be derived from an existing Font using that Font’s

    public Font deriveFont(int style, int pixelSize)

method.

It is an error if the style argument does not specify a legal style and an IllegalArgumentException will be thrown.

It is an error if the pixelSize is less than zero, or if the Font is not scalable, and an IllegalArgumentException will be thrown.

4.7 Getting The Family Name Of A Font

The family name of a Font can be obtained by calling its

    public String getFamily()

method.

4.8 Additional Font Metrics

The following additional metrics can be obtained from a Font

  • ascent
  • descent
  • leading
  • max ascent
  • max descent
  • pixel size

4.9 Miscellaneous Constants

There are two new constants defined in the Font class

  • public static final int FONT_IDLE_TEXT

  • public static final int FONT_IDLE_HIGHLIGHTED_TEXT

Note

  • It is not clear what the constants are for. In each case the documentation says

    … can be is [sic] used with getFont to retrieve the appropriate Font ...

    where getFont links to the getFont(String,int,int) method.

    As it is an int it is presumably intended to be used as a style, but the method documentation for the style argument
    reads

    the style constant for the Font. The style argument is an integer bitmask that may be STYLE_PLAIN, or a bitwise union of STYLE_BOLD and/or STYLE_ITALIC (for example, STYLE_ITALIC or STYLE_BOLD | STYLE_ITALIC). If the style argument does not conform to one of the expected integer bitmasks then the style is set to STYLE_PLAIN.[Emphasis added]

    which specifically prevents their use.

  • Update

    The explanation turns out to be quite simple. The documentation links to the wrong version of the getFont() method. It should actually link to the

            public static int getFont(int fontSpecifier)
    

    version whose documentation explicitly mentions both constants


Copyright (c) 2009 By Simon Lewis. All Rights Reserved.

July 9, 2009

What’s New In MIDP 3.0 ? Part 24: LCDUI – TabbedPane

Filed under: JME, Java, LCDUI, MIDP, MIDP3, MIDP3Issues, MIDP3LCDUI, Mobile Java — Tags: , , , , , , — Simon Lewis @ 10:30 am

1. The TabbedPane Model

  • A TabbedPane is a container for a collection of Forms and/or Lists

  • Each Form or List is contained in a Tab

  • If the TabbedPane is not empty then at any time only one Tab and the Form or List it contains is potentially visible.

    • This is the current Tab.

  • The UI of a TabbedPane provides the user with a way to switch between Tabs.

  • A TabbedPane can be constructed in either image or string mode.

    • In image mode each Tab is identified by an icon.

      • The image to use to identify the Tab is specified when the Form or List is added to the TabbedPane

      • The image used to identify the Tab can be changed after the Tab has been created.

      • If the image specified is mutable then as is conventional a snapshot of it will be token and used.

    • In string mode each Tab is identified by a string.

      • The string to use to identify the Tab is specified when the Form or List is added to the TabbedPane

  • The displayed title of a TabbedPane will depend upon it’s mode

    • In image mode the title displayed may be either

      • the title of the current Tab, if any

      • the title, if any, of the TabbedPane itself

    • In string mode the title displayed will be that of the TabbedPane itself, if any.

  • Tabs are indexed from zero

  • For a TabbedPane containing N Tabs, where N > 0, a legal Tab index must be in the range 0 to N – 1 inclusive.

  • For an empty TabbedPane no Tab index is legal.

  • A Form or List cannot be added to a TabbedPane if it already a member of that TabbedPane or any other.

  • A Form or List cannot be added to a TabbedPane if it is the current Displayable of a Display.

2. TabListener

The TabListener interface enables an object to listen for the following TabbedPane events

  • the addition of a Tab

  • the removal of a Tab

  • a change in the Tab which is current

Each event is reported via a call to a corresponding method defined in the interface.

2.1 Tab Added Event

When a Tab is added to a TabbedPane with an associated TabListener object, the object’s implementation of the TabListener method

    public void tabAddedEvent(int index, Screen tab)

is called.

Note

  • The method documentation describes the index argument as

    the index of the tab where the insertion is to occur.

    which might imply that at the point this method is called the Form or List specified by the tab argument is not actually a member of the TabbedPane ?

2.2 Tab Removed Event

When a Tab is removed from a TabbedPane with an associated TabListener object, the object’s implementation of the TabListener method

    public void tabRemovedEvent(int index, Screen tab)

is called.

Note

  • The method documentation describes the index argument as

    the index number of the removed tab.

    which might imply that at the point this method is called the Form or List specified by the tab argument is no longer a member of the TabbedPane ?

2.3 Current Tab Changed Event

When the current Tab changes in a TabbedPane with an associated TabListener object, the object’s implementation of the TabListener method

    public void tabChangeEvent(Screen tab)

is called.

The tab argument is the new current Tab

Note

  • The documentation does not specify whether this method is called if there is no longer a current Tab as a result of the removal of the last Tab from the TabbedPane.

3. Constructing A TabbedPane

A TabbedPane can be constructed by using the

    public TabbedPane(String title, boolean stringTab, boolean suppressTitle)

constructor.

If the stringTab argument is true then the TabbedPane is constructed in string mode, otherwise it is constructed in image mode.

If the TabbedPane is being constructed in image mode, then if the suppressTitle argument is true, the displayed title of the TabbedPane will be that of it’s current Tab. Otherwise it will be the value, if any, of the title argument.

If the TabbedPane is being constructed in string mode the suppressTitle argument is ignored.

4. Adding A Tab

A Form or List can be added to a TabbedPane by calling its

    public void addTab(Screen tab, Image icon)

method.

It is an error if the tab argument is neither a Form nor a List, and an IllegalArgumentException will be thrown.

It is an error if the Form or List specified is already a member of a TabbedPane, including this one, or if the Form or List is the current Displayable of a Display, and an IllegalStateException will be thrown.

If the TabbedPane was constructed in image mode, then it is an error if the icon argument is null, and a NullPointerException will be thrown.

If the TabbedPane was constructed in string mode the icon argument is ignored.

Note

  • The method documentation says that an IllegalStateException will be thrown

    if the tab is current on another Display

    but there is no guarantee that the TabbedPane is associated with a Display when the method is called so another is not a particularly useful qualifier in this context.

5. Inserting A Tab

A Form or List can be added to a TabbedPane at a specific index by calling the TabbedPane’s

    public void insertTab(int index, Screen tab, Image icon)

method.

It is an error if the index argument is less than zero or greater than the number of Tabs in the TabbedPane, and an IndexOutOfBoundsException will be thrown

The new Tab is created at the specified index and the indices of all existing Tabs at an index greater than or equal to that specified increase by one.

The semantics of the remaining aguments are identical to those of the addTab(Screen,Image) method above.

6. Removing A Tab

The Form or List at a specified index in a TabbedPane can be removed by passing it’s index to the TabbedPane’s

    public void removeTab(int index)

method.

It is an error if the index argument does not specify a legal Tab index, and an IndexOutOfBoundsException will be thrown.

If the current Tab is removed, then, if the TabbedPane is not empty, the new current Tab is either the Tab at index – 1, if it exists, or the Tab at index + 1

7. Getting The Number Of Tabs

The number of Tabs in a TabbedPane can be obtained by calling its

    public int getCount()

method.

8. Getting The Contents Of A Tab

The Form or List at a specified index in a TabbedPane can be obtained by passing the index to the TabbedPane’s

    public Screen getScreen(int index)

method.

If the TabbedPane is not empty then it is an error if the index argument does not specify a legal Tab index, and an IndexOutOfBoundsException will be thrown.

Note

  • It is not clear what happens if the TabbedPane is empty.

    The method documentation states that the method returns

    a Screen object (tab element) in the TabbedPane referenced by index, or null if index is invalid. [Emphasis added]

    and that it throws an IndexOutOfBoundsException

    if index is not within the range [0..getCount()-1], inclusive.

    There is no explanation of when an index is invalid.

    This could either be a straight forward contradiction or it might possibly be a rather obscure way of specifying that null is returned if the TabbedPane is empty ?

9. Getting A Tab Icon

The Icon of a Form or List at a specified index in a TabbedPane can be obtained by passing its index to the TabbedPane’s

    public Image getTabIcon(int index)

method.

If the TabbedPane was constructed in string mode the method always returns null.

If the TabbedPane is not empty then it is an error if the index argument does not specify a legal Tab index, and an IndexOutOfBoundsException will be thrown.

Notes

  1. It is not clear whether the index argument is actually validated if the TabbedPane was constructed in string mode. The use of the word always in the method documentation could be taken to imply that it is not.

  2. As in the getScreen(int) method above, it is not clear happens when the TabbedPane is empty.

    The method documentation states that the method returns

    the image part of the tab referenced by index, or null if index is invalid or if the TabbedPane is in the “String mode”. [Emphasis added]

    This raises the same kind of questions as above.

10. Setting A Tab Icon

The icon of a Form or List at a specified index in a TabbedPane can be set by calling the TabbedPane’s

    public void setTabIcon(int index, Image icon)

method.

It is an error if the index argument does not specify a legal Tab index, and an IndexOutOfBoundsException will be thrown.

If the TabbedPane was constructed in image mode then it is an error if the icon argument is null, and a NullPointerException will be thown.

If the TabbedPane was constructed in string mode the icon argument is ignored.

11. Getting The Current Tab Index

The index of the current Tab, if any, of a TabbedPane can be obtained by calling its

    public int getSelectedIndex()

method.

If the TabbedPane is empty the method will return -1.

12. Setting The Current Tab

The current Tab of a TabbedPane can be set by calling it’s

    public void setFocus(int index)

method.

It is an error if the index argument does not specify a legal Tab index and an IndexOutOfBoundsException will be thrown.

13. Setting The Tab Listener

The TabListener associated with a TabbedPane can be set by calling the TabbedPane’s

    public void addTabListener(TabListener tabListener)

method.

The tabListener argument may be null in which case the existing TabListener associated with the TabbedPane, if any, will be removed.

14. Commands And Command Layout

TabbedPanes support Command layout. When a TabbedPane is displayed both Commands belonging to it, and to the Form or List in the current Tab can be placed.

If a Command is selected then the CommandListener of the Form or List, if any, is invoked first, followed by the CommandListener, if any, of the TabbedPane itself.

Notes

  • It there is no CommandLayoutPolicy object associated with a TabbedPane, it is not clear what use is made of the TabbedPane and current Form or List Commands by the default platform layout mechanism.

15. Issues

15.1 Tickers ?

The TabbedPane class documentation says

In Image mode, the title shown for the TabbedPane depends on the suppressTitle parameter. In String mode, TabbedPane’s title is always shown to avoid redundancy.

and then goes on to say

Similarly, the TabbedPane’s Ticker (if present) takes precedence over the Ticker belonging to the selected tab’s contents.

which is a trifle obscure.

Unfortunately it is also the only thing it says about TabbedPanes and Tickers, so it is a little difficult to know if there is intended to be any special behaviour associated with them.

15.2 TabbedPanes, Forms, Lists And The Display.setCurrent() Methods

The Display.setCurrent(Displayable) and Display.setCurrent(Alert, Displayable) methods will both throw an IllegalStateException

if the Displayable is currently on a tab of a TabbedPane and the TabbedPane is current on another Display

This is presumably intended to ensure that a Form or List passed to either of the methods cannot be visible on two Displays at once.

If so then it is not clear why an IlegalStateException is not thrown if the Displayable is a member of a TabbedPane and the TabbedPane is not current on another Display. In this case there is nothing to prevent the TabbedPane becoming current on another Display while the Displayable is current on this one. To prevent this it would be necessary to specify an additional constraint on the Displayable passed to the two methods. Namely that passing a TabbedPane any one of whose members is current on another Display will also result in an IllegalStateException.

In fact it is not clear whether even this is enough to prevent problems. Unless a Displayable is deemed to become current on a Display the moment it is passed to one of the Display.setCurrent() methods, a Form or List which is a member of a TabbedPane could be passed to one of the setCurrent() methods of one Display whilest the TabbedPane itself is passed to one of the setCurrent() methods of another Display. At this point neither is current on its respective Display so there will be no IllegalStateExceptions thrown.

When a Displayable is deemed to become current on a Display also affects the effacacy of the checks made in the TabbedPane.addtab(Screen,Image) and TabbedPane.insert(int,Screen,Image) methods. Both methods will throw an IllegalStateException if the Form or List passed to the method

is current on another Display

This is not a very useful test if the Form or List is actually in the process of becoming current on a Display at this point and actually becomes current on the Display only after being successfully added to the TabbedPane.

15.3 Display Capabilities

There are no less than seven Display capabilities that could possibly affect whether a TabbedPane can become current on a Display, and whether a Form or List could be added to it whilest it is current on a Display. They are

  • SUPPORTS_COMMANDS

  • SUPPORTS_FORMS

  • SUPPORTS_LISTS

  • SUPPORTS_MENUS

  • SUPPORTS_TABBEDPANES

  • SUPPORTS_TICKER

  • SUPPORTS_TITLE

If the Display does not support TabbedPanes there are no further issues, however it is not clear, the specification certainly does not explicitly say, whether a Display that does support TabbedPanes must necessarily support the other six features. If this is in fact not the case then it is an interesting exercise, which is left to the reader, to work out the possible permutations of things that could go wrong depending on what is and is not supported on a given Display.

It would be useful if the specification either mandated that support for TabbedPanes requires support for the other features, or documented the fact that the TabbedPane.addTab(Screen,Image) and TabbedPane.insertTab(int,Screen,Image) methods can throw a DisplayCapabilityException in certain circumstances.


Copyright (c) 2009 By Simon Lewis. All Rights Reserved.

Older Posts »

Blog at WordPress.com.