View Javadoc

1   /*
2    * MicroEmulator 
3    * Copyright (C) 2001 Bartek Teodorczyk <barteo@barteo.net>
4    * 
5    * This library is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as published by the
7    * Free Software Foundation; either version 2.1 of the License, or (at your
8    * option) any later version.
9    * 
10   * This library is distributed in the hope that it will be useful, but WITHOUT
11   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12   * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13   * for more details.
14   * 
15   * You should have received a copy of the GNU Lesser General Public License
16   * along with this library; if not, write to the Free Software Foundation,
17   * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18   */
19  
20  package org.microemu.device.swt;
21  
22  import java.util.Enumeration;
23  import java.util.Iterator;
24  import java.util.Timer;
25  import java.util.TimerTask;
26  
27  import javax.microedition.lcdui.Canvas;
28  import javax.microedition.lcdui.Command;
29  
30  import org.eclipse.swt.SWT;
31  import org.eclipse.swt.events.KeyEvent;
32  import org.microemu.CommandManager;
33  import org.microemu.DisplayAccess;
34  import org.microemu.MIDletAccess;
35  import org.microemu.MIDletBridge;
36  import org.microemu.device.DeviceFactory;
37  import org.microemu.device.InputMethodEvent;
38  import org.microemu.device.impl.InputMethodImpl;
39  import org.microemu.device.impl.SoftButton;
40  
41  
42  public class SwtInputMethod extends InputMethodImpl 
43  {
44  	
45  	private Timer keyRepeatTimer;
46  	
47  	private int repeatModeKeyCode;
48  	
49  	private boolean clearRepeatFlag;
50  	
51  	
52  	private class KeyRepeatTask extends TimerTask
53  	{
54  		public void run() {
55  			if (repeatModeKeyCode != Integer.MIN_VALUE) {
56  				MIDletAccess ma = MIDletBridge.getMIDletAccess();
57  				if (ma == null) {
58  					return;
59  				}
60  				
61  				DisplayAccess da = ma.getDisplayAccess();
62  				if (da == null) {
63  					return;
64  				}
65  
66  				if (clearRepeatFlag) {
67  					da.keyReleased(repeatModeKeyCode);							
68  					repeatModeKeyCode = Integer.MIN_VALUE;
69  				}				
70  			}
71  		}
72  	};
73  	
74  	
75  	public SwtInputMethod()
76  	{
77  		super();
78  		
79  		// TODO When InputMethod will be removed from EmulatorContext add:
80  		// if (DeviceFactory.getDevice().hasRepeatEvents()) {
81  		keyRepeatTimer = new Timer();
82  		repeatModeKeyCode = Integer.MIN_VALUE;
83  		clearRepeatFlag = false;
84  	}
85  
86  	public int getGameAction(int keyCode)
87      {
88          // TODO fix KeyEvent
89          switch (keyCode) {
90              case SWT.ARROW_UP:
91                  return Canvas.UP;
92  
93              case SWT.ARROW_DOWN:
94                  return Canvas.DOWN;
95  
96              case SWT.ARROW_LEFT:
97                  return Canvas.LEFT;
98  
99              case SWT.ARROW_RIGHT:
100                 return Canvas.RIGHT;
101 
102             case SWT.CR:
103                 return Canvas.FIRE;
104 
105             /*
106              * case KeyEvent.VK_1: case KeyEvent.VK_A: return Canvas.GAME_A;
107              * 
108              * case KeyEvent.VK_3: case KeyEvent.VK_B: return Canvas.GAME_B;
109              * 
110              * case KeyEvent.VK_7: case KeyEvent.VK_C: return Canvas.GAME_C;
111              * 
112              * case KeyEvent.VK_9: case KeyEvent.VK_D: return Canvas.GAME_D;
113              */
114 
115             default:
116                 return 0;
117         }
118     }
119 
120 	
121     public int getKeyCode(int gameAction)
122     {
123         // TODO fix KeyEvent
124         switch (gameAction) {
125             case Canvas.UP:
126                 return SWT.ARROW_UP;
127 
128             case Canvas.DOWN:
129                 return SWT.ARROW_DOWN;
130 
131             case Canvas.LEFT:
132                 return SWT.ARROW_LEFT;
133 
134             case Canvas.RIGHT:
135                 return SWT.ARROW_RIGHT;
136 
137             case Canvas.FIRE:
138                 return SWT.CR;
139 
140             /*
141              * case Canvas.GAME_A: return KeyEvent.VK_1;
142              * 
143              * case Canvas.GAME_B: return KeyEvent.VK_3;
144              * 
145              * case Canvas.GAME_C: return KeyEvent.VK_7;
146              * 
147              * case Canvas.GAME_D: return KeyEvent.VK_9;
148              */
149 
150             default:
151                 throw new IllegalArgumentException();
152         }
153     }
154 
155 
156 	public String getKeyName(int keyCode) throws IllegalArgumentException
157     {
158 		for (Iterator it = DeviceFactory.getDevice().getButtons().iterator(); it.hasNext(); ) {
159 			SwtButton button = (SwtButton) it.next();
160 			if (button.getKeyCode() == keyCode) {
161 				return button.getName();
162 			}
163 		}
164 
165 		for (Iterator it = DeviceFactory.getDevice().getButtons().iterator(); it.hasNext(); ) {
166 			SwtButton button = (SwtButton) it.next();
167 			if (button.getKeyboardKey() == keyCode) {
168 				return button.getName();
169 			}
170 		}
171 
172 		throw new IllegalArgumentException();
173     }
174 
175 	
176 	private boolean commonKeyPressed(KeyEvent ev) 
177 	{
178 		int keyCode = ev.keyCode;
179 		if (inputMethodListener == null) {
180 			int midpKeyCode;
181 			switch (ev.keyCode) {
182 				case SWT.BS :
183 					return true;
184 				default :
185 					midpKeyCode = keyCode;
186 			}
187 			switch (ev.character) {
188 				case '*' :
189 					midpKeyCode = Canvas.KEY_STAR;
190 					break;
191 				case '#' :
192 					midpKeyCode = Canvas.KEY_POUND;
193 					break;
194 				default :
195 					midpKeyCode = keyCode;
196 			}
197 			MIDletBridge.getMIDletAccess().getDisplayAccess().keyPressed(midpKeyCode);
198 			return true;
199 		}
200 
201 		if (getGameAction(keyCode) == Canvas.UP || getGameAction(keyCode) == Canvas.DOWN) {
202 			MIDletBridge.getMIDletAccess().getDisplayAccess().keyPressed(keyCode);
203 			return true;
204 		}
205 
206 		// TODO fix KeyEvent
207 		/*
208 		 * if (keyCode == KeyEvent.VK_MODECHANGE) { if (getInputMode() ==
209 		 * InputMethod.INPUT_123) { setInputMode(InputMethod.INPUT_ABC_UPPER); }
210 		 * else if (getInputMode() == InputMethod.INPUT_ABC_UPPER) {
211 		 * setInputMode(InputMethod.INPUT_ABC_LOWER); } else if (getInputMode() ==
212 		 * InputMethod.INPUT_ABC_LOWER) { setInputMode(InputMethod.INPUT_123); }
213 		 * synchronized (this) { if (lastButton != null) { caret++; lastButton =
214 		 * null; lastButtonCharIndex = -1; } } InputMethodEvent event = new
215 		 * InputMethodEvent(InputMethodEvent.CARET_POSITION_CHANGED, caret,
216 		 * text); inputMethodListener.caretPositionChanged(event); return true;
217 		 */
218 
219 		int caret = inputMethodListener.getCaretPosition();
220 		
221 		if (getGameAction(keyCode) == Canvas.LEFT || getGameAction(keyCode) == Canvas.RIGHT) {
222 			synchronized (this) {
223 				if (getGameAction(keyCode) == Canvas.LEFT && caret > 0) {
224 					caret--;
225 				}
226 				if (getGameAction(keyCode) == Canvas.RIGHT && caret < inputMethodListener.getText().length()) {
227 					caret++;
228 				}
229 				lastButton = null;
230 				lastButtonCharIndex = -1;
231 			}
232 			InputMethodEvent event = new InputMethodEvent(InputMethodEvent.CARET_POSITION_CHANGED, caret, inputMethodListener.getText());
233 			inputMethodListener.caretPositionChanged(event);
234 			return true;
235 		}
236 
237 		if (keyCode == SWT.BS) {
238 			String tmp = inputMethodListener.getText();
239 			synchronized (this) {
240 				if (lastButton != null) {
241 					caret++;
242 					lastButton = null;
243 					lastButtonCharIndex = -1;
244 				}
245 				if (caret > 0) {
246 					caret--;
247 					tmp = "";
248 					if (caret > 0) {
249 						tmp += inputMethodListener.getText().substring(0, caret);
250 					}
251 					if (caret < inputMethodListener.getText().length() - 1) {
252 						tmp += inputMethodListener.getText().substring(caret + 1);
253 					}
254 				}
255 			}
256             if (!validate(tmp, inputMethodListener.getConstraints())) {
257                 return true;
258             }
259 			InputMethodEvent event = new InputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED, caret, tmp);
260 			inputMethodListener.inputMethodTextChanged(event);
261 			event = new InputMethodEvent(InputMethodEvent.CARET_POSITION_CHANGED, caret, tmp);
262 			inputMethodListener.caretPositionChanged(event);
263 			return true;
264 		}
265 		
266 		if (keyCode == SWT.DEL) {
267 			String tmp = inputMethodListener.getText();
268 			synchronized (this) {
269 				if (lastButton != null) {
270 					lastButton = null;
271 					lastButtonCharIndex = -1;
272 				}
273 				if (caret != inputMethodListener.getText().length()) {
274 					tmp = inputMethodListener.getText().substring(0, caret) + inputMethodListener.getText().substring(caret + 1);
275 				}
276 			}
277             if (!validate(tmp, inputMethodListener.getConstraints())) {
278                 return true;
279             }
280 			InputMethodEvent event = new InputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED, caret, tmp);
281 			inputMethodListener.inputMethodTextChanged(event);
282 			event = new InputMethodEvent(InputMethodEvent.CARET_POSITION_CHANGED, caret, tmp);
283 			inputMethodListener.caretPositionChanged(event);
284 			return true;
285 		}
286 		
287 		if (keyCode == SWT.SHIFT || keyCode == SWT.CTRL || keyCode == SWT.ALT) {
288 			return true;
289 		}
290 
291 		return false;
292 	}
293 
294 	
295 	public void keyPressed(KeyEvent ev) 
296 	{
297 		if (DeviceFactory.getDevice().hasRepeatEvents() && inputMethodListener == null) {
298 			clearRepeatFlag = false;
299 			if (repeatModeKeyCode == ev.keyCode) {
300 				MIDletAccess ma = MIDletBridge.getMIDletAccess();
301 				if (ma == null) {
302 					return;
303 				}
304 				
305 				DisplayAccess da = ma.getDisplayAccess();
306 				if (da == null) {
307 					return;
308 				}
309 
310 				da.keyRepeated(ev.keyCode);		
311 				
312 				return;
313 			}
314 			
315 			repeatModeKeyCode = ev.keyCode;			
316 		}
317 
318 		// invoke any associated commands, but send the raw key codes instead
319 		boolean rawSoftKeys = DeviceFactory.getDevice().getDeviceDisplay().isFullScreenMode();
320 		SwtButton pressedButton = getButton(ev);
321 		if (pressedButton != null) {
322 		    if (pressedButton instanceof SoftButton && !rawSoftKeys) {
323 			    Command cmd = ((SoftButton) pressedButton).getCommand();
324 			    if (cmd != null) {
325 					CommandManager.getInstance().commandAction(cmd);
326 					return;
327 			    }
328 			}
329 		}
330 
331 		if (commonKeyPressed(ev)) {
332 			return;
333 		}
334 
335 		if (inputMethodListener.getText().length() < maxSize && (ev.keyCode & SWT.EMBEDDED) == 0) {
336 			insertText(new Character(ev.character).toString());
337 		}
338 	}
339 
340 	
341 	public void keyReleased(KeyEvent ev) 
342 	{
343 		if (DeviceFactory.getDevice().hasRepeatEvents() && inputMethodListener == null) {
344 			clearRepeatFlag = true;
345 			keyRepeatTimer.schedule(new KeyRepeatTask(), 50);
346 		} else {		
347 			MIDletAccess ma = MIDletBridge.getMIDletAccess();
348 			if (ma == null) {
349 				return;
350 			}
351 			
352 			DisplayAccess da = ma.getDisplayAccess();
353 			if (da == null) {
354 				return;
355 			}
356 	
357 			da.keyReleased(ev.keyCode);
358 		}
359 	}
360 
361 	
362 	public void mousePressed(KeyEvent ev) 
363 	{
364 		if (commonKeyPressed(ev)) {
365 			return;
366 		}
367 
368 		if (inputMethodListener.getText().length() < maxSize) {
369 			for (Enumeration e = DeviceFactory.getDevice().getButtons().elements(); e.hasMoreElements();) {
370 				SwtButton button = (SwtButton) e.nextElement();
371 				if (ev.keyCode == button.getKeyCode()) {
372 					int caret = inputMethodListener.getCaretPosition();
373 					String tmp = inputMethodListener.getText();
374 					synchronized (this) {
375 						lastButtonCharIndex++;
376 						char[] buttonChars = filterConstraints(filterInputMode(button.getChars(getInputMode())));
377 						if (buttonChars.length > 0) {
378 							if (lastButtonCharIndex == buttonChars.length) {
379 								if (buttonChars.length == 1) {
380 									if (lastButton != null) {
381 										caret++;
382 									}
383 									lastButton = null;
384 								} else {
385 									lastButtonCharIndex = 0;
386 								}
387 							}
388 							if (lastButton != button) {
389 								if (lastButton != null) {
390 									caret++;
391 								}
392 								tmp = "";
393 								if (caret > 0) {
394 									tmp += inputMethodListener.getText().substring(0, caret);
395 								}
396 								tmp += buttonChars[0];
397 								if (caret < inputMethodListener.getText().length()) {
398 									tmp += inputMethodListener.getText().substring(caret);
399 								}
400 								lastButton = button;
401 								lastButtonCharIndex = 0;
402 							} else {
403 								tmp = "";
404 								if (caret > 0) {
405 									tmp += inputMethodListener.getText().substring(0, caret);
406 								}
407 								tmp += buttonChars[lastButtonCharIndex];
408 								if (caret < inputMethodListener.getText().length() - 1) {
409 									tmp += inputMethodListener.getText().substring(caret + 1);
410 								}
411 								lastButton = button;
412 							}
413 						} else {
414 							lastButton = null;
415 							lastButtonCharIndex = -1;
416 						}
417 						resetKey = false;
418 						notify();
419 					}
420                     if (!validate(tmp, inputMethodListener.getConstraints())) {
421                         return;
422                     }
423 					InputMethodEvent event = new InputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED, caret, tmp);
424 					inputMethodListener.inputMethodTextChanged(event);
425 					break;
426 				}
427 			}
428 		}
429 	}
430 
431 	
432 	public void mouseReleased(int keyCode) 
433 	{
434 		MIDletAccess ma = MIDletBridge.getMIDletAccess();
435 		if (ma == null) {
436 			return;
437 		}
438 		
439 		DisplayAccess da = ma.getDisplayAccess();
440 		if (da == null) {
441 			return;
442 		}
443 
444 		da.keyReleased(keyCode);
445 	}
446 
447 	
448 	public SwtButton getButton(KeyEvent ev)
449 	{
450 		for (Enumeration e = DeviceFactory.getDevice().getButtons().elements(); e.hasMoreElements(); ) {
451 			SwtButton button = (SwtButton) e.nextElement();
452 			if (ev.keyCode == button.getKeyCode()) {
453 				return button;
454 			}
455 			if (button.isChar(ev.character, getInputMode())) {
456 				return button;
457 			}
458 		}
459 		        
460 		return null;
461 	}
462 
463 }