/*********************************************************************** * 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.KeyEvent; import java.util.ArrayList; import java.util.List; import java.util.Locale; import org.mt4j.IMTApplication; import org.mt4j.components.TransformSpace; import org.mt4j.components.bounds.BoundsArbitraryPlanarPolygon; import org.mt4j.components.interfaces.IMTComponent3D; 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.MTTextArea; import org.mt4j.components.visibleComponents.widgets.buttons.MTSvgButton; import org.mt4j.input.IKeyListener; import org.mt4j.input.gestureAction.DefaultDragAction; import org.mt4j.input.gestureAction.DefaultRotateAction; import org.mt4j.input.gestureAction.DefaultScaleAction; 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.IAnimation; import org.mt4j.util.animation.IAnimationListener; import org.mt4j.util.animation.MultiPurposeInterpolator; import org.mt4j.util.font.FontManager; import org.mt4j.util.font.IFont; 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 implements IKeyListener { /** 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; /** 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(pApplet,0,0, 0, 700, 245,30, 30); this.pa = pApplet; //Set drawing mode this.setDrawSmooth(true); this.setHardwareInputEnabled(true); this.setName("unnamed mt-keyboard"); this.textInputAcceptors = new ArrayList<ITextInputListener>(); if (MT4jSettings.getInstance().isOpenGlMode()) this.setUseDirectGL(true); //TODO button textarea clear //TODO keyboard animated creation MTColor keyColor = new MTColor(0,0,0,255); // INIT FIELDS //Load the Key font keyFont = FontManager.getInstance().createFont(pa, "keys.svg", 30, keyColor); keyList = new ArrayList<MTKey>(); shiftChangers = new ArrayList<MTKey>(); shiftPressed = false; keyClickAction = new KeyClickAction(); // /* //TODO load button only once! MTSvgButton keybCloseSvg = new MTSvgButton(pa, MT4jSettings.getInstance().getDefaultSVGPath() + "keybClose.svg"); //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.addGestureListener(TapProcessor.class, new IGestureEventListener() { @Override public boolean processGestureEvent(MTGestureEvent ge) { TapEvent te = (TapEvent)ge; if (te.isTapped()){ onCloseButtonClicked(); } return false; } }); this.addChild(keybCloseSvg); // */ /* We get the key's shapes from the keys.svg svg font. To save memory, we share the font's characters geometryinfo with the MTKey shapes. */ //INITIALIZE SPACE-Button "by hand" VectorFontCharacter SpaceF = (VectorFontCharacter) keyFont.getFontCharacterByUnicode("k"); MTKey space = new MTKey(/*spaceOutlines,*/pa, SpaceF.getGeometryInfo(), " ", " "); 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.getGeometryInfo().setDisplayListIDs(SpaceF.getGeometryInfo().getDisplayListIDs()); //Wenn nicht displaylisten, m�ssen wir geometry auch �bernehmen! space.setUseDisplayList(true); } space.setFillColor(keyColor); 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(); 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 (KeyInfo keyInfo : keyInfos) { VectorFontCharacter fontChar = (VectorFontCharacter) keyFont.getFontCharacterByUnicode(keyInfo.keyfontUnicode); MTKey key = new MTKey(pa, fontChar.getGeometryInfo(), keyInfo.charUnicodeToWrite, keyInfo.charUnicodeToWriteShifted); key.setName(fontChar.getName()); key.setPickable(true); key.setFillColor(keyColor); 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); } scaleKey(key, 40); //Scale ENTER and BACKSPACE if (key.getCharacterToWrite().equals("\n")) { 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); TapProcessor tp = new TapProcessor(pa); // tp.setLockPriority(1.5f); tp.setLockPriority(5f); //FIXME TEST tp.setStopPropagation(false); key.registerInputProcessor(tp); 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 = key.getCenterPointLocal(); key.scale(scale * (1/key.getHeightXY(TransformSpace.RELATIVE_TO_PARENT)), scale* (1/key.getHeightXY(TransformSpace.RELATIVE_TO_PARENT)), 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(width * (1/this.getWidthXY(TransformSpace.RELATIVE_TO_PARENT)) , width* (1/this.getWidthXY(TransformSpace.RELATIVE_TO_PARENT)), 1, centerPoint); return true; }else return false; } @Override protected void setDefaultGestureActions() { // super.setDefaultGestureActions(); this.addGestureListener(DragProcessor.class, new InertiaDragAction()); DragProcessor dp = new DragProcessor(getRenderer()); // dp.setLockPriority(0.5f); registerInputProcessor(dp); addGestureListener(DragProcessor.class, new DefaultDragAction()); dp.setBubbledEventsEnabled(true); //FIXME TEST RotateProcessor rp = new RotateProcessor(getRenderer()); // rp.setLockPriority(0.8f); registerInputProcessor(rp); addGestureListener(RotateProcessor.class, new DefaultRotateAction()); rp.setBubbledEventsEnabled(true); //FIXME TEST ScaleProcessor sp = new ScaleProcessor(getRenderer()); // sp.setLockPriority(0.8f); registerInputProcessor(sp); addGestureListener(ScaleProcessor.class, new DefaultScaleAction()); sp.setBubbledEventsEnabled(true); //FIXME TEST } /** * 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 { /** The key press indent. */ private int keyPressIndent; /** * Instantiates a new key click action. */ public KeyClickAction(){ keyPressIndent = 3; } public boolean processGestureEvent(MTGestureEvent g) { if (g instanceof TapEvent){ TapEvent clickEvent = (TapEvent)g; IMTComponent3D clicked = clickEvent.getTarget(); if (clicked != null && clicked instanceof MTKey){ MTKey clickedKey = (MTKey)clicked; switch (clickEvent.getTapID()) { case TapEvent.TAP_DOWN: pressKey(clickedKey); onKeyboardButtonDown(clickedKey, shiftPressed); break; case TapEvent.TAP_UP: unpressKey(clickedKey); onKeyboardButtonUp(clickedKey, shiftPressed); break; case TapEvent.TAPPED: unpressKey(clickedKey); onKeyboardButtonClicked(clickedKey, shiftPressed); break; default: break; }//switch }//instance of key }//instanceof clickevent return false; }//method private void pressKey(MTKey clickedKey) { clickedKey.setPressed(true); float keyHeight = clickedKey.getHeightXY(TransformSpace.RELATIVE_TO_PARENT); float keyWidth = clickedKey.getWidthXY(TransformSpace.RELATIVE_TO_PARENT); 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()); } } } private void unpressKey(MTKey clickedKey){ clickedKey.setPressed(false); float kHeight = clickedKey.getHeightXY(TransformSpace.RELATIVE_TO_PARENT); float kWidth = clickedKey.getWidthXY(TransformSpace.RELATIVE_TO_PARENT); 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()); } } } /** * 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 neccessary? }else{ centerPoint = shape.getCenterPointGlobal(); centerPoint.transform(shape.getGlobalInverseMatrix()); } shape.scale(width* (1/shape.getWidthXY(TransformSpace.RELATIVE_TO_PARENT)), height*(1/shape.getHeightXY(TransformSpace.RELATIVE_TO_PARENT)), 1, centerPoint); return true; }else return false; } }//class /** * Called after keyboard button pressed. * * @param clickedKey the clicked key * @param shiftPressed the shift pressed */ protected void onKeyboardButtonDown(MTKey clickedKey, boolean shiftPressed){ ITextInputListener[] listeners = this.getTextInputListeners(); for (ITextInputListener textInputListener : listeners) { 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 onKeyboardButtonUp(MTKey clickedKey, boolean shiftPressed){ } /** * Keyboard button clicked. * * @param clickedKey the clicked key * @param shiftPressed the shift pressed */ protected void onKeyboardButtonClicked(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); IAnimation 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) { switch (ae.getId()) { case AnimationEvent.ANIMATION_STARTED: case AnimationEvent.ANIMATION_UPDATED: float currentVal = ae.getAnimation().getValue(); setWidthRelativeToParent(currentVal); break; case AnimationEvent.ANIMATION_ENDED: setVisible(false); destroy(); break; default: break; }//switch }//processanimation }); keybCloseAnim.start(); } protected void onCloseButtonClicked(){ this.close(); } public void setHardwareInputEnabled(boolean hardwareInput){ try { IMTApplication app = (IMTApplication) getRenderer(); // if (hardwareInput) { // app.registerKeyEvent(this); // }else{ // app.unregisterKeyEvent(this); // } if (hardwareInput) { app.addKeyListener(this); }else{ app.removeKeyListener(this); } } catch (Exception e) { System.err.println(e.getMessage()); } this.hardwareInput = hardwareInput; } public boolean isHardwareInputEnabled(){ return this.hardwareInput; } @Override public void keyPressed(char key, int keyCode) { //TODO // //System.out.println("Key input: " + keyCode); // ITextInputListener[] listeners = this.getTextInputListeners(); // for (ITextInputListener textInputListener : listeners) { // 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 public void keyRleased(char key , int keyCode) { } public void keyEvent(KeyEvent e){ if (this.isEnabled()){ if (e.getID()!= KeyEvent.KEY_PRESSED) return; String keyCharString = String.valueOf(e.getKeyChar()); //System.out.println("Key input: " + keyCode); ITextInputListener[] listeners = this.getTextInputListeners(); for (ITextInputListener textInputListener : listeners) { 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(keyCharString); } } } } @Override protected void destroyComponent() { super.destroyComponent(); keyFont = null; keyList.clear(); shiftChangers.clear(); textInputAcceptors.clear(); if (this.isHardwareInputEnabled()){ try { ((IMTApplication) getRenderer()).removeKeyListener(this); getRenderer().unregisterKeyEvent(this); } catch (Exception e) { System.err.println(e.getMessage()); } } } /** * Snap to keyboard. * * @param mtKeyboard the mt keyboard */ public void snapToKeyboard(MTTextArea textArea){ //OLD WAY // this.translate(new Vector3D(30, -(getFont().getFontAbsoluteHeight() * (getLineCount())) + getFont().getFontMaxDescent() - borderHeight, 0)); this.addChild(textArea); textArea.setPositionRelativeToParent(new Vector3D(40, -textArea.getHeightXY(TransformSpace.LOCAL)*0.5f)); } }