4 using System.Diagnostics;
7 using SiliconStudio.Core;
8 using SiliconStudio.Core.Mathematics;
9 using SiliconStudio.Paradox.Games;
10 using SiliconStudio.Paradox.Graphics;
12 using SiliconStudio.Paradox.UI.Events;
14 namespace SiliconStudio.
Paradox.UI.Controls
19 [DebuggerDisplay(
"EditText - Name={Name}")]
22 private float? textSize;
26 private const char PasswordHidingCharacter =
'*';
28 private string text =
"";
29 private string textToDisplay =
"";
31 private int selectionStart;
32 private int selectionStop;
33 private bool caretAtStart;
35 private float caretWith;
36 private float caretFrequency;
37 private bool caretHided;
38 private float accumulatedTime;
40 private bool synchronousCharacterGeneration;
42 private readonly StringBuilder builder =
new StringBuilder();
58 #region Dependency Properties
89 DefaultValueMetadata.Static(int.MaxValue),
ValidateValueMetadata.New<
int>(CheckStrictlyPositive), ObjectInvalidationMetadata.New<
int>(InvalidateMaxLength));
95 DefaultValueMetadata.Static(int.MaxValue),
ValidateValueMetadata.New<
int>(CheckStrictlyPositive), ObjectInvalidationMetadata.New<
int>(InvalidateMaxLines));
101 DefaultValueMetadata.Static(1),
ValidateValueMetadata.New<
int>(CheckStrictlyPositive), ObjectInvalidationMetadata.New<
int>(InvalidateMinLines));
118 private static void CheckStrictlyPositive(ref
int value)
121 throw new ArgumentOutOfRangeException(
"value");
127 element.InvalidateMeasure();
131 private static void InvalidateIsReadOnly(
object propertyOwner,
PropertyKey<bool> propertykey,
bool propertyoldvalue)
133 var editText = (EditText)propertyOwner;
135 editText.OnIsReadOnlyChanged();
138 private static void InvalidateMaxLength(
object propertyOwner,
PropertyKey<int> propertyKey,
int propertyOldValue)
140 var editText = (EditText)propertyOwner;
142 editText.OnMaxLengthChanged();
145 private static void InvalidateMaxLines(
object propertyOwner,
PropertyKey<int> propertyKey,
int propertyOldValue)
147 var editText = (EditText)propertyOwner;
149 editText.OnMaxLinesChanged();
152 private static void InvalidateMinLines(
object propertyOwner,
PropertyKey<int> propertyKey,
int propertyOldValue)
154 var editText = (EditText)propertyOwner;
156 editText.OnMinLinesChanged();
164 IsSelectionActive =
false;
172 var previousCaret = CaretPosition;
173 var previousSelectionStart = SelectionStart;
174 var previousSelectionLength = SelectionLength;
178 CaretPosition = previousCaret;
179 Select(previousSelectionStart, previousSelectionLength);
187 OnMaxLinesChangedImpl();
196 OnMinLinesChangedImpl();
204 EventManager.RegisterClassHandler(typeof(
EditText), TextChangedEvent, TextChangedClassHandler);
206 InitializeStaticImpl();
217 if (services == null)
218 throw new ArgumentNullException(
"services");
222 throw new ArgumentException(
"Provided services need to contain a provider for the IGame interface.");
227 CanBeHitByUser =
true;
228 IsSelectionActive =
false;
230 DrawLayerNumber += 4;
235 private bool isSelectionActive;
240 private Func<char, bool> characterFilterPredicate;
245 public bool IsSelectionActive
247 get {
return isSelectionActive; }
250 if (isSelectionActive == value)
253 if(IsReadOnly && value)
256 isSelectionActive = value;
258 if (IsSelectionActive)
260 var previousEditText = FocusedElement as
EditText;
261 if (previousEditText != null)
262 previousEditText.IsSelectionActive =
false;
264 FocusedElement =
this;
265 ActivateEditTextImpl();
269 DeactivateEditTextImpl();
274 public override bool IsEnabled
278 if (!value && IsSelectionActive)
279 IsSelectionActive =
false;
281 base.IsEnabled = value;
290 public bool SynchronousCharacterGeneration
292 get {
return synchronousCharacterGeneration; }
295 if (synchronousCharacterGeneration == value)
298 synchronousCharacterGeneration = value;
300 if (IsMeasureValid && synchronousCharacterGeneration)
308 protected bool ShouldHideText {
get {
return (inputType &
InputTypeFlags.Password) != 0; } }
313 public bool IsReadOnly
315 get {
return DependencyProperties.Get(IsReadOnlyPropertyKey); }
316 set { DependencyProperties.Set(IsReadOnlyPropertyKey, value); }
324 get {
return DependencyProperties.Get(FontPropertyKey); }
325 set { DependencyProperties.Set(FontPropertyKey, value); }
331 public Color TextColor
333 get {
return DependencyProperties.Get(TextColorPropertyKey); }
334 set { DependencyProperties.Set(TextColorPropertyKey, value); }
340 public Color SelectionColor
342 get {
return DependencyProperties.Get(SelectionColorPropertyKey); }
343 set { DependencyProperties.Set(SelectionColorPropertyKey, value); }
349 public Color CaretColor
351 get {
return DependencyProperties.Get(CaretColorPropertyKey); }
352 set { DependencyProperties.Set(CaretColorPropertyKey, value); }
361 get {
return DependencyProperties.Get(MaxLengthPropertyKey); }
362 set { DependencyProperties.Set(MaxLengthPropertyKey, value); }
371 get {
return DependencyProperties.Get(MaxLinesPropertyKey); }
372 set { DependencyProperties.Set(MaxLinesPropertyKey, value); }
381 get {
return DependencyProperties.Get(MinLinesPropertyKey); }
382 set { DependencyProperties.Set(MinLinesPropertyKey, value); }
390 get {
return DependencyProperties.Get(ActiveImagePropertyKey); }
391 set { DependencyProperties.Set(ActiveImagePropertyKey, value); }
399 get {
return DependencyProperties.Get(InactiveImagePropertyKey); }
400 set { DependencyProperties.Set(InactiveImagePropertyKey, value); }
408 get {
return DependencyProperties.Get(MouseOverImagePropertyKey); }
409 set { DependencyProperties.Set(MouseOverImagePropertyKey, value); }
415 public bool SnapText {
get; set; }
420 public int CaretPosition
424 UpdateSelectionFromEditImpl();
426 return caretAtStart? selectionStart: selectionStop;
428 set { Select(value, 0); }
435 public float CaretWidth
437 get {
return caretWith; }
438 set { caretWith = Math.Max(0, Math.Min(float.MaxValue, value));}
445 public float CaretFrequency
447 get {
return caretFrequency; }
448 set { caretFrequency = Math.Max(0, Math.Min(float.MaxValue, value)); }
454 public bool IsCaretVisible {
get {
return IsSelectionActive && !caretHided; } }
456 private void ResetCaretVisibility()
459 accumulatedTime = 0f;
466 if (IsSelectionActive)
468 accumulatedTime += (float)time.
Elapsed.TotalSeconds;
469 var displayTime = Math.Min(
float.MaxValue, Math.Max(
MathUtil.
ZeroTolerance, 1 / (2 * CaretFrequency)));
470 while (accumulatedTime > displayTime)
472 accumulatedTime -= displayTime;
473 caretHided = !caretHided;
478 ResetCaretVisibility();
485 public InputTypeFlags InputType
487 get {
return inputType; }
490 if(inputType == value)
495 UpdateTextToDisplay();
497 UpdateInputTypeImpl();
504 public float TextSize
508 if (textSize.HasValue)
509 return textSize.Value;
518 textSize = Math.Max(0, Math.Min(float.MaxValue, value));
529 get {
return GetLineCountImpl(); }
542 public Func<char, bool> CharacterFilterPredicate
546 return characterFilterPredicate;
550 if(characterFilterPredicate == value)
553 characterFilterPredicate = value;
563 public string SelectedText
565 get {
return Text.Substring(SelectionStart, SelectionLength); }
569 throw new ArgumentNullException(
"value");
571 var stringBfr = Text.Substring(0, SelectionStart);
572 var stringAft = Text.Substring(SelectionStart + SelectionLength);
574 Text = stringBfr + value + stringAft;
575 CaretPosition = stringBfr.Length + value.Length;
585 public int SelectionLength
589 UpdateSelectionFromEditImpl();
591 return selectionStop - selectionStart;
595 Select(SelectionStart, value);
603 public int SelectionStart
607 UpdateSelectionFromEditImpl();
609 return selectionStart;
613 Select(value, SelectionLength);
630 throw new ArgumentNullException(
"value");
632 SetTextInternal(value,
true);
636 var predicate = CharacterFilterPredicate;
637 foreach (var character
in value)
639 if (predicate == null || predicate(character))
640 builder.Append(character);
643 SetTextInternal(builder.ToString(),
true);
647 private void SetTextInternal(
string newText,
bool updateNativeEdit)
649 var truncatedText = newText;
650 if (truncatedText.Length > MaxLength)
651 truncatedText = truncatedText.Substring(0, MaxLength);
654 text = truncatedText;
656 if (updateNativeEdit)
657 UpdateTextToEditImpl();
663 UpdateTextToDisplay();
665 Select(text.Length, 0);
672 private void UpdateTextToDisplay()
674 textToDisplay = ShouldHideText ?
new string(PasswordHidingCharacter, text.Length) : text;
680 public string TextToDisplay
682 get {
return textToDisplay; }
691 if (textData == null)
692 throw new ArgumentNullException(
"textData");
703 Select(0, Text.Length, caretAtBeginning);
722 public void Select(
int start,
int length,
bool caretAtBeginning =
false)
724 var truncatedStart = Math.Max(0, Math.Min(start, Text.Length));
725 var truncatedStop = Math.Max(truncatedStart, Math.Min(Text.Length, truncatedStart + Math.Max(0, length)));
727 selectionStart = truncatedStart;
728 selectionStop = truncatedStop;
729 caretAtStart = caretAtBeginning;
731 ResetCaretVisibility();
733 UpdateSelectionToEditImpl();
742 return CalculateTextSize(TextToDisplay);
752 if (textToMeasure == null ||
Font == null)
755 var sizeRatio = RealSizeVirtualResolutionRatio;
756 var measureFontSize = TextSize * sizeRatio;
757 var realSize = Font.MeasureString(textToMeasure, measureFontSize);
760 if (SynchronousCharacterGeneration)
761 Font.PreGenerateGlyphs(textToMeasure, measureFontSize);
766 realSize.X /= sizeRatio.X;
767 realSize.Y /= sizeRatio.Y;
775 var desiredSize = Vector3.Zero;
779 var fontLineSpacing = Font.GetTotalLineSpacing(TextSize);
780 var currentTextSize =
new Vector3(CalculateTextSize(), 0);
781 desiredSize =
new Vector3(currentTextSize.X, Math.Min(Math.Max(currentTextSize.Y, fontLineSpacing * MinLines), fontLineSpacing * MaxLines), currentTextSize.Z);
785 var desiredSizeWithPadding = CalculateSizeWithThickness(ref desiredSize, ref padding);
787 return desiredSizeWithPadding;
794 Math.Max(finalSizeWithoutMargins.
X, DesiredSize.X),
795 Math.Max(finalSizeWithoutMargins.Y, DesiredSize.Y),
796 Math.Max(finalSizeWithoutMargins.
Z, DesiredSize.Z));
807 public event EventHandler<RoutedEventArgs> TextChanged
809 add { AddHandler(TextChangedEvent, value); }
810 remove { RemoveHandler(TextChangedEvent, value); }
818 RoutingStrategy.Bubble,
821 private static void TextChangedClassHandler(
object sender,
RoutedEventArgs e)
825 editText.OnTextChanged(e);
840 base.OnTouchDown(args);
842 IsSelectionActive = !IsReadOnly;
844 OnTouchDownImpl(args);
849 base.OnTouchMove(args);
851 OnTouchMoveImpl(args);
virtual void OnMaxLengthChanged()
Function triggered when the value of MaxLength changed.
void SelectAll(bool caretAtBeginning=false)
Selects all the contents of the text editing control.
Provides a base class for all the User Interface elements in Paradox applications.
virtual void OnTextChanged(RoutedEventArgs args)
The class handler of the event TextChanged. This method can be overridden in inherited classes to per...
Represents a two dimensional mathematical vector.
virtual void OnMinLinesChanged()
Function triggered when the value of MinLines changed.
Represents the base class for user interface (UI) controls.
void AppendText(string textData)
Appends a string to the contents of a text control.
TextAlignment
Specify the available text alignment when rendering text.
Contains state information and event data associated with a routed event.
float X
The X component of the vector.
const float ZeroTolerance
The value for which all absolute numbers smaller than are considered equal to zero.
Represents a three dimensional mathematical vector.
override Vector3 ArrangeOverride(Vector3 finalSizeWithoutMargins)
When overridden in a derived class, positions possible child elements and determines a size for a UIE...
A service registry is a IServiceProvider that provides methods to register and unregister services...
Describes the thickness of a frame around a cuboid. Six float values describe the Left...
SharpDX.DirectWrite.Font Font
Flags
Enumeration of the new Assimp's flags.
void Clear()
Clears all the content from the text box.
SpriteFont to use with SpriteBatch. See SpriteFont to learn how to use it.
Vector2 CalculateTextSize()
Calculate and returns the size of the Text in virtual pixels size.
Current timing used for variable-step (real time) or fixed-step (game time) games.
void Select(int start, int length, bool caretAtBeginning=false)
Selects a range of text in the text box.
Vector2 CalculateTextSize(string textToMeasure)
Calculate and returns the size of the provided textToMeasure "/> in virtual pixels size...
Represents a 32-bit color (4 bytes) in the form of RGBA (in byte order: R, G, B, A).
Provides data for touch input events.
override void OnTouchMove(TouchEventArgs args)
The class handler of the event TouchMove. This method can be overridden in inherited classes to perfo...
EditText(IServiceRegistry services)
Create a new instance of EditText.
Represents and identifies a routed event and declares its characteristics.
SiliconStudio.Core.Mathematics.Vector3 Vector3
virtual void OnIsReadOnlyChanged()
Function triggered when the value of IsReadOnly changed.
Class holding all the data required to define an UI image.
TimeSpan Elapsed
Gets the elapsed game time since the last update
override void OnTouchDown(TouchEventArgs args)
The class handler of the event TouchDown. This method can be overridden in inherited classes to perfo...
float Z
The Z component of the vector.
A class that represents a tag propety.
virtual void OnMaxLinesChanged()
Function triggered when the value of MaxLines changed.
override Vector3 MeasureOverride(Vector3 availableSizeWithoutMargins)
When overridden in a derived class, measures the size in layout required for possible child elements ...
override void Update(GameTime time)
Method called by IUIElementUpdate.Update. This method can be overridden by inherited classes to perfo...
Represent an edit text where the user can enter text.