Add DateTimeView 62/115062/12
authorchungryeol lim <cdark.lim@samsung.com>
Thu, 16 Feb 2017 07:34:05 +0000 (16:34 +0900)
committerdarkleem <cdark.lim@samsung.com>
Thu, 23 Mar 2017 03:44:08 +0000 (12:44 +0900)
 RFC : http://suprem.sec.samsung.net/confluence/pages/viewpage.action?pageId=73046563

Change-Id: If44b3ba8ac95e2a44349b54185a3c05e9688dfee
Signed-off-by: chungryeol lim <cdark.lim@samsung.com>
Tizen.Xamarin.Forms.Extension.Renderer/DateTimeViewRenderer.cs [new file with mode: 0644]
Tizen.Xamarin.Forms.Extension.Renderer/Tizen.Xamarin.Forms.Extension.Renderer.csproj
Tizen.Xamarin.Forms.Extension/DateTimeView.cs [new file with mode: 0644]
Tizen.Xamarin.Forms.Extension/Tizen.Xamarin.Forms.Extension.csproj

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
index dace14b..74c3e75 100755 (executable)
@@ -47,6 +47,7 @@
     <Compile Include="Cells\TypeCellRenderer.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
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
index 4270d4c..4bd4374 100644 (file)
@@ -65,6 +65,7 @@
     <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="EnumerableExtensions.cs" />\r
     <Compile Include="FloatingButtonItem.cs" />\r
     <Compile Include="FloatingButtonMovablePosition.cs" />\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>