summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Platform.WP8/EntryRenderer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Platform.WP8/EntryRenderer.cs')
-rw-r--r--Xamarin.Forms.Platform.WP8/EntryRenderer.cs324
1 files changed, 324 insertions, 0 deletions
diff --git a/Xamarin.Forms.Platform.WP8/EntryRenderer.cs b/Xamarin.Forms.Platform.WP8/EntryRenderer.cs
new file mode 100644
index 00000000..f96ca312
--- /dev/null
+++ b/Xamarin.Forms.Platform.WP8/EntryRenderer.cs
@@ -0,0 +1,324 @@
+using System;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Windows;
+using System.Windows.Input;
+using System.Windows.Media;
+using static System.String;
+using WControl = System.Windows.Controls.Control;
+
+namespace Xamarin.Forms.Platform.WinPhone
+{
+ internal static class KeyboardExtensions
+ {
+ public static InputScope ToInputScope(this Keyboard self)
+ {
+ var result = new InputScope();
+ var name = new InputScopeName();
+ if (self == Keyboard.Default)
+ name.NameValue = InputScopeNameValue.Default;
+ else if (self == Keyboard.Chat)
+ name.NameValue = InputScopeNameValue.Chat;
+ else if (self == Keyboard.Email)
+ name.NameValue = InputScopeNameValue.EmailNameOrAddress;
+ else if (self == Keyboard.Numeric)
+ name.NameValue = InputScopeNameValue.Number;
+ else if (self == Keyboard.Telephone)
+ name.NameValue = InputScopeNameValue.TelephoneNumber;
+ else if (self == Keyboard.Text)
+ name.NameValue = InputScopeNameValue.Text;
+ else if (self == Keyboard.Url)
+ name.NameValue = InputScopeNameValue.Url;
+ else if (self is CustomKeyboard)
+ {
+ var custom = (CustomKeyboard)self;
+ bool capitalizedSentenceEnabled = (custom.Flags & KeyboardFlags.CapitalizeSentence) == KeyboardFlags.CapitalizeSentence;
+ bool spellcheckEnabled = (custom.Flags & KeyboardFlags.Spellcheck) == KeyboardFlags.Spellcheck;
+ bool suggestionsEnabled = (custom.Flags & KeyboardFlags.Suggestions) == KeyboardFlags.Suggestions;
+
+ if (!capitalizedSentenceEnabled && !spellcheckEnabled && !suggestionsEnabled)
+ name.NameValue = InputScopeNameValue.Default;
+ if (!capitalizedSentenceEnabled && !spellcheckEnabled && suggestionsEnabled)
+ name.NameValue = InputScopeNameValue.Search;
+ if (!capitalizedSentenceEnabled && spellcheckEnabled && !suggestionsEnabled)
+ {
+ Debug.WriteLine("Keyboard: Suggestions cannot be disabled in Windows Phone if spellcheck is enabled");
+ name.NameValue = InputScopeNameValue.Search;
+ }
+ if (!capitalizedSentenceEnabled && spellcheckEnabled && suggestionsEnabled)
+ name.NameValue = InputScopeNameValue.Search;
+ if (capitalizedSentenceEnabled && !spellcheckEnabled && !suggestionsEnabled)
+ {
+ Debug.WriteLine("Keyboard: Suggestions cannot be disabled in Windows Phone if auto Capitalization is enabled");
+ name.NameValue = InputScopeNameValue.Chat;
+ }
+ if (capitalizedSentenceEnabled && !spellcheckEnabled && suggestionsEnabled)
+ name.NameValue = InputScopeNameValue.Chat;
+ if (capitalizedSentenceEnabled && spellcheckEnabled && !suggestionsEnabled)
+ {
+ Debug.WriteLine("Keyboard: Suggestions cannot be disabled in Windows Phone if spellcheck is enabled");
+ name.NameValue = InputScopeNameValue.Text;
+ }
+ if (capitalizedSentenceEnabled && spellcheckEnabled && suggestionsEnabled)
+ name.NameValue = InputScopeNameValue.Text;
+ }
+ else
+ {
+ // Should never happens
+ name.NameValue = InputScopeNameValue.Default;
+ }
+ result.Names.Add(name);
+ return result;
+ }
+ }
+
+ public class EntryRenderer : ViewRenderer<Entry, FormsPhoneTextBox>
+ {
+ bool _fontApplied;
+ bool _ignoreTextChange;
+ Brush _placeholderDefaultBrush;
+
+ public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
+ {
+ if (Children.Count == 0)
+ return new SizeRequest();
+
+ var constraint = new System.Windows.Size(widthConstraint, heightConstraint);
+
+ FormsPhoneTextBox child = Control;
+
+ double oldWidth = child.Width;
+ double oldHeight = child.Height;
+
+ child.Height = double.NaN;
+ child.Width = double.NaN;
+
+ child.Measure(constraint);
+ var result = new Size(Math.Ceiling(child.DesiredSize.Width), Math.Ceiling(child.DesiredSize.Height));
+
+ child.Width = oldWidth;
+ child.Height = oldHeight;
+
+ return new SizeRequest(result);
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
+ {
+ base.OnElementChanged(e);
+
+ var textBox = new FormsPhoneTextBox();
+
+ SetNativeControl(textBox);
+
+ UpdateInputScope();
+ UpdateIsPassword();
+ UpdateText();
+ UpdatePlaceholder();
+ UpdateColor();
+ UpdateFont();
+ UpdateAlignment();
+ UpdatePlaceholderColor();
+ UpdateIsEnabled();
+
+ Control.LostFocus += OnTextBoxUnfocused;
+ Control.TextChanged += TextBoxOnTextChanged;
+ Control.KeyUp += TextBoxOnKeyUp;
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == Entry.TextProperty.PropertyName)
+ UpdateText();
+ else if (e.PropertyName == Entry.PlaceholderProperty.PropertyName)
+ UpdatePlaceholder();
+ else if (e.PropertyName == Entry.IsPasswordProperty.PropertyName)
+ UpdateIsPassword();
+ else if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
+ UpdateIsEnabled();
+ else if (e.PropertyName == Entry.TextColorProperty.PropertyName)
+ UpdateColor();
+ else if (e.PropertyName == InputView.KeyboardProperty.PropertyName)
+ UpdateInputScope();
+ else if (e.PropertyName == Entry.FontAttributesProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == Entry.FontFamilyProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == Entry.FontSizeProperty.PropertyName)
+ UpdateFont();
+ else if (e.PropertyName == Entry.HorizontalTextAlignmentProperty.PropertyName)
+ UpdateAlignment();
+ else if (e.PropertyName == Entry.PlaceholderColorProperty.PropertyName)
+ UpdatePlaceholderColor();
+ }
+
+ protected override void UpdateBackgroundColor()
+ {
+ Control.Background = Element.BackgroundColor.IsDefault ? (Brush)System.Windows.Application.Current.Resources["PhoneTextBoxBrush"] : Element.BackgroundColor.ToBrush();
+ }
+
+ internal override void OnModelFocusChangeRequested(object sender, VisualElement.FocusRequestArgs args)
+ {
+ if (args.Focus)
+ args.Result = Control.Focus();
+ else
+ {
+ UnfocusControl(Control);
+ args.Result = true;
+ }
+ }
+
+ void OnTextBoxUnfocused(object sender, RoutedEventArgs e)
+ {
+ if (Element.TextColor.IsDefault)
+ return;
+
+ if (!IsNullOrEmpty(Element.Text))
+ Control.Foreground = Element.TextColor.ToBrush();
+ }
+
+ void TextBoxOnKeyUp(object sender, KeyEventArgs keyEventArgs)
+ {
+ if (keyEventArgs.Key == Key.Enter)
+ Element.SendCompleted();
+ }
+
+ void TextBoxOnTextChanged(object sender, System.Windows.Controls.TextChangedEventArgs textChangedEventArgs)
+ {
+ // Signal to the UpdateText method that the change to TextProperty doesn't need to update the control
+ // This prevents the cursor position from getting lost
+ _ignoreTextChange = true;
+ ((IElementController)Element).SetValueFromRenderer(Entry.TextProperty, Control.Text);
+
+ // If an Entry.TextChanged handler modified the value of the Entry's text, the values could now be
+ // out-of-sync; re-sync them and force the TextBox cursor to the end of the text
+ string entryText = Element.Text;
+ if (Control.Text != entryText)
+ {
+ Control.Text = entryText;
+ Control.SelectionStart = Control.Text.Length;
+ }
+
+ _ignoreTextChange = false;
+ }
+
+ void UpdateAlignment()
+ {
+ if (Control == null)
+ return;
+
+ Control.TextAlignment = Element.HorizontalTextAlignment.ToNativeTextAlignment();
+ }
+
+ void UpdateColor()
+ {
+ if (Control == null)
+ return;
+
+ Entry entry = Element;
+ if (entry != null)
+ {
+ if (!IsNullOrEmpty(entry.Text))
+ {
+ if (!entry.TextColor.IsDefault)
+ Control.Foreground = entry.TextColor.ToBrush();
+ else
+ Control.Foreground = (Brush)WControl.ForegroundProperty.GetMetadata(typeof(FormsPhoneTextBox)).DefaultValue;
+
+ // Force the PhoneTextBox control to do some internal bookkeeping
+ // so the colors change immediately and remain changed when the control gets focus
+ Control.OnApplyTemplate();
+ }
+ }
+ else
+ Control.Foreground = (Brush)WControl.ForegroundProperty.GetMetadata(typeof(FormsPhoneTextBox)).DefaultValue;
+ }
+
+ void UpdateFont()
+ {
+ if (Control == null)
+ return;
+
+ Entry entry = Element;
+
+ if (entry == null)
+ return;
+
+ bool entryIsDefault = entry.FontFamily == null && entry.FontSize == Device.GetNamedSize(NamedSize.Default, typeof(Entry), true) && entry.FontAttributes == FontAttributes.None;
+
+ if (entryIsDefault && !_fontApplied)
+ return;
+
+ if (entryIsDefault)
+ {
+ Control.ClearValue(WControl.FontStyleProperty);
+ Control.ClearValue(WControl.FontSizeProperty);
+ Control.ClearValue(WControl.FontFamilyProperty);
+ Control.ClearValue(WControl.FontWeightProperty);
+ Control.ClearValue(WControl.FontStretchProperty);
+ }
+ else
+ Control.ApplyFont(entry);
+
+ _fontApplied = true;
+ }
+
+ void UpdateInputScope()
+ {
+ Control.InputScope = Element.Keyboard.ToInputScope();
+ }
+
+ void UpdateIsEnabled()
+ {
+ Control.IsEnabled = Element.IsEnabled;
+ }
+
+ void UpdateIsPassword()
+ {
+ Control.IsPassword = Element.IsPassword;
+ }
+
+ void UpdatePlaceholder()
+ {
+ Control.Hint = Element.Placeholder ?? "";
+ }
+
+ void UpdatePlaceholderColor()
+ {
+ Color placeholderColor = Element.PlaceholderColor;
+
+ if (placeholderColor.IsDefault)
+ {
+ if (_placeholderDefaultBrush == null)
+ return;
+
+ // Use the cached default brush
+ Control.PlaceholderForegroundBrush = _placeholderDefaultBrush;
+ return;
+ }
+
+ if (_placeholderDefaultBrush == null)
+ {
+ // Cache the default brush in case we need to set the color back to default
+ _placeholderDefaultBrush = Control.PlaceholderForegroundBrush;
+ }
+
+ Control.PlaceholderForegroundBrush = placeholderColor.ToBrush();
+ }
+
+ void UpdateText()
+ {
+ // If the text property has changed because TextBoxOnTextChanged called SetValueFromRenderer,
+ // we don't want to re-update the text and reset the cursor position
+ if (_ignoreTextChange)
+ return;
+
+ if (Control.Text == Element.Text)
+ return;
+
+ Control.Text = Element.Text ?? "";
+ Control.Select(Control.Text.Length, 0);
+ }
+ }
+} \ No newline at end of file