javauis/lcdui_qt/src/javax/microedition/lcdui/CanvasKeypad.java
author hgs
Mon, 04 Oct 2010 11:29:25 +0300
changeset 78 71ad690e91f5
parent 57 59b3b4473dc8
permissions -rw-r--r--
v2.2.17_1

/*
 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
 * All rights reserved.
 * This component and the accompanying materials are made available
 * under the terms of "Eclipse Public License v1.0"
 * which accompanies this distribution, and is available
 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
 *
 * Initial Contributors:
 * Nokia Corporation - initial contribution.
 *
 * Contributors:
 *
 * Description:
 *
 */
package javax.microedition.lcdui;

import java.util.Timer;
import java.util.TimerTask;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.extension.ImageUtil;
import org.eclipse.swt.internal.qt.*;

import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;

/**
 * The CanvasKeypad class is designed to generate the on screen keypad and
 * handle graphical operations as well as low-level pointer events. CanvasKeypad
 * maps the pointer events to key events that are needed by the Canvas.
 * 
 */
final class CanvasKeypad implements MouseListener, MouseMoveListener
{
    /**
     * Constant for <code>UP</code> game action.
     */
    private static final int UP = -1;

    /**
     * Constant for <code>DOWN</code> game action.
     */
    private static final int DOWN = -2;

    /**
     * Constant for <code>LEFT</code> game action.
     */
    private static final int LEFT = -3;

    /**
     * Constant for <code>RIGHT</code> game action.
     */
    private static final int RIGHT = -4;

    /**
     * Constant for <code>FIRE</code> game action.
     */
    private static final int FIRE = -5;

    /**
     * Constant for <code>SLK</code> game action.
     */
    private static final int SLK = -6;

    /**
     * Constant for <code>SRK</code> game action.
     */
    private static final int SRK = -7;

    /**
     * Constant for general "<code>A</code>" game action.
     */
    private static final int GAME_A = 55;

    /**
     * Constant for general "<code>B</code>" game action.
     */
    private static final int GAME_B = 57;

    /**
     * Constant for general "<code>C</code>" game action.
     */
    private static final int GAME_C = 42;

    /**
     * Constant for general "<code>D</code>" game action.
     */
    private static final int GAME_D = 35;

    /**
     * Constant for general invalid key code.
     */
    private static final int INVALID_CODE = -99;

    /**
     * Constant for long keypress timeout.
     */
    private static final int KEYREPEAT_INTERVAL = 500;

    /**
     * Alpha value of a transparent pixel.
     */
    private static final int TRANSPARENT = 0;

    /**
     * Keypad and game keys composites.
     */
    private Composite keypadComposite;
    private Composite gameKeysComposite;
    private Canvas canvas;

    /**
     * CSS engine instance
     */
    private BaseCSSEngine cssEngine;

    /**
     * Canvas keypad buttons.
     */
    private Label center;
    private Label up;
    private Label down;
    private Label left;
    private Label right;

    private org.eclipse.swt.graphics.Image center_normal;
    private org.eclipse.swt.graphics.Image center_pressed;
    private org.eclipse.swt.graphics.Image left_normal;
    private org.eclipse.swt.graphics.Image left_pressed;
    private org.eclipse.swt.graphics.Image right_normal;
    private org.eclipse.swt.graphics.Image right_pressed;
    private org.eclipse.swt.graphics.Image up_normal;
    private org.eclipse.swt.graphics.Image up_pressed;
    private org.eclipse.swt.graphics.Image down_normal;
    private org.eclipse.swt.graphics.Image down_pressed;

    private ImageData center_data;
    private ImageData left_data;
    private ImageData right_data;
    private ImageData up_data;
    private ImageData down_data;

    private ImageData pressedKeyData;

    private Button skright;
    private Button skleft;
    private Button gameA;
    private Button gameB;
    private Button gameC;
    private Button gameD;

    private Display display;

