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.
-
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.
-
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
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
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
-
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.
-
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
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.