/* Copyright (c) 2008 Bluendo S.r.L.
* See about.html for details about license.
*
* $Id: UIGauge.java 1574 2009-06-11 14:31:59Z luca $
*/
/**
*
*/
package it.yup.ui;
import java.util.TimerTask;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Gauge;
import javax.microedition.lcdui.Graphics;
/**
* Re-implementation of the {@link Gauge} class using our library. Differences:
* maximum Value cannot be changed after construction.
*/
public class UIGauge extends UIItem {
/** if {@code true} this Gauge may be modified programmatically */
private boolean modifiable;
/** the current value */
private int value;
/** the maximum value */
private int maxValue;
/** the label shown to the user */
private String label;
/** behaviour when the maxValue is indefinite */
private int behaviour;
/** the task used to animate the gauge */
private Ticker ticker;
/**
* Constructor, see Gauge constructor for details.
*
* @param label
* The label to show.
* @param interactive
* tells whether the user can change the value
* @param maxVal
* the maximum value, or INDEFINITE
* @param initVal
* the initial value in the range [0..maxValue], or one of
* CONTINUOUS_IDLE, INCREMENTAL_IDLE, CONTINUOUS_RUNNING, or
* INCREMENTAL_UPDATING if maxVal is INDEFINITE.
*/
public UIGauge(String _label, boolean interactive, int maxVal, int initVal) {
label = _label;
if (interactive && maxVal < 0) { throw new IllegalArgumentException(
"maxValue negative for interactive mode"); }
if (!interactive && maxVal < 0 && maxVal != Gauge.INDEFINITE) { throw new IllegalArgumentException(
"invalid maxValue for non interactive mode"); }
if (maxVal > 0 && initVal < 0) {
initVal = 0;
}
if (maxVal > 0 && initVal > maxVal) {
initVal = maxVal;
}
if (!interactive
&& maxVal == Gauge.INDEFINITE
&& !(initVal == Gauge.CONTINUOUS_IDLE
|| initVal == Gauge.CONTINUOUS_RUNNING
|| initVal == Gauge.INCREMENTAL_IDLE || initVal == Gauge.INCREMENTAL_UPDATING)) { throw new IllegalArgumentException(
"invalid initValue for non interactive mode"); }
modifiable = interactive;
maxValue = maxVal;
if (maxValue == Gauge.INDEFINITE) {
value = 0;
behaviour = initVal;
} else {
value = initVal;
}
if (!modifiable && behaviour == Gauge.CONTINUOUS_RUNNING) {
ticker = new Ticker();
UICanvas.getTimer().scheduleAtFixedRate(ticker, 1000, 1000);
}
setFocusable(modifiable);
}
/*
* (non-Javadoc)
*
* @see it.yup.ui.UIItem#paint(javax.microedition.lcdui.Graphics, int, int)
*/
protected void paint(Graphics g, int w, int h) {
/* get gfx state */
int oc = g.getColor();
Font of = g.getFont();
/* clear area */
int tempBgColor = (getBg_color() >= 0 ? getBg_color()
: UIConfig.bg_color);
g.setColor(tempBgColor);
g.fillRect(0, 0, w, h);
/* draw title (XXX: should clip or put ...) */
g.setColor(UIConfig.fg_color);
g.setFont(UIConfig.gauge_body);
g.drawString(label, 1, 1, Graphics.LEFT | Graphics.TOP);
/* border around progress (black) */
g.setColor(UIConfig.header_bg);
//g.drawRect(1, 2 + UIConfig.gauge_body.getHeight(), w - 3, 16);
int gaugeHeight = UIConfig.gauge_body.getHeight();
//this.drawBorder(g, 1, 2 + gaugeHeight, w - 2, 18 + gaugeHeight);
drawInput(g, 1, 2 + gaugeHeight, w - 2, 18 + gaugeHeight);
int gw = 0;
if (maxValue != Gauge.INDEFINITE) {
gw = value * (w - 8) / maxValue;
} else if (behaviour == Gauge.CONTINUOUS_RUNNING
|| behaviour == Gauge.INCREMENTAL_UPDATING) {
/* value is percentual to width */
gw = value * (w - 8) / 100;
} else {
gw = 2;
}
// if (gw == 0) {
// gw = 2;
// }
/* fill rect */
int blockHeight = 5 + gaugeHeight;
int blockColor = UIConfig.tbs_color;
int x0 = 4, x1 = gw;
float xOffset = ((float) w - 7) / 10;
float count = 0;
float start = 0;
while (count * xOffset < x1) {
g.setColor(blockColor);
g.fillRect((int) (x0 + start), blockHeight, (int) (start + xOffset)
- (int) (start), 11);
blockColor = UIUtils.colorize(blockColor, +10);
start += xOffset;
count++;
}
/* restore state */
g.setColor(oc);
g.setFont(of);
}
/*
* (non-Javadoc)
*
* @see it.yup.ui.UIItem#keyPressed(int)
*/
public boolean keyPressed(int key) {
boolean keepFocus = false;
if (!modifiable || maxValue == Gauge.INDEFINITE) { return keepFocus; }
switch (UICanvas.getInstance().getGameAction(key)) {
case Canvas.LEFT:
keepFocus = true;
if (value > 0) {
value--;
}
dirty = true;
askRepaint();
break;
case Canvas.RIGHT:
keepFocus = true;
if (value < maxValue) {
value++;
}
dirty = true;
askRepaint();
break;
}
return keepFocus;
}
/*
* (non-Javadoc)
*
* @see it.yup.ui.UIItem#getHeight(javax.microedition.lcdui.Graphics)
*/
public int getHeight(Graphics g) {
Font fnt = UIConfig.gauge_body;
/* text row + border(s) + space(s) + gauge */
int mh = fnt.getHeight();
mh += 20;
return mh;
}
/**
* Changes the label shown
*
* @param _label
* the new label
*/
public void setLabel(String _label) {
label = _label;
dirty = true;
askRepaint();
}
/**
* @return the label shown to the user
*/
public String getLabel() {
return label;
}
/**
* Changes the current value
*
* @param newVal
* the new value
*/
public void setValue(int newVal) {
if (!modifiable
&& maxValue == Gauge.INDEFINITE
&& (newVal != Gauge.CONTINUOUS_IDLE
|| newVal != Gauge.CONTINUOUS_RUNNING
|| newVal != Gauge.INCREMENTAL_IDLE || newVal != Gauge.INCREMENTAL_UPDATING)) { throw new IllegalArgumentException(
"invalid value for non interactive mode"); }
if (modifiable && newVal < 0) {
newVal = 0;
}
if (modifiable && newVal > maxValue) {
newVal = maxValue;
}
if (maxValue == Gauge.INDEFINITE
&& behaviour != Gauge.INCREMENTAL_UPDATING) {
/* don't move */
return;
} else if (maxValue == Gauge.INDEFINITE
&& behaviour == Gauge.INCREMENTAL_UPDATING) {
value += 5;
if (value >= 100) {
value = 0;
}
}
value = newVal;
dirty = true;
askRepaint();
}
/**
* @return the current value
*/
public int getValue() {
return value;
}
/**
* @return if this Gauge is modificable (
*/
public boolean isInteractive() {
return modifiable;
}
public void cancel() {
this.ticker.cancel();
}
public void start() {
this.ticker.cancel();
if (!modifiable && behaviour == Gauge.CONTINUOUS_RUNNING) {
ticker = new Ticker();
UICanvas.getTimer().scheduleAtFixedRate(ticker, 1000, 1000);
}
}
/**
* @return the current maximum value
*/
public int getMaxValue() {
return maxValue;
}
public void setOffset(int offset) {
if (screen == null)
return ;
synchronized (screen) {
this.offset = offset;
if (value < offset) value = offset;
}
}
public int getOffset() {
return offset;
}
/*
* The offset at which the gauge starts the line
*/
private int offset = 10;
/**
* Task used to "tick" the clock on a CONTINUOUS_RUNNING Gauge.
*/
private class Ticker extends TimerTask {
/*
* (non-Javadoc)
*
* @see java.util.TimerTask#run()
*/
public void run() {
if (behaviour == Gauge.CONTINUOUS_RUNNING) {
/* ticks in blocks of 10% */
if (screen != null) {
synchronized (screen) {
value += 10;
if (value > 100) {
value = offset;
}
}
}
dirty = true;
askRepaint();
}
}
}
}