Just An Application

July 9, 2009

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

Filed under: Java, JME, 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.

Advertisements

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: