Well, I cant attach the files. Here is the code:
--------------------------------------------------------
src/org/j4me/ui/Menu.java
--------------------------------------------------------
package org.j4me.ui;
import org.j4me.ui.components.*;
/**
* The <code>Menu</code> class is used for creating the application's
menus.
* <p>
* J2ME devices have small screens and are not all very responsive to
scrolling.
* However, they do have keypads. The <code>Menu</code> class
respects this and
* limits menus to a total of 9 possible choices (1-9) plus "Exit".
Usually all
* the choices can be seen on a single screen and selected with a
single button.
* <p>
* Override this class to change how the menu is painted for your
application.
*/
public class Menu
extends Dialog
{
/**
* The screen that invoked this one or <code>null</code> if there is
no
* previous screen.
*/
protected DeviceScreen previous;
/**
* Constructs a menu.
*/
public Menu ()
{
// No spacing between components.
// The MenuOption component will add spacing for us.
setSpacing( 0 );
// Add the menu bar.
Theme theme = UIManager.getTheme();
String rightMenuText = theme.getMenuTextForOK();
setMenuText( null, rightMenuText );
}
/**
* Constructs a menu.
*
* @param name is the title for this menu, for example "Main Menu".
It
* appears at the top of the screen in the title area.
* @param previous is the screen to return to if the user cancels
this.
*/
public Menu (String name, DeviceScreen previous)
{
this();
this.previous = previous;
setTitle( name );
setPrevious( previous );
}
/**
* Sets the screen to return to if the user cancels this menu. If
* <code>previous</code> is <code>null</code>, there will be no
"Cancel" button.
*
* @param previous is the screen to go to if the user presses
"Cancel".
*/
public void setPrevious (DeviceScreen previous)
{
// Record the previous screen.
this.previous = previous;
// Set the menu text.
Theme theme = UIManager.getTheme();
String leftMenuText = (previous == null ? null :
theme.getMenuTextForCancel());
String rightMenuText = theme.getMenuTextForOK();
setMenuText( leftMenuText, rightMenuText );
}
/**
* Appends a new menu option to this menu.
*
* @param option is the menu item to add.
*/
public void appendMenuOption (MenuItem option)
{
MenuOption choice = new MenuOption( option );
append( choice );
}
/**
* Appends a new menu option to this menu.
*
* @param option is the menu item to add.
*/
public void appendMenuOption (Component option, MenuItemX callable)
{
MenuOptionX choice = new MenuOptionX( option, callable );
append(choice);
}
/**
* Appends a screen as a menu option. If selected the screen will be
* shown. The screen's title is used as its text.
*
* @param option is screen to add as a menu item.
*/
public void appendMenuOption (DeviceScreen option)
{
MenuOption choice = new MenuOption( option );
append( choice );
}
/**
* Appends a screen as a menu option. If selected the screen will be
* shown.
*
* @param text is string that appears in the menu option.
* @param option is screen to add as a menu item.
*/
public void appendMenuOption (String text, DeviceScreen option)
{
MenuOption choice = new MenuOption( text, option );
append( choice );
}
/**
* Appends another menu as a menu option. The submenu will have an
* arrow next to it to indicate to the user it is another menu.
* <p>
* To use a <code>Menu</code> as a screen and not a submenu call the
* <code>appendMenuOption</code> method instead.
*
* @param submenu is the screen to add as a menu item.
*/
public void appendSubmenu (Menu submenu)
{
MenuOption choice = new MenuOption( submenu, true );
append( choice );
}
/**
* The left menu button takes the user back to the previous screen.
* If there is no previous screen it has no effect.
*/
protected void declineNotify ()
{
// Go back to the previous screen.
if ( previous != null )
{
previous.show();
}
// Continue processing the event.
super.declineNotify();
}
/**
* The right menu button selects the highlighted menu item.
*/
protected void acceptNotify ()
{
// Go to the highlighted screen.
int highlighted = getSelected();
selection( highlighted );
// Continue processing the event.
super.acceptNotify();
}
/**
* Responds to key press events that are specific to menu screens.
* Selects the highlighted menu choice if the joystick's
* <code>FIRE</code> key is pressed. Scrolls from the last choice to
* the first choice if <code>DOWN</code> is pressed and from the
first to
* the last if <code>UP</code> is pressed.
*
* @param key is the key code of the button the user pressed.
*/
protected void keyPressed (int key)
{
boolean goToFirst = false;
boolean goToLast = false;
// Wrap the scroll around the screen?
if ( key == DOWN )
{
if ( getSelected() == size() - 1 )
{
// Go to the first menu choice.
goToFirst = true;
}
}
else if ( key == UP )
{
if ( (getSelected() == 0) && (size() > 1) )
{
// Go to the last menu choice.
goToLast = true;
}
}
// Process the key event.
super.keyPressed( key );
// Were we going to the first or last menu choice?
// Only do these after super.keyPressed(). Otherwise
// keyPressed() will scroll again so we'll actually wind
// up on the second or second-to-last menu choice.
if ( goToFirst )
{
setSelected( 0 );
}
else if ( goToLast )
{
setSelected( size() - 1 );
}
}
/**
* Selects a menu item.
*
* @param selection is the index of <code>choice</code> that is
selected.
*/
private void selection (int selection)
{
Component component = get( selection );
if ( component instanceof MenuOption )
{
MenuOption chosen = (MenuOption)component;
// Record this as the selection.
setSelected( selection );
// Perform the selection operation.
chosen.select();
}
else if ( component instanceof MenuOptionX )
{
MenuOptionX chosen = (MenuOptionX)component;
// Record this as the selection.
setSelected( selection );
// Perform the selection operation.
chosen.select();
}
}
}
--------------------------------------------------------
--------------------------------------------------------
src/org/j4me/ui/MenuItemX.java
--------------------------------------------------------
package org.j4me.ui;
/**
* Implementing classes can be used as menu choices that draw
themselves in a <code>Menu</code>.
*/
public interface MenuItemX
{
/**
* Called when the user selects this choice from the menu.
*/
public void onSelection ();
}
--------------------------------------------------------
--------------------------------------------------------
src/org/j4me/ui/components/MenuOptionX.java
--------------------------------------------------------
package org.j4me.ui.components;
import javax.microedition.lcdui.*;
import org.j4me.ui.*;
/**
* The <code>Menu</code> screen uses one of these <code>MenuOption</
code> components
* for each menu choice.
* <p>
* The default implementation shows the choice number on the left,
then
* the text for the choice, and an arrow on the right if it is a
submenu.
* The text is clipped if it runs over a single line. This keeps all
* menu items the same height.
*
* @see Menu
*/
public class MenuOptionX
extends Component
{
/**
* The number of pixels that separates the text and submenu
* indicator from the left and right edges of the component.
* Increasing this number reduces the width of usuable space
* to write the menu choice's text.
*/
private static final int HORIZONTAL_MARGIN = 3;
/**
* The number of pixels that separate the text from the top
* and bottom of the menu indicator. Increasing this value
* also increases the spacing between menu items by a factor
* of two (i.e. the bottom of this one plus top of the next).
*/
private static final int VERTICAL_MARGIN = HORIZONTAL_MARGIN;
/**
* The <code>MenuItem</code> encapsulated by this component. If this
* component is for a <code>DeviceScreen</code> option, this will be
* <code>null</code>.
*/
private final MenuItemX menuItem;
private final Component component;
/**
* Creates a new <code>MenuOptionX</code> component that encapsulates
a
* <code>MenuItem</code>.
*
* @param choice is the command that is represented by this
component.
*/
public MenuOptionX (Component component, MenuItemX choice)
{
if ( choice == null )
{
throw new IllegalArgumentException("choice cannot be null");
}
this.menuItem = choice;
this.component= component;
}
/**
* An event raised whenever the component is made visible on the
screen.
* This is called before the <code>paintComponent</code> method.
*/
protected void showNotify ()
{
component.visible(true);
// Continue processing the event.
super.showNotify();
}
/**
* An event raised whenever the component is removed from the screen.
*/
protected void hideNotify ()
{
// Pass the event to contained components.
component.visible( false );
// Continue processing the event.
super.hideNotify();
}
/**
* Paints a <code>MenuOption</code>. On the left is the choice
number in
* a box. The middle has the text for the choice. If it is a
submenu
* the right has an arrow.
*
* @param g is the <code>Graphics</code> object to paint with.
* @param theme is the application's theme used to paint the menu
item.
* @param width is the width of the menu item area in pixels.
* @param height is the height of the menu item area in pixels.
* @param selected is <code>true</code> if this is the currently
highlighted
* menu choice.
*
* @see org.j4me.ui.components.Component#paintComponent
(javax.microedition.lcdui.Graphics, org.j4me.ui.Theme, int, int,
boolean)
*/
protected void paintComponent (Graphics g, Theme theme, int width,
int height, boolean selected)
{
component.paintComponent(g, theme, width, height, selected);
}
/**
* Returns the size of the menu choice. It will be one line of text
* high and as wide as the screen.
*
* @see org.j4me.ui.components.Component#getPreferredComponentSize
(org.j4me.ui.Theme, int, int)
*/
public int[] getPreferredComponentSize (Theme theme, int
viewportWidth, int viewportHeight)
{
return component.getPreferredComponentSize(theme, viewportWidth,
viewportHeight);
}
/**
* @return <code>true</code> because this component accepts user
input.
*/
public boolean acceptsInput ()
{
return true;
}
public void select(){
if (null != menuItem){
menuItem.onSelection();
}
}
/**
* Called when the user presses any key.
*
* @param key is code of the key that was pressed.
*
* @see Component#keyPressed(int)
*/
public void keyPressed (int key)
{
// The joystick's fire button means to select this item.
if ( key == DeviceScreen.FIRE )
{
select();
}
else
{
component.keyPressed(key);
}
super.keyPressed(key);
//component.keyPressed(key);
// Continue processing the key event.
//super.keyPressed( key );
}
/**
* Called when the pointer is pressed.
*
* @param x is the horizontal location where the pointer was pressed
* relative to the top-left corner of the component.
* @param y is the vertical location where the pointer was pressed
* relative to the top-left corner of the component.
*/
public void pointerPressed (int x, int y)
{
// If anywhere on the menu item is pressed it has been selected.
select();
//component.pointerPressed(x, y);
// Continue processing the pointer event.
super.pointerPressed( x, y );
}
}
--------------------------------------------------------
--------------------------------------------------------
examples/org/j4me/examples/ui/UIDemoMidlet.java
--------------------------------------------------------
package org.j4me.examples.ui;
import java.io.IOException;
import javax.microedition.lcdui.Graphics;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
import org.j4me.examples.ui.components.CheckBoxExample;
import org.j4me.examples.ui.components.ContainerComponentX;
import org.j4me.examples.ui.components.LabelExample;
import org.j4me.examples.ui.components.LabelX;
import org.j4me.examples.ui.components.PictureExample;
import org.j4me.examples.ui.components.PictureX;
import org.j4me.examples.ui.components.ProgressBarExample;
import org.j4me.examples.ui.components.RadioButtonExample;
import org.j4me.examples.ui.components.ScrollbarExample;
import org.j4me.examples.ui.components.TextBoxExample;
import org.j4me.examples.ui.themes.ConsoleTheme;
import org.j4me.examples.ui.themes.GreenTheme;
import org.j4me.examples.ui.themes.RedTheme;
import org.j4me.ui.Menu;
import org.j4me.ui.MenuItem;
import org.j4me.ui.Theme;
import org.j4me.ui.UIManager;
import org.j4me.ui.components.Label;
/**
* The demonstration MIDlet for the J4ME UI.
*/
public class UIDemoMidlet
extends MIDlet
{
/* (non-Javadoc)
* @see javax.microedition.midlet.MIDlet#startApp()
*/
protected void startApp () throws MIDletStateChangeException
{
// Initialize the J4ME UI manager.
UIManager.init( this );
// The theme is the default represented <code>Theme</code> class.
// To change it, create a new <code>Theme</code>-derived object and
call
// <code>UIManager.setTheme</code>.
// The first screen is a menu to choose among the example screens.
Menu menu = new Menu( "UI Examples", null );
// Create a submenu for showing component example screens.
Menu componentExampleMenu = new Menu( "Component Examples", menu );
menu.appendSubmenu( componentExampleMenu );
LabelExample labelExample = new LabelExample
( componentExampleMenu );
componentExampleMenu.appendMenuOption( labelExample );
ProgressBarExample progressBarExample = new ProgressBarExample
( componentExampleMenu );
componentExampleMenu.appendMenuOption( progressBarExample );
// ---------------- This draws a picture only as menu item
try {
PictureX pic = new PictureX();
pic.setHorizontalAlignment( Graphics.HCENTER );
pic.setImage("/J4ME.png");
componentExampleMenu.appendMenuOption(pic,pic);
} catch (Exception e) {
e.printStackTrace();
}
// ----------------
TextBoxExample textBoxExample = new TextBoxExample
( componentExampleMenu );
componentExampleMenu.appendMenuOption( textBoxExample );
RadioButtonExample radioButtonExample = new RadioButtonExample
( componentExampleMenu );
componentExampleMenu.appendMenuOption( radioButtonExample );
// ---------------- This draws a label with an icon as menu item
try {
PictureX pic = new PictureX();
pic.setHorizontalAlignment( Graphics.HCENTER );
pic.setImage("/J4ME.png");
Label lb= new Label();
lb.setLabel("000");
lb.setHorizontalAlignment(Graphics.HCENTER);
ContainerComponentX cc= new ContainerComponentX
(ContainerComponentX.LAYOUT_HORIZONTAL);
cc.paintBg(true);
//cc.setKnowHowToPaintBg(false);
cc.append(pic);
cc.append(lb);
componentExampleMenu.appendMenuOption(cc,cc );
}catch (Exception e) {
e.printStackTrace();
}
// ----------------
CheckBoxExample checkBoxExample = new CheckBoxExample
( componentExampleMenu );
componentExampleMenu.appendMenuOption( checkBoxExample );
ScrollbarExample scrollbarExample = new ScrollbarExample
( componentExampleMenu );
componentExampleMenu.appendMenuOption( scrollbarExample );
// ---------------- This draws 3 icons, each one with a label below.
// each icon/label can be selected with the left/right arrows
try {
// label+icon 1
PictureX pic1 = new PictureX();
pic1.setHorizontalAlignment( Graphics.HCENTER );
pic1.setImage("/J4ME.png");
LabelX lb1= new LabelX();
lb1.setLabel("111");
lb1.setHorizontalAlignment(Graphics.HCENTER);
ContainerComponentX cc1= new ContainerComponentX
(ContainerComponentX.LAYOUT_VERTICAL);
cc1.paintBg(true);
cc1.append(pic1);
cc1.append(lb1);
// label+icon 2
PictureX pic2 = new PictureX();
pic2.setHorizontalAlignment( Graphics.HCENTER );
pic2.setImage("/tt.png");
Label lb2= new Label();
lb2.setLabel("222");
lb2.setHorizontalAlignment(Graphics.HCENTER);
ContainerComponentX cc2= new ContainerComponentX
(ContainerComponentX.LAYOUT_VERTICAL);
cc2.paintBg(true);
cc2.append(pic2);
cc2.append(lb2);
// label+icon 3
PictureX pic3 = new PictureX();
pic3.setHorizontalAlignment( Graphics.HCENTER );
pic3.setImage("/J4ME.png");
Label lb3= new Label();
lb3.setLabel("333");
lb3.setHorizontalAlignment(Graphics.HCENTER);
ContainerComponentX cc3= new ContainerComponentX
(ContainerComponentX.LAYOUT_VERTICAL);
cc3.paintBg(true);
cc3.append(pic3);
cc3.append(lb3);
// add all the label/icons in the same menu item row
ContainerComponentX cc4= new ContainerComponentX
(ContainerComponentX.LAYOUT_HORIZONTAL);
cc4.paintBg(false);
cc4.setHorizontalAlignment(Graphics.HCENTER);
cc4.append(cc1);
cc4.append(cc2);
cc4.append(cc3);
componentExampleMenu.appendMenuOption( cc4, cc4 );
} catch (IOException e) {
e.printStackTrace();
}
PictureExample pictureExample = new PictureExample
( componentExampleMenu );
componentExampleMenu.appendMenuOption( pictureExample );
// Create a submenu showing different example themes.
Menu themesMenu = new Menu( "Themes", menu );
menu.appendSubmenu( themesMenu );
ThemeMenuItem defaultTheme = new ThemeMenuItem( "Blue (Default)",
new Theme() );
themesMenu.appendMenuOption( defaultTheme );
ThemeMenuItem greenTheme = new ThemeMenuItem( "Green", new GreenTheme
() );
themesMenu.appendMenuOption( greenTheme );
ThemeMenuItem redTheme = new ThemeMenuItem( "Red", new RedTheme() );
themesMenu.appendMenuOption( redTheme );
ThemeMenuItem consoleTheme = new ThemeMenuItem( "Console", new
ConsoleTheme() );
themesMenu.appendMenuOption( consoleTheme );
// Attach the examples.
KeyCode keyCode = new KeyCode( menu );
menu.appendMenuOption( keyCode );
EtchASketch etchAsketch = new EtchASketch( menu );
menu.appendMenuOption( etchAsketch );
Stopwatch stopwatch = new Stopwatch( menu );
menu.appendMenuOption( stopwatch );
// Attach an exit option.
menu.appendMenuOption( new MenuItem()
{
public String getText ()
{
return "Exit";
}
public void onSelection ()
{
UIDemoMidlet.this.notifyDestroyed();
}
} );
// Show the menu.
menu.show();
}
/* (non-Javadoc)
* @see javax.microedition.midlet.MIDlet#pauseApp()
*/
protected void pauseApp ()
{
// The application has no state so ignore pauses.
}
/* (non-Javadoc)
* @see javax.microedition.midlet.MIDlet#destroyApp(boolean)
*/
protected void destroyApp (boolean cleanup) throws
MIDletStateChangeException
{
// The application holds no resources that need cleanup.
}
}
/**
* Options available from a menu that change the application's theme.
*/
class ThemeMenuItem
implements MenuItem
{
private final String name;
private final Theme theme;
public ThemeMenuItem (String name, Theme theme)
{
this.name = name;
this.theme = theme;
}
public String getText ()
{
// The name as it appears in the menu.
return name;
}
public void onSelection ()
{
// Applies a theme to the example midlet.
UIManager.setTheme( theme );
// Repaint the screen so the changes take effect.
UIManager.getScreen().repaint();
}
}
---------------------------------------------------
---------------------------------------------------
examples/org/j4me/examples/ui/components/ContainerComponent.java (not
mine)
---------------------------------------------------
package org.j4me.examples.ui.components;
/**
* Copied from Jean-Marie Hermelin's post:
*
http://groups.google.com/group/j4me/browse_thread/thread/59fcd040065b9986
* Changed private to protected in selectNextComponent. rafa.
*
*/
import java.util.Enumeration;
import java.util.Vector;
import javax.microedition.lcdui.Graphics;
import org.j4me.ui.DeviceScreen;
import org.j4me.ui.Theme;
import org.j4me.ui.UIManager;
import org.j4me.ui.components.Component;
public class ContainerComponent extends Component {
/**
* The collection of all components on this form. Components are
displayed
* as ordered from top to bottom.
*/
private Vector components = new Vector();
/**
* The index of <code>component</code> the user currently has
highlighted.
* If this is not an index of <code>component</code> nothing is
highlighted.
*/
private int highlightedComponent = -1;
/**
* The number of pixels above and below components.
*/
private int spacing = 1;
/**
* the location { x, y, width, height} of the components
*/
private int[][] location;
/**
* the actual preferred size for this component
*/
private int[] _preferredSize;
/**
* Vertical Layout FLAG
*/
public static final int LAYOUT_VERTICAL = 0;
/**
* Horizontal Layout FLAG
*/
public static final int LAYOUT_HORIZONTAL = 1;
/**
* actual layout
*/
private int _layout = LAYOUT_VERTICAL;
/**
* Implicitly called by derived classes to setup a new J4ME form.
* @param _layout
*/
public ContainerComponent(int layout) {
super();
_layout = layout;
visible(true);
}
/**
* Called immediately before this screen is replaced by another
screen.
* <p>
* Notifies all the components they are hidden. Classes that
override
* this method should be sure to call <code>super.onDeselection</
code>.
*
* @see DeviceScreen#hideNotify()
*/
public void hideNotify() {
// Hide all the components on the screen.
Enumeration e = components.elements();
while (e.hasMoreElements()) {
Component c = (Component) e.nextElement();
c.visible(false);
}
// Continue deselection.
super.hideNotify();
}
/**
* Adds the <code>component</code> to the end of this form.
*
* @param component is the UI component to add to the bottom of the
form.
*/
public void append(Component component) {
clearLayout();
components.addElement(component);
}
/**
* Inserts the <code>component</code> in this form at the specified
<code>index</code>.
* Each component on this form with an index greater or equal to the
* specified <code>index</code> is shifted upward to have an index
one greater
* than the value it had previously.
*
* @param component is the UI component to insert.
* @param index is where to insert <code>component</code> on the
form. It must
* greater than or equal to 0 and less than or equal to the number
of
* components already on the form.
* @throws ArrayIndexOutOfBoundsException if the index was invalid.
*/
public void insert(Component component, int index) {
clearLayout();
components.insertElementAt(component, index);
}
/**
* Sets the <code>component</code> in this form at the specified
<code>index</code>.
* The previous component at that position is discarded.
*
* @param component is the UI component to set to.
* @param index is where to set <code>component</code> on the form.
It must
* greater than or equal to 0 and less than the number of
* components already on the form.
* @throws ArrayIndexOutOfBoundsException if the index was invalid.
*/
public void set(Component component, int index) {
clearLayout();
components.setElementAt(component, index);
}
/**
* Removes the first occurrence of the <code>component</code> from
this form.
* If <code>component</code> is found on this form, each component on
the form
* with an index greater or equal to the <code>component</code>'s
index is
* shifted downward to have an index one smaller than the value it
had
* previously.
*
* @param component is the UI component to remove.
*/
public void delete(Component component) {
int index = components.indexOf(component);
delete(index);
}
/**
* Deletes the <code>component</code> at the specified <code>index</
code>. Each
* component in this vector with an index greater or equal to the
* specified index is shifted downward to have an index one smaller
* than the value it had previously.
*
* @param index is the index of the component to remove. It must be
* a value greater than or equal to 0 and less than the current
* number of components on the form.
* @throws ArrayIndexOutOfBoundsException if the index was invalid.
*/
public void delete(int index) {
clearLayout();
components.removeElementAt(index);
if (highlightedComponent == index) {
highlightedComponent = -1;
} else if (highlightedComponent > index) {
highlightedComponent--;
}
}
/**
* Removes all of the components from this form.
*/
public void deleteAll() {
clearLayout();
components.removeAllElements();
highlightedComponent = -1;
}
/**
* Returns an enumeration of the components on this form.
*
* @return An enumeration of the components on this form.
*/
public Enumeration components() {
clearLayout();
return components.elements();
}
/**
* Returns the number of components on this form.
*
* @return The number of components on this form.
*/
public int size() {
return components.size();
}
/**
* Returns the component at the specified index.
*
* @param index is the value into the component list to get.
* @return The component at <code>index</code> or <code>null</code>
if the
* index is invalid.
*/
public Component get(int index) {
Component c = null;
if ((index >= 0) && (index < components.size())) {
c = (Component) components.elementAt(index);
}
return c;
}
/**
* Returns the index of the currently selected component. It is
* the one the user can currently enter data into.
*
* @return The index of the component on the form that is currently
* selected.
*/
public int getSelected() {
if (highlightedComponent < 0) {
return 0;
} else {
return highlightedComponent;
}
}
/**
* Returns the index of the component that contains the given pixel.
* If no component is at that location, for example it is in the
* spacing between components, then <code>-1</code> is returned.
* <p>
* This method assumes that the click is relative to the form
* area. It may not address the title bar, menu bar, or a
* scroll bar.
*
* @param x is the X-coordinate of the pixel on the form.
* @param y is the Y-coordinate of the pixel on the form.
* @return The index of the component containing the pixel
* (<code>x</code>, <code>y</code>) or <code>-1</code> if no
component contains it.
*/
private int getAt(int x, int y) {
int matched = -1;
// Get the absolute position of y on the form.
int absY = getY() + y;
int absX = getX() + x;
// Walk the list of component positions until absY is found.
for (int i = 0; i < components.size(); i++) {
// Get the dimensions of this component.
Component c = (Component) components.elementAt(i);
int top = c.getY();
int bottom = top + c.getHeight();
int left = c.getX();
int right = left + c.getWidth();
// Does the point fall within this component?
if ((absY >= top) && (absY < bottom) && (absX >= left) && (absX <
right)) {
// This is the component that (x, y) falls within.
matched = i;
break;
}
}
return matched;
}
/**
additionnaly I modify the Dialog.getAt method to behave on absolute
coordinates (this is mandatory if you want the pointer to react as
expected)
private int getAt (int x, int y)
{
Enumeration elts = components.elements();
int count = 0;
while(elts.hasMoreElements())
{
Component c = (Component) elts.nextElement();
int top = c.getY();
int bottom = top+c.getHeight();
int left = c.getX();
int right = c.getWidth();
// Does the point fall within this component?
if ( (y >= top) && (y < bottom) &&
(x >= left) && (x < right) )
{
// This is the component that (x, y) falls within.
return count;
}
count++;
}
return -1;
}
*/
/**
* Sets the selected component. It is the one the user can input
* data into and that the screen is scrolled to.
*
* @param index is the new selected component.
*/
public void setSelected(int index) {
if ((index < 0) || (index >= components.size())) {
throw new IndexOutOfBoundsException(String.valueOf(index));
}
highlightedComponent = index;
}
/**
* Sets the selected component. It is the one the user can input
* data into and that the screen is scrolled to.
*
* @param component is the new selected component. If it is not
* on the form this has no effect.
*/
public void setSelected(Component component) {
int index = 0;
// Walk the list of components until we find it.
Enumeration e = components.elements();
while (e.hasMoreElements()) {
Component c = (Component) e.nextElement();
if (c == component) {
// This is the component.
break;
}
index++;
}
// Set the component as the selected one.
if (index < size()) {
setSelected(index);
}
}
/**
* Returns the vertical spacing between components.
*
* @return The number of pixels that vertically separate components.
*/
public int getSpacing() {
return spacing;
}
/**
* Sets the vertical spacing between components.
*
* @param spacing is the number of pixels that vertically separates
* components. Values less than 0 are be ignored.
*/
public void setSpacing(int spacing) {
if ((spacing >= 0) && (this.spacing != spacing)) {
this.spacing = spacing;
// Recalculate the layout with the new spacings later.
clearLayout();
}
}
/**
* Whenever the form is altered this method should be called to clear
* the layout. The layout will be re-established during the next
painting.
*/
private synchronized void clearLayout() {
location = null;
_preferredSize = null;
}
/**
* Goes through all of the components and determines their vertical
* positioning. The form's overall height, the sum of all the
* components, is set in the <code>height</code> member variable.
*
* @param theme is the application's current <code>Theme</code>.
* @param widht is the number of pixels wide the screen is.
* @param height is the number of pixels high the screen is.
*/
private synchronized int[] calculateLayout(Theme theme, int width,
int height) {
_preferredSize = new int[] { 0, 0 };
//Log.info("Container " + width + "," + height);
location = new int[components.size()][4];
// Scroll through the components determining the vertical position
of each one.
Enumeration list = components.elements();
int top = 0;
int left = 0;
for (int i = 0; list.hasMoreElements(); i++) {
// Calculate the position of the next component.
Component c = (Component) list.nextElement();
int[] dimensions = c.getPreferredSize(theme, width, height);
location[i][0] = left;
location[i][1] = top;
location[i][2] = dimensions[0];
location[i][3] = dimensions[1];
//Log.info("Component " + c + "," + location[i][0] + "," + location
[i][1] + "," + location[i][2] + "/" + width+"," + location[i][3]);
if (_layout == LAYOUT_HORIZONTAL) {
left += dimensions[0] + spacing;
if ((dimensions[1] + top) > _preferredSize[1])
_preferredSize[1] = dimensions[1] + top ;
_preferredSize[0] = left ;
} else if (_layout == LAYOUT_VERTICAL) {
top += dimensions[1] + spacing;
if ((dimensions[0] + left) > _preferredSize[0])
_preferredSize[0] = dimensions[0] + left ;
_preferredSize[1] = top ;
}
// Is this the first component that can be highlighted?
if (highlightedComponent < 0) {
if (c.acceptsInput()) {
highlightedComponent = i;
}
}
}
//Log.info("Container Size " + _preferredSize[0] + "," +
_preferredSize[1]);
return _preferredSize;
}
/**
* Forces the layout of all components to be recalculated. This
should
* be called whenever this screen or its components are altered. For
* example changing a label may change its size and this method will
* account for that.
*/
public void invalidate() {
// Remove the layout of all components.
clearLayout();
// Recalculate the position of all components.
calculateLayout(UIManager.getTheme(), getWidth(), getHeight());
}
/**
*
*
*
* @param down is <code>true</code> when the form should scroll down
and
* <code>false</code> when it should scroll up.
*/
protected boolean selectNextComponent(boolean down) {
// Get the dimensions of the current highlighted component.
//int current = (highlightedComponent >= 0 ? highlightedComponent :
0);
// Get the next component that can be highlighted.
int nextHighlighted = highlightedComponent;
if (down) {
int max = size();
for (int i = highlightedComponent + 1; i < max; i++) {
Component c = get(i);
if (c.acceptsInput()) {
nextHighlighted = i;
break;
}
}
} else // up
{
for (int i = highlightedComponent - 1; i >= 0; i--) {
Component c = get(i);
if (c.acceptsInput()) {
nextHighlighted = i;
break;
}
}
}
boolean modified = (highlightedComponent != nextHighlighted);
// Change the highlighted component.
highlightedComponent = nextHighlighted;
// Redraw the component
//Log.info("repaint" + this + " [" + getX() + "," + getY() + "," +
getWidth() + "," + getHeight() +"]");
repaint();
//UIManager.getScreen().repaint();
return modified;
}
/**
* Called when a key is pressed. It can be identified using the
* constants defined in this class.
*
* @param keyCode is the key code of the key that was pressed.
*/
public void keyPressed(int keyCode) {
// Forward the event to the current component.
Component c = get(highlightedComponent);
if (c != null) {
c.keyPressed(keyCode);
return;
}
// Scrolling vertically?
if (keyCode == DeviceScreen.UP) {
selectNextComponent(false);
} else if (keyCode == DeviceScreen.DOWN) {
selectNextComponent(true);
}
// Continue processing the event.
super.keyPressed(keyCode);
}
/**
* Called when a key is repeated (held down). It can be identified
using the
* constants defined in this class.
*
* @param keyCode is the key code of the key that was held down.
*/
public void keyRepeated(int keyCode) {
// Forward the event to the current component.
Component c = get(highlightedComponent);
if (c != null) {
c.keyRepeated(keyCode);
return ;
}
// Continue processing the event.
super.keyRepeated(keyCode);
}
/**
* Called when a key is released. It can be identified using the
* constants defined in this class.
*
* @param keyCode is the key code of the key that was released.
*/
public void keyReleased(int keyCode) {
// Forward the event to the current component.
Component c = get(highlightedComponent);
if (c != null) {
c.keyReleased(keyCode);
return ;
}
// Continue processing the event.
super.keyReleased(keyCode);
}
/**
* Called when the pointer is pressed.
*
* @param x is the horizontal location where the pointer was pressed.
* @param y is the vertical location where the pointer was pressed.
*/
public void pointerPressed(int x, int y) {
// Highlight the component.
highlightedComponent = getAt(x, y);
// Forward the event to the component for processing.
Component c = get(highlightedComponent);
if (c != null) {
// Adjust the click position relative to the component.
int px = x - location[highlightedComponent][0];
int py = y - location[highlightedComponent][1];
c.pointerPressed(px, py);
return;
}
// Continue processing the event.
super.pointerPressed(x, y);
}
/**
* Called when the pointer is dragged.
*
* @param x is the horizontal location where the pointer was dragged.
* @param y is the vertical location where the pointer was dragged.
*/
public void pointerDragged(int x, int y) {
// Forward the event to the current component.
Component c = get(highlightedComponent);
if (c != null) {
c.pointerDragged(x, y);
return;
}
// Continue processing the event.
super.pointerDragged(x, y);
}
public int[] getPreferredComponentSize(Theme theme, int
viewportWidth, int viewportHeight) {
return calculateLayout(theme, viewportWidth, viewportHeight);
}
protected void paintComponent(Graphics g, Theme theme, int width, int
height, boolean selected) {
//Log.info("PAINT" + " [" + g.getTranslateX() + "," +
g.getTranslateY() + "," + getWidth() + "," + getHeight() +"]");
//Log.info("paint container " + width +"," + height);
if (selected && components.size() == 0)
paintRect(g, theme, 0, 0, width, height, selected);
// Walk the list of components and paint them.
int formWidth = getWidth();
int topOfComponent = getY();
int bottomOfComponent = topOfComponent + height;
int left = 0;
switch (getHorizontalAlignment()) {
case Graphics.HCENTER:
left = (width - _preferredSize[0]) / 2;
break;
case Graphics.RIGHT:
left = width - _preferredSize[0];
break;
default:
break;
}
for (int i = 0; i < components.size(); i++) {
Component c = (Component) components.elementAt(i);
c.visible(true);
boolean cselected = (i == highlightedComponent) && selected;
int cwidth = location[i][2];
int cheight = location[i][3];
if (_layout == LAYOUT_HORIZONTAL)
cheight = height;
else
cwidth = width;
if((cwidth + location[i][0])> width)
cwidth = width-location[i][0];
if((cheight+location[i][1]) > height)
cheight = height-location[i][1];
c.paint(g, theme, getScreen(), location[i][0]+left, location[i][1],
cwidth, cheight, cselected);
}
}
public boolean acceptsInput() {
Enumeration elts = components.elements();
while(elts.hasMoreElements())
{
if(( (Component)elts.nextElement()).acceptsInput())
return true;
}
return false;
}
}
---------------------------------------------------
---------------------------------------------------
examples/org/j4me/examples/ui/components/ContainerComponentX.java
---------------------------------------------------
package org.j4me.examples.ui.components;
import javax.microedition.lcdui.Graphics;
import org.j4me.ui.DeviceScreen;
import org.j4me.ui.MenuItemX;
import org.j4me.ui.Theme;
import org.j4me.ui.UIManager;
import org.j4me.ui.components.Component;
public class ContainerComponentX extends ContainerComponent implements
MenuItemX {
private static final int HORIZONTAL_MARGIN = 3;
private static final int VERTICAL_MARGIN = 3;
/**
* Implicitly called by derived classes to setup a new J4ME form.
* @param _layout
*/
public ContainerComponentX(int layout) {
super(layout);
}
/**
*
*
*
* @param down is <code>true</code> when the form should scroll down
and
* <code>false</code> when it should scroll up.
*/
// I must overload this, because repaint() -in super- do nothing as
screen is null.
// I should investigate why.
protected boolean selectNextComponent(boolean down) {
boolean modified = super.selectNextComponent(down);
if (modified)
{
// Dont know why can't just call super.repaint();
UIManager.getScreen().repaint();
}
return modified;
}
/**
* Called when a key is pressed. It can be identified using the
* constants defined in this class.
*
* @param keyCode is the key code of the key that was pressed.
*/
public void keyPressed(int keyCode) {
System.err.println("ContainerComponent keyPressed " + keyCode);
// Scrolling vertically?
if (keyCode == DeviceScreen.LEFT) {
selectNextComponent(false);
} else if (keyCode == DeviceScreen.RIGHT) {
selectNextComponent(true);
} else {
// Forward the event to the current component.
Component c = get(getSelected());
if (c != null) {
c.keyPressed(keyCode);
return;
}
}
// Continue processing the event.
super.keyPressed(keyCode);
}
public boolean acceptsInput() {
return true;
}
private boolean paintBg= false;
public boolean paintBg() {
return paintBg;
}
public void paintBg(boolean knowHowToPaintBg) {
this.paintBg = knowHowToPaintBg;
}
protected void paintComponent (Graphics g, Theme theme, int width,
int height, boolean selected)
{
// Paint the background for the menu item.
if ( selected && paintBg)
{
int backgroundColor = theme.getHighlightColor();
g.setColor( backgroundColor );
g.fillRect( 0, 0, width, height );
super.paintComponent(g, theme, width-HORIZONTAL_MARGIN, height-
VERTICAL_MARGIN, selected);
}
else
{
super.paintComponent(g, theme, width, height, selected);
}
}
public void onSelection() {
//System.err.println("**** CntainerComponent onSelectcion");
Component c = get(getSelected());
if (c != null) {
if (c instanceof MenuItemX) {
MenuItemX cc = (MenuItemX) c;
cc.onSelection();
}
else
{
c.keyPressed(DeviceScreen.FIRE);
}
return;
}
}
}
---------------------------------------------------
---------------------------------------------------
examples/org/j4me/examples/ui/components/LabelX.java
---------------------------------------------------
package org.j4me.examples.ui.components;
import org.j4me.ui.MenuItemX;
import org.j4me.ui.components.Label;
public class LabelX extends Label implements MenuItemX {
public void onSelection() {
System.err.println("LabelX was selected: " + getLabel());
}
/**
* Needed when used inside a ContainerComponentX
*/
public boolean acceptsInput() {
return true;
}
}
---------------------------------------------------
---------------------------------------------------
examples/org/j4me/examples/ui/components/PictureX.java
---------------------------------------------------
package org.j4me.examples.ui.components;
import javax.microedition.lcdui.Graphics;
import org.j4me.ui.MenuItemX;
import org.j4me.ui.Theme;
import org.j4me.ui.components.Picture;
public class PictureX extends Picture implements MenuItemX {
private static final int HORIZONTAL_MARGIN = 3;
private static final int VERTICAL_MARGIN = 3;
protected synchronized void paintComponent(Graphics g, Theme theme,
int width, int height, boolean selected) {
if ( selected)
{
int backgroundColor = theme.getHighlightColor();
g.setColor( backgroundColor );
g.fillRect( 0, 0, width, height );
super.paintComponent(g, theme, width-HORIZONTAL_MARGIN, height-
VERTICAL_MARGIN, selected);
}
else
{
super.paintComponent(g, theme, width, height, selected);
}
}
/**
* Needed when used inside a ContainerComponentX
*/
public boolean acceptsInput() {
return true;
}
public void onSelection() {
System.err.println("PictureX was selected ");
}
}
---------------------------------------------------
Rafa