Add RadioButton 34/108834/10
authorsung-su.kim <sung-su.kim@samsung.com>
Thu, 12 Jan 2017 08:48:41 +0000 (17:48 +0900)
committersung-su.kim <sung-su.kim@samsung.com>
Thu, 19 Jan 2017 07:01:12 +0000 (16:01 +0900)
- 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

Tizen.Xamarin.Forms.Extension.Renderer/RadioButtonRenderer.cs [new file with mode: 0755]
Tizen.Xamarin.Forms.Extension.Renderer/Tizen.Xamarin.Forms.Extension.Renderer.csproj
Tizen.Xamarin.Forms.Extension/RadioButton.cs [new file with mode: 0755]
Tizen.Xamarin.Forms.Extension/SelectedEventArgs.cs [new file with mode: 0755]
Tizen.Xamarin.Forms.Extension/Tizen.Xamarin.Forms.Extension.csproj

diff --git a/Tizen.Xamarin.Forms.Extension.Renderer/RadioButtonRenderer.cs b/Tizen.Xamarin.Forms.Extension.Renderer/RadioButtonRenderer.cs
new file mode 100755 (executable)
index 0000000..27cf855
--- /dev/null
@@ -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<RadioButton, Radio>
+    {
+        readonly Span _span = new Span();
+
+        static Lazy<RadioGroupManager> s_GroupManager = new Lazy<RadioGroupManager>();
+
+        int _changedCallbackDepth = 0;
+
+        public RadioButtonRenderer()
+        {
+        }
+
+        protected override void OnElementChanged(ElementChangedEventArgs<RadioButton> 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<string, List<RadioButton>> _groupMap = new Dictionary<string, List<RadioButton>>();
+
+        public void JoinGroup(string groupName, RadioButton button)
+        {
+            if (string.IsNullOrEmpty(groupName))
+            {
+                return;
+            }
+
+            if (!_groupMap.ContainsKey(groupName))
+            {
+                _groupMap.Add(groupName, new List<RadioButton>());
+            }
+            _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;
+                }
+            }
+        }
+    }
+}
index b44db5e..e852d86 100755 (executable)
@@ -40,6 +40,7 @@
     <Compile Include="Cells\DoubleLabelCellRenderer.cs" />\r
     <Compile Include="Cells\MultilineCellRenderer.cs" />\r
     <Compile Include="Cells\TypeCellRenderer.cs" />\r
+    <Compile Include="RadioButtonRenderer.cs" />\r
     <Compile Include="TizenExtension.cs" />\r
     <Compile Include="Properties\AssemblyInfo.cs" />\r
   </ItemGroup>\r
