Fix bugs in ContextPopup 28/121528/3
authorSidharth Gupta <sid92.gupta@samsung.com>
Tue, 28 Mar 2017 07:09:16 +0000 (16:09 +0900)
committerSidharth Gupta <sid92.gupta@samsung.com>
Tue, 4 Apr 2017 06:38:50 +0000 (15:38 +0900)
- Correctly update SelectedItem and SelectedIndex when items modified
- Allow ItemsSource to take IList of any type
- Coerce SelectedIndex appropriately

Signed-off-by: Sidharth Gupta <sid92.gupta@samsung.com>
Change-Id: I6b8e138d62634eeb922e72eea6382a0d4b62ae83

Tizen.Xamarin.Forms.Extension/ContextPopup.cs [changed mode: 0755->0644]

old mode 100755 (executable)
new mode 100644 (file)
index ce0909b..47fb135
@@ -51,7 +51,7 @@ namespace Tizen.Xamarin.Forms.Extension
             typeof(ContextPopup), defaultValue: _priorities);
 
         public static readonly BindableProperty SelectedIndexProperty = BindableProperty.Create(nameof(SelectedIndex), typeof(int), typeof(ContextPopup), defaultValue: -1,
-            propertyChanged: OnSelectedIndexChanged);
+            propertyChanged: OnSelectedIndexChanged, coerceValue: CoerceSelectedIndex);
 
         public static readonly BindableProperty SelectedItemProperty = BindableProperty.Create(nameof(SelectedItem), typeof(object), typeof(ContextPopup), null,
             propertyChanged: OnSelectedItemChanged);
@@ -182,29 +182,71 @@ namespace Tizen.Xamarin.Forms.Extension
             switch (e.Action)
             {
                 case NotifyCollectionChangedAction.Add:
-                    var addedItems = e.NewItems.OfType<ContextPopupItem>();
-                    _contextPopup.AddItems(addedItems);
-                    foreach (var item in addedItems)
-                    {
-                        item.PropertyChanged += ContextPopupItemPropertyChanged;
-                    }
+                    AddItems(e);
                     break;
 
                 case NotifyCollectionChangedAction.Remove:
-                    _contextPopup.RemoveItems(e.OldItems.OfType<ContextPopupItem>());
+                    RemoveItems(e);
                     break;
 
-                case NotifyCollectionChangedAction.Reset:
-                    _contextPopup.ClearItems();
-                    SelectedIndex = -1;
+                default: // Move, replace, reset
+                    ResetItems();
                     break;
+            }
 
-                default: //Clear and add again for anything else such as Move
-                    _contextPopup.ClearItems();
-                    _contextPopup.AddItems(_items);
-                    SelectedIndex = -1;
-                    break;
+            SelectedIndex = SelectedIndex.Clamp(-1, Items.Count - 1);
+            UpdateSelectedItem();
+        }
+
+        void ResetItems()
+        {
+            _contextPopup.ClearItems();
+            if (ItemsSource != null)
+            {
+                if (_items.Count != 0)
+                    _items.Clear();
+                else
+                {
+                    foreach (var item in ItemsSource)
+                        _items.Add(ConvertObjectToContextPopupItem(item));
+                }
+            }
+        }
+
+        void RemoveItems(NotifyCollectionChangedEventArgs e)
+        {
+            IList<ContextPopupItem> items = new List<ContextPopupItem>();
+
+            foreach (object oldItem in e.OldItems)
+            {
+                var item = ConvertObjectToContextPopupItem(oldItem);
+                item.PropertyChanged -= ContextPopupItemPropertyChanged;
+                items.Add(item);
+            }
+
+            _contextPopup.RemoveItems(items);
+        }
+
+        void AddItems(NotifyCollectionChangedEventArgs e)
+        {
+            IList<ContextPopupItem> items = new List<ContextPopupItem>();
+
+            foreach (object newItem in e.NewItems)
+            {
+                var item = ConvertObjectToContextPopupItem(newItem);
+                item.PropertyChanged += ContextPopupItemPropertyChanged;
+                items.Add(item);
             }
+
+            _contextPopup.AddItems(items);
+        }
+
+        ContextPopupItem ConvertObjectToContextPopupItem(object item)
+        {
+            if (item is ContextPopupItem)
+                return item as ContextPopupItem;
+            else
+                return new ContextPopupItem(item.ToString());
         }
 
         void ContextPopupItemPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
@@ -225,6 +267,12 @@ namespace Tizen.Xamarin.Forms.Extension
             contextPopup.SelectedIndexChanged?.Invoke(contextPopup, EventArgs.Empty);
         }
 
+        static object CoerceSelectedIndex(BindableObject bindable, object value)
+        {
+            var contextPopup = (ContextPopup)bindable;
+            return contextPopup.Items == null ? -1 : ((int)value).Clamp(-1, contextPopup.Items.Count - 1);
+        }
+
         void UpdateSelectedItem()
         {
             if (SelectedIndex == -1)
@@ -272,11 +320,7 @@ namespace Tizen.Xamarin.Forms.Extension
 
             if (newValue != null)
             {
-                _items.Clear();
-                foreach (var item in newValue)
-                {
-                    _items.Add(item as ContextPopupItem);
-                }
+                ResetItems();
             }
             else
             {
@@ -284,4 +328,12 @@ namespace Tizen.Xamarin.Forms.Extension
             }
         }
     }
+
+    internal static class NumericExtensions
+    {
+        public static int Clamp(this int self, int min, int max)
+        {
+            return Math.Min(max, Math.Max(self, min));
+        }
+    }
 }
\ No newline at end of file