Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
EditText.Windows.Desktop.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 #if SILICONSTUDIO_PLATFORM_WINDOWS_DESKTOP
4 using System;
5 
6 using SiliconStudio.Core.Mathematics;
7 using SiliconStudio.Paradox.Input;
9 
10 namespace SiliconStudio.Paradox.UI.Controls
11 {
12  public partial class EditText
13  {
14  private static void InitializeStaticImpl()
15  {
16  }
17 
18  private void InitializeImpl()
19  {
20  }
21 
22  private int GetLineCountImpl()
23  {
24  if (Font == null)
25  return 1;
26 
27  return text.Split('\n').Length;
28  }
29 
30  private void OnMaxLinesChangedImpl()
31  {
32  }
33 
34  private void OnMinLinesChangedImpl()
35  {
36  }
37 
38  private void ActivateEditTextImpl()
39  {
40  }
41 
42  private void DeactivateEditTextImpl()
43  {
44  FocusedElement = null;
45  }
46 
47  private void OnTouchMoveImpl(TouchEventArgs args)
48  {
49  var currentPosition = FindNearestCharacterIndex(new Vector2(args.WorldPosition.X - WorldMatrix.M41, args.WorldPosition.Y - WorldMatrix.M42));
50 
51  if (caretAtStart)
52  {
53  if (currentPosition < selectionStop)
54  Select(currentPosition, selectionStop - currentPosition, true);
55  else
56  Select(selectionStop, currentPosition - selectionStop);
57  }
58  else
59  {
60  if (currentPosition < SelectionStart)
61  Select(currentPosition, selectionStart - currentPosition, true);
62  else
63  Select(selectionStart, currentPosition - selectionStart);
64  }
65  }
66 
67  private void OnTouchDownImpl(TouchEventArgs args)
68  {
69  // Find the appropriate position for the caret.
70  CaretPosition = FindNearestCharacterIndex(new Vector2(args.WorldPosition.X - WorldMatrix.M41, args.WorldPosition.Y - WorldMatrix.M42));
71  }
72 
73  /// <summary>
74  /// Find the index of the nearest character to the provided position.
75  /// </summary>
76  /// <param name="position">The position in edit text space</param>
77  /// <returns>The 0-based index of the nearest character</returns>
78  protected virtual int FindNearestCharacterIndex(Vector2 position)
79  {
80  if (Font == null)
81  return 0;
82 
83  var textRegionSize = (ActualWidth - Padding.Left - Padding.Right);
84  var fontScale = RealSizeVirtualResolutionRatio;
85  var fontSize = fontScale * TextSize;
86 
87  // calculate the offset of the beginning of the text due to text alignment
88  var alignmentOffset = -textRegionSize / 2f;
89  if (TextAlignment != TextAlignment.Left)
90  {
91  var textWidth = Font.MeasureString(TextToDisplay, ref fontSize).X;
92  if (Font.IsDynamic)
93  textWidth /= fontScale.X;
94 
95  alignmentOffset = TextAlignment == TextAlignment.Center ? -textWidth / 2 : -textRegionSize / 2f + (textRegionSize - textWidth);
96  }
97  var touchInText = position.X - alignmentOffset;
98 
99  // Find the first character starting after the click
100  var characterIndex = 1;
101  var previousCharacterOffset = 0f;
102  var currentCharacterOffset = Font.MeasureString(TextToDisplay, ref fontSize, characterIndex).X;
103  while (currentCharacterOffset < touchInText && characterIndex < textToDisplay.Length)
104  {
105  ++characterIndex;
106  previousCharacterOffset = currentCharacterOffset;
107  currentCharacterOffset = Font.MeasureString(TextToDisplay, ref fontSize, characterIndex).X;
108  if (Font.IsDynamic)
109  currentCharacterOffset /= fontScale.X;
110  }
111 
112  // determine the caret position.
113  if (touchInText < 0) // click before the start of the text
114  {
115  return 0;
116  }
117  if (currentCharacterOffset < touchInText) // click after the end of the text
118  {
119  return textToDisplay.Length;
120  }
121 
122  const float Alpha = 0.66f;
123  var previousElementRatio = Math.Abs(touchInText - previousCharacterOffset) / Alpha;
124  var currentElementRation = Math.Abs(currentCharacterOffset - touchInText) / (1 - Alpha);
125  return previousElementRatio < currentElementRation ? characterIndex - 1 : characterIndex;
126  }
127 
128  internal override void OnKeyPressed(KeyEventArgs args)
129  {
130  base.OnKeyPressed(args);
131 
132  InterpretKey(args.Key, args.Input);
133  }
134 
135  private void InterpretKey(Keys key, InputManagerBase input)
136  {
137  // delete and back space have same behavior when there is a selection
138  if (SelectionLength > 0 && (key == Keys.Delete || key == Keys.Back))
139  {
140  SelectedText = "";
141  return;
142  }
143 
144  // backspace with caret
145  if (key == Keys.Back)
146  {
147  selectionStart = Math.Max(0, selectionStart - 1);
148  SelectedText = "";
149  return;
150  }
151 
152  // delete with caret
153  if (key == Keys.Delete)
154  {
155  SelectionLength = 1;
156  SelectedText = "";
157  return;
158  }
159 
160  // select backward
161  if (key == Keys.Left && (input.IsKeyDown(Keys.LeftShift) || input.IsKeyDown(Keys.RightShift)))
162  {
163  if (caretAtStart || selectionStart == selectionStop)
164  Select(selectionStart - 1, SelectionLength + 1, true);
165  else
166  Select(selectionStart, SelectionLength - 1);
167 
168  return;
169  }
170 
171  // select forward
172  if (key == Keys.Right && (input.IsKeyDown(Keys.LeftShift) || input.IsKeyDown(Keys.RightShift)))
173  {
174  if (caretAtStart && selectionStart != selectionStop)
175  Select(selectionStart + 1, SelectionLength - 1, true);
176  else
177  Select(selectionStart, SelectionLength + 1);
178 
179  return;
180  }
181 
182  // move backward
183  if (key == Keys.Left)
184  {
185  CaretPosition = CaretPosition - 1;
186  return;
187  }
188 
189  // move forward
190  if (key == Keys.Right)
191  {
192  CaretPosition = CaretPosition + 1;
193  return;
194  }
195 
196  // validate the text with "enter" or "escape"
197  if (key == Keys.Enter || key == Keys.Escape)
198  {
199  IsSelectionActive = false;
200  return;
201  }
202 
203  // try to convert the key to character and insert it at the caret position or replace the current selection
204  var character = '\0';
205  if (TryConvertKeyToCharacter(key, input.IsKeyDown(Keys.LeftShift) || input.IsKeyDown(Keys.RightShift), ref character))
206  SelectedText = new string(character, 1);
207  }
208 
209  private bool TryConvertKeyToCharacter(Keys key, bool isMajuscule, ref Char character)
210  {
211  switch (key)
212  {
213  case Keys.None:
214  case Keys.Cancel:
215  case Keys.Back:
216  case Keys.Tab:
217  case Keys.LineFeed:
218  case Keys.Clear:
219  case Keys.Enter:
220  case Keys.Pause:
221  case Keys.Capital:
222  case Keys.HangulMode:
223  case Keys.JunjaMode:
224  case Keys.FinalMode:
225  case Keys.HanjaMode:
226  case Keys.Escape:
227  case Keys.ImeConvert:
228  case Keys.ImeNonConvert:
229  case Keys.ImeAccept:
230  case Keys.ImeModeChange:
231  case Keys.PageUp:
232  case Keys.Next:
233  case Keys.Home:
234  case Keys.End:
235  case Keys.Left:
236  case Keys.Up:
237  case Keys.Right:
238  case Keys.Down:
239  case Keys.Select:
240  case Keys.Print:
241  case Keys.Execute:
242  case Keys.PrintScreen:
243  case Keys.Insert:
244  case Keys.Delete:
245  case Keys.Help:
246  case Keys.LeftWin:
247  case Keys.RightWin:
248  case Keys.Apps:
249  case Keys.Sleep:
250  case Keys.Separator:
251  case Keys.Decimal:
252  case Keys.F1:
253  case Keys.F2:
254  case Keys.F3:
255  case Keys.F4:
256  case Keys.F5:
257  case Keys.F6:
258  case Keys.F7:
259  case Keys.F8:
260  case Keys.F9:
261  case Keys.F10:
262  case Keys.F11:
263  case Keys.F12:
264  case Keys.F13:
265  case Keys.F14:
266  case Keys.F15:
267  case Keys.F16:
268  case Keys.F17:
269  case Keys.F18:
270  case Keys.F19:
271  case Keys.F20:
272  case Keys.F21:
273  case Keys.F22:
274  case Keys.F23:
275  case Keys.F24:
276  case Keys.NumLock:
277  case Keys.Scroll:
278  case Keys.LeftShift:
279  case Keys.RightShift:
280  case Keys.LeftCtrl:
281  case Keys.RightCtrl:
282  case Keys.LeftAlt:
283  case Keys.RightAlt:
284  case Keys.BrowserBack:
285  case Keys.BrowserForward:
286  case Keys.BrowserRefresh:
287  case Keys.BrowserStop:
288  case Keys.BrowserSearch:
289  case Keys.BrowserFavorites:
290  case Keys.BrowserHome:
291  case Keys.VolumeMute:
292  case Keys.VolumeDown:
293  case Keys.VolumeUp:
294  case Keys.MediaNextTrack:
295  case Keys.MediaPreviousTrack:
296  case Keys.MediaStop:
297  case Keys.MediaPlayPause:
298  case Keys.LaunchMail:
299  case Keys.SelectMedia:
300  case Keys.LaunchApplication1:
301  case Keys.LaunchApplication2:
302  case Keys.Oem1:
303  case Keys.OemPlus:
304  case Keys.OemComma:
305  case Keys.OemMinus:
306  case Keys.OemPeriod:
307  case Keys.Oem2:
308  case Keys.Oem3:
309  case Keys.Oem4:
310  case Keys.Oem5:
311  case Keys.Oem6:
312  case Keys.Oem7:
313  case Keys.Oem8:
314  case Keys.Oem102:
315  case Keys.Attn:
316  case Keys.CrSel:
317  case Keys.ExSel:
318  case Keys.EraseEof:
319  case Keys.Play:
320  case Keys.Zoom:
321  case Keys.NoName:
322  case Keys.Pa1:
323  case Keys.OemClear:
324  case Keys.NumPadEnter:
325  case Keys.NumPadDecimal:
326  return false;
327  case Keys.Space:
328  character = ' ';
329  break;
330  case Keys.D0:
331  character = '0';
332  break;
333  case Keys.D1:
334  character = '1';
335  break;
336  case Keys.D2:
337  character = '2';
338  break;
339  case Keys.D3:
340  character = '3';
341  break;
342  case Keys.D4:
343  character = '4';
344  break;
345  case Keys.D5:
346  character = '5';
347  break;
348  case Keys.D6:
349  character = '6';
350  break;
351  case Keys.D7:
352  character = '7';
353  break;
354  case Keys.D8:
355  character = '8';
356  break;
357  case Keys.D9:
358  character = '9';
359  break;
360  case Keys.A:
361  character = isMajuscule? 'A': 'a';
362  break;
363  case Keys.B:
364  character = isMajuscule ? 'B' : 'b';
365  break;
366  case Keys.C:
367  character = isMajuscule ? 'C' : 'c';
368  break;
369  case Keys.D:
370  character = isMajuscule ? 'D' : 'd';
371  break;
372  case Keys.E:
373  character = isMajuscule ? 'E' : 'e';
374  break;
375  case Keys.F:
376  character = isMajuscule ? 'F' : 'f';
377  break;
378  case Keys.G:
379  character = isMajuscule ? 'G' : 'g';
380  break;
381  case Keys.H:
382  character = isMajuscule ? 'H' : 'h';
383  break;
384  case Keys.I:
385  character = isMajuscule ? 'I' : 'i';
386  break;
387  case Keys.J:
388  character = isMajuscule ? 'J' : 'j';
389  break;
390  case Keys.K:
391  character = isMajuscule ? 'K' : 'k';
392  break;
393  case Keys.L:
394  character = isMajuscule ? 'L' : 'l';
395  break;
396  case Keys.M:
397  character = isMajuscule ? 'M' : 'm';
398  break;
399  case Keys.N:
400  character = isMajuscule ? 'N' : 'n';
401  break;
402  case Keys.O:
403  character = isMajuscule ? 'O' : 'o';
404  break;
405  case Keys.P:
406  character = isMajuscule ? 'P' : 'p';
407  break;
408  case Keys.Q:
409  character = isMajuscule ? 'Q' : 'q';
410  break;
411  case Keys.R:
412  character = isMajuscule ? 'R' : 'r';
413  break;
414  case Keys.S:
415  character = isMajuscule ? 'S' : 's';
416  break;
417  case Keys.T:
418  character = isMajuscule ? 'T' : 't';
419  break;
420  case Keys.U:
421  character = isMajuscule ? 'U' : 'u';
422  break;
423  case Keys.V:
424  character = isMajuscule ? 'V' : 'v';
425  break;
426  case Keys.W:
427  character = isMajuscule ? 'W' : 'w';
428  break;
429  case Keys.X:
430  character = isMajuscule ? 'X' : 'x';
431  break;
432  case Keys.Y:
433  character = isMajuscule ? 'Y' : 'y';
434  break;
435  case Keys.Z:
436  character = isMajuscule ? 'Z' : 'z';
437  break;
438  case Keys.NumPad0:
439  character = '0';
440  break;
441  case Keys.NumPad1:
442  character = '1';
443  break;
444  case Keys.NumPad2:
445  character = '2';
446  break;
447  case Keys.NumPad3:
448  character = '3';
449  break;
450  case Keys.NumPad4:
451  character = '4';
452  break;
453  case Keys.NumPad5:
454  character = '5';
455  break;
456  case Keys.NumPad6:
457  character = '6';
458  break;
459  case Keys.NumPad7:
460  character = '7';
461  break;
462  case Keys.NumPad8:
463  character = '8';
464  break;
465  case Keys.NumPad9:
466  character = '9';
467  break;
468  case Keys.Multiply:
469  character = '*';
470  break;
471  case Keys.Add:
472  character = '+';
473  break;
474  case Keys.Subtract:
475  character = '-';
476  break;
477  case Keys.Divide:
478  character = '/';
479  break;
480  default:
481  throw new ArgumentOutOfRangeException("key");
482  }
483 
484  return true;
485  }
486 
487  private void UpdateTextToEditImpl()
488  {
489  }
490 
491  private void UpdateInputTypeImpl()
492  {
493  }
494 
495  private void UpdateSelectionFromEditImpl()
496  {
497  }
498 
499  private void UpdateSelectionToEditImpl()
500  {
501  }
502  }
503 }
504 
505 #endif
SiliconStudio.Paradox.Games.Mathematics.Vector2 Vector2
TextAlignment
Specify the available text alignment when rendering text.
Definition: TextAlignment.cs:8
SiliconStudio.Paradox.Input.Keys Keys
SharpDX.DirectWrite.Font Font
Allow data to be stored in the alpha component.