From c54ed614b9d213dcea8f6682e502985316c71fab Mon Sep 17 00:00:00 2001 From: "sung-su.kim" Date: Thu, 12 Jan 2017 17:48:41 +0900 Subject: [PATCH] Add RadioButton - RFC:http://suprem.sec.samsung.net/confluence/display/SPTDTLC/%5BFormsTizen%5D+RFC+6+-+Radio+Button - Depands on:https://review.tizen.org/gerrit/#/c/109686/ Change-Id: I6be453af733c9bf04049375452252616d5f6cc1b --- .../RadioButtonRenderer.cs | 241 +++++++++++++++++++++ .../Tizen.Xamarin.Forms.Extension.Renderer.csproj | 1 + Tizen.Xamarin.Forms.Extension/RadioButton.cs | 179 +++++++++++++++ Tizen.Xamarin.Forms.Extension/SelectedEventArgs.cs | 24 ++ .../Tizen.Xamarin.Forms.Extension.csproj | 2 + 5 files changed, 447 insertions(+) create mode 100755 Tizen.Xamarin.Forms.Extension.Renderer/RadioButtonRenderer.cs create mode 100755 Tizen.Xamarin.Forms.Extension/RadioButton.cs create mode 100755 Tizen.Xamarin.Forms.Extension/SelectedEventArgs.cs diff --git a/Tizen.Xamarin.Forms.Extension.Renderer/RadioButtonRenderer.cs b/Tizen.Xamarin.Forms.Extension.Renderer/RadioButtonRenderer.cs new file mode 100755 index 0000000..27cf855 --- /dev/null +++ b/Tizen.Xamarin.Forms.Extension.Renderer/RadioButtonRenderer.cs @@ -0,0 +1,241 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using ElmSharp; +using Xamarin.Forms.Platform.Tizen; +using Xamarin.Forms.Platform.Tizen.Native; +using Tizen.Xamarin.Forms.Extension; +using Tizen.Xamarin.Forms.Extension.Renderer; +using TForms = Xamarin.Forms.Platform.Tizen.Forms; + +[assembly: ExportRenderer(typeof(RadioButton), typeof(RadioButtonRenderer))] +namespace Tizen.Xamarin.Forms.Extension.Renderer +{ + public class RadioButtonRenderer : ViewRenderer + { + readonly Span _span = new Span(); + + static Lazy s_GroupManager = new Lazy(); + + int _changedCallbackDepth = 0; + + public RadioButtonRenderer() + { + } + + protected override void OnElementChanged(ElementChangedEventArgs e) + { + if (Control == null) + { + var radio = new Radio(TForms.Context.MainWindow) { StateValue = 1 }; + SetNativeControl(radio); + } + if (e.OldElement != null) + { + Control.ValueChanged -= ChangedEventHandler; + } + if (e.NewElement != null) + { + Control.ValueChanged += ChangedEventHandler; + UpdateAll(); + } + base.OnElementChanged(e); + } + + protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == RadioButton.TextProperty.PropertyName) + { + UpdateText(); + } + else if (e.PropertyName == RadioButton.TextColorProperty.PropertyName) + { + UpdateTextColor(); + } + else if (e.PropertyName == RadioButton.FontProperty.PropertyName) + { + UpdateFont(); + } + else if (e.PropertyName == RadioButton.FontFamilyProperty.PropertyName) + { + UpdateFontFamily(); + } + else if (e.PropertyName == RadioButton.FontSizeProperty.PropertyName) + { + UpdateFontSize(); + } + else if (e.PropertyName == RadioButton.FontAttributesProperty.PropertyName) + { + UpdateFontAttributes(); + } + else if (e.PropertyName == RadioButton.GroupNameProperty.PropertyName) + { + UpdateGroupName(); + } + else if (e.PropertyName == RadioButton.IsSelectedProperty.PropertyName) + { + UpdateIsSelected(); + } + + if (e.PropertyName == RadioButton.TextProperty.PropertyName || e.PropertyName == RadioButton.TextColorProperty.PropertyName || + e.PropertyName == RadioButton.FontProperty.PropertyName || e.PropertyName == RadioButton.FontFamilyProperty.PropertyName || + e.PropertyName == RadioButton.FontSizeProperty.PropertyName || e.PropertyName == RadioButton.FontAttributesProperty.PropertyName) + { + ApplyTextAndStyle(); + } + + base.OnElementPropertyChanged(sender, e); + } + + void ChangedEventHandler(object sender, EventArgs e) + { + _changedCallbackDepth++; + Element.IsSelected = Control.GroupValue == 1 ? true : false; + _changedCallbackDepth--; + } + + void UpdateAll() + { + UpdateText(); + UpdateTextColor(); + UpdateFont(); + UpdateGroupName(); + UpdateIsSelected(); + ApplyTextAndStyle(); + } + + void UpdateText() + { + _span.Text = Element.Text; + } + + void UpdateTextColor() + { + _span.ForegroundColor = Element.TextColor.ToNative(); + } + + void UpdateFont() + { + _span.FontSize = Element.FontSize; + _span.FontAttributes = Element.FontAttributes; + _span.FontFamily = Element.FontFamily; + } + + void UpdateFontFamily() + { + _span.FontFamily = Element.FontFamily; + } + + void UpdateFontSize() + { + _span.FontSize = Element.FontSize; + } + + void UpdateFontAttributes() + { + _span.FontAttributes = Element.FontAttributes; + } + + void UpdateGroupName() + { + s_GroupManager.Value.PartGroup(Element); + s_GroupManager.Value.JoinGroup(Element.GroupName, Element); + } + + void UpdateIsSelected() + { + if (_changedCallbackDepth == 0) + { + Control.GroupValue = Element.IsSelected ? 1 : 0; + } + s_GroupManager.Value.UpdateChecked(Element.GroupName, Element); + } + + void ApplyTextAndStyle() + { + SetInternalTextAndStyle(_span.GetDecoratedText(), _span.GetStyle()); + } + + void SetInternalTextAndStyle(string formattedText, string textStyle) + { + string emission = "elm,state,text,visible"; + if (string.IsNullOrEmpty(formattedText)) + { + formattedText = null; + textStyle = null; + emission = "elm,state,text,hidden"; + } + Control.Text = formattedText; + + var textblock = Control.EdjeObject["elm.text"]; + if (textblock != null) + { + textblock.TextStyle = textStyle; + } + Control.EdjeObject.EmitSignal(emission, "elm"); + } + } + + internal class RadioGroupManager + { + Dictionary> _groupMap = new Dictionary>(); + + public void JoinGroup(string groupName, RadioButton button) + { + if (string.IsNullOrEmpty(groupName)) + { + return; + } + + if (!_groupMap.ContainsKey(groupName)) + { + _groupMap.Add(groupName, new List()); + } + _groupMap[groupName].Add(button); + UpdateChecked(groupName, button); + } + + public void PartGroup(RadioButton button) + { + string groupName = null; + foreach (var list in _groupMap) + { + if (list.Value.Contains(button)) + { + groupName = list.Key; + } + } + PartGroup(groupName, button); + } + + public void PartGroup(string groupName, RadioButton button) + { + if (string.IsNullOrEmpty(groupName)) + { + return; + } + + if (_groupMap.ContainsKey(groupName)) + { + _groupMap[groupName].Remove(button); + } + } + + public void UpdateChecked(string groupName, RadioButton button) + { + if (string.IsNullOrEmpty(groupName)) + { + return; + } + + if (button.IsSelected) + { + foreach (var btn in _groupMap[groupName].Where(b => b.IsSelected && b != button)) + { + btn.IsSelected = false; + } + } + } + } +} diff --git a/Tizen.Xamarin.Forms.Extension.Renderer/Tizen.Xamarin.Forms.Extension.Renderer.csproj b/Tizen.Xamarin.Forms.Extension.Renderer/Tizen.Xamarin.Forms.Extension.Renderer.csproj index b44db5e..e852d86 100755 --- a/Tizen.Xamarin.Forms.Extension.Renderer/Tizen.Xamarin.Forms.Extension.Renderer.csproj +++ b/Tizen.Xamarin.Forms.Extension.Renderer/Tizen.Xamarin.Forms.Extension.Renderer.csproj @@ -40,6 +40,7 @@ + diff --git a/Tizen.Xamarin.Forms.Extension/RadioButton.cs b/Tizen.Xamarin.Forms.Extension/RadioButton.cs new file mode 100755 index 0000000..20b30db --- /dev/null +++ b/Tizen.Xamarin.Forms.Extension/RadioButton.cs @@ -0,0 +1,179 @@ +using System; +using Xamarin.Forms; + +namespace Tizen.Xamarin.Forms.Extension +{ + /// + /// The RadioButton is a widget that allows for 1 or more options to be displayed and have the user choose only 1 of them. + /// + public class RadioButton : View + { + /// + /// BindableProperty. Backing store for the Text bindable property. + /// + public static readonly BindableProperty TextProperty = BindableProperty.Create("Text", typeof(string), typeof(RadioButton), default(string)); + + /// + /// BindableProperty. Backing store for the TextColor bindable property. + /// + public static readonly BindableProperty TextColorProperty = BindableProperty.Create("TextColor", typeof(Color), typeof(RadioButton), Color.Default); + + /// + /// BindableProperty. Backing store for the Font bindable property. + /// + public static readonly BindableProperty FontProperty = BindableProperty.Create("Font", typeof(Font), typeof(RadioButton), default(Font), + propertyChanged: FontStructPropertyChanged); + + /// + /// BindableProperty. Backing store for the FontFamily bindable property. + /// + public static readonly BindableProperty FontFamilyProperty = BindableProperty.Create("FontFamily", typeof(string), typeof(RadioButton), default(string), + propertyChanged: SpecificFontPropertyChanged); + + /// + /// BindableProperty. Backing store for the FontSize bindable property. + /// + public static readonly BindableProperty FontSizeProperty = BindableProperty.Create("FontSize", typeof(double), typeof(RadioButton), -1.0, + propertyChanged: SpecificFontPropertyChanged, + defaultValueCreator: bindable => Device.GetNamedSize(NamedSize.Default, (RadioButton)bindable)); + + /// + /// BindableProperty. Backing store for the FontAttributes bindable property. + /// + public static readonly BindableProperty FontAttributesProperty = BindableProperty.Create("FontAttributes", typeof(FontAttributes), typeof(RadioButton), FontAttributes.None, + propertyChanged: SpecificFontPropertyChanged); + + /// + /// BindableProperty. Backing store for the IsSelected bindable property. + /// + public static readonly BindableProperty IsSelectedProperty = BindableProperty.Create("IsSelected", typeof(bool), typeof(RadioButton), false, + propertyChanged: IsSelectedPropertyChanged); + + /// + /// BindableProperty. Backing store for the GroupName bindable property. + /// + public static readonly BindableProperty GroupNameProperty = BindableProperty.Create("GroupName", typeof(string), typeof(RadioButton), default(string)); + + /// + /// Gets or sets the Text displayed as the content of the RadioButton. This is a bindable property. + /// + public string Text + { + get { return (string)GetValue(TextProperty); } + set { SetValue(TextProperty, value); } + } + + /// + /// Gets or sets the Color for the text of the RadioButton. This is a bindable property. + /// + public Color TextColor + { + get { return (Color)GetValue(TextColorProperty); } + set { SetValue(TextColorProperty, value); } + } + + /// + /// Gets or sets the Font for the RadioButton text. This is a bindable property. + /// + public Font Font + { + get { return (Font)GetValue(FontProperty); } + set { SetValue(FontProperty, value); } + } + + /// + /// Gets the font family to which the font for the RadioButton text belongs. + /// + public string FontFamily + { + get { return (string)GetValue(FontFamilyProperty); } + set { SetValue(FontFamilyProperty, value); } + } + + /// + /// Gets or sets the size of the font of the RadioButton text. + /// + public double FontSize + { + get { return (double)GetValue(FontSizeProperty); } + set { SetValue(FontSizeProperty, value); } + } + + /// + /// Gets a value that indicates whether the font for the RadioButton text is bold, italic, or neither. + /// + public FontAttributes FontAttributes + { + get { return (FontAttributes)GetValue(FontAttributesProperty); } + set { SetValue(FontAttributesProperty, value); } + } + + /// + /// Gets or sets the name that specifies which RadioButton controls are mutually exclusive. + /// + public string GroupName + { + get { return (string)GetValue(GroupNameProperty); } + set { SetValue(GroupNameProperty, value ?? default(string)); } + } + + /// + /// Gets or sets a Boolean value that indicates whether this RadioButton is Selected. + /// + public bool IsSelected + { + get { return (bool)GetValue(IsSelectedProperty); } + set { SetValue(IsSelectedProperty, value); } + } + + /// + /// Occurs when the RadioButton selection was changed. + /// + public event EventHandler Selected; + + static void FontStructPropertyChanged(BindableObject bindable, object oldValue, object newValue) + { + var radioButton = (RadioButton)bindable; + + if (radioButton.Font == Font.Default) + { + radioButton.FontFamily = null; + radioButton.FontSize = Device.GetNamedSize(NamedSize.Default, radioButton); + radioButton.FontAttributes = FontAttributes.None; + } + else + { + radioButton.FontFamily = radioButton.Font.FontFamily; + if (radioButton.Font.UseNamedSize) + { + radioButton.FontSize = Device.GetNamedSize(radioButton.Font.NamedSize, radioButton.GetType()); + } + else + { + radioButton.FontSize = radioButton.Font.FontSize; + } + radioButton.FontAttributes = radioButton.Font.FontAttributes; + } + } + + static void SpecificFontPropertyChanged(BindableObject bindable, object oldValue, object newValue) + { + var radioButton = (RadioButton)bindable; + + if (radioButton.FontFamily != null) + { + radioButton.Font = Font.OfSize(radioButton.FontFamily, radioButton.FontSize).WithAttributes(radioButton.FontAttributes); + } + else + { + radioButton.Font = Font.SystemFontOfSize(radioButton.FontSize, radioButton.FontAttributes); + } + } + + static void IsSelectedPropertyChanged(BindableObject bindable, object oldValue, object newValue) + { + var radioButton = (RadioButton)bindable; + radioButton.Selected?.Invoke(radioButton, new SelectedEventArgs((bool)newValue)); + } + } +} \ No newline at end of file diff --git a/Tizen.Xamarin.Forms.Extension/SelectedEventArgs.cs b/Tizen.Xamarin.Forms.Extension/SelectedEventArgs.cs new file mode 100755 index 0000000..8e53d06 --- /dev/null +++ b/Tizen.Xamarin.Forms.Extension/SelectedEventArgs.cs @@ -0,0 +1,24 @@ +using System; + +namespace Tizen.Xamarin.Forms.Extension +{ + /// + /// Event arguments for events of RadioButton. + /// + public class SelectedEventArgs : EventArgs + { + /// + /// Creates a new SelectedEventArgs object that represents a change from RadioButton. + /// + /// The boolean value that whether the RadioButton is selected. + public SelectedEventArgs(bool value) + { + Value = value; + } + + /// + /// Gets the Value object for this SelectedEventArgs object. + /// + public bool Value { get; private set; } + } +} diff --git a/Tizen.Xamarin.Forms.Extension/Tizen.Xamarin.Forms.Extension.csproj b/Tizen.Xamarin.Forms.Extension/Tizen.Xamarin.Forms.Extension.csproj index 26c4f18..dfd1d65 100755 --- a/Tizen.Xamarin.Forms.Extension/Tizen.Xamarin.Forms.Extension.csproj +++ b/Tizen.Xamarin.Forms.Extension/Tizen.Xamarin.Forms.Extension.csproj @@ -61,6 +61,8 @@ + + -- 2.7.4