/src/org/mt4j/components/visibleComponents/widgets/keyboard/MTTextKeyboard.java

http://mt4j.googlecode.com/ · Java · 372 lines · 177 code · 64 blank · 131 comment · 24 complexity · 3e8aaa937eb585397d886bf8e8f874ea MD5 · raw file

  1. /***********************************************************************
  2. * mt4j Copyright (c) 2008 - 2009, C.Ruff, Fraunhofer-Gesellschaft All rights reserved.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. ***********************************************************************/
  18. package org.mt4j.components.visibleComponents.widgets.keyboard;
  19. import java.awt.event.ActionEvent;
  20. import java.awt.event.ActionListener;
  21. import org.mt4j.components.MTComponent;
  22. import org.mt4j.components.StateChange;
  23. import org.mt4j.components.StateChangeEvent;
  24. import org.mt4j.components.StateChangeListener;
  25. import org.mt4j.components.visibleComponents.font.FontManager;
  26. import org.mt4j.components.visibleComponents.font.IFont;
  27. import org.mt4j.components.visibleComponents.shapes.AbstractShape;
  28. import org.mt4j.components.visibleComponents.widgets.MTTextArea;
  29. import org.mt4j.components.visibleComponents.widgets.MTTextArea.ExpandDirection;
  30. import org.mt4j.components.visibleComponents.widgets.buttons.MTSvgButton;
  31. import org.mt4j.input.gestureAction.DefaultDragAction;
  32. import org.mt4j.input.inputProcessors.MTGestureEvent;
  33. import org.mt4j.input.inputProcessors.componentProcessors.dragProcessor.DragEvent;
  34. import org.mt4j.input.inputProcessors.componentProcessors.dragProcessor.DragProcessor;
  35. import org.mt4j.input.inputProcessors.componentProcessors.lassoProcessor.LassoProcessor;
  36. import org.mt4j.input.inputProcessors.componentProcessors.rotateProcessor.RotateProcessor;
  37. import org.mt4j.input.inputProcessors.componentProcessors.scaleProcessor.ScaleProcessor;
  38. import org.mt4j.input.inputProcessors.componentProcessors.tapProcessor.TapEvent;
  39. import org.mt4j.util.MT4jSettings;
  40. import org.mt4j.util.MTColor;
  41. import org.mt4j.util.math.Matrix;
  42. import org.mt4j.util.math.Vector3D;
  43. import processing.core.PApplet;
  44. /**
  45. * A multitouch keyboard with an attached textfield that can be written to.
  46. *
  47. * @author Christopher Ruff
  48. */
  49. public class MTTextKeyboard extends MTKeyboard {
  50. /** The font for text field. */
  51. private IFont fontForTextField;
  52. /** The parent to add new text area to. */
  53. private MTComponent parentToAddNewTextAreaTo;
  54. /** The clustering gesture analyzer. */
  55. private LassoProcessor lassoProcessor;
  56. //Gesture Actions
  57. /** The default drag action. */
  58. private DefaultDragAction defaultDragAction;
  59. // private DefaultRotateAction defaultRotateAction;
  60. // private DefaultScaleAction defaultScaleAction;
  61. /** The drag from keyb action. */
  62. private DragTextAreaFromKeyboardAction dragFromKeybAction;
  63. /** The pa. */
  64. private PApplet pa;
  65. private ITextInputListener textInputListener;
  66. /**
  67. * Creates a new keyboard with a default font for its textarea.
  68. *
  69. * @param pApplet the applet
  70. */
  71. public MTTextKeyboard(PApplet pApplet) {
  72. this(pApplet, FontManager.getInstance().createFont(pApplet,
  73. "arial.ttf", 35, MTColor.BLACK));
  74. // this(pApplet, FontManager.getInstance().createFont(pApplet, "Eureka90.vlw", 35, new Color(0,0,0,255), new Color(0,0,0,255)));
  75. // this(pApplet, FontManager.getInstance().createFont(pApplet, "arial", 35, new Color(0,0,0,255), new Color(0,0,0,255)));
  76. }
  77. /**
  78. * Creates a new keyboard with the specified font for its textarea.
  79. *
  80. * @param pApplet the applet
  81. * @param fontForTextField the font for text field
  82. */
  83. public MTTextKeyboard(PApplet pApplet, IFont fontForTextField) {
  84. super(pApplet);
  85. this.pa = pApplet;
  86. this.fontForTextField = fontForTextField;
  87. lassoProcessor = null;
  88. //Set up gesture actions
  89. defaultDragAction = new DefaultDragAction();
  90. // defaultRotateAction = new DefaultRotateAction();
  91. // defaultScaleAction = new DefaultScaleAction();
  92. dragFromKeybAction = new DragTextAreaFromKeyboardAction();
  93. MTSvgButton newTextFieldSvg = new MTSvgButton(pa, MT4jSettings.getInstance().getDefaultSVGPath()
  94. + "keybNewTextField.svg");
  95. newTextFieldSvg.setBoundsPickingBehaviour(AbstractShape.BOUNDS_ONLY_CHECK);
  96. newTextFieldSvg.scale(0.8f, 0.8f, 1, new Vector3D(0,0,0));
  97. newTextFieldSvg.translate(new Vector3D(10,5,0));
  98. newTextFieldSvg.addActionListener(new ActionListener() {
  99. public void actionPerformed(ActionEvent arg0) {
  100. if (arg0.getSource() instanceof MTComponent){
  101. MTComponent clickedComp = (MTComponent)arg0.getSource();
  102. switch (arg0.getID()) {
  103. case TapEvent.TAPPED:
  104. //should always be keyboard
  105. MTComponent parent = clickedComp.getParent();
  106. if (parent instanceof MTTextKeyboard){
  107. MTTextKeyboard keyboard = (MTTextKeyboard)parent;
  108. //Remove old Textfield from keyboard if there is any
  109. if (textInputListener != null){
  110. if (textInputListener instanceof MTTextArea){
  111. MTTextArea ta = (MTTextArea)textInputListener;
  112. ta.setGestureAllowance(DragProcessor.class, true);
  113. ta.setGestureAllowance(RotateProcessor.class, true);
  114. ta.setGestureAllowance(ScaleProcessor.class, true);
  115. ta.setEnableCaret(false);
  116. //Add to clusteranylyzer for clustering the tarea
  117. if (getLassoProcessor() != null){
  118. getLassoProcessor().addClusterable(ta);
  119. }
  120. // keyboard.setTextInputAcceptor(null);
  121. removeTextInputListener(textInputListener);
  122. textInputListener = null;
  123. ta.removeAllGestureEventListeners(DragProcessor.class);
  124. ta.addGestureListener(DragProcessor.class, defaultDragAction);
  125. // ta.unassignGestureClassAndAction(DragGestureAnalyzer.class);
  126. // ta.assignGestureClassAndAction(DragGestureAnalyzer.class, defaultDragAction);
  127. //The direction, in which the textarea will float off
  128. Vector3D v = new Vector3D(0,-100, 0);
  129. //Add the textarea to the set parent
  130. if (getParentToAddNewTextAreaTo() != null){
  131. //Transform the textarea so it appears at the same world coords after its added to another parent
  132. Matrix m = MTComponent.getTransformToDestinationParentSpace(ta, getParentToAddNewTextAreaTo());
  133. ta.transform(m);
  134. //Transform the direction vector for the translation animation
  135. //to preserve the direction from the old reference frame to the new parents one
  136. // v.transformNormal(m);
  137. v.transformDirectionVector(m);
  138. ta.tweenTranslate(v, 500, 0.3f, 0.7f);
  139. getParentToAddNewTextAreaTo().addChild(ta);
  140. }else{
  141. //If that isnt set, try to add it to the keyboards parent
  142. if (getParent() != null){
  143. /////////////////////////
  144. // Transform the textarea so it appears at the same place after its added to another parent
  145. Matrix m = MTComponent.getTransformToDestinationParentSpace(ta, getParent());
  146. ta.transform(m);
  147. //Transform the direction vector to preserve the global direction
  148. //from the old reference frame to the new parents one
  149. //The translation part has to be removed from the matrix because we're transforming
  150. //a translation vector not a point vector
  151. v.transformDirectionVector(m);
  152. ta.tweenTranslate(v, 500, 0.3f, 0.7f);
  153. /////////////////////
  154. getParent().addChild(ta);
  155. }else{
  156. //do nothing..?
  157. throw new RuntimeException("Dont know where to add text area to!");
  158. }
  159. }
  160. }//if (text instanceof MTTextArea){
  161. }//if (keyboard.getTextInputAcceptor() != null){
  162. //Create a new textarea
  163. keyboard.createNewTextArea();
  164. }//if (parent instanceof MTTextKeyboard){
  165. break;
  166. default:
  167. break;
  168. }
  169. }
  170. }
  171. });
  172. this.addChild(newTextFieldSvg);
  173. }
  174. // @Override
  175. // protected void keyboardButtonDown(MTKey clickedKey, boolean shiftPressed){
  176. // ITextInputAcceptor textArea = getTextInputAcceptor();
  177. // if (textArea != null){
  178. // if (clickedKey.getCharacterToWrite().equals("back")){
  179. // textArea.removeLastCharacter();
  180. // }else if (clickedKey.getCharacterToWrite().equals("shift")){
  181. // //no nothing
  182. // }else{
  183. // String charToAdd = shiftPressed ? clickedKey.getCharacterToWriteShifted() : clickedKey.getCharacterToWrite();
  184. // textArea.appendCharByUnicode(charToAdd);
  185. // }
  186. // }
  187. // }
  188. /**
  189. * Creates a new textarea at the keyboard.
  190. * Fails if there is still one attached to it.
  191. */
  192. public void createNewTextArea(){
  193. if (this.textInputListener == null){
  194. final MTTextArea t = new MTTextArea(pa, fontForTextField);
  195. this.textInputListener = t;
  196. t.setExpandDirection(ExpandDirection.UP);
  197. t.setStrokeColor(new MTColor(0,0 , 0, 255));
  198. t.setFillColor(new MTColor(205,200,177, 255));
  199. t.setGestureAllowance(DragProcessor.class, true);
  200. t.setGestureAllowance(RotateProcessor.class, false);
  201. t.setGestureAllowance(ScaleProcessor.class, false);
  202. t.removeAllGestureEventListeners(DragProcessor.class);
  203. t.addGestureListener(DragProcessor.class, dragFromKeybAction);
  204. t.setEnableCaret(true);
  205. t.snapToKeyboard(this);
  206. this.addTextInputListener(this.textInputListener);
  207. //Remove textarea from listening if destroyed
  208. t.addStateChangeListener(StateChange.COMPONENT_DESTROYED, new StateChangeListener() {
  209. public void stateChanged(StateChangeEvent evt) {
  210. removeTextInputListener(t);
  211. }
  212. });
  213. }else{
  214. System.err.println("Cant create new textarea - Keyboard still has a textarea attached.");
  215. }
  216. }
  217. /**
  218. * Gets the parent to add new text area to.
  219. *
  220. * @return the parent to add new text area to
  221. */
  222. public MTComponent getParentToAddNewTextAreaTo() {
  223. return parentToAddNewTextAreaTo;
  224. }
  225. /**
  226. * Determines to which parent the textarea of the keyboard will be added to after
  227. * decoupling it from the keyboard.
  228. *
  229. * @param parentToAddNewTextAreaTo the parent to add new text area to
  230. */
  231. public void setParentToAddNewTextAreaTo(MTComponent parentToAddNewTextAreaTo) {
  232. this.parentToAddNewTextAreaTo = parentToAddNewTextAreaTo;
  233. }
  234. /**
  235. * Gets the clustering gesture analyzer.
  236. *
  237. * @return the clustering gesture analyzer
  238. */
  239. public LassoProcessor getLassoProcessor() {
  240. return lassoProcessor;
  241. }
  242. /**
  243. * Sets the clustering gesture analyzer.
  244. *
  245. * @param clusteringGestureAnalyzer the new clustering gesture analyzer
  246. */
  247. public void setLassoProcessor(LassoProcessor clusteringGestureAnalyzer) {
  248. this.lassoProcessor = clusteringGestureAnalyzer;
  249. }
  250. /**
  251. * Gesture action class to be used when a textarea is dragged away from the keyboard.
  252. *
  253. * @author C.Ruff
  254. */
  255. private class DragTextAreaFromKeyboardAction extends DefaultDragAction {
  256. /* (non-Javadoc)
  257. * @see com.jMT.input.gestureAction.DefaultDragAction#processGesture(com.jMT.input.inputAnalyzers.GestureEvent)
  258. */
  259. public boolean processGestureEvent(MTGestureEvent g) {
  260. super.processGestureEvent(g);
  261. if (g.getId() == MTGestureEvent.GESTURE_ENDED){
  262. if (g instanceof DragEvent){
  263. DragEvent dragEvent = (DragEvent)g;
  264. if (dragEvent.getTarget() instanceof MTTextArea){
  265. MTTextArea text = (MTTextArea)dragEvent.getTarget();
  266. //Add default gesture actions to textfield
  267. // text.assignGestureClassAndAction(DragGestureAnalyzer.class, defaultDragAction);
  268. // text.assignGestureClassAndAction(ScaleGestureAnalyzer.class, defaultScaleAction);
  269. // text.assignGestureClassAndAction(RotateGestureAnalyzer.class, defaultRotateAction);
  270. text.setGestureAllowance(DragProcessor.class, true);
  271. text.setGestureAllowance(RotateProcessor.class, true);
  272. text.setGestureAllowance(ScaleProcessor.class, true);
  273. //Disable caret showing
  274. text.setEnableCaret(false);
  275. //Add to clusteranylyzer for clustering the tarea
  276. if (getLassoProcessor() != null){
  277. getLassoProcessor().addClusterable(text);
  278. }
  279. removeTextInputListener(textInputListener);
  280. textInputListener = null;
  281. text.removeAllGestureEventListeners(DragProcessor.class);
  282. text.addGestureListener(DragProcessor.class, defaultDragAction);
  283. // text.unassignGestureClassAndAction(DragGestureAnalyzer.class);
  284. // text.assignGestureClassAndAction(DragGestureAnalyzer.class, defaultDragAction);
  285. // /*
  286. //Add the textare to the set parent
  287. if (getParentToAddNewTextAreaTo() != null){
  288. text.transform(MTComponent.getTransformToDestinationParentSpace(text, getParentToAddNewTextAreaTo()));
  289. getParentToAddNewTextAreaTo().addChild(text);
  290. }else{
  291. //If that isnt set, try to add it to the keyboards parent
  292. if (getParent() != null){
  293. text.transform(MTComponent.getTransformToDestinationParentSpace(text, getParent()));
  294. getParent().addChild(text);
  295. }else{
  296. //do nothing..
  297. // throw new RuntimeException("Dont know where to add text area to!");
  298. System.err.println("Dont know where to add text area to!");
  299. }
  300. }
  301. // */
  302. }
  303. }
  304. }
  305. return false;
  306. }
  307. }
  308. }