157 private static final int FULLSCREEN_MODE = 1 << 2; |
157 private static final int FULLSCREEN_MODE = 1 << 2; |
158 |
158 |
159 private static final int DISABLE_TAPDETECTION = 1 << 3; |
159 private static final int DISABLE_TAPDETECTION = 1 << 3; |
160 private static final int SUPPRESS_GAMEKEYS = 1 << 4; |
160 private static final int SUPPRESS_GAMEKEYS = 1 << 4; |
161 private static final int SUPPRESS_DRAGEVENT = 1 << 5; |
161 private static final int SUPPRESS_DRAGEVENT = 1 << 5; |
162 private static final int CLEANUP_NEEDED = 1 << 6; |
|
163 private static final int REPAINT_PENDING = 1 << 7; |
162 private static final int REPAINT_PENDING = 1 << 7; |
164 private static final int SELECTIONKEY_COMPATIBILITY = 1 << 8; |
163 private static final int SELECTIONKEY_COMPATIBILITY = 1 << 8; |
165 |
164 |
166 private static final int CURRENTLY_VISIBLE = 1 << 9; |
165 private static final int CURRENTLY_VISIBLE = 1 << 9; |
167 |
166 |
203 private Composite canvasComp; |
202 private Composite canvasComp; |
204 private Label tickerLabel; |
203 private Label tickerLabel; |
205 |
204 |
206 private int mode; |
205 private int mode; |
207 private Object modeLock; |
206 private Object modeLock; |
208 private Object cleanupLock; |
|
209 private Object repaintLock; |
207 private Object repaintLock; |
210 private Object flushLock; |
208 private Object flushLock; |
211 |
209 |
212 private Timer timer = new Timer(); |
210 private Timer timer = new Timer(); |
213 private CanvasTimerTask timerTask; |
211 private CanvasTimerTask timerTask; |
237 objectCount++; |
235 objectCount++; |
238 } |
236 } |
239 |
237 |
240 modeLock = new Object(); |
238 modeLock = new Object(); |
241 repaintLock = new Object(); |
239 repaintLock = new Object(); |
242 cleanupLock = new Object(); |
|
243 flushLock = new Object(); |
240 flushLock = new Object(); |
244 setMode(GAME_CANVAS, this instanceof GameCanvas); |
241 setMode(GAME_CANVAS, this instanceof GameCanvas); |
245 construct(); |
242 construct(); |
246 keysPressed = new Vector(); |
243 keysPressed = new Vector(); |
247 } |
244 } |
297 */ |
294 */ |
298 Shell eswtConstructShell(int style) |
295 Shell eswtConstructShell(int style) |
299 { |
296 { |
300 if(isMode(GAME_CANVAS)) |
297 if(isMode(GAME_CANVAS)) |
301 { |
298 { |
302 mShell = super.eswtConstructShell(style); |
299 mShell = super.eswtConstructShell(style|SWT.NO_BACKGROUND); |
303 } |
300 } |
304 else |
301 else |
305 { |
302 { |
306 if(sharedShell == null) |
303 if(sharedShell == null) |
307 { |
304 { |
308 sharedShell = super.eswtConstructShell(style); |
305 sharedShell = super.eswtConstructShell(style|SWT.NO_BACKGROUND); |
309 } |
306 } |
310 mShell = sharedShell; |
307 mShell = sharedShell; |
311 } |
308 } |
312 |
309 |
313 // Give the Shell the maximized size already before it becomes visible |
310 // Give the Shell the maximized size already before it becomes visible |
593 * @param x - left bound of the rectangle to redraw. |
590 * @param x - left bound of the rectangle to redraw. |
594 * @param y - top bound of the rectangle to redraw. |
591 * @param y - top bound of the rectangle to redraw. |
595 * @param width - width of the rectangle to redraw. |
592 * @param width - width of the rectangle to redraw. |
596 * @param height - height of the rectangle to redraw. |
593 * @param height - height of the rectangle to redraw. |
597 */ |
594 */ |
598 public void repaint(int x, int y, int width, int height) |
595 public final void repaint(int x, int y, int width, int height) |
599 { |
596 { |
600 // Paint callback event is posted without any invalid area info. |
597 // Paint callback event is posted without any invalid area info. |
601 // Invalid area info is kept in the member variables. Only one event |
598 // Invalid area info is kept in the member variables. Only one event |
602 // per Canvas is added to the queue. If there are more repaint() calls |
599 // per Canvas is added to the queue. If there are more repaint() calls |
603 // before the already posted event has been served those are merged |
600 // before the already posted event has been served those are merged |
717 { |
714 { |
718 return true; |
715 return true; |
719 } |
716 } |
720 |
717 |
721 /** |
718 /** |
722 * Returns game action for a specified key code. |
719 * Returns game action associated with key code. |
723 * |
720 * |
724 * @param keyCode Key code to map to game action. |
721 * @param keyCode Key code to map to game action. |
725 * @return Game action for a a specified key code or |
722 * @return game action corresponding to key, or 0 if none |
726 * IllegalArgumentException. |
723 * @throws IllegalArgumentException if keyCode is not a valid |
727 */ |
724 */ |
728 public int getGameAction(int keyCode) |
725 public int getGameAction(int aKeyCode) |
729 { |
726 { |
730 return KeyTable.getGameAction(keyCode); |
727 if (aKeyCode == 0) |
|
728 { |
|
729 throw new IllegalArgumentException( |
|
730 MsgRepository.CANVAS_EXCEPTION_INVALID_KEY_CODE); |
|
731 } |
|
732 return KeyTable.getGameAction(aKeyCode); |
731 } |
733 } |
732 |
734 |
733 /** |
735 /** |
734 * Returns the key code specific for a certain game action. |
736 * Returns the key code specific for a certain game action. |
735 * |
737 * |
736 * @param gameAction - game action to be mapped to the key code. |
738 * @param gameAction - game action to be mapped to the key code. |
737 * @return Key code that is mapped to the specified game action. |
739 * @return Key code that is mapped to the specified game action. |
738 */ |
740 * @throws IllegalArgumentException for not valid gameAction |
739 public int getKeyCode(int gameAction) |
741 */ |
740 { |
742 public int getKeyCode(int aGameAction) |
741 return KeyTable.getKeyCode(gameAction); |
743 { |
|
744 int keyCode = KeyTable.getKeyCode(aGameAction); |
|
745 |
|
746 if (keyCode == 0) |
|
747 { |
|
748 throw new IllegalArgumentException( |
|
749 MsgRepository.CANVAS_EXCEPTION_INVALID_GAME_ACTION); |
|
750 } |
|
751 return keyCode; |
742 } |
752 } |
743 |
753 |
744 /** |
754 /** |
745 * Returns the key name specific for a certain key code. |
755 * Returns the key name specific for a certain key code. |
746 * |
756 * |
747 * @param keyCode - key name to get the name of. |
757 * @param keyCode - key name to get the name of. |
748 * @return String that contains textual name of the key specified by the key |
758 * @return String that contains textual name of the key specified by the key |
749 * code. |
759 * code. |
750 */ |
760 */ |
751 public String getKeyName(int keyCode) |
761 public String getKeyName(int aKeyCode) |
752 { |
762 { |
753 return KeyTable.getKeyName(keyCode); |
763 return KeyTable.getKeyName(aKeyCode); |
754 } |
764 } |
755 |
765 |
756 /** |
766 /** |
757 * Callback to be implemented by the application to render the |
767 * Callback to be implemented by the application to render the |
758 * <code>Canvas</code>. The clip region of <code>Graphics</code> object |
768 * <code>Canvas</code>. The clip region of <code>Graphics</code> object |
961 super.handleShellActivatedEvent(); |
971 super.handleShellActivatedEvent(); |
962 |
972 |
963 // reset the game key state |
973 // reset the game key state |
964 gameKeyState = 0; |
974 gameKeyState = 0; |
965 |
975 |
966 synchronized(cleanupLock) |
|
967 { |
|
968 setMode(CLEANUP_NEEDED, true); |
|
969 } |
|
970 |
|
971 LCDUIEvent event = EventDispatcher.instance().newEvent(LCDUIEvent.CANVAS_SHOWNOTIFY, this); |
976 LCDUIEvent event = EventDispatcher.instance().newEvent(LCDUIEvent.CANVAS_SHOWNOTIFY, this); |
972 EventDispatcher.instance().postEvent(event); |
977 EventDispatcher.instance().postEvent(event); |
973 } |
978 } |
974 |
979 |
975 /** |
980 /** |
990 super.eswtHandleResizeEvent(width, height); |
995 super.eswtHandleResizeEvent(width, height); |
991 // update new bounds to graphicsBuffer |
996 // update new bounds to graphicsBuffer |
992 // this call must not be synchronized as we |
997 // this call must not be synchronized as we |
993 // cannot use locking in UI thread |
998 // cannot use locking in UI thread |
994 graphicsBuffer.setControlBounds(getContentComp()); |
999 graphicsBuffer.setControlBounds(getContentComp()); |
995 synchronized(cleanupLock) |
|
996 { |
|
997 setMode(CLEANUP_NEEDED, true); |
|
998 } |
|
999 } |
1000 } |
1000 |
1001 |
1001 /* |
1002 /* |
1002 * UI thread calls |
1003 * UI thread calls |
1003 */ |
1004 */ |
1172 canvasGraphics = graphicsBuffer.getGraphics(); |
1173 canvasGraphics = graphicsBuffer.getGraphics(); |
1173 canvasGraphics.setSyncStrategy(Graphics.SYNC_LEAVE_SURFACE_SESSION_OPEN); |
1174 canvasGraphics.setSyncStrategy(Graphics.SYNC_LEAVE_SURFACE_SESSION_OPEN); |
1174 } |
1175 } |
1175 |
1176 |
1176 // Clean the background if dirty, buffer the operations. |
1177 // Clean the background if dirty, buffer the operations. |
1177 synchronized(cleanupLock) |
1178 if(isMode(NO_BACKGROUND) && event.type == LCDUIEvent.CANVAS_PAINT_NATIVE_REQUEST) |
1178 { |
1179 { |
1179 if(isMode(CLEANUP_NEEDED) && isMode(NO_BACKGROUND)) |
1180 canvasGraphics.setClip(event.x, event.y, event.width, event.height); |
1180 { |
1181 canvasGraphics.cleanBackground(new Rectangle(event.x, event.y, event.width, event.height)); |
1181 // UI thread can change the contentArea object reference at |
|
1182 // any time. Store the object reference locally to ensure it |
|
1183 // points to the same rectangle all the time. |
|
1184 Rectangle contentArea = getContentArea(); |
|
1185 |
|
1186 canvasGraphics.setClip(contentArea.x, contentArea.y, |
|
1187 contentArea.width, contentArea.height); |
|
1188 canvasGraphics.cleanBackground(contentArea); |
|
1189 setMode(CLEANUP_NEEDED, false); |
|
1190 } |
|
1191 } |
1182 } |
1192 |
1183 |
1193 // Clip must define the invalid area |
1184 // Clip must define the invalid area |
1194 canvasGraphics.reset(); |
1185 canvasGraphics.reset(); |
1195 canvasGraphics.setClip(redrawNowX, redrawNowY, redrawNowW, redrawNowH); |
1186 canvasGraphics.setClip(redrawNowX, redrawNowY, redrawNowW, redrawNowH); |
1336 } |
1327 } |
1337 |
1328 |
1338 /** |
1329 /** |
1339 * Updates game key states and returns if the key was a game key. |
1330 * Updates game key states and returns if the key was a game key. |
1340 */ |
1331 */ |
1341 private boolean updateGameKeyState(int keyCode, boolean addKeyState) |
1332 private boolean updateGameKeyState(int aKeyCode, boolean aAddKeyState) |
1342 { |
1333 { |
1343 // Ignore key repeat events |
1334 // Ignore key repeat events |
1344 if(ESWTUIThreadRunner.getKeyRepeatCount() > 1) |
1335 if(ESWTUIThreadRunner.getKeyRepeatCount() > 1) |
1345 { |
1336 { |
1346 return true; |
1337 return true; |
1347 } |
1338 } |
1348 try |
1339 try |
1349 { |
1340 { |
1350 int gameAction = KeyTable.getGameAction(keyCode); |
1341 int gameAction = getGameAction(aKeyCode); |
1351 if(addKeyState) |
1342 boolean result = false; |
1352 { |
1343 |
1353 // set bitfield |
1344 // Key state should be updated only if game action |
1354 gameKeyState |= (1 << gameAction); |
1345 // is associated with keyCode |
1355 } |
1346 if(gameAction != 0) |
1356 return true; |
1347 { |
|
1348 if(aAddKeyState) |
|
1349 { |
|
1350 // set bitfield |
|
1351 gameKeyState |= (1 << gameAction); |
|
1352 } |
|
1353 result = true; |
|
1354 } |
|
1355 return result; |
1357 } |
1356 } |
1358 catch(IllegalArgumentException iae) |
1357 catch(IllegalArgumentException iae) |
1359 { |
1358 { |
1360 return false; |
1359 return false; |
1361 } |
1360 } |