| This article is archived because it is not considered relevant for third-party developers creating commercial solutions today. The article is believed to be still valid for the original topic scope. |
Contents |
This page will introduce you Standard UI and also show usage examples.
Component is base class for user interface elements. All user interface classes in WidSets are extended from Component class.
The picture above shows hierarchy of all available components. The blue one is class for public while the orange one is the class for privileged users only. The red one is deprecated class.
There are some basic functions that every developer should know.
setFlags(int flags)
This function is used for define some basic properties of component. Here are the existed flags.
For example, if you need to make that component Visible and Focusable, you can declare like this.
setFlags(VISIBLE | FOCUSABLE);
setPreferredSize(int width, int height)
This function is used to set size of Component. width and height can be:
For example, if you need to set Component size to 120 width and 140 height, your code should look like this.
setPreferredSize(120, 140);
If you need to set component size to fit your screen, you can use:
setPreferredSize(-100, -100);
Style Sheet and Component are coordinate. Component is used for defining what will be in the screen while style sheet is used for set Component style. So, in WidSets widget development, we have to modify both helium code and style sheet simultaneously as you might already see in WidSets for Rookie EP 3 : Understand Hello World
Shell is a root of single user interface screen. In other words, Shell is the container of Component(s) to show in screen.
Shell consists of 2 areas, Component Area and Softkey Area.
To hide softkey area, you need to modify openWidget function like this.
Shell openWidget()
{
Flow view = createView("viewMaxi", getStyle("bg"));
Shell shell = new Shell(view);
shell[1].setFlags(FOCUSABLE);
return shell;
}
shell[1] means softkey area. Since softkey area is Component too, so you can use setFlags function to changes it appearance. setFlags(FOCUSABLE) means that you need it focusable but don’t need it to be show since no VISIBLE value is declared in parameter.
On the contrary, if you need to make it visible, just add VISIBLE value to parameter like this.
shell[1].setFlags(VISIBLE | FOCUSABLE);
As I said above, Shell is the container of Component(s) to show in screen. Each Widget can have more than one Shell. To make wanted Shell shows, you have to push it on Shell Stack using pushShell or slideIn and use popShell or slideOut to pop it out from Shell Stack and remove it from screen. More information about these functions is available at #Shell Stack Functions section.
Shell that is on the top of stack will be displayed and receive all available events for example, softkey event, key handling, etc.
This thing is very important for making multiple pages application. However, since the way to create custom Shell is little bit complicate, so I will write about it later in #Custom Shell section.
pushShell(Shell shell);
Push the shell on the stack and make it appear immediately.
Usage:
pushShell (shell);
slideIn(int x, int y, int w, int h, Shell shell);
Parameters:
Push the shell on the stack and make it appear in animated fashion.
Usage:
int w, int h = getScreenSize(); slideIn(w, h, w, h, shell);
Here is the result.
popShell(Shell shell);
Parameters:
Pop the shell on the stack and make it disappear immediately.
Usage:
popShell(shell);
slideOut(int x, int y, int w, int h, Shell shell);
Pop the shell on the stack and make it disappear in animated fashion.
Usage:
int w, int h = getScreenSize(); slideOut(w, h, w, h, shell);
Here is the result.
Flow is a container class for other user interface Components.
Flow is very important for display more than one Component in one page.
Modify createElement function in Hello World source code like this.
Component createElement(String viewName,
String elementName,
Style style,
Object context)
{
if (elementName.equals("hello")) {
Flow content = new Flow(getStyle("default"));
content.setPreferredSize(-100, -100);
return content;
}
return null;
}
The first line is code for creating Flow object. (getStyle("default") will return default Style for Component)
Flow content = new Flow(getStyle("default"));
Resize Flow to fit to screen (100% width and 100% height).
content.setPreferredSize(-100, -100);
Return that Flow and make it being a Component in Shell.
return content;
And this is what you get.
Somebody might get white screen. It’s because of I have modified some stylesheet in widget.xml too. If you need black screen, you have to modify widget.xml like this.
bg {
color-1: white;
background: solid black;
align: hcenter vcenter;
border: 1 1 1 1;
border-type: rectangle white;
}
Next let’s try to add some components in Flow.
Label component shows a single line of text. If the text does not fit the assigned area of Label it is cropped and two dots ("..") are appended to end of cropped text.
Now let’s add some Labels to Flow.
widget.css
<stylesheet>
...
menuHeader {
background: solid #453d74;
align: hcenter vcenter;
color: #FFFFFF;
height: 16px;
}
mainMenuLabel {
background: vgradient #888888 #DDDDDD;
padding: 1 5 1 5;
border: 1 0 0 0;
font-1: small;
color-1: #000000;
focused
{
padding: 1 5 1 5;
border-type: rectangle #b54000;
border: 1 0 0 0;
background: vgradient #f3742e #f35600;
color-1: #ffffff;
}
}
...
</stylesheet>
helium source code
...
const int CMD_LABEL1 = 2;
const int CMD_LABEL2 = 3;
...
if (elementName.equals("hello")) {
Flow content = new Flow(getStyle("default"));
content.setPreferredSize(-100, -100);
{
Label label = new Label(getStyle("menuHeader"), "Main Menu");
label.setPreferredWidth(-100);
label.setFlags(VISIBLE|LINEFEED);
content.add(label);
}
{
Label label = new Label(getStyle("mainMenuLabel"), "I am Label");
label.setPreferredWidth(-100);
label.setFlags(VISIBLE|FOCUSABLE|LINEFEED);
label.setAction(CMD_LABEL1);
content.add(label);
}
{
Label label = new Label(getStyle("mainMenuLabel"), "Me too!");
label.setPreferredWidth(-100);
label.setFlags(VISIBLE|FOCUSABLE|LINEFEED);
label.setAction(CMD_LABEL2);
content.add(label);
}
return content;
}
...
And here is the result.
The first Label, Main Menu, use menuHeader stylesheet. That's why text appears at center of screen (align: hcenter), background color is purple (background: solid #453d74) and text color is white (color: #FFFFFF). Moreover, this Label has been flagged as Unfocusable. So user can’t move focus to this Label. In the other words, it's static Label.
While the other Labels, I am Label and Me too!, use mainMenuLabel stylesheet. That’s why text appears at left of screen (align = left by default), background is gray with vertical gradient (background: vgradient #888888 #DDDDDD) and text color is black by default. One more think that they differ from the first one is they are flagged as FOCUSABLE. So user can move focus on these Labels. As you will see as the orange background color one (as defined in focused part in stylesheet).
When user press joystick at the focused Component, action from that Component will be sent to actionPerformed function via action argument.
void actionPerformed(Shell shell, Component source, int action);
You can handle event from this function, for example.
void actionPerformed(Shell shell, Component source, int action)
{
//when CMD_BACK event comes in, pop the current shell (this widget)
if (action == CMD_BACK) {
popShell(shell);
}
if (action == CMD_LABEL1)
{
setBubble(null, "I am Bubble from I am Label!");
}
if (action == CMD_LABEL2)
{
setBubble(null, " I am Bubble from Me Too!");
}
}
Here is the result.
Remark: setBubble is command for show information note with or without picture.
Ticker implements a "ticker-tape", a piece of text that runs continuously across the component area.
There are some special style customizations for ticker.
widget.xml
<stylesheet>
...
tickerloop {
background: vgradient #888888 #DDDDDD;
color: black;
ticker-speed: 100;
ticker-mode: loop;
focused
{
border-type: rectangle #b54000;
border: 1 0 0 0;
background: vgradient #f3742e #f35600;
color-1: #ffffff;
}
}
tickerbounce {
background: vgradient #888888 #DDDDDD;
color: black;
ticker-speed: 100;
ticker-mode: bounce;
focused
{
border-type: rectangle #b54000;
border: 1 0 0 0;
background: vgradient #f3742e #f35600;
color-1: #ffffff;
}
}
...
</stylesheet>
helium source code
Declare action constant.
const int CMD_TICKER1 = 4;
const int CMD_TICKER2 = 5;
Append these codes after Label “Me Too!” declaration from last example.
...
{
Ticker ticker = new Ticker(getStyle("tickerloop"), "Ticker testing in loop mode");
ticker.setPreferredWidth(-100);
ticker.setFlags(VISIBLE|FOCUSABLE|LINEFEED);
ticker.setAction(CMD_TICKER1);
content.add(ticker);
}
{
Ticker ticker = new Ticker(getStyle("tickerbounce"), "Ticker testing in bounce mode. Hu raaaaa");
ticker.setPreferredWidth(-100);
ticker.setFlags(VISIBLE|FOCUSABLE|LINEFEED);
ticker.setAction(CMD_TICKER2);
content.add(ticker);
}
...
Here is the result.
ITEM_CHANGED will be sent to actionPerformed function when whole loop has been completed in loop mode.
Example:
void actionPerformed(Shell shell, Component source, int action)
{
...
if (action == ITEM_CHANGED && source.getAction() == CMD_TICKER1)
{
source.setText("First Loop Finished");
}
...
}
Result:
Picture component shows a single image. The associated image is accessed with Component.getImage(Image) and Component.setImage(Image) methods.
widget.xml
Prepare small picture (87 x 101 in this example) and name it HelloBubble.jpg. And then, add the img tag inside resources tag.
<resources> ... <img scale="true" src="HelloBubble.jpg"/> </resources>
helium source code
Declare action constant.
const int CMD_PICTURE = 6;
Append these codes after Bounce Ticker declaration from last example.
{
Picture pic = new Picture(getStyle("mainMenuLabel"), getImage("HelloBubble.jpg"));
pic.setPreferredWidth(-100);
pic.setFlags(VISIBLE|FOCUSABLE|LINEFEED);
pic.setAction(CMD_PICTURE);
content.add(pic);
}
Handle event in actionPerformed like Label.
void actionPerformed(Shell shell, Component source, int action)
{
...
if (action == CMD_PICTURE)
{
setBubble(getImage("HelloBubble.jpg"), "I am Bubble!");
}
...
}
Result:
Scrollable contains exactly one child component and provides an ability to scroll it automatically when focus changes or programmatically.
I tried to add one more Picture in Flow but they are not fit in the screen. So I tried to move focus to the second Picture and I found this.
The screen didn’t move down to the focused Component! So Scrollable has been used to solve this issue.
helium source code
Change the following line in createElement
return content;
to
return new Scrollable(getStyle("default"), content) ;
Result:
Text component shows multiple lines of text. Text is wrapped to several lines as needed.
Text Usage is very similar with Label.
widget.xml
<stylesheet>
...
textHeader {
background: solid #453d74;
align: hcenter vcenter;
color: #FFFFFF;
}
...
</stylesheet>
helium source code
Replace Main Menu Label with the following code.
{
Text text = new Text(getStyle("textHeader"), "Standard UI\n-Main Menu-");
text.setPreferredWidth(-100);
text.setFlags(VISIBLE|LINEFEED);
content.add(text);
}
Result:
Input creates text field component used for input. This component always uses native MIDP2 TextBox screen for input.
widget.xml
<stylesheet>
...
input {
background: solid white;
border-type: rectangle black;
padding: 1 5 1 5;
border: 1 1 1 1;
focused
{
padding: 1 5 1 5;
border-type: rectangle #b54000;
border: 1 1 1 1;
background: solid white;
}
}
...
</stylesheet>
helium source code
Append these codes after latest Component declaration.
...
{
String text = "Example Text";
Input input = new Input(getStyle("input"), "Enter Text", text, ANY);
input.setFlags(VISIBLE|FOCUSABLE|LINEFEED);
input.setPreferredWidth(-100);
content.add(input);
}
...
Result:
Choice component gives a user a predefined set of choices to choose from. Individual choices are given as Label components.
widget.xml
<stylesheet>
...
choice {
background: vgradient #888888 #DDDDDD;
label-icon-orientation: right;
focused
{
border-type: rectangle #b54000;
border: 1 0 0 0;
background: vgradient #f3742e #f35600;
color-1: #ffffff;
}
}
choicepopup {
width: 100%;
align: left bottom;
background: solid #385179;
border: 2 2 2 2;
border-type: image "form_choice_bg.png";
padding: 3 3 3 3;
focused
{
border-type: rectangle #b54000;
border: 1 0 0 0;
background: vgradient #f3742e #f35600;
color-1: #ffffff;
}
}
choicesel {
padding: 2 10 2 10;
font: proportional medium bold;
color: white;
label-icon-orientation: right;
focused {
border-type: rectangle #b54000;
border: 1 0 0 0;
background: vgradient #f3742e #f35600;
color-1: #ffffff;
}
}
...
</stylesheet>
helium source code
Append these codes after latest Component declaration.
{
List list = new List();
list.add(new Label(getStyle("choicesel"), "[-Select-]").setFlags(VISIBLE|FOCUSABLE|LINEFEED) );
list.add(new Label(getStyle("choicesel"), "Hello").setFlags(VISIBLE|FOCUSABLE|LINEFEED));
list.add(new Label(getStyle("choicesel"), "World").setFlags(VISIBLE|FOCUSABLE|LINEFEED));
Choice choice = new Choice(getStyle("choice"), getStyle("choicepopup"));
choice.setChoices(list, 0);
choice.setFlags(VISIBLE|FOCUSABLE|LINEFEED);
choice.setPreferredWidth(-100);
content.add(choice);
}
Result:
Stylesheet for Choice is quite complicated. Here is the result and stylesheet indicator.
To create custom Shell, you have to create custom functions to handle Softkey Handler, Action Handler and Menu Handler.
The code below is the template function for Custom Shell.
Shell createSubShell()
{
// Create Flow Component
Flow content = new Flow(getStyle("default"));
content.setPreferredSize(-100, -100);
// Add Component(s)
// Create Shell
Shell shell = new Shell(content);
shell.setStyle(getStyle("bg"));
shell.setActionHandler(customActionHandler);
shell.setSoftKeyHandler(customSoftKeyHandler);
shell.setMenuHandler(customMenuHandler);
MenuItem customSoftKeyHandler(final Shell shell, final Component focused, final int key)
{
if (key == SOFTKEY_BACK) {
return BACK;
}
return null;
}
void customActionHandler(final Shell shell, final Component source, final int action)
{
if (action == CMD_BACK) {
popShell(shell);
}
}
Menu customMenuHandler(Shell shell, Component source)
{
return null;
}
return shell;
}
Define template above as function in Helium source code. Next, make it visible by push created Shell on Shell Stack. Let’s modify actionPerformed function.
void actionPerformed(Shell shell, Component source, int action)
{
..
if (action == CMD_TICKER2)
{
pushShell(createSubShell());
}
..
}
Now, test it!
Result:
I suggest you to try slideIn instead of pushShell. It’s really nice. ;)
int w, int h = getScreenSize();
slideIn(w, h, w, h, shell);
Black screen is not nice. Let's add some Component in Custom Shell by modify createSubShell() function.
...
// Add Component(s)
{
Label label = new Label(getStyle("menuHeader"), "Sub Shell");
label.setPreferredWidth(-100);
label.setFlags(VISIBLE|LINEFEED);
content.add(label);
}
{
Label label = new Label(getStyle("mainMenuLabel"), "Hi! We are in Sub Shell!");
label.setPreferredWidth(-100);
label.setFlags(VISIBLE|FOCUSABLE|LINEFEED);
label.setAction(CMD_LABEL1);
content.add(label);
}
{
Label label = new Label(getStyle("mainMenuLabel"), "Glad to see you!");
label.setPreferredWidth(-100);
label.setFlags(VISIBLE|FOCUSABLE|LINEFEED);
label.setAction(CMD_LABEL2);
content.add(label);
}
...
Result:
Last, handle action by customActionHandler function.
void customActionHandler(final Shell shell, final Component source, final int action)
{
if (action == CMD_BACK) {
popShell(shell);
}
if (action == CMD_LABEL1)
{
setBubble(null, "I am Bubble from SubShell Label!");
}
}
Prompt represents a simple popup with text, optional image and optional progress bar.
This class is generally used as confirmation dialog and progress dialog. Prompt have to create in the same way as Custom Shell. That means you have to create custom function to handle action.
Shell createPrompt()
{
final int CMD_LEFT = 1;
final int CMD_RIGHT = 2;
//softkey labels
MenuItem left = new MenuItem(CMD_LEFT, "Yes!");
MenuItem right = new MenuItem(CMD_RIGHT, "Not sure...");
Prompt prompt = new Prompt(null, "Are you sure?", left, right);
prompt.setProgress(0, 0);
prompt.setActionHandler(customActionHandler);
prompt.push();
void customActionHandler(final Shell shell, final Component source, final int action)
{
if (action == CMD_LEFT || action == CMD_RIGHT) {
popShell(shell);
}
}
return null;
}
Prompt is a little bit different from Custom Shell that Prompt doesn’t need to be pushed on Shell Stack using pushShell or slideIn but it has push function itself. So, you can call this function directly without pushShell. For instance,
...
if (action == CMD_PROMPT)
{
createPrompt();
}
...
Result:
HyperText is multiline text component that supports different text styles and embedded links. All whitespace is treated literally. HyperText requires non-zero preferred width.
widget.xml
<stylesheet>
...
hypertext.b {
color: black;
font: medium bold;
}
hypertext.p {
color: black;
font: medium plain;
}
hypertext.a {
color: blue;
font: medium bold;
focused {
color: orange;
border: 0 0 2 0;
border-type: rectangle orange;
}
}
...
</stylesheet>
helium source code
Append these codes after latest Component declaration.
...
{
HyperText hypertext = new HyperText(getStyle("mainMenuLabel"));
hypertext.setPreferredWidth(-100);
hypertext.appendMarkup("hypertext.", "<p><b>Hello</b> World!\nHow are you?\nI'm fine, thank you, and you?\n<a http://www.forum.nokia.com>Forum Nokia</a></p>");
hypertext.setPreferredHeight(0);
content.add(hypertext);
}
...
Remark:
When user clicked at link in HyperText, OPEN_LINK will be sent to actionPerformed with the link location contains in source.getData(). You can handle event there.
if (action == OPEN_LINK)
{
setBubble(null, "You clicked Link to " + source.getData());
}
Result:
Source code for this tuturial is available at File:WidSets Standard UI.zip.
No related wiki articles found