diff --git a/Tizen.Xamarin.Forms.Extension/RadioButton.cs b/Tizen.Xamarin.Forms.Extension/RadioButton.cs
new file mode 100755 (executable)
index 0000000..20b30db
--- /dev/null
@@ -0,0 +1,179 @@
+using System;
+using Xamarin.Forms;
+
+namespace Tizen.Xamarin.Forms.Extension
+{
+    /// <summary>
+    /// The RadioButton is a widget that allows for 1 or more options to be displayed and have the user choose only 1 of them.
+    /// </summary>
+    public class RadioButton : View
+    {
+        /// <summary>
+        /// BindableProperty. Backing store for the Text bindable property.
+        /// </summary>
+        public static readonly BindableProperty TextProperty = BindableProperty.Create("Text", typeof(string), typeof(RadioButton), default(string));
+
+        /// <summary>
+        /// BindableProperty. Backing store for the TextColor bindable property.
+        /// </summary>
+        public static readonly BindableProperty TextColorProperty = BindableProperty.Create("TextColor", typeof(Color), typeof(RadioButton), Color.Default);
+
+        /// <summary>
+        /// BindableProperty. Backing store for the Font bindable property.
+        /// </summary>
+        public static readonly BindableProperty FontProperty = BindableProperty.Create("Font", typeof(Font), typeof(RadioButton), default(Font),
+            propertyChanged: FontStructPropertyChanged);
+
+        /// <summary>
+        /// BindableProperty. Backing store for the FontFamily bindable property.
+        /// </summary>
+        public static readonly BindableProperty FontFamilyProperty = BindableProperty.Create("FontFamily", typeof(string), typeof(RadioButton), default(string),
+            propertyChanged: SpecificFontPropertyChanged);
+
+        /// <summary>
+        /// BindableProperty. Backing store for the FontSize bindable property.
+        /// </summary>
+        public static readonly BindableProperty FontSizeProperty = BindableProperty.Create("FontSize", typeof(double), typeof(RadioButton), -1.0,
+            propertyChanged: SpecificFontPropertyChanged,
+            defaultValueCreator: bindable => Device.GetNamedSize(NamedSize.Default, (RadioButton)bindable));
+
+        /// <summary>
+        /// BindableProperty. Backing store for the FontAttributes bindable property.
+        /// </summary>
+        public static readonly BindableProperty FontAttributesProperty = BindableProperty.Create("FontAttributes", typeof(FontAttributes), typeof(RadioButton), FontAttributes.None,
+            propertyChanged: SpecificFontPropertyChanged);
+
+        /// <summary>
+        /// BindableProperty. Backing store for the IsSelected bindable property.
+        /// </summary>
+        public static readonly BindableProperty IsSelectedProperty = BindableProperty.Create("IsSelected", typeof(bool), typeof(RadioButton), false,
+             propertyChanged: IsSelectedPropertyChanged);
+
+        /// <summary>
+        /// BindableProperty. Backing store for the GroupName bindable property.
+        /// </summary>
+        public static readonly BindableProperty GroupNameProperty = BindableProperty.Create("GroupName", typeof(string), typeof(RadioButton), default(string));
+
+        /// <summary>
+        /// Gets or sets the Text displayed as the content of the RadioButton. This is a bindable property.
+        /// </summary>
+        public string Text
+        {
+            get { return (string)GetValue(TextProperty); }
+            set { SetValue(TextProperty, value); }
+        }
+
+        /// <summary>
+        /// Gets or sets the Color for the text of the RadioButton. This is a bindable property.
+        /// </summary>
+        public Color TextColor
+        {
+            get { return (Color)GetValue(TextColorProperty); }
+            set { SetValue(TextColorProperty, value); }
+        }
+
+        /// <summary>
+        /// Gets or sets the Font for the RadioButton text. This is a bindable property.
+        /// </summary>
+        public Font Font
+        {
+            get { return (Font)GetValue(FontProperty); }
+            set { SetValue(FontProperty, value); }
+        }
+
+        /// <summary>
+        /// Gets the font family to which the font for the RadioButton text belongs.
+        /// </summary>
+        public string FontFamily
+        {
+            get { return (string)GetValue(FontFamilyProperty); }
+            set { SetValue(FontFamilyProperty, value); }
+        }
+
+        /// <summary>
+        /// Gets or sets the size of the font of the RadioButton text.
+        /// </summary>
+        public double FontSize
+        {
+            get { return (double)GetValue(FontSizeProperty); }
+            set { SetValue(FontSizeProperty, value); }
+        }
+
+        /// <summary>
+        /// Gets a value that indicates whether the font for the RadioButton text is bold, italic, or neither.
+        /// </summary>
+        public FontAttributes FontAttributes
+        {
+            get { return (FontAttributes)GetValue(FontAttributesProperty); }
+            set { SetValue(FontAttributesProperty, value); }
+        }
+
+        /// <summary>
+        /// Gets or sets the name that specifies which RadioButton controls are mutually exclusive.
+        /// </summary>
+        public string GroupName
+        {
+            get { return (string)GetValue(GroupNameProperty); }
+            set { SetValue(GroupNameProperty, value ?? default(string)); }
+        }
+
+        /// <summary>
+        /// Gets or sets a Boolean value that indicates whether this RadioButton is Selected.
+        /// </summary>
+        public bool IsSelected
+        {
+            get { return (bool)GetValue(IsSelectedProperty); }
+            set { SetValue(IsSelectedProperty, value); }
+        }
+
+        /// <summary>
+        /// Occurs when the RadioButton selection was changed.
+        /// </summary>
+        public event EventHandler<SelectedEventArgs> 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 (executable)
index 0000000..8e53d06
--- /dev/null
@@ -0,0 +1,24 @@
+using System;
+
+namespace Tizen.Xamarin.Forms.Extension
+{
+    /// <summary>
+    /// Event arguments for events of RadioButton.
+    /// </summary>
+    public class SelectedEventArgs : EventArgs
+    {
+        /// <summary>
+        /// Creates a new SelectedEventArgs object that represents a change from RadioButton.
+        /// </summary>
+        /// <param name="value">The boolean value that whether the RadioButton is selected.</param>
+        public SelectedEventArgs(bool value)
+        {
+            Value = value;
+        }
+
+        /// <summary>
+        /// Gets the Value object for this SelectedEventArgs object.
+        /// </summary>
+        public bool Value { get; private set; }
+    }
+}
index 26c4f18..dfd1d65 100755 (executable)
@@ -61,6 +61,8 @@
     <Compile Include="Cells\BaseTypeCell.cs" />\r
     <Compile Include="Cells\MultilineCell.cs" />\r
     <Compile Include="Properties\AssemblyInfo.cs" />\r
+    <Compile Include="RadioButton.cs" />\r
+    <Compile Include="SelectedEventArgs.cs" />\r
   </ItemGroup>\r
   <ItemGroup>\r
     <Reference Include="Xamarin.Forms.Core, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">\r