[NUI] Add SelectedChanged event to the SelectGroup and etc. (#3221)
authorJiyun Yang <ji.yang@samsung.com>
Tue, 29 Jun 2021 05:33:11 +0000 (14:33 +0900)
committerdongsug-song <35130733+dongsug-song@users.noreply.github.com>
Tue, 29 Jun 2021 06:46:52 +0000 (15:46 +0900)
* Fix default SelectGroup.SelectedIndex value to -1.
* Add event SelectGroup.SelectedChanged.
* Add method SelectGroup.AddAllToView().
* Add method RadioButtonGroup.GetSelectedItem().
* Add attached property RadioButtonGroup.IsGroupHolder. View can make a RadioButtonGroup for its radio button children.
```xaml
<View RadioButtonGroup.IsGroupHolder="true">
  <RadioButton Text="1"/>
  <RadioButton Text="2"/>
</View>
```

Signed-off-by: Jiyun Yang <ji.yang@samsung.com>
src/Tizen.NUI.Components/Controls/RadioButtonGroup.cs
src/Tizen.NUI.Components/Controls/SelectButton.cs
src/Tizen.NUI.Components/Controls/SelectGroup.cs
src/Tizen.NUI/src/public/XamlBinding/BindableObject.cs

index a028465..4897d57 100755 (executable)
  * limitations under the License.
  *
  */
+
+using System;
 using System.ComponentModel;
+using Tizen.NUI.BaseComponents;
+using Tizen.NUI.Binding;
 
 namespace Tizen.NUI.Components
 {
@@ -35,6 +39,14 @@ namespace Tizen.NUI.Components
     public class RadioButtonGroup : SelectGroup
     {
         /// <summary>
+        /// IsGroupHolderProperty
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public static readonly BindableProperty IsGroupHolderProperty = BindableProperty.CreateAttached("IsGroupHolder", typeof(bool), typeof(View), false, propertyChanged: OnIsGroupHolderChanged);
+
+        private static readonly BindableProperty RadioButtonGroupProperty = BindableProperty.CreateAttached("RadioButtonGroup", typeof(RadioButtonGroup), typeof(View), null, propertyChanged: OnRadioButtonGroupChanged);
+
+        /// <summary>
         /// Construct RadioButtonGroup
         /// </summary>
         /// <since_tizen> 6 </since_tizen>
@@ -46,6 +58,28 @@ namespace Tizen.NUI.Components
         }
 
         /// <summary>
+        /// Gets a RadioButtonGroup.IsGroupHolder property of a view.
+        /// </summary>
+        /// <param name="view">The group holder.</param>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public static bool GetIsGroupHolder(View view) => (bool)view.GetValue(IsGroupHolderProperty);
+
+        /// <summary>
+        /// Sets a RadioButtonGroup.IsGroupHolder property for a view.
+        /// </summary>
+        /// <param name="view">The group holder.</param>
+        /// <param name="value">The value to set.</param>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public static void SetIsGroupHolder(View view, bool value) => view.SetValue(IsGroupHolderProperty, value, false, true);
+
+        /// <summary>
+        /// Gets a attached RadioButtonGroup for a view.
+        /// </summary>
+        /// <param name="view">The group holder.</param>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public static RadioButtonGroup GetRadioButtonGroup(View view) => view.GetValue(RadioButtonGroupProperty) as RadioButtonGroup;
+
+        /// <summary>
         /// Get the RadioButton object at the specified index.
         /// </summary>
         /// <param name="index">item index</param>
@@ -59,6 +93,16 @@ namespace Tizen.NUI.Components
         }
 
         /// <summary>
+        /// Get the RadioButton object at the currently selected. If no item selected, returns null.
+        /// </summary>
+        /// <returns>Currently selected radio button</returns>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public RadioButton GetSelectedItem()
+        {
+            return (SelectedIndex >= 0 && SelectedIndex < ItemGroup.Count) ? ItemGroup[SelectedIndex] as RadioButton : null;
+        }
+
+        /// <summary>
         /// Add RadioButton to the end of RadioButtonGroup.
         /// </summary>
         /// <param name="radio">The RadioButton to be added to the RadioButtonGroup</param>
@@ -85,5 +129,64 @@ namespace Tizen.NUI.Components
             base.RemoveSelection(radio);
             radio.ItemGroup = null;
         }