    private int keyPressed;
    private Label rockerKeyPressed;

    /**
     * Timer for handling long key press and mouse move events.
     */
    private Timer timer = new Timer();
    private CanvasKeypadTimerTask timerTask;

    /**
     * Path of the osk graphics
     */
    private static final String RESOURCE_PATH = "c:/data/images/";

    /**
     * Offset on the composite in pixels where the osk rocker keys are layed
     * out.
     */
    private int image_offset;

    /**
     * Constructs a canvas kepad based on the JAD attribute
     * 
     * @param canvas
     *            - canvas for which the keypad is required.
     * @param mode
     *            - the jad attribute as a string.
     */
    CanvasKeypad(Canvas canvas, String mode)
    {

        this.canvas = canvas;
        display = ESWTUIThreadRunner.getInstance().getDisplay();

        cssEngine = new BaseCSSEngine(display);

        // Load the images
        center_normal = ImageUtil.createImageFromTheme(display, "qtg_fr_rocker_normal_c");
        center_pressed = ImageUtil.createImageFromTheme(display, "qtg_fr_rocker_pressed_c");
        left_normal = ImageUtil.createImageFromTheme(display, "qtg_fr_rocker_normal_l");
        left_pressed = ImageUtil.createImageFromTheme(display, "qtg_fr_rocker_pressed_l");
        right_normal = ImageUtil.createImageFromTheme(display, "qtg_fr_rocker_normal_r");
        right_pressed = ImageUtil.createImageFromTheme(display, "qtg_fr_rocker_pressed_r");
        up_normal = ImageUtil.createImageFromTheme(display, "qtg_fr_rocker_normal_t");
        up_pressed = ImageUtil.createImageFromTheme(display, "qtg_fr_rocker_pressed_t");
        down_normal = ImageUtil.createImageFromTheme(display, "qtg_fr_rocker_normal_b");
        down_pressed = ImageUtil.createImageFromTheme(display, "qtg_fr_rocker_pressed_b");

        image_offset = (display.getBounds().width / 2) - (center_normal.getBounds().width / 2);

        // Load image data required to determine the osk button pressed on mouse events
        center_data = center_normal.getImageData();
        left_data = left_normal.getImageData();
        right_data = right_normal.getImageData();
        up_data = up_normal.getImageData();
        down_data = down_normal.getImageData();

        // Set form layout for the shell containing the canvas.
        canvas.getShell().setLayout(new FormLayout());

        // Create the Navigation keypad
        createNavKeypad();

        // Check if game keys are needed
        if (mode.equalsIgnoreCase("gameactions"))
        {
            createGamePad();
        }

        // Layout the game keys, navigation keys and the canvas composites on
        // the shell using form layout
        FormData canvasData = new FormData();
        canvasData.right = new FormAttachment(100);
        canvasData.left = new FormAttachment(0);
        canvasData.top = new FormAttachment(0);
        canvasData.bottom = new FormAttachment(keypadComposite);
        canvas.getContentComp().setLayoutData(canvasData);

        FormData navKeyData = new FormData();
        navKeyData.right = new FormAttachment(100);
        navKeyData.left = new FormAttachment(0);

        if (gameKeysComposite != null)
        {
            // Game keypad was created above, so layout the game keys.
            navKeyData.bottom = new FormAttachment(gameKeysComposite);
        }
        else
        {
            // Game keys are not needed
            navKeyData.bottom = new FormAttachment(100);
        }

        keypadComposite.setLayoutData(navKeyData);

        if (gameKeysComposite != null)
        {
            // Game keys were created, layout the game keys
            FormData gameKeyData = new FormData();
            gameKeyData.right = new FormAttachment(100);
            gameKeyData.left = new FormAttachment(0);
            gameKeyData.bottom = new FormAttachment(100);
            gameKeysComposite.setLayoutData(gameKeyData);
        }

        canvas.getShell().layout();
    }

