/* Copyright (c) 2008 Bluendo S.r.L.
* See about.html for details about license.
*
* $Id: UICanvas.java 1578 2009-06-16 11:07:59Z luca $
*/
/**
*
*/
package it.yup.ui;
// #mdebug
//@
//@import it.yup.util.Logger;
//@
// #enddebug
import it.yup.util.Utils;
import it.yup.xmpp.Config;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.GameCanvas;
/**
* UICanvas is the class that holds all the open screens and shows them. Screens
* are held in a stack-like structure, showing only the one at the top of the
* stack. Screens may be opened, closed, showed and hidden; by pressing and
* holding the '*' key, the user can switch from a screen to another.
*
* The UICanvas is singleton: only one may exist per midlet.
*/
public class UICanvas extends GameCanvas {
/** the key used to activate the left key */
public static int MENU_LEFT = -6;
/** the key used to activate the right key */
public static int MENU_RIGHT = -7;
public static int MENU_CANCEL = -8;
private static final Object[][] keyMaps = {
{ "Nokia", new Integer(-6), new Integer(-7) },
{ "ricsson", new Integer(-6), new Integer(-7) },
{ "iemens", new Integer(-1), new Integer(-4) },
{ "otorola", new Integer(-21), new Integer(-22) },
{ "harp", new Integer(-21), new Integer(-22) },
{ "j2me", new Integer(-6), new Integer(-7) },
{ "SunMicrosystems_wtk", new Integer(-6), new Integer(-7) } };
/** The alert used to show errors (if any) */
private static Alert alert;
/** singleton instance */
private static UICanvas _instance;
/** the display */
private static Display display;
/** a timer to schedule tasks */
private static Timer timer;
/** l'elenco degli screen */
private Vector screenList;
private int viewedIndex = 0;
private boolean qwerty = false;
/**
* @return the screenList
*/
public Vector getScreenList() {
return screenList;
}
/** il "popup" che contiene le finestre aperte */
private UIMenu wlist;
/*
* A semaphore used to lock all the graphical operations.
*/
private Semaphore sem = new Semaphore(1);
// #mdebug
//@ /*
//@ * The time at which the pointer is pressed
//@ */
//@ private long pressedTime;
//@
//@ /*
//@ * The time at which the pointer is released
//@ */
//@ private long releasedTime;
//@
// #enddebug
private int pressedX;
private int pressedY;
/*
* Set to true when dragging an object
*/
private boolean dragged = false;
/*
* A boolean used to know if repeated events are generated.
* If it is false the repeated events are generated artificially.
*/
public boolean hasRE = true;
public static void lock() {
if (_instance == null) return;
try {
_instance.sem.acquire();
} catch (InterruptedException e) {
// #mdebug
//@ Logger.log("In locking UI");
//@ System.out.println(e.getMessage());
//@ e.printStackTrace();
// #enddebug
}
}
public static void unlock() {
if (_instance == null) return;
_instance.sem.release();
}
/**
* The constructor for {@link UICanvas}.
*
* @param suppressKeyEvents
* True to suppress the regular key event mechanism for game
* keys, otherwise False.
*/
private UICanvas() {
super(false);
setFullScreenMode(true);
screenList = new Vector();
this.hasRE = this.hasRepeatEvents();
String keys = Config.getInstance().getProperty(Config.CANVAS_KEYS);
// not initialized
if (keys == null || keys.indexOf(',') == -1) setupdefaultKeyCode();
}
private boolean isMotorola() {
try {
String imei = System.getProperty("IMEI");
// #mdebug
//@ Logger.log("IMEI :" + imei);
//#enddebug
if (imei != null) return true;
imei = System.getProperty("com.motorola.IMEI");
// #mdebug
//@ Logger.log("com.motorola.IMEI :" + imei);
//#enddebug
if (imei != null) return true;
} catch (Exception e) {
}
return false;
}
private void setupdefaultKeyCode() {
String platform = System.getProperty("microedition.platform");
// hack to detect if is a "strange motorola"
if (platform.indexOf("otorola") != -1 || isMotorola()) {
platform = "Motorola";
}
// #mdebug
//@ Logger.log("platform:" + platform);
// #enddebug
for (int i = 0; i < keyMaps.length; ++i) {
String manufacturer = (String) keyMaps[i][0];
if (platform.indexOf(manufacturer) != -1) {
if (i == 1) {
if (platform.indexOf("P900") != -1
|| platform.indexOf("P908") != -1) {
UICanvas.MENU_LEFT = ((Integer) keyMaps[i][2])
.intValue();
UICanvas.MENU_RIGHT = ((Integer) keyMaps[i][1])
.intValue();
} else {
UICanvas.MENU_LEFT = ((Integer) keyMaps[i][1])
.intValue();
UICanvas.MENU_RIGHT = ((Integer) keyMaps[i][2])
.intValue();
}
} else {
UICanvas.MENU_LEFT = ((Integer) keyMaps[i][1]).intValue();
UICanvas.MENU_RIGHT = ((Integer) keyMaps[i][2]).intValue();
}
break;
}
}
}
/**
* Used to get the "effective" height of the canvas. getHeight() sometimes
* computes the menu bar space even if it is not displayed.
*
* @return The height of the clip.
*/
public int getClipHeight() {
return clipHeight; // this.getGraphics().getClipHeight();
}
private long keyReleasedTime = Long.MAX_VALUE;
private long keyPressedTime = Long.MAX_VALUE;
protected void keyReleased(int key) {
if (this.hasRE == false) {
if (System.currentTimeMillis() - keyPressedTime > 1000) {
keyRepeated(key);
}
keyReleasedTime = System.currentTimeMillis();
keyPressedTime = keyReleasedTime - 1;
}
}
/**
* <p>
* Handle the key pressure.
* </p>
* Dispatches the key pressure to the shown screen.
*
* @param key
* The pressed key.
*/
protected void keyPressed(int key) {
// #mdebug
//@ //Logger.log("key pressed:" + key);
// #enddebug
if (this.hasRE == false) {
if (keyPressedTime < keyReleasedTime) {
keyPressedTime = System.currentTimeMillis();
}
if (System.currentTimeMillis() - keyPressedTime > 1000) {
// to be sure the time is reset
try {
keyRepeated(key);
} catch (Exception e) {
// #mdebug
//@ Logger.log("In key pressed:" + e.getMessage() + " "
//@ + e.getClass().getName());
//@ e.printStackTrace();
// #enddebug
}
keyPressedTime = Long.MAX_VALUE;
keyReleasedTime = 0;
return;
}
}
if (screenList.size() == 0 || viewedIndex > screenList.size()
|| viewedIndex < 0) { return; }
// wlist key pressure cannot be handled in UIscreen
// because it has no knowledge of it
// it must be handled here
if (wlist != null && wlist.isOpenedState() == true) {
int ga = this.getGameAction(key);
if (key == UICanvas.MENU_RIGHT || ga == Canvas.FIRE) {
int selectedIndex = wlist.getSelectedIndex();
getCurrentScreen().removePopup(wlist);
change(selectedIndex);
return;
}
}
try {
UIMenu writeScreen = (UIMenu) screenList.elementAt(viewedIndex);
writeScreen.keyPressed(key);
} catch (Exception e) {
// #mdebug
//@ Logger.log("In key pressed:" + e.getMessage() + " "
//@ + e.getClass().getName());
//@ e.printStackTrace();
// #enddebug
}
}
TimerTask longPressedTask = initLongPress(null);
boolean longPressRun = false;
public void pointerPressed(int x, int y) {
// #mdebug
//@
//@ this.pressedTime = System.currentTimeMillis();
//@
// #enddebug
this.pressedX = x;
this.pressedY = y;
this.dragged = false;
final UIScreen paintedScreen = getCurrentScreen();
if (paintedScreen == null) return;
boolean hasSubMenu = handlePointEvent(x, y, paintedScreen, false);
if (hasSubMenu) {
longPressRun = false;
longPressedTask = initLongPress(paintedScreen);
Utils.tasks.schedule(longPressedTask, 750);
}
// #mdebug
//@ //Logger.log("pointerPressed:" + x + " " + y + ":");
// #enddebug
}
private TimerTask initLongPress(final UIScreen paintedScreen) {
return new TimerTask() {
public void run() {
longPress(paintedScreen);
}
};
}
private void longPress(UIScreen paintedScreen) {
synchronized (longPressedTask) {
// #mdebug
//@ Logger.log("longPressed:");
// #enddebug
longPressRun = true;
if (paintedScreen != null) paintedScreen
.keyPressed(UICanvas.MENU_LEFT);
}
}
public void pointerDragged(int x, int y) {
// #mdebug
//@ //Logger.log("pointerDragged:" + x + " " + y + ":");
// #enddebug
UIScreen paintedScreen = getCurrentScreen();
if (paintedScreen == null) return;
int yOffset = y - pressedY;
int xOffset = x - pressedX;
UIItem foundItem = findItem(x, y, paintedScreen);
//if a little movement is made reset the longpressTask
if (Math.abs(yOffset) > 5 || Math.abs(xOffset) > 5) {
synchronized (longPressedTask) {
longPressedTask.cancel();
}
}
if (foundItem != null) if (yOffset >= 5 || yOffset <= -5) paintedScreen
.startDrag(foundItem);
int ka = -1;
if (yOffset >= 20) {
ka = this.getKeyCode(Canvas.DOWN);
this.dragged = true;
paintedScreen.keyRepeated(ka);
this.pressedX = x;
this.pressedY = y;
return;
}
if (yOffset <= -20) {
ka = this.getKeyCode(Canvas.UP);
this.dragged = true;
paintedScreen.keyRepeated(ka);
this.pressedX = x;
this.pressedY = y;
return;
}
if (yOffset >= 15) {
ka = this.getKeyCode(Canvas.DOWN);
this.dragged = true;
paintedScreen.keyPressed(ka);
this.pressedX = x;
this.pressedY = y;
return;
}
if (yOffset <= -15) {
ka = this.getKeyCode(Canvas.UP);
this.dragged = true;
paintedScreen.keyPressed(ka);
this.pressedX = x;
this.pressedY = y;
return;
}
ka = -1;
if (xOffset >= 15) {
this.dragged = true;
if (foundItem != null) {
ka = this.getKeyCode(Canvas.RIGHT);
foundItem.keyPressed(ka);
}
this.pressedX = x;
this.pressedY = y;
return;
}
if (xOffset <= -15) {
this.dragged = true;
if (foundItem != null) {
ka = this.getKeyCode(Canvas.LEFT);
foundItem.keyPressed(ka);
}
this.pressedX = x;
this.pressedY = y;
return;
}
}
/**
* <p>
* Handle the pointer pressure.
* </p>
* Determines where the pointer were pressed
*
* @param key
* The pressed key.
*
* @return <code>true</code> if the screen will keep the selection
*/
public void pointerReleased(int x, int y) {
// #mdebug
//@
//@ this.releasedTime = System.currentTimeMillis();
//@
// #enddebug
// #mdebug
//@ //Logger.log("pointerReleased:" + x + " " + y + ":");
// #enddebug
synchronized (longPressedTask) {
longPressedTask.cancel();
if (longPressRun == true) {
this.dragged = false;
longPressRun = false;
return;
}
}
UIScreen paintedScreen = getCurrentScreen();
if (paintedScreen == null) {
this.dragged = false;
return;
}
if (this.dragged == true) {
this.dragged = false;
paintedScreen.endDrag();
return;
}
// #mdebug
//@ Logger.log("paintedScreen found:");
// #enddebug
handlePointEvent(x, y, paintedScreen, true);
}
private boolean handlePointEvent(int x, int y, UIScreen paintedScreen,
boolean up) {
UIItem foundItem = null;
foundItem = findItem(x, y, paintedScreen);
if (foundItem != null) {
// #mdebug
//@ try {
//@ Logger.log("Found item in pointerReleased:");
//@ Logger
//@ .log("Pression time: " + releasedTime + " "
//@ + pressedTime);
//@ if (foundItem instanceof UILabel) {
//@ UILabel new_name = (UILabel) foundItem;
//@ Logger.log("Label: " + new_name.getText()
//@ + foundItem.getWidth() + " "
//@ + foundItem.getHeight(canvasGraphics));
//@ } else if (foundItem instanceof UILayout) {
//@ UILayout new_name = (UILayout) foundItem;
//@ Logger.log("Layout " + new_name.getWidth() + " "
//@ + new_name.getHeight(canvasGraphics));
//@ } else if (foundItem instanceof UITextField) {
//@ UITextField new_name = (UITextField) foundItem;
//@ Logger.log("TextField " + new_name.getText());
//@ } else if (foundItem instanceof UIPanel) {
//@ UIPanel new_name = (UIPanel) foundItem;
//@ Logger.log("Panel " + new_name.getWidth() + " "
//@ + new_name.getHeight(canvasGraphics));
//@ } else if (foundItem instanceof UIMenu) {
//@ Logger.log("Menu ");
//@ UIMenu new_name = (UIMenu) foundItem;
//@ try {
//@ Logger.log(((UILabel) new_name.getItemList().elementAt(
//@ 0)).getText()
//@ + " "
//@ + new_name.getWidth()
//@ + " "
//@ + new_name.getHeight(canvasGraphics));
//@ } catch (Exception e) {
//@ Logger.log(e.getMessage() + e.getClass().getName());
//@ }
//@ } else {
//@ Logger.log("Found other ");
//@ try {
//@ Logger.log(foundItem.getWidth() + " "
//@ + foundItem.getHeight(canvasGraphics));
//@ } catch (Exception e) {
//@ Logger.log(e.getMessage() + e.getClass().getName());
//@ }
//@ }
//@ } catch (Exception e) {
//@ }
// #enddebug
if (foundItem == paintedScreen.footerLeft) {
if (up) {
this.keyPressed(UICanvas.MENU_LEFT);
}
return false;
}
if (foundItem == paintedScreen.footerRight) {
if (up) {
this.keyPressed(UICanvas.MENU_RIGHT);
}
return false;
}
// check if it is the screen menus list
if (wlist != null && wlist.isOpenedState() == true) {
int selectedIndex = wlist.getItemList().indexOf(foundItem);
if (selectedIndex >= 0) {
if (up) {
paintedScreen.removePopup(wlist);
change(selectedIndex);
}
return false;
}
}
// first check if its a menu
UIMenu paintedMenu = paintedScreen.getMenu();
if (paintedMenu != null && paintedMenu.contains(foundItem)) {
if (!up) {
foundItem.getContainer().setSelectedItem(foundItem);
paintedScreen.askRepaint();
} else {
paintedScreen.handleMenuKey(paintedMenu, UICanvas
.getInstance().getKeyCode(UICanvas.FIRE));
}
return false;
} else { // then a popup or an item
Enumeration enPopup = paintedScreen.popupList.elements();
while (enPopup.hasMoreElements()) {
UIMenu ithMenu = (UIMenu) enPopup.nextElement();
if (ithMenu.contains(foundItem)) {
if (!up) {
foundItem.getContainer().setSelectedItem(foundItem);
paintedScreen.askRepaint();
} else {
paintedScreen.handleMenuKey(ithMenu, UICanvas
.getInstance().getKeyCode(UICanvas.FIRE));
}
return false;
}
}
}
// then the title
if (foundItem == paintedScreen.titleLabel) {
if (up) {
this.keyRepeated(UICanvas.KEY_STAR);
}
}
if (foundItem.isFocusable() == false) return false;
// if any kind of menu is opened return (menus are modals)
if ((paintedMenu != null && paintedMenu.isOpenedState())
|| paintedScreen.popupList.size() > 0) { return false; }
if (foundItem.getContainer() != null) {
if (!up) {
// #mdebug
//@ Logger.log("pressed");
// #enddebug
foundItem.getContainer().setSelectedItem(foundItem);
paintedScreen.askRepaint();
return true;
} else {
// #mdebug
//@ Logger.log("released");
// #enddebug
paintedScreen.keyPressed(UICanvas.getInstance().getKeyCode(
UICanvas.FIRE));
return false;
}
}
} else {
// check if it is the menucursor
if (screenList.size() > 1 && up) {
if (x < this.lag.getWidth() && y < this.lag.getHeight()) {
// check if it is the screen right or left cursor
int la = UICanvas.getInstance().getKeyCode(Canvas.LEFT);
paintedScreen.keyPressed(la);
return false;
}
if (x > canvasGraphics.getClipWidth() - 2 * this.lag.getWidth()
&& y < canvasGraphics.getClipHeight() - 2
* this.lag.getHeight()) {
// check if it is the screen right or left cursor
int ra = UICanvas.getInstance().getKeyCode(Canvas.RIGHT);
paintedScreen.keyPressed(ra);
return false;
}
}
}
return false;
}
private UIItem findItem(int x, int y, UIScreen paintedScreen) {
UIItem foundItem = null;
Enumeration en = paintedScreen.getPaintedItems().elements();
while (en.hasMoreElements()) {
UIItem ithItem = (UIItem) en.nextElement();
int[] coors = ithItem.coors;
int originalX = coors[0];
int originalY = coors[1];
int w = coors[2];
int h = coors[3];
if (x > originalX && x < originalX + w && y > originalY
&& y <= originalY + h) {
foundItem = ithItem;
break;
}
}
return foundItem;
}
public int getGameAction(int keyCode) {
// some mobile phones throw an Exception when pressing
// a key that is not associated to a game key
// even if the keyCode is a valid key code
int retVal = 0;
try {
retVal = super.getGameAction(keyCode);
} catch (Exception e) {
// #mdebug
//@ Logger.log("In getGameAction:" + keyCode + " "
//@ + e.getClass().getName());
// #enddebug
}
return retVal;
}
/**
* <p>
* Handle an event of keyRepeated.
* </p>
* If the key repeated is the '*', opens the "window list".
*
* @param key
* The pressed key.
*/
protected void keyRepeated(int key) {
if (screenList.size() == 0 || viewedIndex < 0
|| viewedIndex >= screenList.size()) { return; }
UIScreen s0 = (UIScreen) screenList.elementAt(viewedIndex);
if (key == Canvas.KEY_STAR) {
if (s0.popupIsPresent(this.wlist) == false && screenList.size() > 1) {
wlist = UIUtils.easyMenu("", 20, this.getClipHeight() / 4,
getWidth() - 40, null);
for (int i = 0; i < screenList.size(); i++) {
UIScreen si = (UIScreen) screenList.elementAt(i);
if (si != null) {
UILabel um = new UILabel(si.getTitle());
wlist.append(um);
}
}
s0.addPopup(wlist);
return;
}
}
s0.keyRepeated(key);
}
private Graphics canvasGraphics = this.getGraphics();
private int clipHeight = canvasGraphics.getClipHeight();
/**
* Used by screen to ask a repaint.
*
* @param screen
* The screen to repaint. It may be {@code null} to indicate that
* the current shown screen should be repainted. Otherwise, the
* given screen will be checked if it is the screen currently
* shown.
*/
public/*synchronized*/void askRepaint(UIScreen screen) {
if (screenList.size() == 0) { return; }
if (screen == null) {
screen = (UIScreen) _instance.screenList.elementAt(viewedIndex);
screen.setDirty(true);
} else if (screen != (UIScreen) screenList.elementAt(viewedIndex)) { return; }
try {
UICanvas.lock();
if (screen.isFreezed() == false) {
screen.setFreezed(true);
Graphics g = canvasGraphics; // this.getGraphics();
g.setFont(UIConfig.font_body);
// in case a sizeChanged has changed it
this.clipHeight = canvasGraphics.getClipHeight();
int originalX = g.getTranslateX();
int originalY = g.getTranslateY();
int originalClipX = g.getClipX();
int originalClipY = g.getClipY();
int originalClipWidth = g.getClipWidth();
int originalClipHeight = g.getClipHeight();
// g.translate(-g.getTranslateX(), -g.getTranslateY());
// g.setClip(0, 0, this.getWidth(), this.getHeight());
// #mdebug
//@ // Logger.log(g.getTranslateX() + " " + g.getTranslateY() + " "
//@ // + g.getClipX() + " " + g.getClipY() + " "
//@ // + g.getClipWidth() + " " + g.getClipHeight() + " "
//@ // + this.getWidth() + " " + this.getHeight());
// #enddebug
setTabs();
boolean needFlush = screen.paint(g);
g.translate(originalX - g.getTranslateX(), originalY
- g.getTranslateY());
g.setClip(originalClipX, originalClipY, originalClipWidth,
originalClipHeight);
// g.translate(-g.getTranslateX(), -g.getTranslateY());
// g.setClip(0, 0, this.getWidth(), this.getHeight());
if (needFlush) {
flushGraphics();
}
screen.setFreezed(false);
}
} catch (Exception ex) {
// #mdebug
//@ Logger.log("In painting UI");
//@ System.out.println(ex.getMessage());
//@ ex.printStackTrace();
// #enddebug
} finally {
UICanvas.unlock();
}
}
private Image rag = UICanvas.getUIImage("/icons/rag.png");
private Image lag = UICanvas.getUIImage("/icons/lag.png");
private Image rab = UICanvas.getUIImage("/icons/rab.png");
private Image lab = UICanvas.getUIImage("/icons/lab.png");
private void setTabs() {
UIScreen cs = this.getCurrentScreen();
if (cs == null) return;
if (this.screenList.size() <= 1) {
cs.ra = rag;
cs.la = lag;
} else {
cs.ra = rab;
cs.la = lab;
}
}
/*
private void paintNav(Graphics g) {
if (this.screenList.size() == 1) return;
String navString = (this.viewedIndex + 1) + "/"
+ this.screenList.size();
Font navFont = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_BOLD,
Font.SIZE_SMALL);
g.setFont(navFont);
int navWidth = navFont.stringWidth(navString);
g.translate(this.getWidth() - g.getTranslateX() - navWidth - 2, 2 - g
.getTranslateY());
g.setColor(UIConfig.header_bg);
g.fillRect(-2, 0, navWidth + 2, navFont.getHeight());
g.setColor(0x333333);
g.drawString(navString, 0, 0, Graphics.LEFT | Graphics.TOP);
g.translate(-1, -1);
g.setColor(0xFFFFFF);
g.drawString(navString, 0, 0, Graphics.LEFT | Graphics.TOP);
g.translate(-g.getTranslateX(), -g.getTranslateY());
}
*/
/**
* Open and shows the given screen, optionally the screen can be shown
* immediately. If the screen is immediately shown, it's inserted at
* position 0, otherwise it's placed at the end of the list.
*
* @param screen
* the screen to show
* @param show
* if true, the screen is immediately shown otherwise it's left
* hidden
*/
public void open(UIScreen screen, boolean show) {
if (!show || (wlist != null && wlist.isOpenedState() == true)) {
if (!screenList.contains(screen)) screenList.addElement(screen);
} else {
if (screenList.contains(screen)) screenList.removeElement(screen);
screenList.insertElementAt(screen, screenList.size());
}
if (wlist != null) {
wlist.append(new UILabel(screen.getTitle()));
}
if (show == false) { return; }
if (viewedIndex >= 0) {
((UIScreen) screenList.elementAt(viewedIndex)).setDirty(true);
((UIScreen) screenList.elementAt(viewedIndex)).hideNotify();
}
/* if the screen is the only one, it's painted immediately */
screen.setDirty(true);
viewedIndex = this.screenList.indexOf(screen);
// changing index -> mandatory to repaint the background
screen.firstPaint = true;
screen.askRepaint();
screen.showNotify();
}
/**
* Shows a screen by placing it on top of the stack. If the screen is not in
* the stack of open screens, this method fails silently.
*
* @param screen
* the screen to show
*/
public void show(UIScreen screen) {
int idx = screenList.indexOf(screen);
if (idx == -1) { return; }
change(idx);
}
public void show(int idx) {
if (idx >= 0 && idx < this.screenList.size()) change(idx);
}
/**
* Hides a screen and shows the next in the stack. If the screen is not the
* visible one, this method fails silently. If this screen is the only one
* in the stack, this method does nothing.
*
* @param screen
* the screen to hide
*/
public void hide(UIScreen screen) {
if (screenList.size() < 2) { return; }
UIMenu s0 = (UIMenu) screenList.elementAt(viewedIndex);
if (s0 != screen) { return; }
change(0);
}
/**
* Closes a screen, removing it from the stack and showing the next one. If
* the screen is not in the stack of open screens, or is the last of the
* stack, this method fails silently.
*
* @param screen
* the screen to close
* @return true if the screen has been closed, false otherwhise
*/
public boolean close(UIScreen screen) {
int idx = screenList.indexOf(screen);
if (idx == -1) { return false; }
((UIScreen) screenList.elementAt(idx)).setDirty(true);
((UIScreen) screenList.elementAt(idx)).hideNotify();
screenList.removeElementAt(idx);
// if all the screens have been removed the list could be empty
if (idx <= viewedIndex) viewedIndex--;
if (viewedIndex < 0) viewedIndex = 0;
if (screenList.size() > 0) {
int newIdx = idx;
if (idx >= screenList.size()) newIdx = screenList.size() - 1;
change(newIdx);
}
if (wlist != null && wlist.getItemList().size() > 0) {
wlist.remove(idx);
}
return true;
}
/**
* Change the visible screen to the one given and redraws everything.
*
* @param i
* the id of the screen to change to
*/
private void change(int i) {
UIScreen si = (UIScreen) screenList.elementAt(viewedIndex);
si.setDirty(true);
si.hideNotify();
si = (UIScreen) screenList.elementAt(i);
si.setDirty(true);
si.firstPaint = true;
viewedIndex = i;
si.askRepaint();
si.showNotify();
// if (wlist != null) {
/* switch also wlist */
// UIItem ui = wlist.remove(i);
// if
// wlist.insert(0, ui);
// }
}
/**
* Called when the Canvas changes size or even rotation
*/
synchronized protected void sizeChanged(int w, int h) {
try {
// sometimes the graphics can be null
// if the screen cannot be painted
// i.e. in N95
UIScreen activeScreen = this.getCurrentScreen();
// to initialize it at least at start
if (activeScreen != null || screenList == null
|| screenList.size() == 0) {
this.canvasGraphics = this.getGraphics();
this.clipHeight = canvasGraphics.getClipHeight();
}
if (activeScreen != null) {
activeScreen.invalidate(w, h);
activeScreen.askRepaint();
}
} catch (Exception e) {
// #mdebug
//@ System.out.println(e.getMessage());
//@ e.printStackTrace();
// #enddebug
}
}
/**
* Gets the currently displayed Screen
*
* @return The currently displayed screen or {@code null} if no screen is
* available
*/
public UIScreen getCurrentScreen() {
if (!isShown()) { return null; }
return (UIScreen) ((screenList.size() > 0 && viewedIndex >= 0 && viewedIndex < screenList
.size()) ? screenList.elementAt(viewedIndex) : null);
}
/**
* Singleton factory
*/
public static synchronized UICanvas getInstance() {
if (_instance == null) {
_instance = new UICanvas();
}
return _instance;
}
/**
* Sets the display to use for the change-screen operations
*
* @param _display
* The display to use.
*/
public static void setDisplay(Display _display) {
display = _display;
}
/**
* Sets the key code to use for the two buttons with which menu will be
* activated.
*
* @param left_key
* the key code for the left button
* @param right_key
* the key code for the right button
*/
public static void setMenuKeys(int left_key, int right_key) {
MENU_LEFT = left_key;
MENU_RIGHT = right_key;
}
/**
* Display a different
*
* @param disp
*/
public static void display(Displayable disp) {
if (display == null) { return; }
/*
* using getInstance() instead of _instance as it may be null so it gets
* created
*/
display.setCurrent(disp == null ? getInstance() : disp);
if (disp == null) {
_instance.askRepaint(null);
}
}
/**
* Show an error screen, if multiple errors occur only append the message
*
* @param type
* The alert type as per {@link AlertType}
* @param title
* Title of the screen
* @param text
* Displayed error message
*/
public static void showAlert(AlertType type, String title, String text) {
// a native alert screen may be available in case the UI has not
// been set alrealy
Displayable cur = display.getCurrent();
if (cur.equals(alert)) {
alert.setString(alert.getString() + "\n" + text);
return;
}
Image img;
try {
if (AlertType.INFO.equals(type)) {
img = Image.createImage("/icons/warning.png");
} else if (AlertType.WARNING.equals(type)) {
img = Image.createImage("/icons/warning.png");
} else if (AlertType.ERROR.equals(type)) {
img = Image.createImage("/icons/error.png");
} else {
img = Image.createImage("/icons/error.png");
}
} catch (IOException e) {
img = null;
}
Font bigFont = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_PLAIN,
Font.SIZE_MEDIUM);
UIScreen currentScreen = UICanvas.getInstance().getCurrentScreen();
// if no screen is available it means the UI is not "ready"
// in that case we use a native alert screen
if (currentScreen != null) {
UILabel titleLabel = new UILabel(img, title);
UIMenu alertMenu = UIUtils.easyMenu("", 10, 20, UICanvas
.getInstance().getWidth() - 20, titleLabel);
titleLabel.setFont(bigFont);
titleLabel.setFocusable(false);
UILabel textLabel = new UILabel(text);
alertMenu.append(textLabel);
textLabel.setWrappable(true, alertMenu.getWidth() - 5);
textLabel.setFont(bigFont);
alertMenu.setSelectedIndex(1);
Graphics cg = UICanvas.getInstance().canvasGraphics;
int offset = (cg.getClipHeight() - alertMenu.getHeight(cg)) / 2;
alertMenu.setAbsoluteY(offset);
alertMenu.cancelMenuString = "";
alertMenu.selectMenuString = "OK";
currentScreen.addPopup(alertMenu);
} else {
Alert alert = new Alert(title, text, img, type);
alert.setType(type);
alert.setTimeout(Alert.FOREVER);
display.setCurrent(alert, getInstance());
}
}
/**
* Used to get predefined images "internal" to the UI. XXX: Maybe it is even
* better to get a cache for them.
*
* @param imgName
* @return
*/
public static Image getUIImage(String imgName) {
try {
return Image.createImage(imgName);
} catch (IOException e) {
System.out.println("Impossible to get : " + imgName);
}
return null;
}
public static Timer getTimer() {
if (timer == null) {
timer = new Timer();
}
return timer;
}
/**
* @return the viewedIndex
*/
public int getViewedIndex() {
return viewedIndex;
}
// #mdebug
//@ private static UIMenu logMenu = new UIMenu("log");
//@
//@ public static void clearLog() {
//@ logMenu.clear();
//@ }
//@
//@ public static void log(String logString) {
//@ UILabel uil = new UILabel(logString);
//@ logMenu.append(uil);
//@ logMenu.setAbsoluteX(10);
//@ logMenu.setAbsoluteY(20);
//@ logMenu.setWidth(UICanvas.getInstance().getWidth());
//@ UICanvas.getInstance().getCurrentScreen().addPopup(logMenu);
//@ }
//@
//@ public static void log(Vector logStrings) {
//@ logMenu.setAbsoluteX(10);
//@ logMenu.setAbsoluteY(20);
//@ logMenu.setWidth(UICanvas.getInstance().getWidth());
//@ for (Enumeration en = logStrings.elements(); en.hasMoreElements();) {
//@ String logString = (String) en.nextElement();
//@ if (logString != null) {
//@ UILabel uil = new UILabel(logString);
//@ logMenu.append(uil);
//@ }
//@ }
//@ UIScreen cs = UICanvas.getInstance().getCurrentScreen();
//@ if (cs != null) cs.addPopup(logMenu);
//@ }
//@
// #enddebug
public boolean hasQwerty() {
// TODO Auto-generated method stub
return qwerty;
}
public void setQwerty(boolean qwerty) {
this.qwerty = qwerty;
}
}