+
+        private static void OnIsGroupHolderChanged(Binding.BindableObject bindable, object oldValue, object newValue)
+        {
+            var view = bindable as View;
+
+            if (view == null) return;
+
+            if (!(bool)newValue)
+            {
+                view.SetValue(RadioButtonGroupProperty, null, false, true);
+                return;
+            }
+
+            if (view.GetValue(RadioButtonGroupProperty) == null)
+            {
+                view.SetValue(RadioButtonGroupProperty, new RadioButtonGroup(), false, true);
+            }
+        }
+
+        private static void OnRadioButtonGroupChanged(Binding.BindableObject bindable, object oldValue, object newValue)
+        {
+            var view = bindable as View;
+
+            if (view == null) return;
+
+            if (oldValue is RadioButtonGroup oldGroup)
+            {
+                view.ChildAdded -= oldGroup.OnChildChanged;
+                view.ChildRemoved -= oldGroup.OnChildChanged;
+                oldGroup.RemoveAll();
+            }
+
+            if (newValue is RadioButtonGroup newGroup)
+            {
+                view.ChildAdded += newGroup.OnChildChanged;
+                view.ChildRemoved += newGroup.OnChildChanged;
+                newGroup.OnChildChanged(view, null);
+            }
+        }
+
+        private void OnChildChanged(object sender, EventArgs args)
+        {
+            if (sender is View view)
+            {
+                RemoveAll();
+                foreach (var child in view.Children)
+                    if (child is RadioButton radioButton)
+                        Add(radioButton);
+            }
+        }
+
+        private void RemoveAll()
+        {
+            var copied = ItemGroup.ToArray();
+            foreach (var button in copied)
+            {
+                Remove(button as RadioButton);
+            }
+        }
     }
 }
index 5d0ba7d..8a62bc4 100755 (executable)
@@ -126,6 +126,7 @@ namespace Tizen.NUI.Components
 
             if (type == DisposeTypes.Explicit)
             {
+                RemoveFromGroup();
             }
 
             base.Dispose(type);
@@ -234,5 +235,9 @@ namespace Tizen.NUI.Components
                 }
             }
         }
+
+        internal void RemoveFromGroup() => itemGroup?.RemoveSelection(this);
+
+        internal void ResetItemGroup() => itemGroup = null;
     }
 }
index 01c638d..d022532 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2019 Samsung Electronics Co., Ltd.
+ * Copyright(c) 2019-2021 Samsung Electronics Co., Ltd.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
+using Tizen.NUI.BaseComponents;
 
 namespace Tizen.NUI.Components
 {
     /// <summary>
-    /// Selection group event arguments
-    /// </summary>
-    /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
-    [EditorBrowsable(EditorBrowsableState.Never)]
-    public class GroupSelectedChangedEventArgs : EventArgs
-    {
-        /// <summary>The index of selected item</summary>
-        /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public int SelectedIndex { get; set; }
-    }
-
-    /// <summary>
     /// SelectionGroup is the base class of CheckBoxGroup and RadioButtonGroup.
     /// It defines a group that is set of selections and enables the user to choose one or multiple selection.
     /// </summary>
@@ -51,7 +39,14 @@ namespace Tizen.NUI.Components
         [EditorBrowsable(EditorBrowsableState.Never)]
         protected List<SelectButton> ItemGroup { get; }
 
-        private int selectedIndex;
+        private int selectedIndex = -1;
+        private bool isSelectionChanging = false;
+
+        /// <summary>
+        /// An event for the item selected changed.
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public event EventHandler SelectedChanged;
 
         /// <summary>
         /// Get the number of items in the SelectionGroup.
@@ -63,6 +58,7 @@ namespace Tizen.NUI.Components
 
         /// <summary>
         /// Get the index of currently or latest selected item.
+        /// If no item is selected, returns -1.
         /// </summary>
         /// <since_tizen> 6 </since_tizen>
         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
@@ -113,21 +109,35 @@ namespace Tizen.NUI.Components
         }
 
         /// <summary>