    /**
     * creates the navigation keypad - the directional keys and selctio key.
     */
    private void createNavKeypad()
    {
        // Create the navigation key composite
        keypadComposite = new Composite(canvas.getShell(), SWT.NONE);

        center = new Label(keypadComposite, SWT.NONE);
        left = new Label(keypadComposite, SWT.NONE);
        right = new Label(keypadComposite, SWT.NONE);
        up = new Label(keypadComposite, SWT.NONE);
        down = new Label(keypadComposite, SWT.NONE);

        center.setImage(center_normal);
        center.pack();
        left.setImage(left_normal);
        left.pack();
        right.setImage(right_normal);
        right.pack();
        up.setImage(up_normal);
        up.pack();
        down.setImage(down_normal);
        down.pack();

        // layout the navigation keys
        keypadComposite.setLayout(new FormLayout());

        FormData navkeysFormData = new FormData();
        navkeysFormData.top = new FormAttachment(0);
        navkeysFormData.left = new FormAttachment(0, image_offset);
        center.setLayoutData(navkeysFormData);
        left.setLayoutData(navkeysFormData);
        right.setLayoutData(navkeysFormData);
        up.setLayoutData(navkeysFormData);
        down.setLayoutData(navkeysFormData);

        keypadComposite.pack(); // will also layout

        // The down Label will catch all mouse down events as it is covering
        // all other rocker Labels, with the assumption that they all have 
        // the same bounds!
        down.addMouseListener(this);
        down.addMouseMoveListener(this);
        
        // We want to catch all drag events occurring on top of the rocker 
        // including those starting outside. 
        keypadComposite.addMouseListener(this);
        keypadComposite.addMouseMoveListener(this);
    }

    /**
     * creates the game keypad - the game action keys A, B, C and D.
     */
    private void createGamePad()
    {
        // create the game pad composite
        gameKeysComposite = new Composite(canvas.getShell(), SWT.NONE);
        gameKeysComposite.setLayout(new FormLayout());

        // Add the game buttons
        gameA = new Button(gameKeysComposite, SWT.PUSH);
        gameA.addMouseListener(this);

        gameB = new Button(gameKeysComposite, SWT.PUSH);
        gameB.addMouseListener(this);

        gameC = new Button(gameKeysComposite, SWT.PUSH);
        gameC.addMouseListener(this);

        gameD = new Button(gameKeysComposite, SWT.PUSH);
        gameD.addMouseListener(this);

        // Set the game key style sheets
        cssEngine.applyCSS(gameA, "QPushButton" + "{" + "background-color:white;"
            + "border-style: outset;" + "border-width: 1px; " + "border-color: black;"
            + "border-radius: 2px;" + "font: bold 14px;" + "min-height: 2em;" + "min-width: 5.1em;"
            + "}"
            + "QPushButton:pressed { border-style: inset;" + "}");
        cssEngine.applyCSS(gameB, "QPushButton" + "{" + "background-color:white;"
            + "border-style: outset;" + "border-width: 1px; " + "border-color: black;"
            + "border-radius: 2px;" + "font: bold 14px;" + "min-height: 2em;" + "min-width: 5.1em;"
            + "}"
            + "QPushButton:pressed { border-style: inset;" + "}");
        cssEngine.applyCSS(gameC, "QPushButton" + "{" + "background-color:white;"
            + "border-style: outset;" + "border-width: 1px; " + "border-color: black;"
            + "border-radius: 2px;" + "font: bold 14px;" + "min-height: 2em;" + "min-width: 5.1em;"
            + "}"
            + "QPushButton:pressed { border-style: inset;" + "}");
        cssEngine.applyCSS(gameD, "QPushButton" + "{" + "background-color:white;"
            + "border-style: outset;" + "border-width: 1px; " + "border-color: black;"
            + "border-radius: 2px;" + "font: bold 14px;" + "min-height: 2em;" + "min-width: 5.1em;"
            + "}"
            + "QPushButton:pressed { border-style: inset;" + "}");
            
        gameA.setText("A");
		    gameB.setText("B");
		    gameC.setText("C");
		    gameD.setText("D");

        // layout the game Keys
        FormData gameAFormData = new FormData();
        gameAFormData.bottom = new FormAttachment(100, 0);
        gameAFormData.left = new FormAttachment(0, 0);
        gameA.setLayoutData(gameAFormData);

        FormData gameBFormData = new FormData();
        gameBFormData.bottom = new FormAttachment(100, 0);
        gameBFormData.left = new FormAttachment(gameA, 0);
        gameB.setLayoutData(gameBFormData);

        FormData gameCFormData = new FormData();
        gameCFormData.bottom = new FormAttachment(100, 0);
        gameCFormData.left = new FormAttachment(gameB, 0);
        gameC.setLayoutData(gameCFormData);

        FormData gameDFormData = new FormData();
        gameDFormData.bottom = new FormAttachment(100, 0);
        gameDFormData.left = new FormAttachment(gameC, 0);
        gameD.setLayoutData(gameDFormData);

        gameKeysComposite.layout();
    }

