PageRenderTime 64ms CodeModel.GetById 12ms app.highlight 46ms RepoModel.GetById 1ms app.codeStats 1ms

/extensions/org/mt4jx/components/visibleComponents/widgets/MTSuggestionTextArea.java

http://mt4j.googlecode.com/
Java | 428 lines | 222 code | 52 blank | 154 comment | 42 complexity | 47774bae63fd9caa9f38d3db792ab28d MD5 | raw file
  1package org.mt4jx.components.visibleComponents.widgets;
  2
  3import java.util.ArrayList;
  4import java.util.List;
  5
  6import org.mt4j.MTApplication;
  7import org.mt4j.components.StateChange;
  8import org.mt4j.components.StateChangeEvent;
  9import org.mt4j.components.StateChangeListener;
 10import org.mt4j.components.TransformSpace;
 11import org.mt4j.components.css.style.CSSStyle;
 12import org.mt4j.components.visibleComponents.font.IFont;
 13import org.mt4j.components.visibleComponents.shapes.MTPolygon;
 14import org.mt4j.components.visibleComponents.shapes.MTRectangle;
 15import org.mt4j.components.visibleComponents.widgets.MTTextArea;
 16import org.mt4j.components.visibleComponents.widgets.keyboard.MTKeyboard;
 17import org.mt4j.input.inputProcessors.IGestureEventListener;
 18import org.mt4j.input.inputProcessors.MTGestureEvent;
 19import org.mt4j.input.inputProcessors.componentProcessors.tapProcessor.TapEvent;
 20import org.mt4j.input.inputProcessors.componentProcessors.tapProcessor.TapProcessor;
 21import org.mt4j.util.MTColor;
 22import org.mt4j.util.math.Tools3D;
 23import org.mt4j.util.math.Vector3D;
 24import processing.core.PGraphics;
 25
 26/**
 27 * The Class MTSuggestionTextArea.
 28 */
 29public class MTSuggestionTextArea extends MTTextArea {
 30
 31	/** The available suggestions. */
 32	private List<String> availableValues;
 33
 34	/** The MTApplication. */
 35	private MTApplication app;
 36
 37	/** The suggestion box. */
 38	private MTTextArea suggestionBox;
 39
 40	/** The keyboard. */
 41	private MTKeyboard keyboard;
 42
 43	/** The width. */
 44	private float width = -1f;
 45
 46	/** The current suggestions. */
 47	private List<String> currentSuggestions = new ArrayList<String>();
 48
 49	/** The o (Counting Variable). */
 50	private int o = 0;
 51
 52	/** The p (Counting Variable). */
 53	private int p = 0;
 54
 55	/**
 56	 * Instantiates a new MTSuggestionTextArea.
 57	 * 
 58	 * @param app
 59	 *            the MTApplication
 60	 * @param width
 61	 *            the width
 62	 */
 63	public MTSuggestionTextArea(MTApplication app, float width) {
 64		this(app, width, new ArrayList<String>());
 65	}
 66
 67	/**
 68	 * Instantiates a new MTSuggestionTextArea.
 69	 * 
 70	 * @param app
 71	 *            the MTApplication
 72	 * @param width
 73	 *            the width of the text input box
 74	 * @param suggestions
 75	 *            the suggestions as List<String>
 76	 */
 77	public MTSuggestionTextArea(MTApplication app, float width,
 78			List<String> suggestions) {
 79		// Instantiate with default font, can be changed using CSS
 80		super(app);
 81		this.init(app, width, suggestions);
 82	}
 83
 84	/**
 85	 * Instantiates a new MTSuggestionTextArea.
 86	 * 
 87	 * @param app
 88	 *            the MTApplication
 89	 * @param font
 90	 *            the font
 91	 * @param width
 92	 *            the width of the text input box
 93	 */
 94	public MTSuggestionTextArea(MTApplication app, IFont font, float width) {
 95		this(app, font, width, new ArrayList<String>());
 96	}
 97
 98	/**
 99	 * Instantiates a new MTSuggestionTextArea.
100	 * 
101	 * @param app
102	 *            the MTApplication
103	 * @param font
104	 *            the font
105	 * @param width
106	 *            the width of the text input box
107	 * @param suggestions
108	 *            the suggestions as List<String>
109	 */
110	public MTSuggestionTextArea(MTApplication app, IFont font, float width,
111			List<String> suggestions) {
112		super(app, font);
113		this.init(app, width, suggestions);
114	}
115
116	/*
117	 * (non-Javadoc)
118	 * 
119	 * @see
120	 * org.mt4j.components.visibleComponents.widgets.MTTextArea#drawComponent
121	 * (processing.core.PGraphics)
122	 */
123	@Override
124	public void drawComponent(PGraphics g) {
125		super.drawComponent(g);
126		if (keyboard != null) {
127			if (o++ > 30) {
128				o = 0;
129				drawSuggestionBox();
130
131			}
132			if (p++ > 4) {
133				this.setWidthLocal(width);
134			}
135		} else {
136			if (suggestionBox.isVisible() == true)
137				suggestionBox.setVisible(false);
138		}
139
140	}
141
142	/**
143	 * Gets the relevant strings (for the current content of the TextArea).
144	 * 
145	 * @return the relevant strings
146	 */
147	public List<String> getRelevantStrings() {
148		List<String> newList = new ArrayList<String>();
149		if (!availableValues.isEmpty()) {
150			String currentText = this.getText();
151			for (String s : availableValues) {
152				if (currentText != "") {
153					if (s.toUpperCase().contains(currentText.toUpperCase())) {
154						newList.add(s.replaceAll("\n", " "));
155					}
156				} else {
157					newList.add(s.replace("\n", ""));
158				}
159			}
160		}
161		return newList;
162	}
163
164	/**
165	 * Style suggestion box.
166	 */
167	public void styleSuggestionBox() {
168		suggestionBox.setNoFill(this.isNoFill());
169		suggestionBox.setNoStroke(this.isNoStroke());
170		suggestionBox.setFillColor(this.getFillColor());
171		suggestionBox.setStrokeColor(new MTColor(this.getStrokeColor().getR(),
172				this.getStrokeColor().getG(), this.getStrokeColor().getG(),
173				this.getStrokeColor().getAlpha() * 0.75f));
174		suggestionBox.setStrokeWeight(0.25f);
175	}
176
177	/**
178	 * Calculate the Coordinates needed for placing the Rectangle.
179	 * 
180	 * @param rect
181	 *            the Rectangle
182	 * @param ta
183	 *            the TextArea
184	 * @param xo
185	 *            the x-offset
186	 * @param yo
187	 *            the y-offset
188	 * @return the position as Vector3D
189	 */
190	private Vector3D calcPos(MTRectangle rect, MTPolygon ta, float xo, float yo) {
191		return new Vector3D((ta.getWidthXY(TransformSpace.LOCAL) / 2)
192				+ rect.getVerticesLocal()[0].getX() + xo, 
193				(ta.getHeightXY(TransformSpace.LOCAL) / 2)
194				+ rect.getVerticesLocal()[0].getY() + yo);
195	}
196
197	/**
198	 * Draw suggestion box.
199	 */
200	private void drawSuggestionBox() {
201		String suggestions = "";
202		int i = 0;
203		List<String> strings = this.getRelevantStrings();
204		if (strings.size() > 0) {
205			suggestionBox.setVisible(true);
206			currentSuggestions.clear();
207			for (String s : strings) {
208				if (i != 0 && i < 5)
209					suggestions += "\n";
210
211				if (i++ < 5) {
212					suggestions += s;
213					currentSuggestions.add(s);
214				} else {
215					break;
216				}
217
218			}
219			suggestionBox.setText(suggestions);
220			suggestionBox.setWidthLocal(width);
221			suggestionBox.setPositionRelativeToParent(calcPos(this,
222					suggestionBox, 0, this.getHeightXY(TransformSpace.LOCAL)));
223		} else {
224			suggestionBox.setVisible(false);
225		}
226		if (keyboard == null)
227			suggestionBox.setVisible(false);
228	}
229
230	/**
231	 * Inits the MTSuggestionTextArea
232	 * 
233	 * @param app
234	 *            the app
235	 * @param width
236	 *            the width
237	 * @param suggestions
238	 *            the suggestions as List<String>
239	 */
240	private void init(MTApplication app, float width, List<String> suggestions) {
241		this.width = width;
242		
243		this.availableValues = suggestions;
244		this.app = app;
245		this.setFont(this.getCssHelper().getVirtualStyleSheet().getFont());
246		this.setWidthLocal(width);
247		
248		this.removeAllChildren();
249		this.removeAllGestureEventListeners(TapProcessor.class);
250		
251		// Add Tap listener to evoke Keyboard
252		this.setGestureAllowance(TapProcessor.class, true);
253		this.registerInputProcessor(new TapProcessor(app));
254		this.addGestureListener(TapProcessor.class, new EditListener(this));
255
256		// Create Suggestion Box
257		suggestionBox = new MTTextArea(app, this.getFont());
258		suggestionBox.setWidthLocal(width);
259		suggestionBox.setCssForceDisable(true);
260		styleSuggestionBox();
261
262		suggestionBox.removeAllGestureEventListeners();
263		suggestionBox.setGestureAllowance(TapProcessor.class, true);
264		suggestionBox.registerInputProcessor(new TapProcessor(app));
265		suggestionBox.addGestureListener(TapProcessor.class,
266				new SuggestionBoxListener());
267
268		this.addChild(suggestionBox);
269		drawSuggestionBox();
270	}
271	
272	public void init() {
273		if (app != null && width != -1f && this.availableValues != null) {
274			init(app, width, this.availableValues);
275		}
276	}
277	
278	
279	@Override
280	protected void applyStyleSheetCustom(CSSStyle virtualStyleSheet) {
281		super.applyStyleSheetCustom(virtualStyleSheet);
282		this.init();
283	}
284
285
286	/**
287	 * The listener interface for receiving suggestionBox events. The class that
288	 * is interested in processing a suggestionBox event implements this
289	 * interface, and the object created with that class is registered with a
290	 * component using the component's
291	 * <code>addSuggestionBoxListener<code> method. When
292	 * the suggestionBox event occurs, that object's appropriate
293	 * method is invoked.
294	 * 
295	 * @see SuggestionBoxEvent
296	 */
297	public class SuggestionBoxListener implements IGestureEventListener {
298	
299		/*
300		 * (non-Javadoc)
301		 * 
302		 * @see
303		 * org.mt4j.input.inputProcessors.IGestureEventListener#processGestureEvent
304		 * (org.mt4j.input.inputProcessors.MTGestureEvent)
305		 */
306		public boolean processGestureEvent(MTGestureEvent ge) {
307			if (ge instanceof TapEvent) {
308				TapEvent te = (TapEvent) ge;
309				if (te.getTapID() == TapEvent.TAPPED) {
310					Vector3D w = Tools3D.project(app, app.getCurrentScene()
311							.getSceneCam(), te.getLocationOnScreen());
312					Vector3D x = suggestionBox.globalToLocal(w);
313					float zero = suggestionBox.getVerticesLocal()[0].y;
314					float heightPerLine = suggestionBox
315							.getHeightXY(TransformSpace.LOCAL)
316							/ (float) (suggestionBox.getLineCount() + 1);
317					int line = (int) ((x.y - zero) / heightPerLine);
318	
319					if (currentSuggestions.size() > line) {
320						setText(currentSuggestions.get(line));
321					}
322	
323				}
324			}
325			return false;
326		}
327	
328	}
329
330	/**
331	 * The listener interface for receiving keyboard events. The class that is
332	 * interested in processing a keyboard event implements this interface, and
333	 * the object created with that class is registered with a component using
334	 * the component's <code>addKeyboardListener<code> method. When
335	 * the keyboard event occurs, that object's appropriate
336	 * method is invoked.
337	 * 
338	 * @see KeyboardEvent
339	 */
340	public class KeyboardListener implements StateChangeListener {
341	
342		/*
343		 * (non-Javadoc)
344		 * 
345		 * @see
346		 * org.mt4j.components.StateChangeListener#stateChanged(org.mt4j.components
347		 * .StateChangeEvent)
348		 */
349		public void stateChanged(StateChangeEvent evt) {
350			if (evt.getState() == StateChange.COMPONENT_DESTROYED) {
351				keyboard = null;
352			}
353	
354		}
355	
356	}
357
358	/**
359	 * The listener interface for receiving edit events. The class that is
360	 * interested in processing a edit event implements this interface, and the
361	 * object created with that class is registered with a component using the
362	 * component's <code>addEditListener<code> method. When
363	 * the edit event occurs, that object's appropriate
364	 * method is invoked.
365	 * 
366	 * @see EditEvent
367	 */
368	public class EditListener implements IGestureEventListener {
369	
370		/** The ta. */
371		private MTTextArea ta;
372	
373		/**
374		 * Instantiates a new edits the listener.
375		 * 
376		 * @param ta
377		 *            the ta
378		 */
379		public EditListener(MTTextArea ta) {
380			this.ta = ta;
381		}
382	
383		/*
384		 * (non-Javadoc)
385		 * 
386		 * @see
387		 * org.mt4j.input.inputProcessors.IGestureEventListener#processGestureEvent
388		 * (org.mt4j.input.inputProcessors.MTGestureEvent)
389		 */
390		public boolean processGestureEvent(MTGestureEvent ge) {
391			if (ge instanceof TapEvent) {
392				TapEvent te = (TapEvent) ge;
393				if (te.getTapID() == TapEvent.TAPPED) {
394					System.out.println(ta.getText() + ": " + te.getTapID() + " (" + te.getId() + ")");
395					if (keyboard == null
396							&& te.getTapID() == TapEvent.TAPPED) {
397						keyboard = new MTKeyboard(app);
398						addChild(keyboard);
399						keyboard.addTextInputListener(ta);
400						keyboard.addStateChangeListener(
401								StateChange.COMPONENT_DESTROYED,
402								new KeyboardListener());
403	
404						keyboard.setCssForceDisable(true);
405	
406						keyboard.setNoFill(ta.isNoFill());
407						keyboard.setNoStroke(ta.isNoStroke());
408						keyboard.setFillColor(ta.getFillColor());
409						keyboard.setStrokeColor(new MTColor(ta.getStrokeColor().getR(),
410								ta.getStrokeColor().getG(), ta.getStrokeColor().getG(),
411								ta.getStrokeColor().getAlpha() * 0.75f));
412						keyboard.setStrokeWeight(ta.getStrokeWeight());
413	
414						keyboard.setPositionRelativeToParent(calcPos(
415								ta,
416								keyboard,
417								0,
418								ta.getHeightXY(TransformSpace.LOCAL)
419								+ suggestionBox
420								.getHeightXY(TransformSpace.LOCAL)));
421					}
422				}
423			}
424			return false;
425		}
426	
427	}
428}