+        /// Adds all existing items in the group to the View.
+        /// </summary>
+        /// <param name="target">The target view.</param>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public void AddAllToView(View target)
+        {
+            if (target == null) throw new global::System.ArgumentNullException(nameof(target));
+
+            foreach (SelectButton button in ItemGroup) target.Add(button);
+        }
+
+        /// <summary>
         /// Adds an selection to the end of the SelectionGroup
         /// </summary>
         /// <param name="selection">The selection to be added to the end of the SelectionGroup</param>
         /// <since_tizen> 6 </since_tizen>
         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
         [EditorBrowsable(EditorBrowsableState.Never)]
-        protected void AddSelection(SelectButton selection)
+        protected internal void AddSelection(SelectButton selection)
         {
             if (null == selection) return;
             if (ItemGroup.Contains(selection))
             {
                 return;
             }
+
+            selection.RemoveFromGroup();
             ItemGroup.Add(selection);
-            selection.SelectedChanged += OnSelectedChanged;
+            selection.SelectedChanged += GroupSelectionHandler;
         }
 
         /// <summary>
@@ -137,32 +147,38 @@ namespace Tizen.NUI.Components
         /// <since_tizen> 6 </since_tizen>
         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
         [EditorBrowsable(EditorBrowsableState.Never)]
-        protected void RemoveSelection(SelectButton selection)
+        protected internal void RemoveSelection(SelectButton selection)
         {
             if (!ItemGroup.Contains(selection))
             {
                 return;
             }
-            selection.SelectedChanged -= OnSelectedChanged;
+            selection.SelectedChanged -= GroupSelectionHandler;
             ItemGroup.Remove(selection);
+            selection.ResetItemGroup();
         }
 
         /// <summary>
         /// Called when the state of Selected is changed.
         /// </summary>
         /// <param name="selection">The selection selected by user</param>
-        /// <since_tizen> 6 </since_tizen>
-        /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
         [EditorBrowsable(EditorBrowsableState.Never)]
-        protected virtual void SelectionHandler(SelectButton selection)
+        protected virtual void OnSelectedChanged(SelectButton selection)
         {
+            SelectedChanged?.Invoke(this, new EventArgs());
         }
 
-        private void OnSelectedChanged(object sender, SelectedChangedEventArgs args)
+        private void GroupSelectionHandler(object sender, SelectedChangedEventArgs args)
         {
-            SelectButton selection = sender as SelectButton;
-            if (selection != null)
+            if (isSelectionChanging)
             {
+                return;
+            }
+
+            if (sender is SelectButton selection)
+            {
+                isSelectionChanging = true;
+
                 if (args.IsSelected == true)
                 {
                     selectedIndex = selection.Index;
@@ -177,9 +193,10 @@ namespace Tizen.NUI.Components
                             }
                         }
                     }
-
-                    SelectionHandler(selection);
                 }
+
+                isSelectionChanging = false;
+                OnSelectedChanged(selection);
             }
         }
     }
index cadc3af..714e5ed 100755 (executable)
@@ -845,7 +845,7 @@ namespace Tizen.NUI.Binding
             context.Binding = null;
         }
 
-        void SetValue(BindableProperty property, object value, bool fromStyle, bool checkAccess)
+        internal void SetValue(BindableProperty property, object value, bool fromStyle, bool checkAccess)
         {
             if (property == null)
                 throw new ArgumentNullException(nameof(property));