    /**
     * Handles orientation changes.
     */
    void handleOrientationChange(int mode)
    {
        // change the layout as per orientation mode
    }

    /**
     * Sets the currect Canvas for Key events.
     * 
     * @param canvas
     *            - Current Canvas to which the key events needs to be
     *            delivered.
     */
    void setCurrentCanvas(Canvas canvas)
    {
        this.canvas = canvas;
    }

    /**
     * Adds LSk and RSK keys to navigation keypad if the canvas is set to full
     * screen mode.
     * 
     * @param mode
     *            - Indicates if the canvas is in fullscreen mode or not. True
     *            if fullscreen, False otherwise.
     */
    void setFullScreenMode(boolean mode)
    {

        // add the soft keys if the canvas is set to full screen mode/remove
        // otherwise
        if (mode == true)
        {

            if (keypadComposite != null)
            {

                Color black = display.getSystemColor(SWT.COLOR_BLACK);
                keypadComposite.setBackground(black);

                skright = new Button(keypadComposite, SWT.PUSH);
                skright.addMouseListener(this);

                skleft = new Button(keypadComposite, SWT.PUSH);
                skleft.addMouseListener(this);

                // Set the style sheet
                cssEngine.applyCSS(skright, "QPushButton" + "{" + "background-color:white;"
                    + "border-style: outset;" + "border-width: 1px; "
                    + "border-bottom-left-radius: 22px;" + "border-color: black;"
                    + "font: bold 14px;" + "min-width: 3em;" + "min-height: 2em;" + "}"
                    + "QPushButton:pressed { border-style: inset;" + "}");

                cssEngine.applyCSS(skleft, "QPushButton" + "{" + "background-color:white;"
                    + "border-style: outset;" + "border-width: 1px; "
                    + "border-bottom-right-radius: 22px;" + "border-color: black;"
                    + "font: bold 14px;" + "min-width: 3em;" + "min-height: 2em;" + "}"
                    + "QPushButton:pressed { border-style: inset;" + "}");
                    
                skleft.setText("LSK");
                skright.setText("RSK");

                FormData sklFormData = new FormData();
                sklFormData.top = new FormAttachment(0, 0);
                sklFormData.left = new FormAttachment(0, 0);
                skleft.setLayoutData(sklFormData);

                FormData skrFormData = new FormData();
                skrFormData.top = new FormAttachment(0, 0);
                skrFormData.right = new FormAttachment(100, 0);
                skright.setLayoutData(skrFormData);

                keypadComposite.layout();
            }
        }
        else
        {
            // LSK and RSK buttons are not needed, remove the buttons from
            // navigation keypad
            if (skright != null)
                skright.dispose();
            if (skleft != null)
                skleft.dispose();

            keypadComposite.setBackground(null);
        }

    }

