1 package javax.microedition.lcdui;
\r
3 import lejos.nxt.Button;
\r
4 import lejos.nxt.ButtonListener;
\r
5 import lejos.util.Timer;
\r
6 import lejos.util.TimerListener;
\r
10 * @author Andre Nijholt
\r
12 public class Display {
\r
13 private static final int TICKER_INTERVAL_MSEC = 500;
\r
15 public static final int SCREEN_WIDTH = 100;
\r
16 public static final int SCREEN_HEIGHT = 64;
\r
18 public static final int CHAR_WIDTH = 6;
\r
19 public static final int CHAR_HEIGHT = 8;
\r
21 public static final int SCREEN_CHAR_WIDTH = SCREEN_WIDTH / CHAR_WIDTH;
\r
22 public static final int SCREEN_CHAR_DEPTH = CHAR_HEIGHT;
\r
24 private static Display display;
\r
26 private Screen current;
\r
27 private Screen alertBackup;
\r
28 private int alertTimeout;
\r
30 private Timer tickerTimer;
\r
31 private int tickerOffset = SCREEN_CHAR_WIDTH;
\r
33 protected Graphics graphics;
\r
34 private boolean quit;
\r
37 graphics = new Graphics();
\r
40 public static Display getDisplay() {
\r
41 if (display == null) {
\r
42 display = new Display();
\r
48 public void setCurrent(Screen nextDisplayable) {
\r
49 if (nextDisplayable != null) {
\r
50 if (nextDisplayable instanceof Alert) {
\r
51 alertBackup = current;
\r
52 alertTimeout = (((Alert) nextDisplayable).getTimeout() == Alert.FOREVER) ? Alert.FOREVER
\r
53 : ((int) System.currentTimeMillis()) + ((Alert) nextDisplayable).getTimeout();
\r
55 if (current != null) {
\r
56 current.hideNotify();
\r
59 tickerOffset = SCREEN_CHAR_WIDTH;
\r
60 current = nextDisplayable;
\r
61 current.showNotify();
\r
66 public void setCurrent(Alert alert, Screen nextDisplayable) {
\r
67 if ((alert != null) && (nextDisplayable != null)) {
\r
68 alertBackup = nextDisplayable;
\r
69 if (current != null) {
\r
70 current.hideNotify();
\r
73 // Store timeout for alert screen
\r
74 alertTimeout = (alert.getTimeout() == Alert.FOREVER) ? Alert.FOREVER
\r
75 : ((int) System.currentTimeMillis()) + alert.getTimeout();
\r
77 tickerOffset = SCREEN_CHAR_WIDTH;
\r
79 current.showNotify();
\r
84 public Displayable getCurrent() {
\r
89 * Start displaying the installed menus
\r
91 * @param polling true to poll for button updates (recommended)
\r
93 public void show(boolean polling) {
\r
95 // Use non-polling implementation
\r
96 showUsingListeners();
\r
101 int tsTickerUpdate = (int) System.currentTimeMillis();
\r
103 // Wait for button release
\r
104 while (!quit && (Button.readButtons() > 0)) {
\r
107 // Wait for button pressed and handle main timer checks
\r
108 while (!quit && (Button.readButtons() == 0)) {
\r
109 if (msecPassed(tsTickerUpdate)) {
\r
110 int tickerLen = updateTicker(tickerOffset);
\r
111 if (tickerLen > 0) {
\r
113 if (tickerOffset < -tickerLen) {
\r
114 tickerOffset = SCREEN_CHAR_WIDTH;
\r
117 tsTickerUpdate = (int) System.currentTimeMillis() + TICKER_INTERVAL_MSEC;
\r
120 if ((current != null) && (current instanceof Alert)
\r
121 && (alertTimeout != Alert.FOREVER) && msecPassed(alertTimeout)) {
\r
122 // Hide alert screen and replace backup without notify
\r
123 current.hideNotify();
\r
124 current = alertBackup;
\r
127 // Handle repaint requests from outside
\r
131 // Check if menu to handle
\r
132 if (current == null) {
\r
136 // Debounce button press
\r
139 } catch (InterruptedException e) {}
\r
141 // Handle debounced button press
\r
142 btnPressed = Button.readButtons();
\r
143 if (btnPressed == 1) {
\r
144 // ENTER button pressed
\r
145 if (current instanceof Alert) {
\r
146 // Hide alert screen and replace backup without notify
\r
147 current.keyPressed(Displayable.KEY_ENTER);
\r
148 current.hideNotify();
\r
149 current = alertBackup;
\r
151 current.keyPressed(Displayable.KEY_ENTER);
\r
154 } else if (btnPressed == 2) {
\r
155 // LEFT button pressed
\r
156 current.keyPressed(Displayable.KEY_LEFT);
\r
158 } else if (btnPressed == 4) {
\r
159 // RIGHT button pressed
\r
160 current.keyPressed(Displayable.KEY_RIGHT);
\r
162 } else if (btnPressed == 8) {
\r
163 // ESCAPE button pressed
\r
164 current.keyPressed(Displayable.KEY_BACK);
\r
173 public void quit() {
\r
177 private void showUsingListeners() {
\r
178 Button.ENTER.addButtonListener(new ButtonListener() {
\r
179 public void buttonReleased (Button b) {}
\r
180 public void buttonPressed (Button b) {
\r
181 if (current != null) {
\r
182 if (current instanceof Alert) {
\r
183 // Hide alert screen and replace backup without notify
\r
184 current.keyPressed(Displayable.KEY_ENTER);
\r
185 current.hideNotify();
\r
186 current = alertBackup;
\r
188 current.keyPressed(Displayable.KEY_ENTER);
\r
194 Button.ESCAPE.addButtonListener(new ButtonListener() {
\r
195 public void buttonReleased (Button b) {}
\r
196 public void buttonPressed (Button b) {
\r
197 if (current != null) {
\r
198 current.keyPressed(Displayable.KEY_BACK);
\r
203 Button.LEFT.addButtonListener(new ButtonListener() {
\r
204 public void buttonReleased (Button b) {}
\r
205 public void buttonPressed (Button b) {
\r
206 if (current != null) {
\r
207 current.keyPressed(Displayable.KEY_LEFT);
\r
212 Button.RIGHT.addButtonListener(new ButtonListener() {
\r
213 public void buttonReleased (Button b) {}
\r
214 public void buttonPressed (Button b) {
\r
215 if (current != null) {
\r
216 current.keyPressed(Displayable.KEY_RIGHT);
\r
222 tickerTimer = new Timer(500, new TimerListener() {
\r
223 public void timedOut() {
\r
224 int tickerLen = updateTicker(tickerOffset);
\r
225 if (tickerLen > 0) {
\r
227 if (tickerOffset < -tickerLen) {
\r
228 tickerOffset = SCREEN_CHAR_WIDTH;
\r
233 tickerTimer.start();
\r
235 // Start update timer task
\r
236 new Timer(50, new TimerListener() {
\r
237 public void timedOut() {
\r
238 if ((current != null) && (current instanceof Alert)
\r
239 && (alertTimeout != Alert.FOREVER) && msecPassed(alertTimeout)) {
\r
240 // Hide alert screen and replace backup without notify
\r
241 current.hideNotify();
\r
242 current = alertBackup;
\r
254 private void update() {
\r
255 if (current.getPaintRequest()) {
\r
257 updateTicker(tickerOffset);
\r
259 current.paint(graphics);
\r
260 current.clearPaintRequest();
\r
261 graphics.refresh();
\r
265 private int updateTicker(int offset) {
\r
266 Ticker ticker = current.getTicker();
\r
267 if (ticker != null) {
\r
268 int tickerLen = ticker.getString().length();
\r
269 for (int i = 0; i < SCREEN_CHAR_WIDTH; i++) {
\r
270 if ((i >= offset) && ((i - offset) < tickerLen)) {
\r
271 graphics.drawChar(ticker.getString().charAt(i - offset),
\r
272 i * Display.CHAR_WIDTH, 0, false);
\r
274 graphics.drawChar(' ', i * Display.CHAR_WIDTH, 0, false);
\r
277 graphics.refresh();
\r
285 * Returns true if the given timestamp passed
\r
287 * @param ts Timestamp in milliseconds
\r
288 * @return true if ts already passed, otherwise false
\r
290 private boolean msecPassed(int ts) {
\r
291 return (((int) System.currentTimeMillis() - ts) > 0);
\r