/* Copyright (c) 2008 Bluendo S.r.L.
* See about.html for details about license.
*
* $Id: UIItem.java 1577 2009-06-15 14:38:27Z luca $
*/
/**
*
*/
package it.yup.ui;
//#mdebug
//@
//@import it.yup.util.Logger;
//@
//#enddebug
import javax.microedition.lcdui.Graphics;
/**
* Un generico Item della lista contenuta in un {@link UIScreen}.
*
* XXX: forse sarebbe meglio trasformarlo in una interfaccia e non farlo classe
* astratta?
*/
public abstract class UIItem {
/*
* Constants used to draw the borders of the UIItem
*/
public static final int OUTER_UP = 0;
public static final int INNER_UP = 1;
public static final int INNER_DOWN = 2;
public static final int OUTER_DOWN = 3;
private int gradientColor = -1;
private int gradientSelectedColor = -1;
/**
* The type of column or row in a {@link UILayout} (can be
* UIHLayout.CONSTRAINT_PIXELS or UIHLayout.CONSTRAINT_PERCENTUAL).
*/
private int type;
/**
* The width to keep within the layout.
*
*/
private int layoutWidth;
/**
* The height to keep within the layout.
*
*/
private int layoutHeight;
/** flag che indica se l'item e' stato selezionato */
protected boolean selected;
/** lo schermo che contiene questo item */
protected UIScreen screen;
/**
* Identify if the item can obtain focus and hence be selected.
*/
protected boolean focusable = false;
/**
* The height of the {@link UIItem}
*/
protected int height = -1;
/**
* The width of the {@link UIItem}
*/
protected int width = -1;
/** The submenu associated with this item */
private UIMenu subMenu;
/*
* The container of this object
*/
private UIIContainer container = null;
/**
* Each UIItem will use a bg_color to draw its background; if bg_color is a
* valid color then bg_color will be used to paint otherwise
* UIConfig.bg_color will be used.
*/
int bg_color = -1;
int fg_color = -1;
int selectedColor = -1;
/*
* A status used to carry data between object accesses (like MFC visual objects status)
*/
private Object status = null;
/**
* @return the status
*/
public Object getStatus() {
return status;
}
/**
* @param status the status to set
*/
public void setStatus(Object status) {
this.status = status;
}
/**
* @return the type
*/
public int getType() {
return type;
}
/**
* @return the layoutWidth
*/
public int getLayoutWidth() {
return layoutWidth;
}
/**
* @return the layoutHeight
*/
public int getLayoutHeight() {
return layoutHeight;
}
/**
* @return the submenu
*/
public UIMenu getSubmenu() {
return subMenu;
}
/**
* @return Set the submenu
*/
public void setSubmenu(UIMenu subMenu) {
this.subMenu = subMenu;
}
/**
* Constructor.
*/
public UIItem() {
}
/**
* Asks the screen that contains this {@link UIItem} to repaint itself and
* hence this item.
*
* @return
*/
protected boolean askRepaint() {
if (this.screen != null) {
this.screen.askRepaint();
return true;
}
return false;
}
/**
* This value keeps information about the fact that the item should be
* repainted or not.
*/
protected boolean dirty = true;
/*
* The coordinates at which the Item painted last time:
* coors[0]: X
* coors[1]: Y
* coors[2]: Width
* coors[3]: Height
*/
int[] coors = new int[4];
/**
* imposta lo schermo che contiene questo item.
*/
public void setScreen(UIScreen _us) {
screen = _us;
if (subMenu != null) {
subMenu.setScreen(screen);
}
}
public UIScreen getScreen() {
return screen;
}
/**
* @return la dimensione dell'item o -1 se l'item deve utilizzare tutta la
* larghezza disponibile dello schermo
*/
public int getWidth() {
return this.width;
}
/**
* Called when a key is pressed over this {@link UIItem}
*
* @param ka
* The key that is pressed.
* @return true if the {@link UIItem} needs to have the selection after the
* keyPressed (for example a radio button or a list would need the
* selection multiple times); false otherwise
*/
public boolean keyPressed(int key) {
return false;
}
public void setWidth(int width) {
this.width = width;
}
/**
* @return The height of the item
* @param g
* the {@link Graphics} on which to paint into
*/
public int getHeight(Graphics g) {
return this.height;
}
/**
* imposta l'Item come selezionato
*
* @param _selected
* {@code true} se l'item � stato selezionato, {@code false} se
* non � stato selezionato.
*/
public void setSelected(boolean _selected) {
this.dirty = true;
if (_selected && (this.focusable || this.subMenu != null)) selected = true;
else
selected = false;
}
/**
* @return {@code true} if the item is selected, {@code false} otherwhise.
*/
public boolean isSelected() {
return selected;
}
/**
* Impone di disegnare l'elemento usando il contesto grafico e mantenendo le
* dimensioni in quelle fornite.
*
* XXX: nota, tramite le chiamate {@link Graphics#translate(int, int)} �
* possibile fare in modo che l'item si disegni a partire dalle coordinate
* (0, 0). Sarebbe carino fare in modo che (visto che assumiamo 1 item = 1
* riga) l'item o ritornasse o spostasse lo (0, 0) del {@link Graphics} per
* indicare la propria dimensione. E' vero che ci sono delle interessanti
* chiamate {@link #getItemHeight()} e {@link #getItemWidth()} che
* dovrebbero essere vincolanti, ma non sarebbe male se l'item invece si
* "accomodasse su una riga intera" fornendo indietro poi le dimensioni che
* ha usato.
*
* @param g
* il contesto grafico da usare per disegnare l'item
* @param w
* la larghezza massima del box in cui deve stare l'oggetto
* @param h
* l'altezza massima del box in cui deve stare l'oggetto
*/
protected abstract void paint(Graphics g, int w, int h);
/**
* This is the paint method invoked by the Screen, it will dispatch to the
* {@link #paint(Graphics, int, int)} method overridden by the item.
*/
public final void paint0(Graphics g, int w, int h) {
// first save the clip and coordinate status
int originalX = g.getTranslateX();
int originalY = g.getTranslateY();
int originalClipX = g.getClipX();
int originalClipY = g.getClipY();
int originalClipWidth = g.getClipWidth();
int originalClipHeight = g.getClipHeight();
this.setWidth(w);
// UIMenu computes its clip by itself
if (this instanceof UIMenu == false) g.clipRect(0, 0, w, h);
// notify the screen my coordinates
coors[0] = originalX;
coors[1] = originalY;
coors[2] = g.getClipWidth();
// items can be painted in space lower than h or their clip
coors[3] = g.getClipHeight();
if (this.screen != null) {
this.screen.addPaintedItem(this);
}
// then draw it and catch any eventual exception
try {
paint(g, w, h);
} catch (Exception e) {
// #mdebug
//@ System.out.println(e);
//@ e.printStackTrace();
//@ System.out.println("In paint0: " + e.getMessage());
//@ Logger.log("In paint0:" + e.getMessage());
// #enddebug
}
this.dirty = false;
// and reset the original values
g.translate(originalX - g.getTranslateX(), originalY
- g.getTranslateY());
g.setClip(originalClipX, originalClipY, originalClipWidth,
originalClipHeight);
if (this instanceof UIMenu == false && this.subMenu != null
&& this.selected == true) {
this.subMenu.setAbsoluteX(g.getTranslateX() + 10);
this.subMenu.setAbsoluteY(g.getTranslateY() + 2);
this.subMenu.setWidth(w - 20);
}
}
/**
* If true then the UIItem should be repainted.
*
* @return
*/
public boolean isDirty() {
return dirty;
}
/*
* draw the borders of UIItem
*
* @param g
* the {@link Graphics} on which to paint into
*
* @param rect
* the coordinate of the rectangle to paint in this order: X0,Y0,X1,Y1,
*
* @param colors
* the colors used to paint the borders in this order (and -1 is the transparent color): OUTER_UP,INNER_UP, INNER_DOWN,OUTER_DOWN,
*
* @param colors
* the color matrix for the upper left corner (will be mirrored to be painted in all other corners) and -1 is the transparent color
*
*/
protected void drawBorder(Graphics g, int[] rect, int[] colors,
int[][] border) {
int oldColor = g.getColor();
int x0 = rect[0], y0 = rect[1], x1 = rect[2], y1 = rect[3];
// This block is a condensed way of doing the next commented
// block
int[] color_mappings = new int[] { y0, x0, y0 + 1, x0 + 1, y1 - 1,
x1 - 1, y1, x1 };
for (int i = OUTER_UP; i <= OUTER_DOWN; i++) {
int ithColor = colors[i];
if (ithColor >= 0) {
g.setColor(ithColor);
g.drawLine(x0 + 2, color_mappings[2 * i], x1 - 2,
color_mappings[2 * i]);
g.drawLine(color_mappings[2 * i + 1], y0 + 2,
color_mappings[2 * i + 1], y1 - 2);
}
}
// if (colors[OUTER_UP]>=0){
// g.setColor(colors[OUTER_UP]);
// g.drawLine(x0+2,y0,x1-2,y0);
// g.drawLine(x0,y0+2,x0,y1-2);
// }
// if (colors[INNER_UP]>=0){
// g.setColor(colors[INNER_UP]);
// g.drawLine(x0+2,y0+1,x1-2,y0+1);
// g.drawLine(x0+1,y0+2,x0+1,y1-2);
// }
// if (colors[INNER_DOWN]>=0){
// g.setColor(colors[INNER_DOWN]);
// g.drawLine(x0+2,y1-1,x1-2,y1-1);
// g.drawLine(x1-1,y0+2,x1-1,y1-2);
// }
// if (colors[OUTER_DOWN]>=0){
// g.setColor(colors[OUTER_DOWN]);
// g.drawLine(x0+2,y1,x1-2,y1);
// g.drawLine(x1,y0+2,x1,y1-2);
// }
for (int i = 0; i <= 2; i++) {
for (int j = 0; j <= 2; j++) {
int colorij = border[i][j];
if (colorij >= 0) {
g.setColor(colorij);
drawPixel(g, i + x0, j + y0);
drawPixel(g, x1 - i, j + y0);
drawPixel(g, x0 + i, y1 - j);
drawPixel(g, x1 - i, y1 - j);
}
}
}
g.setColor(oldColor);
}
protected void drawPixel(Graphics g, int x, int y) {
g.drawLine(x, y, x, y);
}
protected void drawInput(Graphics g, int x0, int y0, int x1, int y1) {
int oldColor = g.getColor();
g.setColor(UIConfig.input_color);
g.fillRect(x0 + 1, y0 + 1, x1 - x0 - 1, y1 - y0 - 1);
int selColor = isSelected() ? UIConfig.tbs_color : -1;
int colors[] = new int[] { UIConfig.tbb_color, selColor, selColor,
UIConfig.tbb_color };
int border[][] = new int[][] {
new int[] { -1, UIConfig.tbb_color, -1 },
new int[] { UIConfig.tbb_color, selColor, -1 },
new int[] { -1, -1, -1 }, };
drawBorder(g, new int[] { x0, y0, x1, y1 }, colors, border);
g.setColor(oldColor);
}
// protected void drawBorder(Graphics g, int x0, int y0, int x1, int y1) {
// g.setColor(UIConfig.tbb_color);
// g.drawLine(x0 + 1, y0, x1 - 1, y0);
// g.drawLine(x1, y0 + 1, x1, y1 - 1);
// g.drawLine(x1 - 1, y1, x0 + 1, y1);
// g.drawLine(x0, y1 - 1, x0, y0 + 1);
// g.setColor(UIConfig.input_color);
// g.fillRect(x0 + 1, y0 + 1, x1 - x0 - 2, y1 - y0 - 2);
// if (this.isSelected()) {
// g.setColor(UIConfig.tbs_color);
// g.drawRect(x0 + 1, y0 + 1, x1 - x0 - 2, y1 - y0 - 2);
// }
// }
/**
* Set the {@link UIScreen} to be repainted.
*
* @param dirty
* The new value for dirty.
*/
public void setDirty(boolean dirty) {
this.dirty = dirty;
// this.height = -1;
// this.width = -1;
}
/**
* @return the focusable
*/
public boolean isFocusable() {
// an UIItem can be focusable or have a subMenu
// in both cases it must be "focusable" from outside
return focusable || this.subMenu != null;
}
/**
* @param focusable
* the focusable to set
*/
public void setFocusable(boolean focusable) {
this.focusable = focusable;
}
/**
* @param layoutWidth
* the layoutWidth to set
*/
public void setLayoutWidth(int layoutWidth) {
this.layoutWidth = layoutWidth;
}
/**
* @param type
* the type to set
*/
public void setType(int type) {
this.type = type;
}
/**
* @param layoutHeight
* the layoutHeight to set
*/
public void setLayoutHeight(int layoutHeight) {
this.layoutHeight = layoutHeight;
}
/**
* Return the selected UIItem within the UIItem itselft; usually it is the
* UIItem itself but in the subclasses (like UIVLayout) it could one of the
* contained object.
*
* @return
*/
public UIItem getSelectedItem() {
return this;
}
/**
* @param bg_color
* the bg_color to set
*/
public void setBg_color(int bg_color) {
this.bg_color = bg_color;
}
/**
* @return the bg_color
*/
public int getBg_color() {
return bg_color;
}
/**
* @param bg_color
* the bg_color to set
*/
public void setFg_color(int fg_color) {
this.fg_color = fg_color;
}
/**
* @return the bg_color
*/
public int getFg_color() {
return fg_color;
}
public void setContainer(UIIContainer container) {
this.container = container;
}
public UIIContainer getContainer() {
return container;
}
public void setSelectedColor(int selectedColor) {
this.selectedColor = selectedColor;
}
public int getSelectedColor() {
return selectedColor >= 0 ? selectedColor : UIConfig.selected_color;
}
public void setGradientColor(int gradientColor) {
this.gradientColor = gradientColor;
}
public int getGradientColor() {
return gradientColor;
}
public void setGradientSelectedColor(int gradientSelectedColor) {
this.gradientSelectedColor = gradientSelectedColor;
}
public int getGradientSelectedColor() {
return gradientSelectedColor;
}
}