    /**
     * returns the height of the canvas keypad in pixels.
     * 
     * @return Height of the canvas keypad in pixels.
     */
    int getHeight()
    {

        int navKeyPadHeight = 0;
        int gameKeyPadHeight = 0;

        if (keypadComposite != null)
        {
            // calculate the navigation keypad height
            navKeyPadHeight = keypadComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT).y;
        }

        if (gameKeysComposite != null)
        {
            // calculate the game keypad height
            gameKeyPadHeight = gameKeysComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT).y;
        }

        // return the total height
        return (navKeyPadHeight + gameKeyPadHeight);
    }

    /**
     * returns the keycode corresponding to the canvas keypad button.
     * 
     * @return keycode.
     */
    private int getKeyCode(Widget w)
    {
        int keyCode = INVALID_CODE;

        // Find out which osk button was pressed
        if (w == up)
        {
            keyCode = UP;
        }
        else if (w == down)
        {
            keyCode = DOWN;
        }
        else if (w == left)
        {
            keyCode = LEFT;
        }
        else if (w == right)
        {
            keyCode = RIGHT;
        }
        else if (w == center)
        {
            keyCode = FIRE;
        }
        else if (w == skleft)
        {
            keyCode = SLK;
        }
        else if (w == skright)
        {
            keyCode = SRK;
        }
        else if (w == gameA)
        {
            keyCode = GAME_A;
        }
        else if (w == gameB)
        {
            keyCode = GAME_B;
        }
        else if (w == gameC)
        {
            keyCode = GAME_C;
        }
        else if (w == gameD)
        {
            keyCode = GAME_D;
        }
        else
        {
            keyCode = INVALID_CODE;
        }

        return keyCode;
    }

    /**
     * Mouse listeners.
     */
    public void mouseDown(MouseEvent e)
    {
        handleMouseDown(e);
    }

    public void mouseUp(MouseEvent e)
    {
        handleMouseUp(e);
    }

    public void mouseMove(MouseEvent e)
    {
        handleMouseMove(e);
    }

    public void mouseDoubleClick(MouseEvent event)
    {
        // Do nothing
    }

    /**
     * Handles the mouse down event
     * Note that e.x and e.y are relative to the widget that was pressed.
     */
    private void handleMouseDown(MouseEvent e)
    {
        if (e.widget == down) // highest in the z-order
        {
            keyPressed = handleRockerPressed(e);
        }
        else
        {
            keyPressed = getKeyCode(e.widget);
        }

        if (keyPressed != INVALID_CODE)
        {
            canvas.doKeyPressed(keyPressed);

            timerTask = new CanvasKeypadTimerTask();
            timer.schedule(timerTask, KEYREPEAT_INTERVAL);
        }
    }

    /**
     * Handles the mouse up event
     * Note that e.x and e.y are relative to the widget that was pressed.
     */
    private void handleMouseUp(MouseEvent e)
    {
        int keyReleased;

        if (timerTask != null)
        {
            timerTask.cancel();
            timerTask = null;
        }

        if (e.widget == down || e.widget == keypadComposite)
        {
            keyReleased = handleRockerReleased(e);
        }
        else
        {
            keyReleased = getKeyCode(e.widget);
        }

        if (keyReleased != INVALID_CODE)
        {
            canvas.doKeyReleased(keyReleased);
        }
    }

    /**
     * Handles the mouse move event
     * Note that e.x and e.y are relative to the widget that was pressed.
     */
    private void handleMouseMove(MouseEvent e)
    {
        if (timerTask != null)
        {
            timerTask.cancel();
            timerTask = null;
        }
        
        if (e.widget == down || e.widget == keypadComposite)
        {
            handleRockerMoved(e);    
        }
        else
        {
            keyPressed = getKeyCode(e.widget);
            canvas.doKeyPressed(keyPressed);
            timerTask = new CanvasKeypadTimerTask();
            timer.schedule(timerTask, KEYREPEAT_INTERVAL);
        }
    }

    /**
     * Handles the rocker key press
     */
    private int handleRockerPressed(MouseEvent e)
    {
        keyPressed = INVALID_CODE;
        
        Point rockerSize = center.getSize();
        if (e.x >= 0 && e.x <= rockerSize.x && e.y >= 0 && e.y <= rockerSize.y)
        {
            if (center_data.getAlpha(e.x, e.y) != TRANSPARENT)
            {
                keyPressed = FIRE;
                rockerKeyPressed = center;
                center.setImage(center_pressed);
            }
            else if (left_data.getAlpha(e.x, e.y) != TRANSPARENT)
            {
                keyPressed = LEFT;
                rockerKeyPressed = left;
                left.setImage(left_pressed);
            }
            else if (right_data.getAlpha(e.x, e.y) != TRANSPARENT)
            {
                keyPressed = RIGHT;
                rockerKeyPressed = right;
                right.setImage(right_pressed);
            }
            else if (up_data.getAlpha(e.x, e.y) != TRANSPARENT)
            {
                keyPressed = UP;
                rockerKeyPressed = up;
                up.setImage(up_pressed);
            }
            else if (down_data.getAlpha(e.x, e.y) != TRANSPARENT)
            {
                keyPressed = DOWN;
                rockerKeyPressed = down;
                down.setImage(down_pressed);
            }
            else
            {
                keyPressed = INVALID_CODE;
            }
        }

        return keyPressed;
    }

    /**
     * Handles the mouse released on the rocker keys
     */
    private int handleRockerReleased(MouseEvent e)
    {
        int keyReleased = INVALID_CODE;

        Point rockerSize = center.getSize();
        Point rockerLoc = center.getLocation();
        
        if (e.widget == keypadComposite)
        {
            // Drag started outside rocker
            e.x -= rockerLoc.x;
            e.y -= rockerLoc.y;
        }

        if (e.x >= 0 && e.x <= rockerSize.x && e.y >= 0 && e.y <= rockerSize.y)
        {
            if ((rockerKeyPressed == center)
                && (center_data.getAlpha(e.x, e.y) != TRANSPARENT))
            {
                keyReleased = FIRE;
                center.setImage(center_normal);
            }
            else if ((rockerKeyPressed == left)
                && (left_data.getAlpha(e.x, e.y) != TRANSPARENT))
            {
                keyReleased = LEFT;
                left.setImage(left_normal);
            }
            else if ((rockerKeyPressed == right)
                && (right_data.getAlpha(e.x, e.y) != TRANSPARENT))
            {
                keyReleased = RIGHT;
                right.setImage(right_normal);
            }
            else if ((rockerKeyPressed == up)
                && (up_data.getAlpha(e.x, e.y) != TRANSPARENT))
            {
                keyReleased = UP;
                up.setImage(up_normal);
            }
            else if ((rockerKeyPressed == down)
                && (down_data.getAlpha(e.x, e.y) != TRANSPARENT))
            {
                keyReleased = DOWN;
                down.setImage(down_normal);
            }
            else
            {
                keyReleased = INVALID_CODE;
            }
        }

        return keyReleased;
    }

    /**
     * Handles the mouse move on the rocker keys
     */
    private void handleRockerMoved(MouseEvent e)
    {
        keyPressed = INVALID_CODE;
        Point size = center.getSize();
        Point rockerLoc = center.getLocation();
        
        if (e.widget == keypadComposite)
        {
            // Drag started outside rocker
            e.x -= rockerLoc.x;
            e.y -= rockerLoc.y;
        }

        if (e.x >= 0 && e.x <= size.x && e.y >= 0 && e.y <= size.y)
        {
            if ((center_data.getAlpha(e.x, e.y) != TRANSPARENT)
                && (rockerKeyPressed != center))
            {
                // Mouse moved to center rocker key from another rocker key,
                // release the other(source) rocker key
                releaseRockerKey(rockerKeyPressed);
            }
            else if ((left_data.getAlpha(e.x, e.y) != TRANSPARENT)
                && (rockerKeyPressed != left))
            {
                // Mouse moved to left rocker key from another rocker key,
                // release the other(source) rocker key
                // and press the left key
                releaseRockerKey(rockerKeyPressed);
                keyPressed = LEFT;
                left.setImage(left_pressed);
                rockerKeyPressed = left;
                canvas.doKeyPressed(keyPressed);
                pressedKeyData = left_data;
            }
            else if ((right_data.getAlpha(e.x, e.y) != TRANSPARENT)
                && (rockerKeyPressed != right))
            {
                // Mouse moved to right rocker key from another rocker key,
                // release the other(source) rocker key
                // and press the right key
                releaseRockerKey(rockerKeyPressed);
                keyPressed = RIGHT;
                right.setImage(right_pressed);
                rockerKeyPressed = right;
                canvas.doKeyPressed(keyPressed);
                pressedKeyData = right_data;
            }
            else if ((up_data.getAlpha(e.x, e.y) != TRANSPARENT)
                && (rockerKeyPressed != up))
            {
                // Mouse moved to up rocker key from another rocker key, release
                // the other(source) rocker key
                // and press the up key
                releaseRockerKey(rockerKeyPressed);
                keyPressed = UP;
                up.setImage(up_pressed);
                canvas.doKeyPressed(keyPressed);
                rockerKeyPressed = up;
                pressedKeyData = up_data;
            }
            else if ((down_data.getAlpha(e.x, e.y) != TRANSPARENT)
                && (rockerKeyPressed != down))
            {
                // Mouse moved to down rocker key from another rocker key,
                // release the other(source) rocker key
                // and press the down key
                releaseRockerKey(rockerKeyPressed);
                keyPressed = DOWN;
                down.setImage(down_pressed);
                rockerKeyPressed = down;
                canvas.doKeyPressed(keyPressed);
                pressedKeyData = down_data;
            }
            else
            {
                if ((pressedKeyData != null)
                    && (pressedKeyData.getAlpha(e.x, e.y) == TRANSPARENT))
                {
                    // Mouse moved to out of all rocker keys from another rocker
                    // key, release the other(source) rocker key
                    releaseRockerKey(rockerKeyPressed);
                    pressedKeyData = null;
                    rockerKeyPressed = null;

                }
            }
        }
        else
        {
            // Mouse moved to out of all rocker keys, release the other(source)
            // rocker key
            releaseRockerKey(rockerKeyPressed);
        }
    }

    /**
     * Releases a rocker key
     */
    private void releaseRockerKey(Label rockerKeyPressed)
    {
        if (rockerKeyPressed == center)
        {
            center.setImage(center_normal);
            canvas.doKeyReleased(FIRE);
        }
        else if (rockerKeyPressed == left)
        {
            left.setImage(left_normal);
            canvas.doKeyReleased(LEFT);
        }
        else if (rockerKeyPressed == right)
        {
            right.setImage(right_normal);
            canvas.doKeyReleased(RIGHT);
        }
        else if (rockerKeyPressed == up)
        {
            up.setImage(up_normal);
            canvas.doKeyReleased(UP);
        }
        else if (rockerKeyPressed == down)
        {
            down.setImage(down_normal);
            canvas.doKeyReleased(DOWN);
        }
    }

    /**
     * Canvas Keypad timer task
     */
    class CanvasKeypadTimerTask extends TimerTask
    {
        public void run()
        {
            ESWTUIThreadRunner.syncExec(new Runnable()
            {
                public void run()
                {
                    canvas.doKeyPressed(keyPressed);
                }
            });
        }
    }
}