Merge "Add CalendarView" into tizen
authorKangho Hur <kangho.hur@samsung.com>
Thu, 23 Mar 2017 04:45:42 +0000 (21:45 -0700)
committerGerrit Code Review <gerrit@review.vlan103.tizen.org>
Thu, 23 Mar 2017 04:45:42 +0000 (21:45 -0700)
22 files changed:
Tizen.Xamarin.Forms.Extension.Renderer/DateTimeViewRenderer.cs [new file with mode: 0644]
Tizen.Xamarin.Forms.Extension.Renderer/DialogImplementation.cs [new file with mode: 0644]
Tizen.Xamarin.Forms.Extension.Renderer/DropdownListRenderer.cs [new file with mode: 0755]
Tizen.Xamarin.Forms.Extension.Renderer/FloatingButtonImplementation.cs [new file with mode: 0644]
Tizen.Xamarin.Forms.Extension.Renderer/Tizen.Xamarin.Forms.Extension.Renderer.csproj [changed mode: 0644->0755]
Tizen.Xamarin.Forms.Extension.Renderer/Tizen.Xamarin.Forms.Extension.Renderer.project.json
Tizen.Xamarin.Forms.Extension.Renderer/ToastImplementation.cs [new file with mode: 0644]
Tizen.Xamarin.Forms.Extension/DateTimeView.cs [new file with mode: 0644]
Tizen.Xamarin.Forms.Extension/Dialog.cs [new file with mode: 0644]
Tizen.Xamarin.Forms.Extension/DropdownList.cs [new file with mode: 0755]
Tizen.Xamarin.Forms.Extension/FloatingButton.cs [new file with mode: 0644]
Tizen.Xamarin.Forms.Extension/FloatingButtonItem.cs [new file with mode: 0644]
Tizen.Xamarin.Forms.Extension/FloatingButtonMovablePosition.cs [new file with mode: 0644]
Tizen.Xamarin.Forms.Extension/FloatingButtonPosition.cs [new file with mode: 0644]
Tizen.Xamarin.Forms.Extension/IDialog.cs [new file with mode: 0644]
Tizen.Xamarin.Forms.Extension/IFloatingButton.cs [new file with mode: 0644]
Tizen.Xamarin.Forms.Extension/IToast.cs [new file with mode: 0644]
Tizen.Xamarin.Forms.Extension/Properties/AssemblyInfo.cs
Tizen.Xamarin.Forms.Extension/Tizen.Xamarin.Forms.Extension.csproj
Tizen.Xamarin.Forms.Extension/Toast.cs [new file with mode: 0644]
Tizen.Xamarin.Forms.Extension/ToastProxy.cs [new file with mode: 0644]
packaging/xamarin-forms-extension.spec

