package javax.microedition.lcdui;
import java.util.ArrayList;
/**
*
* @author Andre Nijholt
*/
public class ChoiceGroup extends Item implements Choice {
protected int choiceType;
protected ArrayList<ChoiceItem> choiceItems;
// private int fitPolicy;
/** Scrolling administration */
private int scrollFirst = 0;
private int scrollCurr = 0;
private int scrollLast = 0;
private boolean scrollWrap = true;
public ChoiceGroup(String label, int choiceType) {
if (choiceType == Choice.IMPLICIT) {
// Type IMPLICIT not allowed
throw new IllegalArgumentException();
}
this.label = label;
this.choiceType = choiceType;
choiceItems = new ArrayList<ChoiceItem>();
interactive = true;
if (label != null) {
// Only show label or first item when POPUP list is used
minWidth = (label.length() * Display.CHAR_WIDTH);
minHeight = ((choiceType == Choice.POPUP) ? 1 : 2) * Display.CHAR_HEIGHT;
} else {
minWidth = Display.CHAR_WIDTH;
minHeight = Display.CHAR_HEIGHT;
}
}
public ChoiceGroup(String label, int choiceType, String[] stringElements, Image[] imageElements) {
if (choiceType == Choice.IMPLICIT) {
// Type IMPLICIT not allowed
throw new IllegalArgumentException();
}
this.label = label;
this.choiceType = choiceType;
interactive = true;
if (label != null) {
minWidth = (label.length() * Display.CHAR_WIDTH);
minHeight = 2 * Display.CHAR_HEIGHT;
} else {
minWidth = Display.CHAR_WIDTH;
minHeight = Display.CHAR_HEIGHT;
}
choiceItems = new ArrayList<ChoiceItem>(stringElements.length);
for (int i = 0; i < stringElements.length; i++) {
choiceItems.add(new ChoiceItem(
((stringElements != null) && (stringElements.length < i))
? stringElements[i] : null,
((imageElements != null) && (imageElements.length < i))
? imageElements[i] : null));
// Update minimum width
int itemWidth = (((stringElements != null) && (stringElements.length < i))
? stringElements[i].length() * Display.CHAR_WIDTH : 0)
+ (((imageElements != null) && (imageElements.length < i))
? imageElements[i].getWidth() : 0);
if (itemWidth > minWidth) {
minWidth = itemWidth;
}
scrollLast++;
}
}
public int append(String stringPart, Image imagePart) {
// Add item and update minimum size
choiceItems.add(new ChoiceItem(stringPart, imagePart));
int itemWidth = ((stringPart != null) ? stringPart.length() * Display.CHAR_WIDTH : 0)
+ ((imagePart != null) ? imagePart.getWidth() : 0);
if (itemWidth > minWidth) {
minWidth = itemWidth;
}
scrollLast++;
return choiceItems.size();
}
public void delete(int elementNum) {
scrollLast--;
choiceItems.remove(elementNum);
}
public void deleteAll() {
scrollLast = 0;
choiceItems.clear();
}
// TODO: FitPolicy currently not supported: no wrapping allowed
// public int getFitPolicy() {
// return fitPolicy;
// }
//
// public void setFitPolicy(int fitPolicy) {
// this.fitPolicy = fitPolicy;
// }
// TODO: Multiple fonts currently not supported
// public Font getFont(int elementNum) {
// return ((ListItem) listItems.get(elementNum)).font;
// }
//
// public void setFont(int elementNum, Font font) {
// ((ListItem) listItems.get(elementNum)).font = font;
// }
public Image getImage(int elementNum) {
return choiceItems.get(elementNum).img;
}
public int getSelectedFlags(boolean[] selectedArray_return) {
selectedArray_return = new boolean[choiceItems.size()];
for (int i = 0; i < selectedArray_return.length; i++) {
selectedArray_return[i] = choiceItems.get(i).selected;
}
return selectedArray_return.length;
}
public int getSelectedIndex() {
for (int i = 0; i < choiceItems.size(); i++) {
if (choiceItems.get(i).selected) {
return i;
}
}
return -1;
}
public String getString(int elementNum) {
return choiceItems.get(elementNum).str;
}
public void insert(int elementNum, String stringPart, Image imagePart) {
choiceItems.add(elementNum, new ChoiceItem(stringPart, imagePart));
}
public boolean isSelected(int elementNum) {
return choiceItems.get(elementNum).selected;
}
public void set(int elementNum, String stringPart, Image imagePart) {
choiceItems.set(elementNum, new ChoiceItem(stringPart, imagePart));
}
public void setScrollWrap(boolean scrollWrap) {
this.scrollWrap = scrollWrap;
}
public void setSelectedFlags(boolean[] selectedArray) {
for (int i = 0; i < choiceItems.size(); i++) {
choiceItems.get(i).selected = selectedArray[i];
}
}
public void setSelectedIndex(int elementNum, boolean selected) {
if ((choiceType == Choice.MULTIPLE) || !selected) {
// Just set/clear selection
choiceItems.get(elementNum).selected = selected;
} else {
// Set single selection for these types
for (int i = 0; i < choiceItems.size(); i++) {
ChoiceItem li = choiceItems.get(i);
li.selected = (i == elementNum);
}
}
}
public int size() {
return choiceItems.size();
}
protected void keyPressed(int keyCode) {
if (keyCode == Screen.KEY_RIGHT) {
if (scrollWrap) {
scrollCurr = (scrollCurr + 1) % choiceItems.size();
} else if (scrollCurr < (choiceItems.size() - 1)) {
scrollCurr++;
}
repaint();
} else if (keyCode == Screen.KEY_LEFT) {
if (scrollWrap) {
scrollCurr = (scrollCurr == 0)
? (choiceItems.size() - 1) : (scrollCurr - 1);
} else if (scrollCurr > 0) {
scrollCurr--;
}
repaint();
} else if (keyCode == Screen.KEY_BACK) {
// BACK key has no function
} else if (keyCode == Screen.KEY_ENTER) {
ChoiceItem li = choiceItems.get(scrollCurr);
setSelectedIndex(scrollCurr, !li.selected);
notifyStateChanged();
}
}
protected void paint(Graphics g, int x, int y, int w, int h, boolean selected) {
if (label != null) {
g.drawString(label, x, y,
(selected && (choiceType == Choice.POPUP)));
y += Display.CHAR_HEIGHT;
h -= Display.CHAR_HEIGHT;
}
if (h <= 0) {
// No items allowed to draw (especially for POPUP)
return;
}
// Update scrolling administration
int scrollLines = h / Display.CHAR_HEIGHT;
if (scrollCurr == 0) {
// Init top item
scrollFirst = 0;
scrollLast = scrollLines;
} else if ((choiceItems.size() >= scrollLines)
&& (scrollCurr >= (choiceItems.size() - 1))) {
// Init bottom item
scrollFirst = choiceItems.size() - scrollLines;
scrollLast = choiceItems.size() - 1;
} else if (scrollCurr >= scrollLast) {
scrollFirst++;
scrollLast++;
} else if (scrollCurr < scrollFirst) {
scrollFirst--;
scrollLast--;
}
// TODO: Drawing a rectangle around menu would be nice, but is very slow
// if (choiceType == Choice.POPUP) {
// g.drawRect(x, y, w, h);
// }
// Display list items with current highlighted
int xOffset = (choiceType == Choice.POPUP) ? x : (x + 2 * Display.CHAR_WIDTH);
for (int i = scrollFirst; (i < choiceItems.size()) && (i <= scrollLast); i++) {
ChoiceItem li = choiceItems.get(i);
g.drawString(li.str, xOffset, y,
(selected && (i == scrollCurr)));
if ((choiceType == Choice.EXCLUSIVE) || (choiceType == Choice.MULTIPLE)) {
// Draw selection state
if (li.selected) {
g.fillArc(x, y, 8, 8, 0, 360);
} else {
g.drawArc(x, y, 8, 8, 0, 360);
}
// } else if (choiceType == Choice.POPUP) {
// TODO Filling remaing text withing rectangle is even slower...
// for (int j = li.str.length(); j < (w * Display.CHAR_WIDTH); j++) {
// g.drawChar(' ', xOffset + li.str.length() * Display.CHAR_WIDTH,
// y / Display.CHAR_HEIGHT, (i == scrollCurr));
// }
}
y += Display.CHAR_HEIGHT;
h -= Display.CHAR_HEIGHT;
if (h <= 0) {
// No more items allowed
break;
}
}
}
private class ChoiceItem {
String str;
Image img;
boolean selected;
// Font font;
ChoiceItem(String stringPart, Image imagePart) {
this.str = stringPart;
this.img = imagePart;
this.selected = false;
// this.font = null;
}
}
}