View Javadoc

1   /*
2    * MicroEmulator 
3    * Copyright (C) 2001 Bartek Teodorczyk <barteo@barteo.net>
4    *  Copyright (C) 2005 Andres Navarro
5    * 
6    * This library is free software; you can redistribute it and/or modify it
7    * under the terms of the GNU Lesser General Public License as published by the
8    * Free Software Foundation; either version 2.1 of the License, or (at your
9    * option) any later version.
10   * 
11   * This library is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
14   * for more details.
15   * 
16   * You should have received a copy of the GNU Lesser General Public License
17   * along with this library; if not, write to the Free Software Foundation,
18   * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19   * 
20   * Contributor(s): 
21   *   3GLab
22   */
23  
24  package javax.microedition.lcdui;
25  
26  import java.util.Vector;
27  
28  import org.microemu.device.DeviceFactory;
29  
30  //TODO implement pointer events
31  public class Form extends Screen 
32  {
33  	Item items[] = new Item[4];
34  	int numOfItems = 0;
35  	int focusItemIndex;
36  	ItemStateListener itemStateListener = null;
37  
38  	
39  	public Form(String title) 
40  	{
41  		super(title);
42  		super.setUI(DeviceFactory.getDevice().getUIFactory().createFormUI(this));
43  		
44  		focusItemIndex = -2;
45  	}
46  
47  	
48  	public Form(String title, Item[] items) 
49  	{
50  		this(title);
51  
52  		// TODO add this to MIDP1
53  		if (items != null) {
54  			this.items = new Item[items.length];
55  			System.arraycopy(items, 0, this.items, 0, items.length);
56  			numOfItems = this.items.length;
57  			for (int i = 0; i < numOfItems; i++) {
58  				verifyItem(this.items[i]);
59  			}
60  		}
61  	}
62  
63  	
64  	public int append(Item item) 
65  	{
66  		verifyItem(item);
67  
68  		if (numOfItems + 1 >= items.length) {
69  			Item newitems[] = new Item[numOfItems + 4];
70  			System.arraycopy(items, 0, newitems, 0, numOfItems);
71  			items = newitems;
72  		}
73  		items[numOfItems] = item;
74  		numOfItems++;
75  		
76  		repaint();
77  
78  		return (numOfItems - 1);
79  	}
80  
81  	
82  	public int append(Image img) 
83  	{
84  		return append(new ImageItem(null, img, ImageItem.LAYOUT_DEFAULT, null));
85  	}
86  
87  	
88  	public int append(String str) 
89  	{
90  		if (str == null) {
91  			throw new NullPointerException();
92  		}
93  
94  		return append(new StringItem(null, str));
95  	}
96  
97  	
98  	public void delete(int itemNum) 
99  	{
100 		verifyItemNum(itemNum);
101 
102 		items[itemNum].setOwner(null);
103 		System.arraycopy(items, itemNum + 1, items, itemNum, numOfItems - itemNum - 1);
104 		numOfItems--;
105 		
106 		repaint();
107 	}
108 	
109 	
110 	public void deleteAll()
111 	{
112 		for (int i = 0; i < numOfItems; i++) {
113 			items[i].setOwner(null);
114 		}
115 		numOfItems = 0;
116 		
117 		repaint();
118 	}
119 
120 	
121 	public Item get(int itemNum) 
122 	{
123 		verifyItemNum(itemNum);
124 
125 		return items[itemNum];
126 	}
127 	
128 	
129 	public int getHeight()
130 	{
131 		return super.getHeight();
132 	}
133 	
134 	
135 	public int getWidth()
136 	{
137 		return super.getWidth();
138 	}
139 
140 	
141 	public void insert(int itemNum, Item item) 
142 	{
143 		verifyItemNum(itemNum);
144 		verifyItem(item);
145 
146 		if (numOfItems + 1 == items.length) {
147 			Item newitems[] = new Item[numOfItems + 4];
148 			System.arraycopy(items, 0, newitems, 0, numOfItems);
149 			items = newitems;
150 		}
151 		System.arraycopy(
152 			items,
153 			itemNum,
154 			items,
155 			itemNum + 1,
156 			numOfItems - itemNum);
157 		items[itemNum] = item;
158 		items[itemNum].setOwner(this);
159 		numOfItems++;
160 		
161 		repaint();
162 	}
163 
164 	
165 	public void set(int itemNum, Item item) 
166 	{
167 		verifyItemNum(itemNum);
168 		verifyItem(item);
169 
170 		// TODO add this to MIDP1
171 		items[itemNum].setOwner(null);
172 		
173 		items[itemNum] = item;
174 		items[itemNum].setOwner(this);
175 		
176 		repaint();
177 	}
178 
179 	
180 	public void setItemStateListener(ItemStateListener iListener) 
181 	{
182 		itemStateListener = iListener;
183 	}
184 
185 	
186 	public int size() 
187 	{
188 		return numOfItems;
189 	}
190 
191 	
192 	int paintContent(Graphics g) 
193 	{
194 		int contentHeight = 0;
195 		int translateY;
196 		for (int i = 0; i < numOfItems; i++) {
197 			translateY = items[i].paint(g);
198 			g.translate(0, translateY);
199 			contentHeight += translateY;
200 		}
201 		g.translate(0, -contentHeight);
202 
203 		return contentHeight;
204 	}
205     
206     
207 	void fireItemStateListener(Item item) {
208         if (itemStateListener != null) {
209             itemStateListener.itemStateChanged(item);
210         }
211 	}
212 	
213 	void fireItemStateListener()
214     {
215 		if (focusItemIndex >= 0 && focusItemIndex < items.length)
216 			fireItemStateListener(items[focusItemIndex]);
217     }
218 
219 	
220 	void hideNotify() 
221 	{
222 		super.hideNotify();
223 		// TODO eliminate this to
224 		// allow focus restoring
225 		for (int i = 0; i < numOfItems; i++) {
226 			if (items[i].isFocusable() && items[i].hasFocus()) {
227 				items[i].setFocus(false);
228 				focusItemIndex = -2;
229 				break;
230 			}
231 		}
232 	}
233 
234 	
235 	void keyPressed(int keyCode) 
236 	{
237 		if (focusItemIndex != -1) {
238 			if (Display.getGameAction(keyCode) == Canvas.FIRE) {
239 				items[focusItemIndex].select();
240 				// why do we call this here?
241 				// Andres Navarro
242                 fireItemStateListener();
243 			} else {
244 				items[focusItemIndex].keyPressed(keyCode);
245 			}
246 		}
247 
248 		super.keyPressed(keyCode);
249 	}
250 
251 	
252 	void showNotify() 
253 	{
254 		super.showNotify();
255 		if (focusItemIndex == -2) {
256 			focusItemIndex = -1;
257 
258 			for (int i = 0; i < numOfItems; i++) {
259 				if (items[i].isFocusable()) {
260 					items[i].setFocus(true);
261 					focusItemIndex = i;
262 					break;
263 				}
264 			}
265 		}
266 		if (focusItemIndex < 0)
267 			return;
268 		int heightToItem = getHeightToItem(focusItemIndex);
269 		int heightAfterItem = heightToItem + items[focusItemIndex].getHeight();
270 		if (viewPortY > heightToItem) {
271 			viewPortY = heightToItem;
272 		} else if ((viewPortY + viewPortHeight) < heightAfterItem) {
273 			viewPortY = heightAfterItem - viewPortHeight;
274 		}
275 	}
276 	
277 	int traverse(int gameKeyCode, int top, int bottom) 
278 	{
279 		int height, testItemIndex, traverse, i;
280 		int topItemIndex, bottomItemIndex;
281 
282 		if (numOfItems == 0) {
283 			return 0;
284 		}
285 
286 		if (gameKeyCode == Canvas.UP) {
287 			topItemIndex = getTopVisibleIndex(top);
288 			if (focusItemIndex == -1) {
289 				testItemIndex = topItemIndex;
290 				height = getHeightToItem(testItemIndex);
291 				traverse =
292 					items[testItemIndex].traverse(
293 						gameKeyCode,
294 						top - height,
295 						bottom - height,
296 						false);
297 			} else {
298 				testItemIndex = focusItemIndex;
299 				height = getHeightToItem(testItemIndex);
300 				traverse =
301 					items[testItemIndex].traverse(
302 						gameKeyCode,
303 						top - height,
304 						bottom - height,
305 						true);
306 			}
307 			if (traverse != Item.OUTOFITEM) {
308 				if (focusItemIndex == -1
309 					&& items[testItemIndex].isFocusable()) {
310 					items[testItemIndex].setFocus(true);
311 					focusItemIndex = testItemIndex;
312 				}
313 				return traverse;
314 			} else {
315 				if (testItemIndex > 0) {
316 					// Czy istnieje obiekt focusable powyzej testItemIndex
317 					// widoczny na ekranie
318 					// jesli tak to zrob na nim traverse(false) i return
319 					// traverse
320 					for (i = testItemIndex - 1; i >= topItemIndex; i--) {
321 						if (items[i].isFocusable()) {
322 							if (focusItemIndex != -1) {
323 								items[focusItemIndex].setFocus(false);
324 							}
325 							items[i].setFocus(true);
326 							focusItemIndex = i;
327 							height = getHeightToItem(i);
328 							traverse =
329 								items[i].traverse(
330 									gameKeyCode,
331 									top - height,
332 									bottom - height,
333 									false);
334 							if (traverse == Item.OUTOFITEM) {
335 								return 0;
336 							} else {
337 								return traverse;
338 							}
339 						}
340 					}
341 					// Na najnizszym widocznym item zrob traverse(false)
342 					height = getHeightToItem(topItemIndex);
343 					traverse =
344 						items[topItemIndex].traverse(
345 							gameKeyCode,
346 							top - height,
347 							bottom - height,
348 							false);
349 					if (traverse == Item.OUTOFITEM) {
350 					} else {
351 						// Sprawdzenie czy znajduje sie powyzej na ekranie
352 						// focusable item
353 						// jesli tak zrob co trzeba
354 						bottomItemIndex = getTopVisibleIndex(bottom + traverse);
355 						if (focusItemIndex != -1
356 							&& focusItemIndex > bottomItemIndex) {
357 							items[focusItemIndex].setFocus(false);
358 							focusItemIndex = -1;
359 						}
360 						return traverse;
361 					}
362 				}
363 			}
364 		}
365 		if (gameKeyCode == Canvas.DOWN) {
366 			bottomItemIndex = getBottomVisibleIndex(bottom);
367 			if (focusItemIndex == -1) {
368 				testItemIndex = bottomItemIndex;
369 				height = getHeightToItem(testItemIndex);
370 				traverse =
371 					items[testItemIndex].traverse(
372 						gameKeyCode,
373 						top - height,
374 						bottom - height,
375 						false);
376 			} else {
377 				testItemIndex = focusItemIndex;
378 				height = getHeightToItem(testItemIndex);
379 				traverse =
380 					items[testItemIndex].traverse(
381 						gameKeyCode,
382 						top - height,
383 						bottom - height,
384 						true);
385 			}
386 			if (traverse != Item.OUTOFITEM) {
387 				if (focusItemIndex == -1
388 					&& items[testItemIndex].isFocusable()) {
389 					items[testItemIndex].setFocus(true);
390 					focusItemIndex = testItemIndex;
391 				}
392 				return traverse;
393 			} else {
394 				if (testItemIndex < numOfItems - 1) {
395 					// Czy istnieje obiekt focusable ponizej testItemIndex
396 					// widoczny na ekranie
397 					// jesli tak to zrob na nim traverse(false) i return
398 					// traverse
399 					for (i = testItemIndex + 1; i <= bottomItemIndex; i++) {
400 						if (items[i].isFocusable()) {
401 							if (focusItemIndex != -1) {
402 								items[focusItemIndex].setFocus(false);
403 							}
404 							items[i].setFocus(true);
405 							focusItemIndex = i;
406 							height = getHeightToItem(i);
407 							traverse =
408 								items[i].traverse(
409 									gameKeyCode,
410 									top - height,
411 									bottom - height,
412 									false);
413 							if (traverse == Item.OUTOFITEM) {
414 								return 0;
415 							} else {
416 								return traverse;
417 							}
418 						}
419 					}
420 					// Na najnizszym widocznym item zrob traverse(false)
421 					height = getHeightToItem(bottomItemIndex);
422 					traverse =
423 						items[bottomItemIndex].traverse(
424 							gameKeyCode,
425 							top - height,
426 							bottom - height,
427 							false);
428 					if (traverse == Item.OUTOFITEM) {
429 					} else {
430 						// Sprawdzenie czy znajduje sie powyzej na ekranie
431 						// focusable item
432 						// jesli tak zrob co trzeba
433 						topItemIndex = getTopVisibleIndex(top + traverse);
434 						if (focusItemIndex != -1
435 							&& focusItemIndex < topItemIndex) {
436 							items[focusItemIndex].setFocus(false);
437 							focusItemIndex = -1;
438 						}
439 						return traverse;
440 					}
441 				}
442 			}
443 		}
444 
445 		return 0;
446 	}
447 
448 	
449 	private int getTopVisibleIndex(int top) 
450 	{
451 		int height = 0;
452 
453 		for (int i = 0; i < numOfItems; i++) {
454 			height += items[i].getHeight();
455 			if (height >= top) {
456 				return i;
457 			}
458 		}
459 
460 		return numOfItems - 1;
461 	}
462 
463 	
464 	private int getBottomVisibleIndex(int bottom) 
465 	{
466 		int height = 0;
467 
468 		for (int i = 0; i < numOfItems; i++) {
469 			height += items[i].getHeight();
470 			if (height > bottom) {
471 				return i;
472 			}
473 		}
474 
475 		return numOfItems - 1;
476 	}
477 
478 	
479 	private int getHeightToItem(int itemIndex) 
480 	{
481 		int height = 0;
482 
483 		for (int i = 0; i < itemIndex; i++) {
484 			height += items[i].getHeight();
485 		}
486 
487 		return height;
488 	}
489 
490 	/**
491 	 * Verify that the item is non null and is not owned by this form or anyone
492 	 * else. If all is ok set the owner to this Form
493 	 * 
494 	 * @param item the item to be verified
495 	 * @throws IllegalStateException
496 	 * @throws NullPointerException
497 	 */
498 	private void verifyItem(Item item) 
499 	{
500 		// Check that we are being passed valid items
501 		if (item == null) {
502 			throw new NullPointerException("item is null");
503 		}
504 		if (item.getOwner() != null) {
505 			throw new IllegalStateException("item is already owned");
506 		}
507 		// All is ok make ourselves the owner
508 		item.setOwner(this);
509 	}
510 
511 	/**
512 	 * Verify that the index passed in is valid for this form. ie within the
513 	 * range 0..size-1
514 	 * 
515 	 * @param itemNum the number of the item
516 	 * @throws IndexOutOfBoundsException
517 	 */
518 	private void verifyItemNum(int itemNum) 
519 	{
520 		if (itemNum < 0 || itemNum >= numOfItems) {
521 			throw new IndexOutOfBoundsException("item number is outside range of Form");
522 		}
523 	}
524 
525 	Vector getCommands() {
526 		Vector formCommands = super.getCommands();
527 		if (focusItemIndex < 0)
528 			return formCommands;
529 		
530 		Item item = items[focusItemIndex];
531 		Vector itemCommands = item.commands;
532 		if (itemCommands.isEmpty())
533 			return formCommands;
534 
535 		// if the focused item has commands we
536 		// need a new Vector with the special commands
537 		// for the items (see code at the end of class
538 		// Command and in CommandManager for more info)
539 		Vector allCommands = new Vector();
540 		for (int i = 0; i < formCommands.size(); i++)
541 			allCommands.add(formCommands.elementAt(i));
542 		
543 		for (int i = 0; i < itemCommands.size(); i++) {
544 			Command itemCommand = (Command)itemCommands.elementAt(i);
545 			itemCommand = itemCommand.getItemCommand(item);
546 			allCommands.add(itemCommand);
547 		}
548 		return allCommands;
549 	}
550 }