/***********************************************************************
* mt4j Copyright (c) 2008 - 2009, C.Ruff, Fraunhofer-Gesellschaft All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
***********************************************************************/
package org.mt4j.components.visibleComponents.widgets.keyboard;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import org.mt4j.components.TransformSpace;
import org.mt4j.components.bounds.BoundsArbitraryPlanarPolygon;
import org.mt4j.components.interfaces.IMTComponent3D;
import org.mt4j.components.visibleComponents.font.FontManager;
import org.mt4j.components.visibleComponents.font.IFont;
import org.mt4j.components.visibleComponents.font.VectorFontCharacter;
import org.mt4j.components.visibleComponents.shapes.AbstractShape;
import org.mt4j.components.visibleComponents.shapes.MTRoundRectangle;
import org.mt4j.components.visibleComponents.widgets.buttons.MTSvgButton;
import org.mt4j.input.gestureAction.InertiaDragAction;
import org.mt4j.input.inputProcessors.IGestureEventListener;
import org.mt4j.input.inputProcessors.MTGestureEvent;
import org.mt4j.input.inputProcessors.componentProcessors.dragProcessor.DragProcessor;
import org.mt4j.input.inputProcessors.componentProcessors.rotateProcessor.RotateProcessor;
import org.mt4j.input.inputProcessors.componentProcessors.scaleProcessor.ScaleProcessor;
import org.mt4j.input.inputProcessors.componentProcessors.tapProcessor.TapEvent;
import org.mt4j.input.inputProcessors.componentProcessors.tapProcessor.TapProcessor;
import org.mt4j.util.MT4jSettings;
import org.mt4j.util.MTColor;
import org.mt4j.util.animation.Animation;
import org.mt4j.util.animation.AnimationEvent;
import org.mt4j.util.animation.IAnimationListener;
import org.mt4j.util.animation.MultiPurposeInterpolator;
import org.mt4j.util.math.Vector3D;
import org.mt4j.util.math.Vertex;
import processing.core.PApplet;
/**
* A multitouch keyboard using vector graphics.
*
* @author Christopher Ruff
*/
public class MTKeyboard extends MTRoundRectangle {
/** The pa. */
private PApplet pa;
/** The key font. */
private IFont keyFont;
/** The key list. */
private ArrayList<MTKey> keyList;
/** The shift changers. */
private ArrayList<MTKey> shiftChangers;
/** The shift pressed. */
private boolean shiftPressed;
/** The key click action. */
private KeyClickAction keyClickAction;
// private CloseClickAction closeClickButtonAction;
/** The text input acceptors. */
private List<ITextInputListener> textInputAcceptors;
private boolean hardwareInput;
/**
* Creates a new keyboard without an text input acceptor.
*
* @param pApplet the applet
*/
public MTKeyboard(PApplet pApplet) {
super(0,0,0, 700, 245, 30,30, pApplet);
this.pa = pApplet;
//Set drawing mode
this.setDrawSmooth(true);
//FIXME TEST
this.setHardwareInputEnabled(true);
this.setName("unnamed mt-keyboard");
this.textInputAcceptors = new ArrayList<ITextInputListener>();
if (MT4jSettings.getInstance().isOpenGlMode())
this.setUseDirectGL(true);
//TODO textareas an keyboard andocken lassen zum schreiben, oder doppelklick auf textarea?
//TODO buttons textarea clear machen
//TODO keyboard durch button heranimated
// INIT FIELDS
//Load the Key font
keyFont = FontManager.getInstance().createFont(pa,
"keys.svg", 30,
new MTColor(0,0,0,255),
new MTColor(0,0,0,255));
// new MTColor(250,250,250,255),
// new MTColor(250,250,250,255));
keyList = new ArrayList<MTKey>();
shiftChangers = new ArrayList<MTKey>();
shiftPressed = false;
keyClickAction = new KeyClickAction();
// /*
//TODO load button only once!
MTSvgButton keybCloseSvg = new MTSvgButton(MT4jSettings.getInstance().getDefaultSVGPath()
+ "keybClose.svg", pa);
//Transform
keybCloseSvg.scale(0.8f, 0.8f, 1, new Vector3D(0,0,0));
keybCloseSvg.translate(new Vector3D(640,5,0));
keybCloseSvg.setBoundsPickingBehaviour(AbstractShape.BOUNDS_ONLY_CHECK);
keybCloseSvg.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if (arg0.getID() == TapEvent.BUTTON_CLICKED)
closeButtonClicked();
}
});
this.addChild(keybCloseSvg);
// */
//INITIALIZE SPACE-Button "by hand"
VectorFontCharacter SpaceF = (VectorFontCharacter) keyFont.getFontCharacterByUnicode("k");
// MTKey space = new MTKey(SpaceF.getGeometryInfo().getVertices(), /*spaceOutlines,*/pa, " ", " ");
MTKey space = new MTKey(SpaceF.getGeometryInfo(), /*spaceOutlines,*/pa, " ", " ");
space.setName(SpaceF.getName());
//Set the contours to draw the outline - do this after settings the geominfo
//so the outline displaylist will be overridden with the new contours list
space.setOutlineContours(SpaceF.getContours()); //FIXME do we have to in opengl mode? -> we will use displayLists anyway..
if (MT4jSettings.getInstance().isOpenGlMode()){
space.setUseDirectGL(true);
// System.out.println(SpaceF.getDisplayListIDs()[0] + " - " + SpaceF.getDisplayListIDs()[1]);
// space.setDisplayListIDs(SpaceF.getDisplayListIDs()); //Wenn nicht displaylisten, m�ssen wir geometry auch �bernehmen!
space.getGeometryInfo().setDisplayListIDs(SpaceF.getGeometryInfo().getDisplayListIDs()); //Wenn nicht displaylisten, m�ssen wir geometry auch �bernehmen!
space.setUseDisplayList(true);
}
space.setNoStroke(false);
space.setDrawSmooth(true);
space.setPickable(true);
space.setGestureAllowance(DragProcessor.class, false);
space.setGestureAllowance(RotateProcessor.class, false);
space.setGestureAllowance(ScaleProcessor.class, false);
space.unregisterAllInputProcessors();
// space.translate(new Vector3D(100, space.getOriginalHeight(), 0)); //Translate to 0,0
// space.translate(new Vector3D(225, 190,0));
scaleKey(space, 40);
space.setPositionRelativeToParent(new Vector3D(350,210,0));
space.setGestureAllowance(TapProcessor.class, true);
space.registerInputProcessor(new TapProcessor(pa));
space.addGestureListener(TapProcessor.class, keyClickAction);
SpaceF = null;
keyList.add(space);
this.addChild(space);
KeyInfo[] keyInfos = this.getKeysLayout();
//CREATE THE KEYS \\
// for (int i = 0; i < keyInfos.size(); i++) {
// KeyInfo keyInfo = keyInfos.get(i);
for (int i = 0; i < keyInfos.length; i++) {
KeyInfo keyInfo = keyInfos[i];
VectorFontCharacter fontChar = (VectorFontCharacter) keyFont.getFontCharacterByUnicode(keyInfo.keyfontUnicode);
//FIXME expensive..
// MTKey key = new MTKey(fontChar.getGeometryInfo().getVertices(), fontChar.getContours(),pa, keyInfo.charUnicodeToWrite, keyInfo.charUnicodeToWriteShifted);
// MTKey key = new MTKey(new Vertex[]{new Vertex(0,0,0),new Vertex(10,0,0),new Vertex(0,10,0),}, /*fontChar.getContours(),*/ pa, keyInfo.charUnicodeToWrite, keyInfo.charUnicodeToWriteShifted);
MTKey key = new MTKey(fontChar.getGeometryInfo(), pa, keyInfo.charUnicodeToWrite, keyInfo.charUnicodeToWriteShifted);
// key.setGeometryInfo(fontChar.getGeometryInfo());
key.setName(fontChar.getName());
key.setPickable(true);
key.unregisterAllInputProcessors();
key.setOutlineContours(fontChar.getContours());
if (MT4jSettings.getInstance().isOpenGlMode()){
key.setUseDirectGL(true);
//Use the display lists already created for the font characters of the key-font
key.getGeometryInfo().setDisplayListIDs(fontChar.getGeometryInfo().getDisplayListIDs());
key.setUseDisplayList(true);
}
// key.setOutlineContours(fontChar.getContours());
//Translate to 0,0
// key.translate(new Vector3D(0,key.getOriginalHeight(),0));
//Translate to its designated position
// key.translate(keyInfo.position);
scaleKey(key, 40);
//Scale ENTER and BACKSPACE
if (key.getCharacterToWrite().equals("\n")){
// key.scale(1.60f, 1.60f, 1, key.getCenterPointLocal());
// key.scale(1.70f, 1.70f, 1, new Vector3D(0,0,0), TransformSpace.LOCAL);
key.scale(1.70f, 1.70f, 1, key.getCenterPointLocal(), TransformSpace.LOCAL);
}
key.setPositionRelativeToParent(keyInfo.position);
//this is a hack to fit the bounding shape of the "enter" key to its non-rectangular shape
if (key.getCharacterToWrite().equals("\n")){
Vector3D[] v = key.getBounds().getVectorsLocal();
float indent = (v[1].getX()-v[0].getX())/2f;
Vertex[] vNew = new Vertex[]{
new Vertex(v[0].getX(),v[0].getY()+indent,0)
,new Vertex(v[0].getX()+indent -indent/8f ,v[0].getY()+indent,0) //
,new Vertex(v[0].getX()+indent -indent/8f,v[0].getY(),0) //
,new Vertex(v[1])
,new Vertex(v[2])
,new Vertex(v[3])
,new Vertex(v[0].getX(),v[0].getY()+indent,0)
};
BoundsArbitraryPlanarPolygon newBounds = new BoundsArbitraryPlanarPolygon(key, vNew); //Expensive..
key.setBoundsBehaviour(AbstractShape.BOUNDS_ONLY_CHECK);
key.setBounds(newBounds);
}
keyList.add(key);
key.setGestureAllowance(TapProcessor.class, true);
key.registerInputProcessor(new TapProcessor(pa));
key.addGestureListener(TapProcessor.class, keyClickAction);
//Add keys that change during SHIFT to a list
if (keyInfo.visibilityInfo == KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED){
shiftChangers.add(key);
}else if (keyInfo.visibilityInfo == KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED){
key.setVisible(false);
shiftChangers.add(key);
}
fontChar = null;
this.addChild(key);
}
//Draw this component and its children above
//everything previously drawn and avoid z-fighting
this.setDepthBufferDisabled(true);
}
private KeyInfo[] getKeysLayout(){
Locale l = Locale.getDefault();
/*
System.out.println(" Language, Country, Variant, Name");
System.out.println("");
System.out.println("Default locale: ");
System.out.println(" "+l.getLanguage()+", "+l.getCountry()+", "
+", "+l.getVariant()+", "+l.getDisplayName());
*/
if (l.getLanguage().equalsIgnoreCase(Locale.GERMANY.getLanguage())){
return getGermanLayout();
}else{
return getUSLayout();
}
}
private KeyInfo[] getGermanLayout(){
ArrayList<KeyInfo> keyInfos = new ArrayList<KeyInfo>();
float lineY = 35;
// float advanceMent = keyFont.getFontCharacterByUnicode("A").getHorizontalDist()-10;
float advanceMent = 42;
float startX = 60;
// keyInfos.add(new KeyInfo("^", "^", "^", new Vector3D(startX,lineY), KeyInfo.NORMAL_KEY)); //ESC key
keyInfos.add(new KeyInfo("1", "1", "1", new Vector3D(startX+1*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo("!", "!", "!", new Vector3D(startX+1*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
keyInfos.add(new KeyInfo("2", "2", "2", new Vector3D(startX+2*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo("\"", "\"", "\"", new Vector3D(startX+2*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
keyInfos.add(new KeyInfo("3", "3", "3", new Vector3D(startX+3*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("4", "4", "4", new Vector3D(startX+4*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo("$", "$", "$", new Vector3D(startX+4*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
keyInfos.add(new KeyInfo("5", "5", "5", new Vector3D(startX+5*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo("%", "%", "%", new Vector3D(startX+5*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
keyInfos.add(new KeyInfo("6", "6", "6", new Vector3D(startX+6*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo("&", "&", "&", new Vector3D(startX+6*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
keyInfos.add(new KeyInfo("7", "7", "7", new Vector3D(startX+7*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo("/", "/", "/", new Vector3D(startX+7*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
keyInfos.add(new KeyInfo("8", "8", "8", new Vector3D(startX+8*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo("(", "(", "(", new Vector3D(startX+8*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
keyInfos.add(new KeyInfo("9", "9", "9", new Vector3D(startX+9*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo(")", ")", ")", new Vector3D(startX+9*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
keyInfos.add(new KeyInfo("0", "0", "0", new Vector3D(startX+10*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo("=", "=", "=", new Vector3D(startX+10*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
keyInfos.add(new KeyInfo("\\", "\\", "\\", new Vector3D(startX+11*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo("?", "?", "?", new Vector3D(startX+11*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
//////////////////
lineY = 77;
startX = 80; // | + 27
keyInfos.add(new KeyInfo("Q", "q", "Q", new Vector3D(startX+1*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("W", "w", "W", new Vector3D(startX+2*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("E", "e", "E", new Vector3D(startX+3*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("R", "r", "R", new Vector3D(startX+4*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("T", "t", "T", new Vector3D(startX+5*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("Z", "z", "Z", new Vector3D(startX+6*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("U", "u", "U", new Vector3D(startX+7*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("I", "i", "I", new Vector3D(startX+8*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("O", "o", "O", new Vector3D(startX+9*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("P", "p", "P", new Vector3D(startX+10*advanceMent,lineY), KeyInfo.NORMAL_KEY));
//Ü
keyInfos.add(new KeyInfo("111", "ü", "Ü", new Vector3D(startX+11*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("+", "+", "+", new Vector3D(startX+12*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo("*", "*", "*", new Vector3D(startX+12*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
lineY = 119;
startX = 136; //+58
keyInfos.add(new KeyInfo("A", "a", "A", new Vector3D(startX,lineY), KeyInfo.NORMAL_KEY)); //
keyInfos.add(new KeyInfo("S", "s", "S", new Vector3D(startX+1*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("D", "d", "D", new Vector3D(startX+2*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("F", "f", "F", new Vector3D(startX+3*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("G", "g", "G", new Vector3D(startX+4*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("H", "h", "H", new Vector3D(startX+5*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("J", "j", "J", new Vector3D(startX+6*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("K", "k", "K", new Vector3D(startX+7*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("L", "l", "L", new Vector3D(startX+8*advanceMent,lineY), KeyInfo.NORMAL_KEY));
//Ö
keyInfos.add(new KeyInfo("1111", "ö", "Ö", new Vector3D(startX+9*advanceMent,lineY), KeyInfo.NORMAL_KEY));
//Ä
keyInfos.add(new KeyInfo("11", "ä", "Ä", new Vector3D(startX+10*advanceMent,lineY), KeyInfo.NORMAL_KEY));
////////////////////
lineY = 161;
startX = 70; // -60
keyInfos.add(new KeyInfo("<", "<", "<", new Vector3D(startX+1*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo(">", ">", ">", new Vector3D(startX+1*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
keyInfos.add(new KeyInfo("Y", "y", "Y", new Vector3D(startX+2*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("X", "x", "X", new Vector3D(startX+3*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("C", "c", "C", new Vector3D(startX+4*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("V", "v", "V", new Vector3D(startX+5*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("B", "b", "B", new Vector3D(startX+6*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("N", "n", "N", new Vector3D(startX+7*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("M", "m", "M", new Vector3D(startX+8*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo(",", ",", ",", new Vector3D(startX+9*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo(";", ";", ";", new Vector3D(startX+9*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
keyInfos.add(new KeyInfo(".", ".", ".", new Vector3D(startX+10*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo(":", ":", ":", new Vector3D(startX+10*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
keyInfos.add(new KeyInfo("-", "-", "-", new Vector3D(startX+11*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("#", "#", "#", new Vector3D(startX+12*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo("'", "'", "'", new Vector3D(startX+12*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
///////////
//Special keys
keyInfos.add(new KeyInfo("z", "back", "back", new Vector3D(580,35), KeyInfo.NORMAL_KEY));//Backspace
keyInfos.add(new KeyInfo("v", "\t", "\t", new Vector3D(62,77), KeyInfo.NORMAL_KEY)); //Tab
keyInfos.add(new KeyInfo("j", "shift", "shift", new Vector3D(78,120), KeyInfo.NORMAL_KEY)); //Shift
keyInfos.add(new KeyInfo("f", "\n", "\n", new Vector3D(615, 105),KeyInfo.NORMAL_KEY)); //Enter
return keyInfos.toArray(new KeyInfo[keyInfos.size()]);
}
//FIXME no "@" available in key font?
private KeyInfo[] getUSLayout(){
ArrayList<KeyInfo> keyInfos = new ArrayList<KeyInfo>();
float lineY = 35;
// float advanceMent = keyFont.getFontCharacterByUnicode("A").getHorizontalDist()-10;
float advanceMent = 42;
float startX = 60;
// keyInfos.add(new KeyInfo("^", "^", "^", new Vector3D(startX,lineY), KeyInfo.NORMAL_KEY)); //ESC key
keyInfos.add(new KeyInfo("1", "1", "1", new Vector3D(startX+1*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo("!", "!", "!", new Vector3D(startX+1*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
keyInfos.add(new KeyInfo("2", "2", "2", new Vector3D(startX+2*advanceMent,lineY), KeyInfo.NORMAL_KEY));
//FIXME should be "@" here
keyInfos.add(new KeyInfo("3", "3", "3", new Vector3D(startX+3*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo("#", "#", "#", new Vector3D(startX+3*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
keyInfos.add(new KeyInfo("4", "4", "4", new Vector3D(startX+4*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo("$", "$", "$", new Vector3D(startX+4*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
keyInfos.add(new KeyInfo("5", "5", "5", new Vector3D(startX+5*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo("%", "%", "%", new Vector3D(startX+5*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
keyInfos.add(new KeyInfo("6", "6", "6", new Vector3D(startX+6*advanceMent,lineY), KeyInfo.NORMAL_KEY));
//FIXME "^" missing
keyInfos.add(new KeyInfo("7", "7", "7", new Vector3D(startX+7*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo("&", "&", "&", new Vector3D(startX+7*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
keyInfos.add(new KeyInfo("8", "8", "8", new Vector3D(startX+8*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo("*", "*", "*", new Vector3D(startX+8*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
keyInfos.add(new KeyInfo("9", "9", "9", new Vector3D(startX+9*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo("(", "(", "(", new Vector3D(startX+9*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
keyInfos.add(new KeyInfo("0", "0", "0", new Vector3D(startX+10*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo(")", ")", ")", new Vector3D(startX+10*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
keyInfos.add(new KeyInfo("=", "=", "=", new Vector3D(startX+11*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo("+", "+", "+", new Vector3D(startX+11*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
//////////////////
lineY = 77;
startX = 80; // | + 27
keyInfos.add(new KeyInfo("Q", "q", "Q", new Vector3D(startX+1*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("W", "w", "W", new Vector3D(startX+2*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("E", "e", "E", new Vector3D(startX+3*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("R", "r", "R", new Vector3D(startX+4*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("T", "t", "T", new Vector3D(startX+5*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("Y", "y", "Y", new Vector3D(startX+6*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("U", "u", "U", new Vector3D(startX+7*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("I", "i", "I", new Vector3D(startX+8*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("O", "o", "O", new Vector3D(startX+9*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("P", "p", "P", new Vector3D(startX+10*advanceMent,lineY), KeyInfo.NORMAL_KEY));
//�
// keyInfos.add(new KeyInfo("111", "�", "�", new Vector3D(startX+11*advanceMent,lineY), KeyInfo.NORMAL_KEY));
//FIXME woanders hin
keyInfos.add(new KeyInfo("\\", "\\", "\\", new Vector3D(startX+11*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("-", "-", "-", new Vector3D(startX+12*advanceMent,lineY), KeyInfo.NORMAL_KEY));
lineY = 119;
startX = 136; //+58
keyInfos.add(new KeyInfo("A", "a", "A", new Vector3D(startX,lineY), KeyInfo.NORMAL_KEY)); //
keyInfos.add(new KeyInfo("S", "s", "S", new Vector3D(startX+1*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("D", "d", "D", new Vector3D(startX+2*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("F", "f", "F", new Vector3D(startX+3*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("G", "g", "G", new Vector3D(startX+4*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("H", "h", "H", new Vector3D(startX+5*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("J", "j", "J", new Vector3D(startX+6*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("K", "k", "K", new Vector3D(startX+7*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("L", "l", "L", new Vector3D(startX+8*advanceMent,lineY), KeyInfo.NORMAL_KEY));
//�
// keyInfos.add(new KeyInfo("1111", "�", "�", new Vector3D(startX+9*advanceMent,lineY), KeyInfo.NORMAL_KEY));
//�
// keyInfos.add(new KeyInfo("11", "�", "�", new Vector3D(startX+10*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo(";", ";", ";", new Vector3D(startX+9*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo(":", ":", ":", new Vector3D(startX+9*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
keyInfos.add(new KeyInfo("'", "'", "'", new Vector3D(startX+10*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo("\"", "\"", "\"", new Vector3D(startX+10*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
////////////////////
lineY = 161;
startX = 70; // -60
keyInfos.add(new KeyInfo("Z", "z", "Z", new Vector3D(startX+2*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("X", "x", "X", new Vector3D(startX+3*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("C", "c", "C", new Vector3D(startX+4*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("V", "v", "V", new Vector3D(startX+5*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("B", "b", "B", new Vector3D(startX+6*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("N", "n", "N", new Vector3D(startX+7*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo("M", "m", "M", new Vector3D(startX+8*advanceMent,lineY), KeyInfo.NORMAL_KEY));
keyInfos.add(new KeyInfo(",", ",", ",", new Vector3D(startX+9*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo("<", "<", "<", new Vector3D(startX+9*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
keyInfos.add(new KeyInfo(".", ".", ".", new Vector3D(startX+10*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo(">", ">", ">", new Vector3D(startX+10*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
//FIXME wohin
keyInfos.add(new KeyInfo("/", "/", "/", new Vector3D(startX+11*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED));
keyInfos.add(new KeyInfo("?", "?", "?", new Vector3D(startX+11*advanceMent,lineY), KeyInfo.KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED));
///////////
//Special keys
keyInfos.add(new KeyInfo("z", "back", "back", new Vector3D(580,35), KeyInfo.NORMAL_KEY));//Backspace
keyInfos.add(new KeyInfo("v", "\t", "\t", new Vector3D(62,77), KeyInfo.NORMAL_KEY)); //Tab
keyInfos.add(new KeyInfo("j", "shift", "shift", new Vector3D(78,120), KeyInfo.NORMAL_KEY)); //Shift
keyInfos.add(new KeyInfo("f", "\n", "\n", new Vector3D(615, 105),KeyInfo.NORMAL_KEY)); //Enter
return keyInfos.toArray(new KeyInfo[keyInfos.size()]);
}
private void scaleKey(MTKey key, float scale){
// Vector3D scalingPoint = new Vector3D(0,0,0);
Vector3D scalingPoint = key.getCenterPointLocal();
key.scale(1/key.getHeightXY(TransformSpace.RELATIVE_TO_PARENT), 1/key.getHeightXY(TransformSpace.RELATIVE_TO_PARENT), 1, scalingPoint);
key.scale(scale, scale, 1, scalingPoint);
}
private boolean setWidthRelativeToParent(float width){
if (width > 0){
Vector3D centerPoint;
if (this.hasBounds()){
centerPoint = this.getBounds().getCenterPointLocal();
centerPoint.transform(this.getLocalMatrix());
}else{
centerPoint = this.getCenterPointGlobal();
centerPoint.transform(this.getGlobalInverseMatrix());
}
this.scale(1/this.getWidthXY(TransformSpace.RELATIVE_TO_PARENT), 1/this.getWidthXY(TransformSpace.RELATIVE_TO_PARENT), 1, centerPoint);
this.scale(width, width, 1, centerPoint);
// this.scale(1/this.getWidthLocal(), 1/this.getWidthLocal(), 1, centerPoint, TransformSpace.RELATIVE_TO_SELF);
// this.scale(width, width, 1, centerPoint, TransformSpace.RELATIVE_TO_SELF);
return true;
}else
return false;
}
@Override
protected void setDefaultGestureActions() {
super.setDefaultGestureActions();
this.addGestureListener(DragProcessor.class, new InertiaDragAction());
}
/**
* The Class KeyInfo.
*
* @author C.Ruff
*/
private class KeyInfo{
/** The keyfont unicode. */
String keyfontUnicode;
/** The char unicode to write. */
String charUnicodeToWrite;
/** The char unicode to write shifted. */
String charUnicodeToWriteShifted;
/** The position. */
Vector3D position;
/** The visibility info. */
int visibilityInfo;
/** The Constant NORMAL_KEY. */
public static final int NORMAL_KEY = 0;
/** The Constant KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED. */
public static final int KEY_ONLY_VISIBLE_WHEN_SHIFT_NOTPRESSED = 1;
/** The Constant KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED. */
public static final int KEY_ONLY_VISIBLE_WHEN_SHIFT_PRESSED = 2;
/**
* Instantiates a new key info.
*
* @param keyfontUnicode the keyfont unicode
* @param charUnicodeToWrite the char unicode to write
* @param charUnicodeToWriteShifted the char unicode to write shifted
* @param position the position
* @param visibilityInfo the visibility info
*/
public KeyInfo(String keyfontUnicode, String charUnicodeToWrite, String charUnicodeToWriteShifted, Vector3D position, int visibilityInfo) {
super();
this.keyfontUnicode = keyfontUnicode;
this.charUnicodeToWrite = charUnicodeToWrite;
this.charUnicodeToWriteShifted = charUnicodeToWriteShifted;
this.position = position;
this.visibilityInfo = visibilityInfo;
}
}
/**
* The Class KeyClickAction.
*
* @author C.Ruff
*/
private class KeyClickAction implements IGestureEventListener {
// private HashMap<MTKey, MTKey> keysNotToScaleBack;
/** The key press indent. */
private int keyPressIndent;
/**
* Instantiates a new key click action.
*/
public KeyClickAction(){
// keysNotToScaleBack = new HashMap<MTKey, MTKey>();
keyPressIndent = 3;
}
public boolean processGestureEvent(MTGestureEvent g) {
if (g instanceof TapEvent){
TapEvent clickEvent = (TapEvent)g;
IMTComponent3D clicked = clickEvent.getTargetComponent();
if (clicked != null && clicked instanceof MTKey){
MTKey clickedKey = (MTKey)clicked;
switch (clickEvent.getTapID()) {
case TapEvent.BUTTON_DOWN:
clickedKey.setPressed(true);
float keyHeight = clickedKey.getHeightXY(TransformSpace.RELATIVE_TO_PARENT);
float keyWidth = clickedKey.getWidthXY(TransformSpace.RELATIVE_TO_PARENT);
// clickedKey.setSizeXYRelativeToParent(keyWidth-keyPressIndent, keyHeight-keyPressIndent);
setSizeXYRelativeToParent(clickedKey, keyWidth-keyPressIndent, keyHeight-keyPressIndent);
if (clickedKey.getCharacterToWrite().equals("shift")){
shiftPressed = true;
// Make certain keys visible / not visible when shift pressed!
for (MTKey key: shiftChangers){
key.setVisible(!key.isVisible());
}
}
keyboardButtonDown(clickedKey, shiftPressed);
break;
case TapEvent.BUTTON_UP:
case TapEvent.BUTTON_CLICKED:
clickedKey.setPressed(false);
float kHeight = clickedKey.getHeightXY(TransformSpace.RELATIVE_TO_PARENT);
float kWidth = clickedKey.getWidthXY(TransformSpace.RELATIVE_TO_PARENT);
// if (keysNotToScaleBack.get(clickedKey) == null){
// clickedKey.setSizeLocal(kWidth+keyPressIndent, kHeight+keyPressIndent);
// }else{
// keysNotToScaleBack.remove(clickedKey);
// }
// clickedKey.setSizeXYRelativeToParent(kWidth+keyPressIndent, kHeight+keyPressIndent);
setSizeXYRelativeToParent(clickedKey, kWidth+keyPressIndent, kHeight+keyPressIndent);
//System.out.println("Button CLICKED: " + clickedKey.getCharacterToWrite());
if (clickedKey.getCharacterToWrite().equals("shift")){
shiftPressed = false;
//Set shift visible keys visible/not visible
for (MTKey key: shiftChangers){
key.setVisible(!key.isVisible());
}
}
keyboardButtonClicked(clickedKey, shiftPressed);
break;
default:
break;
}//switch
}//instance of key
}//instanceof clickevent
return false;
}//method
}//class
/**
* Sets the size xy relative to parent.
*
* @param shape the shape
* @param width the width
* @param height the height
*
* @return true, if successful
*/
private boolean setSizeXYRelativeToParent(AbstractShape shape, float width, float height){
if (width > 0 && height > 0){
Vector3D centerPoint;
if (shape.hasBounds()){
centerPoint = shape.getBounds().getCenterPointLocal();
centerPoint.transform(shape.getLocalMatrix()); //TODO n�tig?
}else{
centerPoint = shape.getCenterPointGlobal();
centerPoint.transform(shape.getGlobalInverseMatrix());
}
shape.scale(1/shape.getWidthXY(TransformSpace.RELATIVE_TO_PARENT), 1/shape.getHeightXY(TransformSpace.RELATIVE_TO_PARENT), 1, centerPoint);
shape.scale(width, height, 1, centerPoint);
return true;
}else
return false;
}
/**
* Called after keyboard button pressed.
*
* @param clickedKey the clicked key
* @param shiftPressed the shift pressed
*/
protected void keyboardButtonDown(MTKey clickedKey, boolean shiftPressed){
ITextInputListener[] listeners = this.getTextInputListeners();
for (int i = 0; i < listeners.length; i++) {
ITextInputListener textInputListener = listeners[i];
if (clickedKey.getCharacterToWrite().equals("back")){
textInputListener.removeLastCharacter();
}else if (clickedKey.getCharacterToWrite().equals("shift")){
//no nothing
}else{
String charToAdd = shiftPressed ? clickedKey.getCharacterToWriteShifted() : clickedKey.getCharacterToWrite();
textInputListener.appendCharByUnicode(charToAdd);
}
}
}
/**
* Keyboard button up.
*
* @param clickedKey the clicked key
* @param shiftPressed the shift pressed
*/
protected void keyboardButtonUp(MTKey clickedKey, boolean shiftPressed){
// keyboardButtonClicked(clickedKey, shiftPressed);
}
/**
* Keyboard button clicked.
*
* @param clickedKey the clicked key
* @param shiftPressed the shift pressed
*/
protected void keyboardButtonClicked(MTKey clickedKey, boolean shiftPressed){
}
public synchronized void addTextInputListener(ITextInputListener textListener){
if (!this.textInputAcceptors.contains(textListener)){
this.textInputAcceptors.add(textListener);
}
}
public synchronized ITextInputListener[] getTextInputListeners(){
return this.textInputAcceptors.toArray(new ITextInputListener[this.textInputAcceptors.size()]);
}
public synchronized void removeTextInputListener(ITextInputListener textListener){
if (this.textInputAcceptors.contains(textListener)){
this.textInputAcceptors.remove(textListener);
}
}
public void close(){
this.closeKeyboard();
}
protected void closeKeyboard(){
float width = this.getWidthXY(TransformSpace.RELATIVE_TO_PARENT);
Animation keybCloseAnim = new Animation("Keyboard Fade", new MultiPurposeInterpolator(width, 1, 300, 0.2f, 0.5f, 1), this);
keybCloseAnim.addAnimationListener(new IAnimationListener(){
public void processAnimationEvent(AnimationEvent ae) {
// float delta = ae.getAnimation().getInterpolator().getCurrentStepDelta();
switch (ae.getId()) {
case AnimationEvent.ANIMATION_STARTED:
case AnimationEvent.ANIMATION_UPDATED:
float currentVal = ae.getAnimation().getInterpolator().getCurrentValue();
// keyboard.setWidthXYRelativeToParent(currentVal);
setWidthRelativeToParent(currentVal);
break;
case AnimationEvent.ANIMATION_ENDED:
setVisible(false);
destroy();
break;
default:
break;
}//switch
}//processanimation
});
keybCloseAnim.start();
}
protected void closeButtonClicked(){
this.close();
}
public void setHardwareInputEnabled(boolean hardwareInput){
try {
PApplet app = getRenderer();
if (hardwareInput) {
app.registerKeyEvent(this);
}else{
app.unregisterKeyEvent(this);
}
} catch (Exception e) {
System.err.println(e.getMessage());
}
this.hardwareInput = hardwareInput;
}
public boolean isHardwareInputEnabled(){
return this.hardwareInput;
}
public void keyEvent(KeyEvent e){
if (this.isEnabled()){
if (e.getID()!= KeyEvent.KEY_PRESSED) return;
String keyCode = String.valueOf(e.getKeyChar());
//System.out.println("Key input: " + keyCode);
ITextInputListener[] listeners = this.getTextInputListeners();
for (int i = 0; i < listeners.length; i++) {
ITextInputListener textInputListener = listeners[i];
if (e.getKeyCode() == KeyEvent.VK_BACK_SPACE){
textInputListener.removeLastCharacter();
}else if (e.getKeyCode() == KeyEvent.VK_SHIFT
|| e.getKeyCode() == KeyEvent.VK_ALT
|| e.getKeyCode() == KeyEvent.VK_ALT_GRAPH
|| e.getKeyCode() == KeyEvent.VK_CONTROL
){
//do nothing
}else{
textInputListener.appendCharByUnicode(keyCode);
}
}
}
}
@Override
protected void destroyComponent() {
super.destroyComponent();
keyFont = null;
keyList.clear();
shiftChangers.clear();
textInputAcceptors.clear();
if (this.isHardwareInputEnabled()){
try {
getRenderer().unregisterKeyEvent(this);
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}
}