javauis/lcdui_qt/src/javax/microedition/lcdui/CanvasKeypad.java
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 03 May 2010 12:27:20 +0300
changeset 21 2a9601315dfc
child 23 98ccebc37403
permissions -rw-r--r--
Revision: v2.1.22 Kit: 201018

/*
* 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.Vector;
import java.util.Timer;
import java.util.TimerTask;

import org.eclipse.ercp.swt.mobile.MobileShell;
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.qt.*;
import com.nokia.mj.impl.rt.support.ApplicationInfo;

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

import javax.microedition.lcdui.EventDispatcher.LCDUIEvent;



final class CanvasKeypad {

    /**
     *  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;
    
    private BaseCSSEngine cssEngine;

     /**
             * keypad and game keys composites.
             */
    private Composite keypadComposite;
    private Composite gameKeysComposite;
    private Canvas canvas;
    
     /**
             * Listener for receiving mouse events on the keypad buttons.
             */
    private CanvasKeypadMouseListener mouseListener = new CanvasKeypadMouseListener();
    
     /**
             * Canvas keypad buttons.
             */
    private Button up;
    private Button down;
    private Button left;
    private Button right;
    private Button center;
    private Button skright;
    private Button skleft;
    private Button gameA;
    private Button gameB;
    private Button gameC;
    private Button gameD;
    
    private int keyPressed;
        
    private Timer timer = new Timer();
    private CanvasKeypadTimerTask timerTask;
    
	/**
             * Constructs a canvas kepad based on the JAD attribute
             *
             * @param canvas - canvas for which the keypad is required.
             * @param canvasComp - Composite corresponding to the canvas.
             * @param mode- the jad attribute as a string.
             */
	CanvasKeypad(Canvas canvas, Composite canvasComp, String mode) {
		
		this.canvas = canvas;
        cssEngine = new BaseCSSEngine(Display.getCurrent());
        
        //Set form layout for the shell conatining the canvas.
        canvas.getShell().setLayout(new FormLayout());
        
        //Create the Navigation keypad 
        createNavKeypad();
        
        //check if game keys are needed
        if( mode.equalsIgnoreCase("gameactions") ) {
            //create the game key pad
            createGamePad();
        }
        		
		        
        //Layout the game keys, navigation keys and the canvas 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);
        canvasComp.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) {
            //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);
        }
        
        //layout the shell
        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);
        
        //Create the buttons of the navigation keypad
        
        up = new Button(keypadComposite, SWT.PUSH);
        up.addMouseListener(mouseListener);

		left = new Button(keypadComposite, SWT.PUSH);
        left.addMouseListener(mouseListener);
        
		center = new Button(keypadComposite, SWT.PUSH);
        center.addMouseListener(mouseListener);
        
		right = new Button(keypadComposite, SWT.PUSH);
        right.addMouseListener(mouseListener);
        
		down = new Button(keypadComposite, SWT.PUSH);
        down.addMouseListener(mouseListener);
        
		//up.setStyleSheet(
        cssEngine.applyCSS(up,"QPushButton" +
                "{" +
				"background-color:blue;" +
				"border-style: outset;" +
				"border-width: 2px; " +
				"border-radius: 5px;" +
				"border-top-right-radius: 27px;"+
				"border-top-left-radius: 27px;"+
				"border-color: beige;" +
				"font: bold 14px;" +
				"min-width: 3em;" +
				"min-height: 2em;" +
				"}" +
				"QPushButton:pressed { background-color: rgb(224, 0, 0);" +
				" border-style: inset;" +
				"}");
		
		cssEngine.applyCSS(down,"QPushButton" +
                "{" +
				"background-color:blue;" +
				"border-style: outset;" +
				"border-width: 2px; " +
				"border-radius: 5px;" +
				"border-bottom-right-radius: 27px;"+
				"border-bottom-left-radius: 27px;"+
				"border-color: beige;" +
				"font: bold 14px;" +
				"min-width: 3em;" +
				"min-height: 2em;" +
				"}" +
				"QPushButton:pressed { background-color: rgb(224, 0, 0);" +
				" border-style: inset;" +
				"}");

		cssEngine.applyCSS(left,"QPushButton" +
                "{" +
				"background-color:blue;" +
				"border-style: outset;" +
				"border-width: 2px; " +
				"border-radius: 5px;" +
				"border-top-left-radius: 27px;"+
				"border-bottom-left-radius: 27px;"+
				"border-color: beige;" +
				"font: bold 14px;" +
				"min-height: 3em;" +
				"min-width: 2em;" +
				"}" +
				"QPushButton:pressed { background-color: rgb(224, 0, 0);" +
				" border-style: inset;" +
				"}");

		cssEngine.applyCSS(right,"QPushButton" +
                "{" +
				"background-color:blue;" +
				"border-style: outset;" +
				"border-width: 2px; " +
				"border-radius: 5px;" +
				"border-top-right-radius: 27px;"+
				"border-bottom-right-radius: 27px;"+
				"border-color: beige;" +
				"font: bold 14px;" +
				"min-height: 3em;" +
				"min-width: 2em;" +
				"}" +
				"QPushButton:pressed { background-color: rgb(224, 0, 0);" +
				" border-style: inset;" +
				"}");
		
		cssEngine.applyCSS(center, "QPushButton" +
                "{" +
				"background-color:blue;" +
				"border-style: outset;" +
				"border-width: 2px; " +
				"border-radius: 27px;" +
				"border-color: beige;" +
				"font: bold 14px;" +
				"min-height: 3em;" +
				"min-width: 3em;" +
				"}" +
				"QPushButton:pressed { background-color: rgb(224, 0, 0);" +
				" border-style: inset;" +
				"}");

		up.setText("^");
		center.setText("*");
		left.setText("<");
		right.setText(">");
		down.setText("v");
		
        
        //layout the navigation keys
        keypadComposite.setLayout(new FormLayout());
        
        		
		FormData upFormData = new FormData();
		upFormData.top=new FormAttachment(0,10);
		upFormData.left=new FormAttachment(40);
		up.setLayoutData(upFormData);
		
		FormData centerFormData = new FormData();
		centerFormData.top=new FormAttachment(up,0,SWT.CENTER|SWT.TRAIL);
		centerFormData.left=new FormAttachment(40);
		center.setLayoutData(centerFormData);
		
		FormData downFormData = new FormData();
		downFormData.top = new FormAttachment(center,0,SWT.TRAIL);
		downFormData.left=new FormAttachment(left);
        down.setLayoutData(downFormData);
		
		FormData rightFormData = new FormData();
		rightFormData.top=new FormAttachment(up,0,SWT.TRAIL);
		rightFormData.left=new FormAttachment(center);
		right.setLayoutData(rightFormData);
		
		FormData leftFormData = new FormData();
		leftFormData.top= new FormAttachment(up);
		leftFormData.right = new FormAttachment(center);
		left.setLayoutData(leftFormData);
		
		keypadComposite.layout();
    }
    
    
    /**
             * 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(mouseListener);
        
		gameB = new Button(gameKeysComposite, SWT.PUSH);
        gameB.addMouseListener(mouseListener);
        
		gameC = new Button(gameKeysComposite, SWT.PUSH);
        gameC.addMouseListener(mouseListener);
        
		gameD = new Button(gameKeysComposite, SWT.PUSH);
        gameD.addMouseListener(mouseListener);
        
        //set the style sheet
        String gameKeysStylesheet = "QPushButton" +
                "{" +
				"background-color:blue;" +
				"border-style: outset;" +
				"border-width: 0px; " +
				"border-color: beige;" +
				"font: bold 14px;" +
				"min-height: 2em;" +
				"min-width: 5.5em;" +
				"}" +
				"QPushButton:pressed { background-color: rgb(224, 0, 0);" +
				" border-style: inset;" +
				"}";
                
		cssEngine.applyCSS(gameA,gameKeysStylesheet);
		cssEngine.applyCSS(gameB,gameKeysStylesheet);
		cssEngine.applyCSS(gameC,gameKeysStylesheet);
		cssEngine.applyCSS(gameD,gameKeysStylesheet);
                
        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
    }
    
    
    /**
             * 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) {
        
                skright = new Button(keypadComposite, SWT.PUSH);
                skright.addMouseListener(mouseListener);
            
                skleft = new Button(keypadComposite, SWT.PUSH);
                skleft.addMouseListener(mouseListener);
            
                //Set the style sheet
        		cssEngine.applyCSS(skright,"QPushButton" +
                        "{" +
        				"background-color:blue;" +
        				"border-style: outset;" +
        				"border-width: 1px; " +
        				"border-bottom-left-radius: 22px;"+
        				"border-color: beige;" +
        				"font: bold 14px;" +
        				"min-width: 3em;" +
        				"min-height: 2em;" +
        				"}" +
        				"QPushButton:pressed { background-color: rgb(224, 0, 0);" +
        				" border-style: inset;" +
        				"}");

        		cssEngine.applyCSS(skleft,"QPushButton" +
                        "{" +
        				"background-color:blue;" +
        				"border-style: outset;" +
        				"border-width: 1px; " +
        				"border-bottom-right-radius: 22px;"+
        				"border-color: beige;" +
        				"font: bold 14px;" +
        				"min-width: 3em;" +
        				"min-height: 2em;" +
        				"}" +
        				"QPushButton:pressed { background-color: rgb(224, 0, 0);" +
        				" border-style: inset;" +
        				"}");
                        
                skright.setText("RSK");
                skleft.setText("LSK");
                        
                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();
        }
        
    }

    Button getLeftSoftKey()
    {
        return skleft;
    }
    
    Button getRightSoftKey()
    {
        return skright;
    }

    /**
             * 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 listener.
             */
    class CanvasKeypadMouseListener implements MouseListener {

        public void mouseDown(MouseEvent e) {
                      
            canvas.doKeyPressed(getKeyCode(e.widget));
            
            keyPressed = getKeyCode(e.widget);          
            
            // Create and Schedule the long keypress timer
            timerTask = new CanvasKeypadTimerTask();
            timer.schedule(timerTask, KEYREPEAT_INTERVAL);
        }

        public void mouseUp(MouseEvent e) {
                       
            if( timerTask != null ) {
                //cancel the long keypress timer if it is running
                timerTask.cancel();
                timerTask = null;
            }
            canvas.doKeyReleased(getKeyCode(e.widget));
        }

        public void mouseMove(MouseEvent e) {
        
            if( timerTask != null ) {
                timerTask.cancel();
                timerTask = null;
            }
  
            canvas.doKeyPressed(getKeyCode(e.widget));
            
            keyPressed = getKeyCode(e.widget);
            
            // Create and Schedule Timer
            timerTask = new CanvasKeypadTimerTask();
            timer.schedule(timerTask, KEYREPEAT_INTERVAL);
        	  
        }

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

        
    }
    
    class CanvasKeypadTimerTask extends TimerTask {

        public void run() {
        	
            ESWTUIThreadRunner.syncExec(new Runnable() {
            public void run() {
                canvas.doKeyPressed(keyPressed);
            }
            });
            
            
        }
    }
    
    

}