package javax.microedition.lcdui;
import java.util.ArrayList;
/**
*
* @author Andre Nijholt
*/
public class Form extends Screen implements CommandListener {
private static final Command EDIT_COMMAND = new Command(1, Command.SCREEN, 0);
private ItemStateListener itemStateListener;
private ArrayList<Object> items = new ArrayList<Object>();
private int curItemIdx = 0;
private boolean selectedItem;
private int height;
private int width;
private TextBox editBox;
public Form(String title) {
this.title = title;
editBox = new TextBox(null, null, 0, TextField.ANY);
editBox.setCommandListener(this);
editBox.addCommand(EDIT_COMMAND);
}
public Form(String title, Item[] items) {
this.title = title;
for (int i = 0; (items != null) && (i < items.length); i++) {
this.items.add(items[i]);
}
}
public int append(Image img) {
items.add(img);
return (items.size() - 1);
}
public int append(Item item) {
items.add(item);
return (items.size() - 1);
}
public int append(String str) {
items.add(str);
return (items.size() - 1);
}
public void delete(int itemNum) {
items.remove(itemNum);
}
public void deleteAll() {
items.clear();
}
public Object get(int itemNum) {
return items.get(itemNum);
}
public void set(int itemNum, Item item) {
items.set(itemNum, item);
}
public void insert(int itemNum, Item item) {
items.add(itemNum, item);
}
public int getHeight() {
return height;
}
public int getWidth() {
return width;
}
public int size() {
return items.size();
}
public void setItemStateListener(ItemStateListener i) {
this.itemStateListener = i;
}
protected void callItemStateListener() {
Object o = items.get(curItemIdx);
if ((itemStateListener != null) && (o instanceof Item)) {
itemStateListener.itemStateChanged((Item) o);
}
}
protected void keyPressed(int keyCode) {
if (selectedItem && curItemIdx >= 0) {
if ((keyCode == Screen.KEY_RIGHT)
|| (keyCode == Screen.KEY_LEFT)
|| (keyCode == Screen.KEY_ENTER)) {
// Update currently selected item
((Item) items.get(curItemIdx)).keyPressed(keyCode);
} else if (keyCode == Screen.KEY_BACK) {
Object o = items.get(curItemIdx);
if (o instanceof TextField) {
// Update currently selected TextField until keyboard enter pressed
editBox.keyPressed(keyCode);
} else {
// Notify item changed and leave current selection
callItemStateListener();
selectedItem = false;
}
}
} else {
// Select new item
if (keyCode == Screen.KEY_RIGHT) {
for (int i = curItemIdx + 1; i != curItemIdx; i++) {
// Wrap when last item checked
if (i >= items.size()) {
i = 0;
}
Object o = items.get(i);
if ((o instanceof Item) && (((Item) o).isInteractive())) {
curItemIdx = i;
break;
}
}
} else if (keyCode == Screen.KEY_LEFT) {
for (int i = curItemIdx - 1; i != curItemIdx; i--) {
// Wrap when first item checked
if (i < 0) {
i = (items.size() - 1);
}
Object o = items.get(i);
if ((o instanceof Item) && (((Item) o).isInteractive())) {
curItemIdx = i;
break;
}
}
} else if (keyCode == Screen.KEY_BACK) {
for (int i = 0; i < commands.size(); i++) {
callCommandListener();
}
} else if (keyCode == Screen.KEY_ENTER) {
Object o = items.get(curItemIdx);
if (o instanceof TextField) {
// Show text box for editing
editBox.setTitle(((TextField) o).getLabel());
editBox.setText(((TextField) o).getText());
editBox.setMaxSize(((TextField) o).getMaxSize());
editBox.setConstraints(((TextField) o).getConstraints());
Display.getDisplay().setCurrent(editBox);
} else {
// Set current selection
selectedItem = true;
}
}
}
repaint();
}
public void commandAction(Command c, Displayable d) {
if ((c == EDIT_COMMAND) && (d == editBox)) {
// Update textfield and return to form display
TextField tf = (TextField) items.get(curItemIdx);
tf.setText(editBox.getText());
callItemStateListener();
Display.getDisplay().setCurrent(this);
}
}
public void paint(Graphics g) {
int curX = 0;
int curY = 0;
int curWidth;
int curHeight;
ChoiceGroup activePopup = null;
int popupX = 0;
int popupY = 0;
// Draw title on entire line
if (title != null) {
g.drawString(title, 0, 0);
curY += Display.CHAR_HEIGHT;
}
// Draw all items
for (int i = 0; i < items.size(); i++) {
// Calculate position and size for current item
curWidth = getItemWidth(i);
curHeight = getItemHeight(i);
if (((curX + curWidth) < Display.SCREEN_WIDTH)
&& ((curX + curWidth + getItemWidth(i + 1)) > Display.SCREEN_WIDTH)) {
// Next item doesn't fit on current line: allow entire line for current item
curWidth = Display.SCREEN_WIDTH - curX;
}
// Draw current item
Object o = items.get(i);
if (o instanceof Image) {
g.drawImage((Image) o, curX, curY, false);
} else if (o instanceof String) {
g.drawString(((String) o), curX, curY);
} else if (o instanceof Item) {
((Item) o).paint(g, curX, curY, curWidth, curHeight, (i == curItemIdx));
if (selectedItem && (i == curItemIdx) && (o instanceof ChoiceGroup)
&& (((ChoiceGroup) o).choiceType == Choice.POPUP)) {
// Draw popup window again after all items drawn
activePopup = (ChoiceGroup) o;
popupX = curX;
popupY = curY;
}
}
if ((curX + curWidth) < Display.SCREEN_WIDTH) {
// Draw next item on current line
curX += curWidth;
if (curHeight > Display.CHAR_HEIGHT) {
curY += (curHeight - Display.CHAR_HEIGHT);
}
} else {
// Start new line and draw item
curX = 0;
curY += curHeight;
}
}
// Draw popup menu above currently drawn items
if (activePopup != null) {
int popupHeight = ((activePopup.label != null) ? Display.CHAR_HEIGHT : 0)
+ (activePopup.size() * Display.CHAR_HEIGHT);
if ((popupY + popupHeight) > Display.SCREEN_HEIGHT) {
popupHeight = Display.SCREEN_HEIGHT - popupY;
}
activePopup.paint(g, popupX, popupY, activePopup.getMinimumWidth(),
popupHeight, true);
}
}
private int getItemWidth(int itemIdx) {
if (itemIdx >= items.size()) {
return 0;
}
Object o = items.get(itemIdx);
if (o instanceof Image) {
return ((Image) o).getWidth();
} else if (o instanceof String) {
return ((String) o).length() * Display.CHAR_WIDTH;
} else if (o instanceof Item) {
return Math.max(((Item) o).getMinimumWidth(), ((Item) o).getPreferredWidth());
}
return 0;
}
private int getItemHeight(int itemIdx) {
if (itemIdx >= items.size()) {
return 0;
}
Object o = items.get(itemIdx);
int height = 0;
if (o instanceof Image) {
height = ((Image) o).getHeight();
} else if (o instanceof String) {
// Always single line string
height = Display.CHAR_HEIGHT;
} else if (o instanceof Item) {
height = Math.max(((Item) o).getMinimumHeight(), ((Item) o).getPreferredHeight());
}
// Round to multiple of line height
height = (((height + Display.CHAR_HEIGHT - 1) / Display.CHAR_HEIGHT)) * Display.CHAR_HEIGHT;
return height;
}
}