diff --git a/Tizen.Xamarin.Forms.Extension.Renderer/DateTimeViewRenderer.cs b/Tizen.Xamarin.Forms.Extension.Renderer/DateTimeViewRenderer.cs
new file mode 100644 (file)
index 0000000..8058722
--- /dev/null
@@ -0,0 +1,113 @@
+using System.ComponentModel;
+using System.Linq;
+using Tizen.Xamarin.Forms.Extension;
+using Tizen.Xamarin.Forms.Extension.Renderer;
+using Xamarin.Forms.Platform.Tizen;
+using EDateTimeSelector = ElmSharp.DateTimeSelector;
+using TForms = Xamarin.Forms.Platform.Tizen.Forms;
+
+[assembly: ExportRenderer(typeof(DateTimeView), typeof(DateTimeViewRenderer))]
+
+namespace Tizen.Xamarin.Forms.Extension.Renderer
+{
+    public class DateTimeViewRenderer : ViewRenderer<DateTimeView, EDateTimeSelector>
+    {
+        static readonly string DateStyle = "date_layout";
+        static readonly string TimeStyle = "time_layout";
+
+        static readonly string[] UseDateFormat = { "%Y", "%m", "%b", "%B", "%h", "%d", "%e", "%c", "%x", "%F" };
+        static readonly string[] UseTimeFormat = { "%I", "%H", "%k", "%l", "%M", "%p", "%P", "%X", "%r", "%R", "%T" };
+
+        int _changedCallbackDepth = 0;
+
+        protected override void OnElementChanged(ElementChangedEventArgs<DateTimeView> e)
+        {
+            if (Control == null)
+            {
+                var selector = new EDateTimeSelector(TForms.Context.MainWindow);
+                SetNativeControl(selector);
+            }
+
+            if (e.OldElement != null)
+            {
+                Control.DateTimeChanged -= DateTimeChangedHandler;
+            }
+
+            if (e.NewElement != null)
+            {
+                Control.DateTimeChanged += DateTimeChangedHandler;
+            }
+
+            UpdateMaximumDate();
+            UpdateMinimumDate();
+            UpdateDate();
+            UpdateDisplayFormat();
+
+            base.OnElementChanged(e);
+        }
+
+        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+        {
+            if (e.PropertyName == DateTimeView.DateTimeProperty.PropertyName)
+            {
+                UpdateDate();
+            }
+            else if (e.PropertyName == DateTimeView.MinimumDateProperty.PropertyName)
+            {
+                UpdateMinimumDate();
+            }
+            else if (e.PropertyName == DateTimeView.MaximumDateProperty.PropertyName)
+            {
+                UpdateMaximumDate();
+            }
+            else if (e.PropertyName == DateTimeView.DisplayFormatProperty.PropertyName)
+            {
+                UpdateDisplayFormat();
+            }
+
+            base.OnElementPropertyChanged(sender, e);
+        }
+
+        void DateTimeChangedHandler(object sender, ElmSharp.DateChangedEventArgs e)
+        {
+            _changedCallbackDepth++;
+            Element.DateTime = e.NewDate;
+            _changedCallbackDepth--;
+        }
+
+        void UpdateDisplayFormat()
+        {
+            string targetStyle = DateStyle;
+            string targetFormat = Element.DisplayFormat;
+
+            bool isTimeFormat = UseDateFormat.Count(b => targetFormat.Contains(b)) == 0;
+            bool isDateFormat = UseTimeFormat.Count(b => targetFormat.Contains(b)) == 0;
+
+            if (isTimeFormat && isDateFormat == false)
+                targetStyle = TimeStyle;
+            else if (isDateFormat && isTimeFormat == false)
+                targetStyle = DateStyle;
+
+            Control.Style = targetStyle;
+            Control.Format = targetFormat;
+        }
+
+        void UpdateMinimumDate()
+        {
+            Control.MinimumDateTime = Element.MinimumDate;
+        }
+
+        void UpdateMaximumDate()
+        {
+            Control.MaximumDateTime = Element.MaximumDate;
+        }
+
+        void UpdateDate()
+        {
+            if (_changedCallbackDepth == 0)
+            {
+                Control.DateTime = Element.DateTime;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Tizen.Xamarin.Forms.Extension.Renderer/DialogImplementation.cs b/Tizen.Xamarin.Forms.Extension.Renderer/DialogImplementation.cs
new file mode 100644 (file)
index 0000000..36f60f7
--- /dev/null
@@ -0,0 +1,378 @@
+using System;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+using Xamarin.Forms;
+using Xamarin.Forms.Platform.Tizen;
+using TForms = Xamarin.Forms.Platform.Tizen.Forms;
+using EPopup = ElmSharp.Popup;
+using Tizen.Xamarin.Forms.Extension.Renderer;
+
+[assembly: Dependency(typeof(DialogImplementation))]
+
+namespace Tizen.Xamarin.Forms.Extension.Renderer
+{
+    class DialogImplementation : IDialog, INotifyPropertyChanged, IDisposable
+    {
+        EPopup _control;
+        View _content;
+        Button _positive;
+        Button _neutral;
+        Button _negative;
+        string _title;
+        string _subtitle;
+
+        bool _isDisposed = false;
+
+        bool _isNullable = false;
+        ElmSharp.Button _nativePositive;
+        ElmSharp.Button _nativeNeutral;
+        ElmSharp.Button _nativeNegative;
+        ElmSharp.EvasObject _nativeContent;
+
+        public event EventHandler Dismissed;
+
+        public event EventHandler OutsideClicked;
+
+        public event EventHandler Shown;
+
+        public event EventHandler BackButtonPressed;
+
+        public event PropertyChangedEventHandler PropertyChanged;
+
+        public DialogImplementation()
+        {
+            _control = new EPopup(TForms.Context.MainWindow);
+
+            _control.ShowAnimationFinished += ShowAnimationFinishedHandler;
+            _control.Dismissed += DismissedHandler;
+            _control.OutsideClicked += OutsideClickedHandler;
+            _control.KeyUp += BackButtonPressedHandler;
+
+            PropertyChanged += PropertyChangedHandler;
+        }
+
+        ~DialogImplementation()
+        {
+            Dispose(false);
+        }
+
+        public View Content
+        {
+            get
+            {
+                return _content;
+            }
+            set
+            {
+                _content = value;
+                OnPropertyChanged();
+            }
+        }
+
+        public Button Positive
+        {
+            get
+            {
+                return _positive;
+            }
+            set
+            {
+                _positive = value;
+                OnPropertyChanged();
+            }
+        }
+
+        public Button Neutral
+        {
+            get
+            {
+                return _neutral;
+            }
+            set
+            {
+                _neutral = value;
+                OnPropertyChanged();
+            }
+        }
+
+        public Button Negative
+        {
+            get
+            {
+                return _negative;
+            }
+            set
+            {
+                _negative = value;
+                OnPropertyChanged();
+            }
+        }
+
+        public string Title
+        {
+            get
+            {
+                return _title;
+            }
+            set
+            {
+                _title = value;
+                OnPropertyChanged();
+            }
+        }
+
+        public string Subtitle
+        {
+            get
+            {
+                return _subtitle;
+            }
+            set
+            {
+                _subtitle = value;
+                OnPropertyChanged();
+            }
+        }
+
+        public void Show()
+        {
+            _control.Show();
+        }
+
+        public void Hide()
+        {
+            _control.Hide();
+        }
+
+        public void Dismiss()
+        {
+            _control.Dismiss();
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (_isDisposed)
+                return;
+
+            if (disposing)
+            {
+                PropertyChanged -= PropertyChangedHandler;
+
+                if (_nativePositive != null)
+                {
+                    _nativePositive.Unrealize();
+                    _nativePositive = null;
+                }
+                if (_nativeNeutral != null)
+                {
+                    _nativeNeutral.Unrealize();
+                    _nativeNeutral = null;
+                }
+                if (_nativeNegative != null)
+                {
+                    _nativeNegative.Unrealize();
+                    _nativeNegative = null;
+                }
+                if (_nativeContent != null)
+                {
+                    _nativeContent.Unrealize();
+                    _nativeContent = null;
+                }
+
+                if (_control != null)
+                {
+                    _control.ShowAnimationFinished -= ShowAnimationFinishedHandler;
+                    _control.Dismissed -= DismissedHandler;
+                    _control.OutsideClicked -= OutsideClickedHandler;
+                    _control.KeyUp -= BackButtonPressedHandler;
+
+                    _control.Unrealize();
+                    _control = null;
+                }
+            }
+
+            _isDisposed = true;
+        }
+
+        void ShowAnimationFinishedHandler(object sender, EventArgs e)
+        {
+            Shown?.Invoke(this, EventArgs.Empty);
+            GrabBackkey();
+        }
+
+        void DismissedHandler(object sender, EventArgs e)
+        {
+            Dismissed?.Invoke(this, EventArgs.Empty);
+            UngrabBackKey();
+        }
+
+        void OutsideClickedHandler(object sender, EventArgs e)
+        {
+            OutsideClicked?.Invoke(this, EventArgs.Empty);
+        }
+
+        void BackButtonPressedHandler(object sender, ElmSharp.EvasKeyEventArgs e)
+        {
+            if (e.KeyName == ElmSharp.EvasKeyEventArgs.PlatformBackButtonName)
+            {
+                BackButtonPressed?.Invoke(this, EventArgs.Empty);
+            }
+        }
+
+        void PropertyChangedHandler(object sender, PropertyChangedEventArgs e)
+        {
+            if (e.PropertyName == Dialog.ContentProperty.PropertyName)
+            {
+                UpdateContent();
+            }
+            else if (e.PropertyName == Dialog.PositiveProperty.PropertyName)
+            {
+                UpdatePositive();
+            }
+            else if (e.PropertyName == Dialog.NeutralProperty.PropertyName)
+            {
+                UpdateNeutral();
+            }
+            else if (e.PropertyName == Dialog.NegativeProperty.PropertyName)
+            {
+                UpdateNegative();
+            }
+            else if (e.PropertyName == Dialog.TitleProperty.PropertyName)
+            {
+                UpdateTitle();
+            }
+            else if (e.PropertyName == Dialog.SubtitleProperty.PropertyName)
+            {
+                UpdateSubtitle();
+            }
+        }
+
+        void OnPropertyChanged([CallerMemberName] string propertyName = null)
+        {
+            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+        }
+
+        void UpdateContent()
+        {
+            _isNullable = _nativeContent != null ? true : false;
+
+            _nativeContent?.Hide();
+
+            View contentView = null;
+
+            if (Content.GetType() == typeof(ScrollView))
+            {
+                contentView = new StackLayout
+                {
+                    Children =
+                    {
+                        Content
+                    }
+                };
+            }
+            else
+            {
+                contentView = Content;
+            }
+
+            if (contentView != null)
+            {
+                contentView.Parent = Application.Current.MainPage;
+                _nativeContent = Platform.GetOrCreateRenderer(contentView).NativeView;
+
+                var sizeRequest = contentView.Measure(TForms.Context.MainWindow.ScreenSize.Width, TForms.Context.MainWindow.ScreenSize.Height).Request.ToPixel();
+
+                _nativeContent.MinimumHeight = sizeRequest.Height;
+            }
+            else
+            {
+                _nativeContent = null;
+            }
+
+            _control.SetPartContent("default", _nativeContent, _isNullable);
+        }
+
+        void UpdatePositive()
+        {
+            _isNullable = _nativePositive != null ? true : false;
+
+            _nativePositive?.Hide();
+
+            if (Positive != null)
+            {
+                _nativePositive = (ElmSharp.Button)Platform.GetOrCreateRenderer(Positive).NativeView;
+                _nativePositive.Style = "bottom";
+            }
+            else
+            {
+                _nativePositive = null;
+            }
+
+            _control.SetPartContent("button1", _nativePositive, _isNullable);
+        }
+
+        void UpdateNeutral()
+        {
+            _isNullable = _nativeNeutral != null ? true : false;
+
+            _nativeNeutral?.Hide();
+
+            if (Neutral != null)
+            {
+                _nativeNeutral = (ElmSharp.Button)Platform.GetOrCreateRenderer(Neutral).NativeView;
+                _nativeNeutral.Style = "bottom";
+            }
+            else
+            {
+                _nativeNeutral = null;
+            }
+
+            _control.SetPartContent("button2", _nativeNeutral, _isNullable);
+        }
+
+        void UpdateNegative()
+        {
+            _isNullable = _nativeNegative != null ? true : false;
+
+            _nativeNegative?.Hide();
+
+            if (Negative != null)
+            {
+                _nativeNegative = (ElmSharp.Button)Platform.GetOrCreateRenderer(Negative).NativeView;
+                _nativeNegative.Style = "bottom";
+            }
+            else
+            {
+                _nativeNegative = null;
+            }
+
+            _control.SetPartContent("button3", _nativeNegative, _isNullable);
+        }
+
+        void UpdateTitle()
+        {
+            _control.SetPartText("title,text", Title);
+        }
+
+        void UpdateSubtitle()
+        {
+            _control.SetPartText("subtitle,text", Subtitle);
+        }
+
+        void GrabBackkey()
+        {
+            _control.KeyGrab(ElmSharp.EvasKeyEventArgs.PlatformBackButtonName, true);
+        }
+
+        void UngrabBackKey()
+        {
+            _control.KeyUngrab(ElmSharp.EvasKeyEventArgs.PlatformBackButtonName);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Tizen.Xamarin.Forms.Extension.Renderer/DropdownListRenderer.cs b/Tizen.Xamarin.Forms.Extension.Renderer/DropdownListRenderer.cs
new file mode 100755 (executable)
index 0000000..94ecf0c
--- /dev/null
@@ -0,0 +1,150 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Linq;
+using Tizen.Xamarin.Forms.Extension;
+using Tizen.Xamarin.Forms.Extension.Renderer;
+using Xamarin.Forms.Platform.Tizen;
+using EHoversel = ElmSharp.Hoversel;
+using TForms = Xamarin.Forms.Platform.Tizen.Forms;
+
+[assembly: ExportRenderer(typeof(DropdownList), typeof(DropdownListRenderer))]
+namespace Tizen.Xamarin.Forms.Extension.Renderer
+{
+    public class DropdownListRenderer : ViewRenderer<DropdownList, EHoversel>
+    {
+        Dictionary<ElmSharp.HoverselItem, object> _items = new Dictionary<ElmSharp.HoverselItem, object>();
+
+        public DropdownListRenderer()
+        {
+        }
+
+        protected override void OnElementChanged(ElementChangedEventArgs<DropdownList> e)
+        {
+            if (Control == null)
+            {
+                var dropdownList = new EHoversel(TForms.Context.MainWindow);
+                SetNativeControl(dropdownList);
+            }
+            if (e.OldElement != null)
+            {
+                ((ObservableCollection<object>)e.OldElement.InternalItems).CollectionChanged -= OnCollectionChanged;
+                Control.ItemSelected -= ItemSelectedEventHandler;
+                Control.Dismissed -= OnDismissed;
+            }
+            if (e.NewElement != null)
+            {
+                ((ObservableCollection<object>)e.NewElement.InternalItems).CollectionChanged += OnCollectionChanged;
+                Control.ItemSelected += ItemSelectedEventHandler;
+                Control.Dismissed += OnDismissed;
+
+                Control.HoverParent = Platform.GetRenderer(Element.Parent)?.NativeView;
+
+                ClearItems();
+                AddItems(e.NewElement.InternalItems);
+
+                UpdateIsHorizontal();
+                UpdateIsExpanded();
+            }
+            base.OnElementChanged(e);
+        }
+
+        void ItemSelectedEventHandler(object sender, ElmSharp.HoverselItemEventArgs e)
+        {
+            Element.SelectedItem = _items[e.Item];
+        }
+
+        void OnDismissed(object sender, EventArgs e)
+        {
+            Element.IsExpanded = false;
+        }
+
+        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+        {
+            if (e.PropertyName == DropdownList.IsHorizontalProperty.PropertyName)
+            {
+                UpdateIsHorizontal();
+            }
+            else if (e.PropertyName == DropdownList.IsExpandedProperty.PropertyName)
+            {
+                UpdateIsExpanded();
+            }
+            else if (e.PropertyName == DropdownList.SelectedItemProperty.PropertyName)
+            {
+                UpdateText();
+            }
+            base.OnElementPropertyChanged(sender, e);
+        }
+
+        void UpdateIsHorizontal()
+        {
+            Control.IsHorizontal = Element.IsHorizontal;
+        }
+
+        void UpdateIsExpanded()
+        {
+            if (Element.IsExpanded)
+            {
+                Control.HoverBegin();
+            }
+            else
+            {
+                Control.HoverEnd();
+            }
+        }
+
+        void UpdateText()
+        {
+            Control.Text = Element.SelectedItem != null ? Element.SelectedItem.ToString() : string.Empty;
+        }
+
+        void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+        {
+            if (e.NewItems != null)
+            {
+                AddItems(e.NewItems);
+            }
+            if (e.OldItems != null)
+            {
+                RemoveItems(e.OldItems);
+            }
+            if (e.Action == NotifyCollectionChangedAction.Reset)
+            {
+                ClearItems();
+            }
+        }
+
+        void AddItems(IEnumerable items)
+        {
+            foreach (object item in items)
+            {
+                _items.Add(Control.AddItem(item.ToString()), item);
+            }
+        }
+
+        void RemoveItems(IEnumerable items)
+        {
+            foreach (object item in items)
+            {
+                var target = _items.Where(d => d.Value == item).ToList();
+                if (target.Count == 1)
+                {
+                    Element.SelectedItem = null;
+                }
+                _items.Remove(target[0].Key);
+                target[0].Key.Delete();
+            }
+        }
+
+        void ClearItems()
+        {
+            Control.Clear();
+            _items.Clear();
+
+            Element.SelectedItem = null;
+        }
+    }
+}
diff --git a/Tizen.Xamarin.Forms.Extension.Renderer/FloatingButtonImplementation.cs b/Tizen.Xamarin.Forms.Extension.Renderer/FloatingButtonImplementation.cs
new file mode 100644 (file)
index 0000000..76fb55b
--- /dev/null
@@ -0,0 +1,216 @@
+// Copyright 2016 by Samsung Electronics, Inc.,
+//
+// This software is the confidential and proprietary information
+// of Samsung Electronics, Inc. ("Confidential Information"). You
+// shall not disclose such Confidential Information and shall use
+// it only in accordance with the terms of the license agreement
+// you entered into with Samsung.
+
+using System;
+using Tizen.Xamarin.Forms.Extension;
+using Xamarin.Forms;
+using Xamarin.Forms.Platform.Tizen;
+using ElmSharp;
+using Button = Xamarin.Forms.Button;
+using EFloatingButton = ElmSharp.FloatingButton;
+using EFloatingButtonPosition = ElmSharp.FloatingButtonPosition;
+using TForms = Xamarin.Forms.Platform.Tizen.Forms;
+
+[assembly: Dependency(typeof(FloatingButtonImplementation))]
+
+namespace Tizen.Xamarin.Forms.Extension
+{
+    internal class FloatingButtonImplementation : IFloatingButton, IDisposable
+    {
+        EFloatingButton _control = null;
+        FloatingButtonMovablePosition _movablePosition = FloatingButtonMovablePosition.All;
+        FloatingButtonPosition _position = FloatingButtonPosition.Right;
+        bool _isShown = true;
+        FloatingButtonItem _firstButton = null;
+        FloatingButtonItem _secondButton = null;
+        EvasObject _firstNativeButton = null;
+        EvasObject _secondNativeButton = null;
+        bool _isDisposed = false;
+
+        public FloatingButtonImplementation()
+        {
+            _control = new EFloatingButton(TForms.Context.MainWindow)
+            {
+                Mode = FloatingButtonMode.All,
+                MinimumHeight = 100,
+                MinimumWidth = 100,
+            };
+            UpdateLocation();
+            TForms.Context.MainWindow.RotationChanged += (s, e) => { UpdateLocation(); };
+        }
+
+        ~FloatingButtonImplementation()
+        {
+            Dispose();
+        }
+
+        public FloatingButtonMovablePosition MovablePosition
+        {
+            get { return _movablePosition; }
+            set
+            {
+                _movablePosition = (FloatingButtonMovablePosition)value;
+                UpdateMovablePosition();
+            }
+        }
+
+        public FloatingButtonPosition Position
+        {
+            get { return _position; }
+        }
+
+        public bool IsShown
+        {
+            get { return _isShown; }
+        }
+
+        public FloatingButtonItem FirstButton
+        {
+            get { return _firstButton; }
+            set
+            {
+                _firstButton = (FloatingButtonItem)value;
+                UpdateButton(FloatingButtonItemPosition.First);
+            }
+        }
+
+        public FloatingButtonItem SecondButton
+        {
+            get { return _secondButton; }
+            set
+            {
+                _secondButton = (FloatingButtonItem)value;
+                UpdateButton(FloatingButtonItemPosition.Second);
+            }
+        }
+
+        public void SetPosition(FloatingButtonPosition position, bool animated)
+        {
+            if (_movablePosition != FloatingButtonMovablePosition.None)
+            {
+                _position = (FloatingButtonPosition)position;
+                UpdatePosition(animated);
+            }
+        }
+
+        public void Show()
+        {
+            _isShown = true;
+            _control.Show();
+        }
+
+        public void Hide()
+        {
+            _isShown = false;
+            _control.Hide();
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (_isDisposed)
+                return;
+
+            if (_firstNativeButton != null)
+            {
+                _firstNativeButton?.Unrealize();
+                _firstNativeButton = null;
+            }
+
+            if (_secondNativeButton != null)
+            {
+                _secondNativeButton?.Unrealize();
+                _secondNativeButton = null;
+            }
+
+            if (_control != null)
+            {
+                _control?.Unrealize();
+                _control = null;
+            }
+
+            _isDisposed = true;
+        }
+
+        void UpdateLocation()
+        {
+            var window = TForms.Context.MainWindow;
+            var size = window.ScreenSize;
+            if (window.Rotation == 0)
+            {
+                _control.Resize(size.Width, size.Height);
+                var h = (int)(size.Height * 0.8);
+                _control.Move(0, h);
+            }
+            else
+            {
+                _control.Resize(size.Height, size.Width);
+                var h = (int)(size.Width * 0.8);
+                _control.Move(0, h);
+            }
+            _control.Show();
+        }
+
+        void UpdateMovablePosition()
+        {
+            if (MovablePosition == FloatingButtonMovablePosition.None)
+                _control.MovementBlock = true;
+            else
+            {
+                _control.MovementBlock = false;
+                _control.Mode = (FloatingButtonMode)MovablePosition;
+            }
+        }
+
+        void UpdatePosition(bool animated)
+        {
+            if (MovablePosition != FloatingButtonMovablePosition.None)
+                _control.SetPosition((EFloatingButtonPosition)Position, animated);
+        }
+
+        void UpdateButton(FloatingButtonItemPosition position)
+        {
+            switch (position)
+            {
+                case FloatingButtonItemPosition.First:
+                    _firstNativeButton?.Unrealize();
+                    _firstNativeButton = GetNativeButton(FirstButton);
+                    _control.SetPartContent("button1", _firstNativeButton, true);
+                    break;
+
+                case FloatingButtonItemPosition.Second:
+                    _secondNativeButton?.Unrealize();
+                    _secondNativeButton = GetNativeButton(SecondButton);
+                    _control.SetPartContent("button2", _secondNativeButton, true);
+                    break;
+            }
+        }
+
+        EvasObject GetNativeButton(FloatingButtonItem item)
+        {
+            if (item == null) return null;
+            Button button = new Button();
+            if (item.Icon != null)
+                button.Image = item.Icon;
+            button.Clicked += (s, e) => { item.OnClicked(); };
+            EvasObject nativeView = Platform.GetOrCreateRenderer(button).NativeView;
+            return nativeView;
+        }
+
+        enum FloatingButtonItemPosition
+        {
+            First,
+            Second,
+        }
+    }
+}
\ No newline at end of file
old mode 100644 (file)
new mode 100755 (executable)
index af02ca8..5d47097
@@ -38,6 +38,7 @@
   <ItemGroup>\r
     <Compile Include="ColorPickerViewRenderer.cs" />\r
     <Compile Include="MediaViewRenderer.cs" />\r
+    <Compile Include="DropdownListRenderer.cs" />\r
     <Compile Include="BackgroundRenderer.cs" />\r
     <Compile Include="CalendarViewRenderer.cs" />\r
     <Compile Include="Cells\DoubleLabelCellRenderer.cs" />\r
     <Compile Include="Cells\GridViewTypeCellRenderer.cs" />\r
     <Compile Include="Cells\MultilineCellRenderer.cs" />\r
     <Compile Include="Cells\TypeCellRenderer.cs" />\r
+    <Compile Include="DialogImplementation.cs" />\r
     <Compile Include="LongTapGestureHandler.cs" />\r
+    <Compile Include="FloatingButtonImplementation.cs" />\r
+    <Compile Include="DateTimeViewRenderer.cs" />\r
     <Compile Include="RadioButtonRenderer.cs" />\r
     <Compile Include="GridViewRenderer.cs" />\r
     <Compile Include="TizenExtension.cs" />\r
     <Compile Include="Properties\AssemblyInfo.cs" />\r
+    <Compile Include="ToastImplementation.cs" />\r
   </ItemGroup>\r
   <ItemGroup>\r
     <None Include="Tizen.Xamarin.Forms.Extension.Renderer.project.json" />\r
index 0e4c6ac..e34d76d 100644 (file)
@@ -1,15 +1,15 @@
 {\r
   "dependencies": {\r
-    "ElmSharp": "1.1.0-beta-013",\r
+    "ElmSharp": "1.1.0-beta-016",\r
     "NETStandard.Library": "1.6.0",\r
     "Tizen.Applications": "1.2.5",\r
     "Tizen.Multimedia": "1.0.41",\r
     "Xamarin.Forms": "2.3.3.175",\r
-    "Xamarin.Forms.Platform.Tizen": "2.3.4-r192-001"\r
+    "Xamarin.Forms.Platform.Tizen": "2.3.4-r192-004"\r
   },\r
   "frameworks": {\r
     "netstandard1.6": {\r
       "imports": "portable-net45+win8+wpa81+wp8"\r
     }\r
   }\r
-}
+}
\ No newline at end of file
diff --git a/Tizen.Xamarin.Forms.Extension.Renderer/ToastImplementation.cs b/Tizen.Xamarin.Forms.Extension.Renderer/ToastImplementation.cs
new file mode 100644 (file)
index 0000000..549e352
--- /dev/null
@@ -0,0 +1,108 @@
+using System;
+using Tizen.Xamarin.Forms.Extension.Renderer;
+using Xamarin.Forms;
+using EPopup = ElmSharp.Popup;
+using TForms = Xamarin.Forms.Platform.Tizen.Forms;
+
+[assembly: Dependency(typeof(ToastImplementation))]
+
+namespace Tizen.Xamarin.Forms.Extension.Renderer
+{
+    internal class ToastImplementation : IToast, IDisposable
+    {
+        static readonly string DefaultStyle = "toast";
+        static readonly string DefaultPart = "default";
+
+        int _duration = 3000;
+        string _text = string.Empty;
+        EPopup _control = null;
+        bool _isDisposed = false;
+
+        public int Duration
+        {
+            get
+            {
+                return _duration;
+            }
+            set
+            {
+                _duration = value;
+                UpdateDuration();
+            }
+        }
+
+        public string Text
+        {
+            get
+            {
+                return _text;
+            }
+            set
+            {
+                _text = value;
+                UpdateText();
+            }
+        }
+
+        public ToastImplementation()
+        {
+            _control = new EPopup(TForms.Context.MainWindow)
+            {
+                Orientation = ElmSharp.PopupOrientation.Bottom,
+                Style = DefaultStyle,
+                AllowEvents = true,
+            };
+
+            UpdateText();
+            UpdateDuration();
+        }
+
+        ~ToastImplementation()
+        {
+            Dispose(false);
+        }
+
+        public void Show()
+        {
+            _control.Show();
+        }
+
+        public void Dismiss()
+        {
+            _control.Dismiss();
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool isDisposing)
+        {
+            if (_isDisposed)
+                return;
+
+            if (isDisposing)
+            {
+                if (_control != null)
+                {
+                    _control.Unrealize();
+                    _control = null;
+                }
+            }
+
+            _isDisposed = true;
+        }
+
+        void UpdateDuration()
+        {
+            _control.Timeout = Duration / 1000.0;
+        }
+
+        void UpdateText()
+        {
+            _control.SetPartText(DefaultPart, Text);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Tizen.Xamarin.Forms.Extension/DateTimeView.cs b/Tizen.Xamarin.Forms.Extension/DateTimeView.cs
new file mode 100644 (file)
index 0000000..bfa5b38
--- /dev/null
@@ -0,0 +1,174 @@
+using System;
+using Xamarin.Forms;
+
+namespace Tizen.Xamarin.Forms.Extension
+{
+    /// <summary>
+    /// The Datetime view is used to display the input date & time values.
+    /// </summary>
+    /// <example>
+    /// <code>
+    /// var dateView = new DateTimeView
+    /// {
+    ///     HorizontalOptions = LayoutOptions.Center,
+    ///     VerticalOptions = LayoutOptions.Start,
+    ///     DateTime = DateTime.Now,
+    ///     MaximumDate = new DateTime(2030, 12, 31),
+    ///     MinimumDate = new DateTime(2017, 1, 1),
+    ///     DisplayFormat = "%F",
+    /// }
+    /// </code>
+    /// </example>
+    public class DateTimeView : View
+    {
+        /// <summary>
+        /// Identifies the DateTime bindable property.
+        /// </summary>
+        public static readonly BindableProperty DateTimeProperty = BindableProperty.Create(nameof(DateTime), typeof(DateTime), typeof(DateTimeView), DateTime.Now, BindingMode.TwoWay, coerceValue: CoerceDate,
+            propertyChanged: DatePropertyChanged);
+
+        /// <summary>
+        /// Identifies the DisplayFormat bindable property.
+        /// </summary>
+        public static readonly BindableProperty DisplayFormatProperty = BindableProperty.Create(nameof(DisplayFormat), typeof(string), typeof(DateTimeView), "%F");
+
+        /// <summary>
+        /// Identifies the MinimumDate bindable property.
+        /// </summary>
+        public static readonly BindableProperty MinimumDateProperty = BindableProperty.Create(nameof(MinimumDate), typeof(DateTime), typeof(DateTimeView), new DateTime(1900, 1, 1),
+            validateValue: ValidateMinimumDate, coerceValue: CoerceMinimumDate);
+
+        /// <summary>
+        /// Identifies the MaximumDate bindable property.
+        /// </summary>
+        public static readonly BindableProperty MaximumDateProperty = BindableProperty.Create(nameof(MaximumDate), typeof(DateTime), typeof(DateTimeView), new DateTime(2100, 12, 31),
+            validateValue: ValidateMaximumDate, coerceValue: CoerceMaximumDate);
+
+        /// <summary>
+        ///  Gets or sets the current value of a DateTime.
+        /// </summary>
+        public DateTime DateTime
+        {
+            get { return (DateTime)GetValue(DateTimeProperty); }
+            set { SetValue(DateTimeProperty, value); }
+        }
+
+        /// <summary>
+        /// Gets or sets the datetime format.
+        /// Format is a combination of allowed LIBC date format specifiers like: "%b %d, %Y %I : %M %p".
+        /// </summary>
+        /// <remarks>
+        /// These specifiers can be arranged in any order and the widget displays the fields accordingly.
+        /// However, you can not use Date and Time settings in combination.
+        /// The default format is taken as per the system locale settings.
+        /// </remarks>
+        /// <remarks>
+        /// The maximum allowed format length is 64 chars.
+        /// The format can include separators for each individual datetime field except for the AM/PM field.
+        /// Each separator can be a maximum of 6 UTF-8 bytes.Space is also taken as a separator.
+        /// Following are the allowed set of format specifiers for each datetime field.
+        /// %Y : The year as a decimal number including the century.
+        /// %m : The month as a decimal number (range 01 to 12).
+        /// %b : The abbreviated month name according to the current locale.
+        /// %B : The full month name according to the current locale.
+        /// %h : The abbreviated month name according to the current locale(same as %b).
+        /// %d : The day of the month as a decimal number(range 01 to 31).
+        /// %e : The day of the month as a decimal number(range 1 to 31). Single digits are preceded by a blank.
+        /// %I : The hour as a decimal number using a 12-hour clock(range 01 to 12).
+        /// %H : The hour as a decimal number using a 24-hour clock(range 00 to 23).
+        /// %k : The hour(24-hour clock) as a decimal number(range 0 to 23). Single digits are preceded by a blank.
+        /// %l : The hour(12-hour clock) as a decimal number(range 1 to 12). Single digits are preceded by a blank.
+        /// %M : The minute as a decimal number(range 00 to 59).
+        /// %p : Either 'AM' or 'PM' according to the given time value, or the corresponding strings for the current locale.Noon is treated as 'PM' and midnight as 'AM'.
+        /// %P : Like p, but in lower case: 'am' or 'pm' or a corresponding string for the current locale.
+        /// %c : The preferred date and time representation for the current locale.
+        /// %x : The preferred date representation for the current locale without the time.
+        /// %X : The preferred time representation for the current locale without the date.
+        /// %r : The complete calendar time using the AM/PM format of the current locale.
+        /// %R : The hour and minute in decimal numbers using the format H:M.
+        /// %T : The time of the day in decimal numbers using the format H:M:S.
+        /// %F : The date using the format %Y-%m-%d.
+        /// </remarks>
+        public string DisplayFormat
+        {
+            get { return (string)GetValue(DisplayFormatProperty); }
+            set { SetValue(DisplayFormatProperty, value); }
+        }
+
+        /// <summary>
+        /// Gets or sets the upper boundary of a DateTime value.
+        /// </summary>
+        public DateTime MaximumDate
+        {
+            get { return (DateTime)GetValue(MaximumDateProperty); }
+            set { SetValue(MaximumDateProperty, value); }
+        }
+
+        /// <summary>
+        /// Gets or sets the lower boundary of a DateTime value.
+        /// </summary>
+        public DateTime MinimumDate
+        {
+            get { return (DateTime)GetValue(MinimumDateProperty); }
+            set { SetValue(MinimumDateProperty, value); }
+        }
+
+        /// <summary>
+        /// An event fired when the DateTime property changes.
+        /// </summary>
+        public event EventHandler<DateChangedEventArgs> DateChanged;
+
+        static object CoerceDate(BindableObject bindable, object value)
+        {
+            var picker = (DateTimeView)bindable;
+            DateTime dateValue = (DateTime)value;
+
+            if (dateValue > picker.MaximumDate)
+                dateValue = picker.MaximumDate;
+
+            if (dateValue < picker.MinimumDate)
+                dateValue = picker.MinimumDate;
+
+            return dateValue;
+        }
+
+        static object CoerceMaximumDate(BindableObject bindable, object value)
+        {
+            DateTime dateValue = ((DateTime)value).Date;
+            var selector = (DateTimeView)bindable;
+            if (selector.DateTime > dateValue)
+                selector.DateTime = dateValue;
+
+            return dateValue;
+        }
+
+        static object CoerceMinimumDate(BindableObject bindable, object value)
+        {
+            DateTime dateValue = ((DateTime)value).Date;
+            var selector = (DateTimeView)bindable;
+            if (selector.DateTime < dateValue)
+                selector.DateTime = dateValue;
+
+            return dateValue;
+        }
+
+        static void DatePropertyChanged(BindableObject bindable, object oldValue, object newValue)
+        {
+            var selector = (DateTimeView)bindable;
+            EventHandler<DateChangedEventArgs> selected = selector.DateChanged;
+
+            if (selected != null)
+                selected(selector, new DateChangedEventArgs((DateTime)oldValue, (DateTime)newValue));
+        }
+
+        static bool ValidateMaximumDate(BindableObject bindable, object value)
+        {
+            return (DateTime)value >= ((DateTimeView)bindable).MinimumDate;
+        }
+
+        static bool ValidateMinimumDate(BindableObject bindable, object value)
+        {
+            return (DateTime)value <= ((DateTimeView)bindable).MaximumDate;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Tizen.Xamarin.Forms.Extension/Dialog.cs b/Tizen.Xamarin.Forms.Extension/Dialog.cs
new file mode 100644 (file)
index 0000000..ddf8bbe
--- /dev/null
@@ -0,0 +1,181 @@
+using System;
+using Xamarin.Forms;
+
+namespace Tizen.Xamarin.Forms.Extension
+{
+    /// <summary>
+    /// The dialog widget displays its content with a particular direction.
+    /// </summary>
+    /// <example>
+    /// <code>
+    /// var dialog = new Dialog();
+    /// dialog.Direction = DialogDirection.Bottom;
+    /// dialog.Title = "Dialog"
+    ///
+    /// var positive = new Button()
+    /// {
+    ///     Text = "OK"
+    /// }
+    /// var negative = new Button()
+    /// {
+    ///     Text = "Cancel"
+    /// }
+    /// negative.Clicked += (s,e)=>
+    /// {
+    ///     dialog.Dismiss();
+    /// }
+    ///
+    /// dialog.Positive = positive;
+    /// dialog.Negative = negative;
+    ///
+    /// var label = new Label()
+    /// {
+    ///     Text = "New Dialog"
+    /// }
+    ///
+    /// dialog.Content = label;
+    ///
+    /// dialog.Show();
+    ///
+    /// </code>
+    /// </example>
+    public class Dialog : BindableObject
+    {
+        public static readonly BindableProperty ContentProperty = BindableProperty.Create(nameof(Content), typeof(View), typeof(Dialog), null);
+
+        public static readonly BindableProperty PositiveProperty = BindableProperty.Create(nameof(Positive), typeof(Button), typeof(Dialog), null);
+
+        public static readonly BindableProperty NeutralProperty = BindableProperty.Create(nameof(Neutral), typeof(Button), typeof(Dialog), null);
+
+        public static readonly BindableProperty NegativeProperty = BindableProperty.Create(nameof(Negative), typeof(Button), typeof(Dialog), null);
+
+        public static readonly BindableProperty TitleProperty = BindableProperty.Create(nameof(Title), typeof(string), typeof(Dialog), null);
+
+        public static readonly BindableProperty SubtitleProperty = BindableProperty.Create(nameof(Subtitle), typeof(string), typeof(Dialog), null);
+
+        IDialog _dialog = null;
+
+        public event EventHandler Dismissed;
+
+        public event EventHandler OutsideClicked;
+
+        public event EventHandler Shown;
+
+        public event EventHandler BackButtonPressed;
+
+        public Dialog()
+        {
+            _dialog = DependencyService.Get<IDialog>(DependencyFetchTarget.NewInstance);
+            if (_dialog == null)
+            {
+                throw new Exception("Object reference not set to an instance of a Dialog.");
+            }
+
+            _dialog.Dismissed += (s, e) =>
+            {
+                Dismissed?.Invoke(this, EventArgs.Empty);
+            };
+
+            _dialog.OutsideClicked += (s, e) =>
+            {
+                OutsideClicked?.Invoke(this, EventArgs.Empty);
+            };
+
+            _dialog.Shown += (s, e) =>
+            {
+                Shown?.Invoke(this, EventArgs.Empty);
+            };
+
+            _dialog.BackButtonPressed += (s, e) =>
+            {
+                BackButtonPressed?.Invoke(this, EventArgs.Empty);
+            };
+
+            SetBinding(ContentProperty, new Binding(nameof(Content), mode: BindingMode.TwoWay, source: _dialog));
+            SetBinding(PositiveProperty, new Binding(nameof(Positive), mode: BindingMode.TwoWay, source: _dialog));
+            SetBinding(NeutralProperty, new Binding(nameof(Neutral), mode: BindingMode.TwoWay, source: _dialog));
+            SetBinding(NegativeProperty, new Binding(nameof(Negative), mode: BindingMode.TwoWay, source: _dialog));
+            SetBinding(TitleProperty, new Binding(nameof(Title), mode: BindingMode.TwoWay, source: _dialog));
+            SetBinding(SubtitleProperty, new Binding(nameof(Subtitle), mode: BindingMode.TwoWay, source: _dialog));
+        }
+
+        /// <summary>
+        /// Gets or sets content view of the Dialog.
+        /// </summary>
+        public View Content
+        {
+            get { return (View)GetValue(ContentProperty); }
+            set { SetValue(ContentProperty, value); }
+        }
+
+        /// <summary>
+        /// Gets or sets positive button of the Dialog.
+        /// </summary>
+        public Button Positive
+        {
+            get { return (Button)GetValue(PositiveProperty); }
+            set { SetValue(PositiveProperty, value); }
+        }
+
+        /// <summary>
+        /// Gets or sets neutral button of the Dialog.
+        /// </summary>
+        public Button Neutral
+        {
+            get { return (Button)GetValue(NeutralProperty); }
+            set { SetValue(NeutralProperty, value); }
+        }
+
+        /// <summary>
+        /// Gets or sets negative button of the Dialog.
+        /// </summary>
+        public Button Negative
+        {
+            get { return (Button)GetValue(NegativeProperty); }
+            set { SetValue(NegativeProperty, value); }
+        }
+
+        /// <summary>
+        /// Gets or sets title of the Dialog.
+        /// </summary>
+        public string Title
+        {
+            get { return (string)GetValue(TitleProperty); }
+            set { SetValue(TitleProperty, value); }
+        }
+
+        /// <summary>
+        /// Gets or sets subtitle of the Dialog.
+        /// When Title property value is null, subtitle does not displayed.
+        /// </summary>
+        public string Subtitle
+        {
+            get { return (string)GetValue(SubtitleProperty); }
+            set { SetValue(SubtitleProperty, value); }
+        }
+
+        /// <summary>
+        /// Shows the Dialog.
+        /// </summary>
+        public void Show()
+        {
+            _dialog.Show();
+        }
+
+        /// <summary>
+        /// Hides the Dialog.
+        /// </summary>
+        public void Hide()
+        {
+            _dialog.Hide();
+        }
+
+        /// <summary>
+        /// Dismisses the Dialog.
+        /// </summary>
+        public void Dismiss()
+        {
+            _dialog.Dismiss();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Tizen.Xamarin.Forms.Extension/DropdownList.cs b/Tizen.Xamarin.Forms.Extension/DropdownList.cs
new file mode 100755 (executable)
index 0000000..ac771da
--- /dev/null
@@ -0,0 +1,198 @@
+using System;
+using System.Collections;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.Reflection;
+using Xamarin.Forms;
+
+namespace Tizen.Xamarin.Forms.Extension
+{
+    /// <summary>
+    /// The DropdownList class
+    /// </summary>
+    /// <example>
+    /// <code>
+    /// var dropdownList = new DropdownList()
+    /// dropdownList.ItemSelected += (s, e) =>
+    /// {
+    ///     Debug.WriteLine("e.Selected Item: " + e.SelectedItem);
+    /// };
+    ///
+    /// ObservableCollection<string> ItemsList = new ObservableCollection<string>()
+    /// {
+    ///     "item5", "item6", "item7", "item8"
+    /// };
+    ///
+    /// dropdownList.ItemsSource = ItemsList;
+    /// </code>
+    /// </example>
+    public class DropdownList : View
+    {
+        public static readonly BindableProperty SelectedItemProperty = BindableProperty.Create("SelectedItem", typeof(object), typeof(DropdownList), default(object), BindingMode.TwoWay, coerceValue: OnCoerceSelectedItem, propertyChanged: OnSelectedItemChanged);
+
+        public static readonly BindableProperty IsHorizontalProperty = BindableProperty.Create("IsHorizontal", typeof(bool), typeof(DropdownList), default(bool));
+
+        public static readonly BindableProperty IsExpandedProperty = BindableProperty.Create("IsExpanded", typeof(bool), typeof(DropdownList), default(bool));
+
+        public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create("ItemsSource", typeof(IEnumerable), typeof(DropdownList), default(IEnumerable), propertyChanged: OnItemsSourceChanged);
+
+        public static readonly BindableProperty DisplayMemberPathProperty = BindableProperty.Create("DisplayMemberPath", typeof(string), typeof(DropdownList), default(string), propertyChanged: OnDisplayMemberPathChanged);
+
+        public event EventHandler<SelectedItemChangedEventArgs> ItemSelected;
+
+        internal IEnumerable InternalItems => _items;
+
+        ObservableCollection<object> _items = new ObservableCollection<object>();
+
+        public DropdownList()
+        {
+        }
+
+        /// <summary>
+        /// Gets or sets the currently selected item from the DropdownList.ItemsSource.
+        /// </summary>
+        public object SelectedItem
+        {
+            get { return (object)GetValue(SelectedItemProperty); }
+            set { SetValue(SelectedItemProperty, value); }
+        }
+
+        /// <summary>
+        /// Gets or sets the DropdownList to expand horizontally.
+        /// </summary>
+        public bool IsHorizontal
+        {
+            get { return (bool)GetValue(IsHorizontalProperty); }
+            set { SetValue(IsHorizontalProperty, value); }
+        }
+
+        /// <summary>
+        /// Triggers or dismisses the DropdownList popup from code,
+        /// the same as if the user had clicked the button or clicked outside the DropdownList.
+        /// </summary>
+        public bool IsExpanded
+        {
+            get { return (bool)GetValue(IsExpandedProperty); }
+            set { SetValue(IsExpandedProperty, value); }
+        }
+
+        /// <summary>
+        /// Gets or sets the source of items to template and display.
+        /// </summary>
+        public IEnumerable ItemsSource
+        {
+            get { return (IEnumerable)GetValue(ItemsSourceProperty); }
+            set { SetValue(ItemsSourceProperty, value); }
+        }
+
+        /// <summary>
+        /// Gets or sets a member path to a value on the ItemsSource.
+        /// </summary>
+        public string DisplayMemberPath
+        {
+            get { return (string)GetValue(DisplayMemberPathProperty); }
+            set { SetValue(DisplayMemberPathProperty, value); }
+        }
+
+        static void OnItemsSourceChanged(BindableObject bindable, object oldValue, object newValue)
+        {
+            ((DropdownList)bindable).OnItemsSourceChanged((IEnumerable)oldValue, (IEnumerable)newValue);
+        }
+
+        void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable newValue)
+        {
+            var oldObservable = oldValue as INotifyCollectionChanged;
+            if (oldObservable != null)
+                oldObservable.CollectionChanged -= ItemsSourceCollectionChanged;
+
+            var newObservable = newValue as INotifyCollectionChanged;
+            if (newObservable != null)
+            {
+                newObservable.CollectionChanged += ItemsSourceCollectionChanged;
+            }
+
+            if (newValue != null)
+            {
+                ResetItems();
+            }
+            else
+            {
+                _items.Clear();
+            }
+        }
+
+        void ItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+        {
+            switch (e.Action)
+            {
+                case NotifyCollectionChangedAction.Add:
+                    AddItems(e);
+                    break;
+                case NotifyCollectionChangedAction.Remove:
+                    RemoveItems(e);
+                    break;
+                default: //Move, Replace, Reset
+                    ResetItems();
+                    break;
+            }
+        }
+
+        void AddItems(NotifyCollectionChangedEventArgs e)
+        {
+            foreach (object newItem in e.NewItems)
+                _items.Add(GetDisplayMember(newItem));
+        }
+
+        void RemoveItems(NotifyCollectionChangedEventArgs e)
+        {
+            int index = e.OldStartingIndex < _items.Count ? e.OldStartingIndex : _items.Count;
+            foreach (object _ in e.OldItems)
+                _items.RemoveAt(index--);
+        }
+
+        void ResetItems()
+        {
+            if (ItemsSource == null)
+                return;
+
+            _items.Clear();
+            foreach (object item in ItemsSource)
+                _items.Add(GetDisplayMember(item));
+        }
+
+        object GetDisplayMember(object item)
+        {
+            if (string.IsNullOrEmpty(DisplayMemberPath) || string.IsNullOrWhiteSpace(DisplayMemberPath))
+                return item.ToString();
+
+            PropertyInfo prop = item.GetType().GetRuntimeProperty(DisplayMemberPath);
+
+            if (prop == null)
+                return item.ToString();
+
+            return prop.GetValue(item);
+        }
+
+        static object OnCoerceSelectedItem(BindableObject bindable, object value)
+        {
+            var dropdownList = bindable as DropdownList;
+            if (!dropdownList._items.Contains(value))
+                return null;
+
+            return value;
+        }
+
+        static void OnSelectedItemChanged(BindableObject bindable, object oldValue, object newValue)
+        {
+            var dropdownList = bindable as DropdownList;
+            if (oldValue != newValue)
+                dropdownList.ItemSelected?.Invoke(bindable as DropdownList, new SelectedItemChangedEventArgs(newValue));
+        }
+
+        static void OnDisplayMemberPathChanged(BindableObject bindable, object oldValue, object newValue)
+        {
+            var dropdownList = bindable as DropdownList;
+            dropdownList.ResetItems();
+        }
+    }
+}
diff --git a/Tizen.Xamarin.Forms.Extension/FloatingButton.cs b/Tizen.Xamarin.Forms.Extension/FloatingButton.cs
new file mode 100644 (file)
index 0000000..ebaf8ab
--- /dev/null
@@ -0,0 +1,139 @@
+using System;
+using Xamarin.Forms;
+
+namespace Tizen.Xamarin.Forms.Extension
+{
+    /// <summary>
+    /// The FloatingButton class
+    /// This is only supported for mobile profiles.
+    /// </summary>
+    /// <example>
+    /// <code>
+    /// FloatingButton floatingButton = new FloatingButton
+    /// {
+    ///     MovablePosition = FloatingButtonMovablePosition.All,
+    /// };
+    ///
+    /// FloatingButtonItem item = new FloatingButtonItem();
+    /// item.Icon = new FileImageSource { File = "Icon.png" };
+    /// item.Clicked += (s,e) => { ... };
+    /// floatingButton.FirstButton = item;
+    ///
+    /// this.Appearing += (s,e) =>
+    /// {
+    ///     If (!floatingButton.IsShown)
+    ///         floatingButton.Show();
+    /// }
+    /// this.Disappearing += (s,e) =>
+    /// {
+    ///     If (floatingButton.IsShown)
+    ///         floatingButton.Hide();
+    /// }
+    /// </code>
+    /// </example>
+    public class FloatingButton : BindableObject, IFloatingButton
+    {
+        public static readonly BindableProperty MovablePositionProperty = BindableProperty.Create(nameof(MovablePosition), typeof(FloatingButtonMovablePosition), typeof(FloatingButton), FloatingButtonMovablePosition.All);
+
+        public static readonly BindableProperty PositionProperty = BindableProperty.Create(nameof(Position), typeof(FloatingButtonPosition), typeof(FloatingButton), FloatingButtonPosition.Right);
+
+        public static readonly BindableProperty IsShownProperty = BindableProperty.Create(nameof(IsShown), typeof(bool), typeof(FloatingButton), true);
+
+        public static readonly BindableProperty FirstButtonProperty = BindableProperty.Create(nameof(FirstButton), typeof(FloatingButtonItem), typeof(FloatingButton), null);
+
+        public static readonly BindableProperty SecondButtonProperty = BindableProperty.Create(nameof(SecondButton), typeof(FloatingButtonItem), typeof(FloatingButton), null);
+
+        IFloatingButton _floatingButton = null;
+
+        /// <summary>
+        /// Gets or sets the movability state of the FloatingButton. This is a bindable property.
+        /// </summary>
+        public FloatingButtonMovablePosition MovablePosition
+        {
+            get { return (FloatingButtonMovablePosition)GetValue(MovablePositionProperty); }
+            set { SetValue(MovablePositionProperty, value); }
+        }
+
+        /// <summary>
+        /// Gets the horizontal position of the FloatingButton. This is a bindable property
+        /// </summary>
+        public FloatingButtonPosition Position
+        {
+            get { return (FloatingButtonPosition)GetValue(PositionProperty); }
+        }
+
+        /// <summary>
+        /// Gets the visible state of the FloatingButton.
+        /// </summary>
+        public bool IsShown
+        {
+            get { return (bool)GetValue(IsShownProperty); }
+            internal set { SetValue(IsShownProperty, value); }
+        }
+
+        /// <summary>
+        /// Gets and sets the internal button of the FloatingButton
+        /// </summary>
+        public FloatingButtonItem FirstButton
+        {
+            get { return (FloatingButtonItem)GetValue(FirstButtonProperty); }
+            set { SetValue(FirstButtonProperty, value); }
+        }
+
+        /// <summary>
+        /// Gets and sets the internal button of the FloatingButton
+        /// </summary>
+        public FloatingButtonItem SecondButton
+        {
+            get { return (FloatingButtonItem)GetValue(SecondButtonProperty); }
+            set { SetValue(SecondButtonProperty, value); }
+        }
+
+        /// <summary>
+        /// Sets the horizontal position of the FloatingButton.
+        /// </summary>
+        /// <param name="position"> FloatingButtonPosition value </param>
+        /// <param name="animated"> Bool value to set the animation when moving the position </param>
+        public void SetPosition(FloatingButtonPosition position, bool animated)
+        {
+            if (MovablePosition != FloatingButtonMovablePosition.None)
+            {
+                _floatingButton.SetPosition(position, animated);
+            }
+        }
+
+        /// <summary>
+        /// A method to hide the FloatingButton
+        /// </summary>
+        public void Hide()
+        {
+            IsShown = false;
+            _floatingButton.Hide();
+        }
+
+        /// <summary>
+        /// A method to show the FloatingButton
+        /// </summary>
+        public void Show()
+        {
+            IsShown = true;
+            _floatingButton.Show();
+        }
+
+        public FloatingButton()
+        {
+            if (Device.Idiom != TargetIdiom.Phone)
+                throw new Exception("FloatingButton is support only mobile profile.");
+
+            _floatingButton = DependencyService.Get<IFloatingButton>(DependencyFetchTarget.GlobalInstance);
+
+            if (_floatingButton == null)
+                throw new Exception("Object reference not set to an instance of a FloatingButton.");
+
+            SetBinding(MovablePositionProperty, new Binding(nameof(MovablePosition), mode: BindingMode.TwoWay, source: _floatingButton));
+            SetBinding(PositionProperty, new Binding(nameof(Position), mode: BindingMode.TwoWay, source: _floatingButton));
+            SetBinding(FirstButtonProperty, new Binding(nameof(FirstButton), mode: BindingMode.TwoWay, source: _floatingButton));
+            SetBinding(SecondButtonProperty, new Binding(nameof(SecondButton), mode: BindingMode.TwoWay, source: _floatingButton));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Tizen.Xamarin.Forms.Extension/FloatingButtonItem.cs b/Tizen.Xamarin.Forms.Extension/FloatingButtonItem.cs
new file mode 100644 (file)
index 0000000..0a25f50
--- /dev/null
@@ -0,0 +1,36 @@
+using System;
+using Xamarin.Forms;
+
+namespace Tizen.Xamarin.Forms.Extension
+{
+    /// <summary>
+    /// A class for containing icons and event information
+    /// </summary>
+    public class FloatingButtonItem
+    {
+        FileImageSource _icon = null;
+
+        public FloatingButtonItem()
+        {
+        }
+
+        /// <summary>
+        /// Gets or sets the Icon of the FloatingButtonItem
+        /// </summary>
+        public FileImageSource Icon
+        {
+            get { return _icon; }
+            set { _icon = value; }
+        }
+
+        /// <summary>
+        /// Occurs when the FloatingButtonItem clicked
+        /// </summary>
+        public event EventHandler Clicked;
+
+        internal void OnClicked()
+        {
+            Clicked?.Invoke(this, EventArgs.Empty);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Tizen.Xamarin.Forms.Extension/FloatingButtonMovablePosition.cs b/Tizen.Xamarin.Forms.Extension/FloatingButtonMovablePosition.cs
new file mode 100644 (file)
index 0000000..ef9f67c
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2016 by Samsung Electronics, Inc.,
+//
+// This software is the confidential and proprietary information
+// of Samsung Electronics, Inc. ("Confidential Information"). You
+// shall not disclose such Confidential Information and shall use
+// it only in accordance with the terms of the license agreement
+// you entered into with Samsung.
+
+namespace Tizen.Xamarin.Forms.Extension
+{
+    /// <summary>
+    /// Enumerates values that describe the Mode of FloatingButton.
+    /// </summary>
+    public enum FloatingButtonMovablePosition
+    {
+        /// <summary>
+        /// allows all positions
+        /// </summary>
+        All,
+
+        /// <summary>
+        /// allows LEFT and RIGHT positions only
+        /// </summary>
+        LeftRightOnly,
+
+        /// <summary>
+        /// movement blocked
+        /// </summary>
+        None,
+    }
+}
\ No newline at end of file
diff --git a/Tizen.Xamarin.Forms.Extension/FloatingButtonPosition.cs b/Tizen.Xamarin.Forms.Extension/FloatingButtonPosition.cs
new file mode 100644 (file)
index 0000000..bd9184e
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright 2016 by Samsung Electronics, Inc.,
+//
+// This software is the confidential and proprietary information
+// of Samsung Electronics, Inc. ("Confidential Information"). You
+// shall not disclose such Confidential Information and shall use
+// it only in accordance with the terms of the license agreement
+// you entered into with Samsung.
+
+namespace Tizen.Xamarin.Forms.Extension
+{
+    /// <summary>
+    /// Positions of FloatingButton where floatingbutton can be placed on
+    /// </summary>
+    public enum FloatingButtonPosition
+    {
+        /// <summary>
+        /// hides in the left, but small handler will show only
+        /// </summary>
+        LeftOut,
+
+        /// <summary>
+        /// shows all of buttons, but lies on the left
+        /// </summary>
+        Left,
+
+        /// <summary>
+        /// shows all of buttons, but lies on the center
+        /// </summary>
+        Center,
+
+        /// <summary>
+        /// shows all of buttons, but lies on the right
+        /// </summary>
+        Right,
+
+        /// <summary>
+        /// hides in the right, but small handler will show only
+        /// </summary>
+        RightOut,
+    }
+}
\ No newline at end of file
diff --git a/Tizen.Xamarin.Forms.Extension/IDialog.cs b/Tizen.Xamarin.Forms.Extension/IDialog.cs
new file mode 100644 (file)
index 0000000..f450550
--- /dev/null
@@ -0,0 +1,34 @@
+using System;
+using Xamarin.Forms;
+
+namespace Tizen.Xamarin.Forms.Extension
+{
+    internal interface IDialog
+    {
+        event EventHandler Dismissed;
+
+        event EventHandler OutsideClicked;
+
+        event EventHandler Shown;
+
+        event EventHandler BackButtonPressed;
+
+        View Content { get; set; }
+
+        Button Positive { get; set; }
+
+        Button Neutral { get; set; }
+
+        Button Negative { get; set; }
+
+        string Title { get; set; }
+
+        string Subtitle { get; set; }
+
+        void Show();
+
+        void Hide();
+
+        void Dismiss();
+    }
+}
\ No newline at end of file
diff --git a/Tizen.Xamarin.Forms.Extension/IFloatingButton.cs b/Tizen.Xamarin.Forms.Extension/IFloatingButton.cs
new file mode 100644 (file)
index 0000000..c42ed5b
--- /dev/null
@@ -0,0 +1,25 @@
+using System;
+using Xamarin.Forms;
+using System.Windows.Input;
+
+namespace Tizen.Xamarin.Forms.Extension
+{
+    internal interface IFloatingButton
+    {
+        FloatingButtonPosition Position { get; }
+
+        FloatingButtonMovablePosition MovablePosition { get; set; }
+
+        bool IsShown { get; }
+
+        FloatingButtonItem FirstButton { get; set; }
+
+        FloatingButtonItem SecondButton { get; set; }
+
+        void SetPosition(FloatingButtonPosition position, bool animated);
+
+        void Show();
+
+        void Hide();
+    }
+}
\ No newline at end of file
diff --git a/Tizen.Xamarin.Forms.Extension/IToast.cs b/Tizen.Xamarin.Forms.Extension/IToast.cs
new file mode 100644 (file)
index 0000000..620f83d
--- /dev/null
@@ -0,0 +1,28 @@
+namespace Tizen.Xamarin.Forms.Extension
+{
+    /// <summary>
+    /// This interface which defines the ability to display simple text is used internally.
+    /// </summary>
+    internal interface IToast
+    {
+        /// <summary>
+        /// Gets or sets the duration.
+        /// </summary>
+        int Duration { get; set; }
+
+        /// <summary>
+        /// Gets or sets the Text.
+        /// </summary>
+        string Text { get; set; }
+
+        /// <summary>
+        /// Show the view for the specified duration.
+        /// </summary>
+        void Show();
+
+        /// <summary>
+        /// Dismiss the specified view.
+        /// </summary>
+        void Dismiss();
+    }
+}
\ No newline at end of file
index b298784..c9b1c03 100644 (file)
@@ -11,5 +11,4 @@ using System.Runtime.CompilerServices;
 [assembly: AssemblyTrademark("")]
 [assembly: CompilationRelaxations(8)]
 [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
-
-[assembly: InternalsVisibleTo("Tizen.Xamarin.Forms.Extension.Renderer")]
\ No newline at end of file
+[assembly: InternalsVisibleTo("Tizen.Xamarin.Forms.Extension.Renderer")]
index 973f90b..d8c4480 100644 (file)
     <Compile Include="Cells\Type2Cell.cs" />\r
     <Compile Include="Cells\BaseTypeCell.cs" />\r
     <Compile Include="Cells\MultilineCell.cs" />\r
+    <Compile Include="DateTimeView.cs" />\r
+    <Compile Include="Dialog.cs" />\r
     <Compile Include="EnumerableExtensions.cs" />\r
+    <Compile Include="FloatingButtonItem.cs" />\r
+    <Compile Include="FloatingButtonMovablePosition.cs" />\r
+    <Compile Include="IFloatingButton.cs" />\r
+    <Compile Include="FloatingButton.cs" />\r
+    <Compile Include="FloatingButtonPosition.cs" />\r
     <Compile Include="GridView.cs" />\r
     <Compile Include="GridViewEnums.cs" />\r
     <Compile Include="GridViewEventArgs.cs" />\r
+    <Compile Include="IDialog.cs" />\r
     <Compile Include="ILongTapGestureController.cs" />\r
     <Compile Include="ItemsView.cs" />\r
+    <Compile Include="IToast.cs" />\r
     <Compile Include="ListProxy.cs" />\r
     <Compile Include="LongTapGestureRecognizer.cs" />\r
     <Compile Include="LongTapUpdatedEventArgs.cs" />\r
     <Compile Include="Properties\AssemblyInfo.cs" />\r
+    <Compile Include="DropdownList.cs" />\r
     <Compile Include="RadioButton.cs" />\r
     <Compile Include="SelectedEventArgs.cs" />\r
     <Compile Include="ReadOnlyListAdapter.cs" />\r
     <Compile Include="TemplatedItemsList.cs" />\r
+    <Compile Include="Toast.cs" />\r
+    <Compile Include="ToastProxy.cs" />\r
   </ItemGroup>\r
   <ItemGroup>\r
     <Reference Include="Xamarin.Forms.Core, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">\r
     <Error Condition="!Exists('..\packages\Xamarin.Forms.2.3.3.175\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+Xamarin.iOS10+xamarinmac20\Xamarin.Forms.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Xamarin.Forms.2.3.3.175\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+Xamarin.iOS10+xamarinmac20\Xamarin.Forms.targets'))" />\r
   </Target>\r
   <Import Project="..\packages\Xamarin.Forms.2.3.3.175\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+Xamarin.iOS10+xamarinmac20\Xamarin.Forms.targets" Condition="Exists('..\packages\Xamarin.Forms.2.3.3.175\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+Xamarin.iOS10+xamarinmac20\Xamarin.Forms.targets')" />\r
-  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
-       Other similar extension points exist, see Microsoft.Common.targets.
-  <Target Name="BeforeBuild">
-  </Target>
-  <Target Name="AfterBuild">
-  </Target>
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it.\r
+       Other similar extension points exist, see Microsoft.Common.targets.\r
+  <Target Name="BeforeBuild">\r
+  </Target>\r
+  <Target Name="AfterBuild">\r
+  </Target>\r
   -->\r
-</Project>
+</Project>\r
diff --git a/Tizen.Xamarin.Forms.Extension/Toast.cs b/Tizen.Xamarin.Forms.Extension/Toast.cs
new file mode 100644 (file)
index 0000000..1d578ff
--- /dev/null
@@ -0,0 +1,27 @@
+namespace Tizen.Xamarin.Forms.Extension
+{
+    /// <summary>
+    /// The Toast class provides properties that show simple types of messages.
+    /// </summary>
+    /// <example>
+    /// <code>
+    /// Toast.DisplayText("Hello World", 3000)
+    /// </code>
+    /// </example>
+    public sealed class Toast
+    {
+        /// <summary>
+        /// It shows the simplest form of the message.
+        /// </summary>
+        /// <param name="text">The body text of the toast.</param>
+        /// <param name="duration">How long to display the text in milliseconds.</param>
+        public static void DisplayText(string text, int duration = 3000)
+        {
+            new ToastProxy
+            {
+                Text = text,
+                Duration = duration,
+            }.Show();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Tizen.Xamarin.Forms.Extension/ToastProxy.cs b/Tizen.Xamarin.Forms.Extension/ToastProxy.cs
new file mode 100644 (file)
index 0000000..c2954c1
--- /dev/null
@@ -0,0 +1,57 @@
+using System;
+using Xamarin.Forms;
+
+namespace Tizen.Xamarin.Forms.Extension
+{
+    /// <summary>
+    /// This Class is for internal use by toast.
+    /// </summary>
+    internal class ToastProxy : IToast
+    {
+        IToast _toastProxy = null;
+
+        public ToastProxy()
+        {
+            _toastProxy = DependencyService.Get<IToast>(DependencyFetchTarget.NewInstance);
+
+            if (_toastProxy == null)
+                throw new Exception("RealObject is null, Internal instance via DependecyService was not created.");
+        }
+
+        public int Duration
+        {
+            get
+            {
+                return _toastProxy.Duration;
+            }
+
+            set
+            {
+                _toastProxy.Duration = value;
+            }
+        }
+
+        public string Text
+        {
+            get
+            {
+                return _toastProxy.Text;
+            }
+
+            set
+            {
+                _toastProxy.Text = value;
+            }
+        }
+
+        public void Dismiss()
+        {
+            _toastProxy.Dismiss();
+        }
+
+        public void Show()
+        {
+            _toastProxy.Show();
+        }
+    }
+}
\ No newline at end of file
index 4cb2942..9be4c10 100644 (file)
@@ -25,6 +25,7 @@ BuildRequires: csapi-tizen-nuget
 BuildRequires: csapi-application-nuget
 BuildRequires: elm-sharp-nuget
 BuildRequires: xamarin-forms-tizen-nuget
+BuildRequires: csapi-multimedia-nuget
 
 %description
 %{summary}