/* Copyright (c) 2008 Bluendo S.r.L. * See about.html for details about license. * * $Id: UILayout.java 1471 2009-05-13 21:35:41Z luca $ */ package it.yup.ui; import javax.microedition.lcdui.Canvas; import javax.microedition.lcdui.Graphics; public abstract class UILayout extends UIItem implements UIIContainer { public static final int CONSTRAINT_PIXELS = 0; public static final int CONSTRAINT_PERCENTUAL = 1; protected int selectedIndex = -1; /** * Shows if a layout has been focused and hence its children can receive a * keypress */ boolean layoutFocused = false; /** * a "grouped" Layout shows a border when selected and needs the FIRE * pressed to enter inside. A non-grouped layout does not need the user to * press FIRE to navigate inside the items. A Layout is grouped by default */ private boolean group; /** * The layout elements. */ protected UIItem[] layoutItems; /* * The keys used by subclasses to move (Canvas.LEFT, Canvas.RIGHT , etc...) */ protected int dirKey1 = 0; protected int dirKey2 = 1; public UILayout(int elemNumber) { this.layoutItems = new UIItem[elemNumber]; this.focusable = false; group = true; } public void setSelected(boolean _selected) { if (_selected == selected) return; selected = _selected; setDirty(true); /* when losing selection, remove selection from last selected item */ if (!selected && selectedIndex >= 0 && selectedIndex < layoutItems.length) { layoutItems[selectedIndex].setSelected(false); } if (!selected) { layoutFocused = false; } if (!group && selected) { layoutFocused = true; if (selectedIndex == -1) { do { selectedIndex++; } while (selectedIndex < layoutItems.length && !layoutItems[selectedIndex].isFocusable()); } if (selectedIndex >= 0 && selectedIndex < layoutItems.length) { layoutItems[selectedIndex].setSelected(true); } } /* * select=true on a non-group layout: choose the first selectable item * select=false on a non-group layout: remove selection from current * item select=true on a group layout: just set layoutFocused to true. * select=false on a group layour: set layoutFocused to false */ } /** * Overrides the default behaviour dispatching the screen to all the items * contained * * @param _us * the screen to use */ public void setScreen(UIScreen _us) { screen = _us; for (int i = 0; i < layoutItems.length; i++) { if (layoutItems[i] != null) layoutItems[i].setScreen(screen); } } /** * Set the {@link UIScreen} to be repainted. * * @param dirty * The new value for dirty. */ public void setDirty(boolean dirty) { // this.height = -1; // this.width = -1; this.dirty = dirty; for (int i = 0; i < this.layoutItems.length; i++) this.layoutItems[i].setDirty(dirty); } /** * Set the {@link UIScreen} to be repainted. * * @param dirty * The new value for dirty. */ public boolean isDirty() { // this.height = -1; // this.width = -1; for (int i = 0; i < this.layoutItems.length; i++) if (this.layoutItems[i].isDirty()) return true; if (this.dirty) return true; return false; } protected void updateChildren() { for (int i = 0; i < this.layoutItems.length; i++) { if (this.selectedIndex != i) { this.layoutItems[i].setSelected(false); } } this.layoutItems[this.selectedIndex].setSelected(true); this.setDirty(true); this.askRepaint(); } public UIItem getItem(int position) { return this.layoutItems[position]; } public boolean isFocusable() { for (int i = 0; i < this.layoutItems.length; i++) { if (layoutItems[i].isFocusable()) { return true; } } return focusable; } int traverseFocusable(int startingIndex, boolean directionDown) { if (startingIndex < 0) { startingIndex = 0; } if (directionDown) { while (startingIndex < this.layoutItems.length && this.layoutItems[startingIndex].isFocusable() == false) { startingIndex++; } if (startingIndex >= this.layoutItems.length) return -1; else return startingIndex; } else { while (startingIndex >= 0 && this.layoutItems[startingIndex].isFocusable() == false) { startingIndex--; } if (startingIndex < 0) return -1; else return startingIndex; } } protected void drawSegmentedBorder(Graphics g, int w, int h) { g.setColor(0x223377); // g.setColor(UIScreen.bg_color); // int segmentLength = 2; // for (int i = 0; i < w; i += 2 * segmentLength) { // g.drawLine(i, 0, i + segmentLength, 0); // g.drawLine(i, h - 1, i + segmentLength, h - 1); // } // for (int i = 0; i < h; i += 2 * segmentLength) { // g.drawLine(0, i, 0, i + segmentLength); // g.drawLine(w - 1, i, w - 1, i + segmentLength); // } int oldSTroke = g.getStrokeStyle(); g.setStrokeStyle(Graphics.DOTTED); g.drawRect(0, 0, w - 1, h - 1); g.setStrokeStyle(oldSTroke); } /** * Sets this layout as grouped * * @param group * {@code true} if the lyout is grouped, {@code false} otherwise */ public void setGroup(boolean group) { this.group = group; } /** * @return if this layout is grouped */ public boolean isGroup() { return group; } /** * Return the selected UIItem within the UIItem itself; usually it is the * UIItem itself but in the subclasses (like UIVLayout) it could be one of * the contained object. * * @return */ public UIItem getSelectedItem() { // if (this.group == false) // return this; if (this.selectedIndex >= 0 && this.layoutItems.length >= (this.selectedIndex + 1)) { return this.layoutItems[this.selectedIndex].getSelectedItem(); } else { return this; } } public void setSelectedIndex(int index) { if (index >= 0 && index < this.layoutItems.length) this .setSelectedItem(this.layoutItems[index]); else this.selectedIndex = index; } /** * Return the selected UIItem within the UIItem itself; usually it is the * UIItem itself but in the subclasses (like UIVLayout) it could be one of * the contained object. * * @return */ public void setSelectedItem(UIItem item) { for (int i = 0; i < layoutItems.length; i++) { if (this.layoutItems[i] == item) { if (this.selectedIndex >= 0 && this.selectedIndex < layoutItems.length) { this.layoutItems[selectedIndex].setSelected(false); } this.selectedIndex = i; if (this.layoutItems[selectedIndex].isSelected() == false) { this.layoutItems[selectedIndex].setSelected(true); } } } if (this.getContainer() != null) { this.getContainer().setSelectedItem(this); } } public boolean contains(UIItem item) { for (int i = 0; i < this.layoutItems.length; i++) { UIItem ithItem = layoutItems[i]; if (ithItem == item) return true; if (ithItem instanceof UIIContainer) { UIIContainer iic = (UIIContainer) ithItem; if (iic.contains(item)) return true; } } return false; } public void setBg_color(int bg_color) { this.bg_color = bg_color; for (int i = 0; i < layoutItems.length; i++) { UIItem ithLayout = layoutItems[i]; ithLayout.setBg_color(bg_color); } } public boolean keyPressed(int key) { // first forward the keyPressed!!!! if (selectedIndex >= 0 && selectedIndex < this.layoutItems.length && layoutFocused && layoutItems[selectedIndex].keyPressed(key)) { // this is needed since we cannot know if anything below has been // repainted updateChildren(); return true; } int ga = UICanvas.getInstance().getGameAction(key); if (layoutFocused) { if (ga == dirKey1) { if (this.selectedIndex > 0) { int newSelectedIndex = this.selectedIndex - 1; if (this.isFocusable()) newSelectedIndex = traverseFocusable( newSelectedIndex, false); if (newSelectedIndex >= 0) this.selectedIndex = newSelectedIndex; else return false; updateChildren(); return true; } return false; } else if (ga == dirKey2) { if (this.selectedIndex < this.layoutItems.length - 1) { int newSelectedIndex = this.selectedIndex + 1; if (this.isFocusable()) newSelectedIndex = traverseFocusable( newSelectedIndex, true); if (newSelectedIndex >= 0) this.selectedIndex = newSelectedIndex; else return false; updateChildren(); return true; } return false; } } if ((key == UICanvas.MENU_RIGHT || ga == Canvas.FIRE)) { if (this.isFocusable()) { this.layoutFocused = true; int oldSelectedIndex = selectedIndex; selectedIndex = traverseFocusable(selectedIndex, true); if (selectedIndex >= 0 && oldSelectedIndex != selectedIndex) { this.layoutItems[selectedIndex].setSelected(true); updateChildren(); return true; } } } return false; } }