Support new features of Xamarin.Forms based on 4.6.0 branch (#222)
author유리나/Common Platform Lab(SR)/Staff Engineer/삼성전자 <rina6350.you@samsung.com>
Thu, 14 May 2020 04:48:43 +0000 (13:48 +0900)
committer안주원/Common Platform Lab(SR)/Principal Engineer/삼성전자 <juwon.ahn@samsung.com>
Thu, 14 May 2020 04:48:43 +0000 (13:48 +0900)
* Fix RTL on Shell to correctly propagate FlowDirection through the UIView Stack (#9237)

* Shell iOS RTL fixes

* - simplify

* - change flow direction to use os settings when not specified

* - check for flags

* - unit test fixes

* - rebase fixes

* - remove device default

* - remove explicit parent
fixes #6227
fixes #6342

* AppTheme fix NRE (#10327)

* Various fixes

* Back to basics

* Meets alignment for Xamarin.Forms.Core

* [Tizen] Add material renderers for Editor and Picker (#9384)

* [Tizen] Fix PickerRenderers to disable cursor

* [Tizen] Add material style Editor and Pickers

* [Tizen] Fix typo and modify the event invoking methods

* RadioButton Experimental  Flag (#10370)

* RadioButton Experimental Flag

* - check IsDesignerMode

* Give elements inside flyout a namescope for VSM (#10383)

* Give elements inside flyout a namescope for VSM

* - set binidings through vsm

fixes #10382

* [iOS] Shell fix clear of ShellSection  (#10253)

* Fix clear of ShellSection on iOS

* - additional unit tests

* Update Xamarin.Forms.Core/Shell/ShellSection.cs

* - fix removed items

* - fix check

* - uitests

* - additional clear fixes

* - make get items from shell elements immutable
- pre create all pages before actively adding them to top tabs

* - fix android not setting page if item is removed

* - remove wait

* - add check to make sure you're on correct item before setting content

* Propagate StyleClass from Items correctly (#10381)

* Propagate StyleClass from Items correctly

* - fix uwp to use correct method for flyout

* Expander + CollectionView issues (#10283) fixes #10230

https://github.com/xamarin/Xamarin.Forms/issues/10230

* Fix has VSM check to not use IsSet (#10459)

* Fix has VSM check to not use IsSet

* - fix left over param

* - make test more accurate

fixes #10040

* Indicator shows # of indicators = MaximumVisible even when there are fewer items (#10401)

* Fix iOS & Android

* Moved coerce to renderers

* Moved logic to renderers
fixes #9826

* Fix Collection selection using SwipeView (#9638)

* Fix Collection selection using SwipeView

* Move SwipeView IsOpen property to ISwipeViewController

* Added comment to added ViewCellContainer constructor

* Minor changes based on PR feedback

* Updated SwipeView GestureRecognizers samples to cover all the cases

* Modified ItemContentView ClickOn method to be internal

fixes #9467
fixes #8774
fixes #8903
fixes #9089
fixes #9466
fixes #9027
fixes #10056

* feat!: make managed cookies opt-in, re #10318 (#10474)

* Get rid of pointless Spacing property in Expander (#10460) fixes #10449

* Runtime updating of AppTheme values (#10442)

* Make things BindingBase

* Update OnAppTheme.cs

* Runtime updating

* Fixed

* Cleanup

* Update VisualElement.cs

* Update Application.cs

* Fix NRE for unit tests

* Review feedback

* Update Application.cs

fixes #10391

* If Shell Element is already wrapped up just return the implicit parent (#10418) fixes #10308

* [Tize] Provide way to handle when MoreOption was opened/closed (#10553)

* Set Current Item correctly after items cleared (#10515)

* Set Current Item correctly after items cleared

* - fix disposes

* - null check

* - ios fixes

* - fix pager

* - enough if statements will solve any problem

* - more ifs

* Make cookie handling consistent and non destructive (#10571) fixes #10318

* Make cookie handling consistent and non destructive

* - fix ios

* - ios fixes

* - sync fixes

* - ios fixes

* - fix ui tests

* - fix uwp

* - move buttons around

* - update comments

* - ios10 adjustments

* - use host for key not full url

* Fix TemplatedItemsList incorrect grouped collection range removal (#7891) fixes #7890

* fix

* test added

* uitest added

* ui test fix

Co-authored-by: melimion <Evlentev@molot.net>
* [Tizen] Update ShellRenderer for extend (#10587)

* Fixed wrong namespace in FontFile class (#10496) fixes #10495

* [Tizen] Adds ActiveBezelElement to Application (#10644)

* Added IsOpen property in SwipeEndedEventArgs  (#10467)

* Added IsOpen property in SwipeEndedEventArgs (Android and iOS)

* Fixed build error

* [Tizen] Adds ActiveBezelInteractionElement to Application (#412)

* [Tizen] Adds RotaryFocusView to Application

* Update Xamarin.Forms.Platform.Tizen/Renderers/ViewRenderer.cs

Co-Authored-By: 이승근/Common Platform Lab(SR)/Staff Engineer/삼성전자 <sngn.lee@samsung.com>
* Make ActiveBezelElement as readonly binadable property

* [Tizen] Enhance Stepper for watch (#410)

* Create wearable_app_requirement.md

* [Tizen] Enhance Stepper for watch

* [Tizen] Modify event names

* [Tizen] Change parent of WatchDateTimePicker (#413)

* [Tizen] Update native controls of Date/TimePicker for watch

* [Tizen] Update DateTimePickerRenderer

* [Tizen] Update WatchScroller for extension (#415)

* [Tizen] Update ListView native controls for extension (#416)

* [Tizen] Adds more SwitchStyles (#417)

* [Tizen] Adds Switch.Color as Platform Specifc API (#418)

53 files changed:
src/XSF/Xamarin.Forms.Core/AppThemeColor.cs
src/XSF/Xamarin.Forms.Core/Application.cs
src/XSF/Xamarin.Forms.Core/BindableObjectExtensions.cs
src/XSF/Xamarin.Forms.Core/EffectiveFlowDirection.cs
src/XSF/Xamarin.Forms.Core/Expander.cs
src/XSF/Xamarin.Forms.Core/ExperimentalFlags.cs
src/XSF/Xamarin.Forms.Core/FontFile.cs
src/XSF/Xamarin.Forms.Core/ISwipeViewController.cs
src/XSF/Xamarin.Forms.Core/IndicatorView.cs
src/XSF/Xamarin.Forms.Core/Internals/PropertyPropagationExtensions.cs
src/XSF/Xamarin.Forms.Core/Markup/DefaultBindableProperties.cs
src/XSF/Xamarin.Forms.Core/OnAppTheme.cs
src/XSF/Xamarin.Forms.Core/PlatformConfiguration/TizenSpecific/Application.cs
src/XSF/Xamarin.Forms.Core/PlatformConfiguration/TizenSpecific/StyleValues.cs
src/XSF/Xamarin.Forms.Core/PlatformConfiguration/TizenSpecific/Switch.cs [new file with mode: 0644]
src/XSF/Xamarin.Forms.Core/RadioButton.cs
src/XSF/Xamarin.Forms.Core/Shell/BaseShellItem.cs
src/XSF/Xamarin.Forms.Core/Shell/Shell.cs
src/XSF/Xamarin.Forms.Core/Shell/ShellContent.cs
src/XSF/Xamarin.Forms.Core/Shell/ShellContentCollection.cs
src/XSF/Xamarin.Forms.Core/Shell/ShellItem.cs
src/XSF/Xamarin.Forms.Core/Shell/ShellSection.cs
src/XSF/Xamarin.Forms.Core/SwipeEventArgs.cs
src/XSF/Xamarin.Forms.Core/SwipeView.cs
src/XSF/Xamarin.Forms.Core/TemplatedItemsList.cs
src/XSF/Xamarin.Forms.Core/VisualElement.cs
src/XSF/Xamarin.Forms.Core/VisualStateManager.cs
src/XSF/Xamarin.Forms.Core/WebView.cs
src/XSF/Xamarin.Forms.Platform.Tizen/FormsApplication.cs
src/XSF/Xamarin.Forms.Platform.Tizen/Native/DateTimePicker.cs
src/XSF/Xamarin.Forms.Platform.Tizen/Native/DateTimePickerDialog.cs
src/XSF/Xamarin.Forms.Platform.Tizen/Native/EditfieldEntry.cs
src/XSF/Xamarin.Forms.Platform.Tizen/Native/Entry.cs
src/XSF/Xamarin.Forms.Platform.Tizen/Native/IDateTimeDialog.cs
src/XSF/Xamarin.Forms.Platform.Tizen/Native/IEntry.cs
src/XSF/Xamarin.Forms.Platform.Tizen/Native/Watch/WatchDateTimePicker.cs
src/XSF/Xamarin.Forms.Platform.Tizen/Native/Watch/WatchDateTimePickerDialog.cs [moved from src/XSF/Xamarin.Forms.Platform.Tizen/Native/Watch/WatchDataTimePickerDialog.cs with 53% similarity]
src/XSF/Xamarin.Forms.Platform.Tizen/Native/Watch/WatchListView.cs
src/XSF/Xamarin.Forms.Platform.Tizen/Native/Watch/WatchScroller.cs
src/XSF/Xamarin.Forms.Platform.Tizen/Native/Watch/WatchSpinner.cs [new file with mode: 0644]
src/XSF/Xamarin.Forms.Platform.Tizen/Renderers/DatePickerRenderer.cs
src/XSF/Xamarin.Forms.Platform.Tizen/Renderers/EditorRenderer.cs
src/XSF/Xamarin.Forms.Platform.Tizen/Renderers/ListViewRenderer.cs
src/XSF/Xamarin.Forms.Platform.Tizen/Renderers/PageRenderer.cs
src/XSF/Xamarin.Forms.Platform.Tizen/Renderers/PickerRenderer.cs
src/XSF/Xamarin.Forms.Platform.Tizen/Renderers/StepperRenderer.cs
src/XSF/Xamarin.Forms.Platform.Tizen/Renderers/SwipeViewRenderer.cs
src/XSF/Xamarin.Forms.Platform.Tizen/Renderers/SwitchRenderer.cs
src/XSF/Xamarin.Forms.Platform.Tizen/Renderers/TimePickerRenderer.cs
src/XSF/Xamarin.Forms.Platform.Tizen/Renderers/ViewRenderer.cs
src/XSF/Xamarin.Forms.Platform.Tizen/Shell/Watch/ShellRenderer.cs
src/XSF/Xamarin.Forms.Xaml/MarkupExtensionParser.cs
src/XSF/Xamarin.Forms.Xaml/MarkupExtensions/OnAppThemeExtension.cs

index 1d908df..9ac8648 100644 (file)
@@ -1,81 +1,4 @@
-using System;
-
-namespace Xamarin.Forms
+namespace Xamarin.Forms
 {
-       public class AppThemeColor : BindableObject
-       {
-               public AppThemeColor()
-               {
-                       ExperimentalFlags.VerifyFlagEnabled(nameof(AppThemeColor), ExperimentalFlags.AppThemeExperimental, nameof(AppThemeColor));
-
-                       Application.Current.RequestedThemeChanged += RequestedThemeChanged;
-               }
-
-               public static readonly BindableProperty LightProperty = BindableProperty.Create(nameof(Light), typeof(Color), typeof(AppThemeColor), default(Color), propertyChanged: (bo, __, ___) => UpdateActualValue(bo));
-
-               public Color Light
-               {
-                       get => (Color)GetValue(LightProperty);
-                       set => SetValue(LightProperty, value);
-               }
-
-               public static readonly BindableProperty DarkProperty = BindableProperty.Create(nameof(Dark), typeof(Color), typeof(AppThemeColor), default(Color), propertyChanged: (bo, __, ___) => UpdateActualValue(bo));
-
-               public Color Dark
-               {
-                       get => (Color)GetValue(DarkProperty);
-                       set => SetValue(DarkProperty, value);
-               }
-
-               public static readonly BindableProperty DefaultProperty = BindableProperty.Create(nameof(Default), typeof(Color), typeof(AppThemeColor), default(Color), propertyChanged: (bo, __, ___) => UpdateActualValue(bo));
-
-               public Color Default
-               {
-                       get => (Color)GetValue(DefaultProperty);
-                       set => SetValue(DefaultProperty, value);
-               }
-
-               private Color _value;
-               public Color Value
-               {
-                       get => _value;
-                       private set
-                       {
-                               _value = value;
-                               OnPropertyChanged();
-                       }
-               }
-
-               public static implicit operator Color(AppThemeColor appThemeColor)
-               {
-                       switch (Application.Current?.RequestedTheme)
-                       {
-                               default:
-                               case OSAppTheme.Light:
-                                       return appThemeColor.IsSet(LightProperty) ? appThemeColor.Light : (appThemeColor.IsSet(DefaultProperty) ? appThemeColor.Default : default(Color));
-                               case OSAppTheme.Dark:
-                                       return appThemeColor.IsSet(DarkProperty) ? appThemeColor.Dark : (appThemeColor.IsSet(DefaultProperty) ? appThemeColor.Default : default(Color));
-                       }
-               }
-
-               static void UpdateActualValue(BindableObject bo)
-               {
-                       var appThemeColor = bo as AppThemeColor;
-                       switch (Application.Current?.RequestedTheme)
-                       {
-                               default:
-                               case OSAppTheme.Light:
-                                       appThemeColor.Value = appThemeColor.IsSet(LightProperty) ? appThemeColor.Light : (appThemeColor.IsSet(DefaultProperty) ? appThemeColor.Default : default(Color));
-                                       break;
-                               case OSAppTheme.Dark:
-                                       appThemeColor.Value = appThemeColor.IsSet(DarkProperty) ? appThemeColor.Dark : (appThemeColor.IsSet(DefaultProperty) ? appThemeColor.Default : default(Color));
-                                       break;
-                       }
-               }
-
-               void RequestedThemeChanged(object sender, AppThemeChangedEventArgs e)
-               {
-                       UpdateActualValue(this);
-               }
-       }
+       public class AppThemeColor : OnAppTheme<Color> { }
 }
\ No newline at end of file
index 110c00d..cd4cf9b 100644 (file)
@@ -6,8 +6,6 @@ using System.ComponentModel;
 using System.Threading.Tasks;
 using Xamarin.Forms.Internals;
 using Xamarin.Forms.Platform;
-using System.Diagnostics;
-using Xamarin.Forms.Core;
 
 namespace Xamarin.Forms
 {
@@ -78,6 +76,7 @@ namespace Xamarin.Forms
                                if (_mainPage != null)
                                {
                                        InternalChildren.Remove(_mainPage);
+
                                        _mainPage.Parent = null;
                                }
 
@@ -160,18 +159,36 @@ namespace Xamarin.Forms
 
                public event EventHandler<AppThemeChangedEventArgs> RequestedThemeChanged
                {
-                       add
-                       {
-                               ExperimentalFlags.VerifyFlagEnabled(nameof(Application), ExperimentalFlags.AppThemeExperimental, nameof(RequestedThemeChanged));
-
-                               _weakEventManager.AddEventHandler(value);
-                       }
+                       add => _weakEventManager.AddEventHandler(value);
                        remove => _weakEventManager.RemoveEventHandler(value);
                }
 
+               bool _themeChangedFiring;
+               OSAppTheme _lastAppTheme;
+
                [EditorBrowsable(EditorBrowsableState.Never)]
                public void OnRequestedThemeChanged(AppThemeChangedEventArgs args)
-                       => _weakEventManager.HandleEvent(this, args, nameof(RequestedThemeChanged));
+               {
+                       if (Device.Flags.IndexOf(ExperimentalFlags.AppThemeExperimental) == -1)
+                               return;
+
+                       // On iOS the event is triggered more than once.
+                       // To minimize that for us, we only do it when the theme actually changes and it's not currently firing
+                       if (!_themeChangedFiring && RequestedTheme != _lastAppTheme)
+                       {
+                               try
+                               {
+                                       _themeChangedFiring = true;
+                                       _lastAppTheme = RequestedTheme;
+
+                                       _weakEventManager.HandleEvent(this, args, nameof(RequestedThemeChanged));
+                               }
+                               finally
+                               {
+                                       _themeChangedFiring = false;
+                               }
+                       }
+               }
 
                public event EventHandler<ModalPoppedEventArgs> ModalPopped;
 
index 440325b..463a6ff 100644 (file)
@@ -67,5 +67,21 @@ namespace Xamarin.Forms
 
                        return returnIfNotSet;
                }
+
+               public static void SetOnAppTheme<T>(this BindableObject self, BindableProperty targetProperty, T light, T dark, T defaultValue = default)
+               {
+                       ExperimentalFlags.VerifyFlagEnabled(nameof(BindableObjectExtensions), ExperimentalFlags.AppThemeExperimental, nameof(BindableObjectExtensions), nameof(SetOnAppTheme));
+
+                       var appTheme = new OnAppTheme<T> { Light = light, Dark = dark, Default = defaultValue };
+                       self.SetBinding(targetProperty, appTheme);
+               }
+
+               public static void SetAppThemeColor(this BindableObject self, BindableProperty targetProperty, Color light, Color dark, Color defaultValue = default)
+               {
+                       ExperimentalFlags.VerifyFlagEnabled(nameof(BindableObjectExtensions), ExperimentalFlags.AppThemeExperimental, nameof(BindableObjectExtensions), nameof(SetAppThemeColor));
+
+                       var appTheme = new AppThemeColor { Light = light, Dark = dark, Default = defaultValue };
+                       self.SetBinding(targetProperty, appTheme);
+               }
        }
 }
\ No newline at end of file
index d492c17..027837f 100644 (file)
@@ -6,6 +6,6 @@ namespace Xamarin.Forms
        public enum EffectiveFlowDirection
        {
                RightToLeft = 1 << 0,
-               Explicit = 1 << 1,
+               Explicit = 1 << 1
        }
 }
\ No newline at end of file
index 00171a4..67f5a9b 100644 (file)
@@ -13,14 +13,11 @@ namespace Xamarin.Forms
 
                public event EventHandler Tapped;
 
-               public static readonly BindableProperty SpacingProperty = BindableProperty.Create(nameof(Spacing), typeof(double), typeof(Expander), 0d, propertyChanged: (bindable, oldvalue, newvalue)
-                       => ((Expander)bindable).ExpanderLayout.Spacing = (double)newvalue);
-
                public static readonly BindableProperty HeaderProperty = BindableProperty.Create(nameof(Header), typeof(View), typeof(Expander), default(View), propertyChanged: (bindable, oldValue, newValue)
                        => ((Expander)bindable).SetHeader((View)oldValue));
 
                public static readonly BindableProperty ContentProperty = BindableProperty.Create(nameof(Content), typeof(View), typeof(Expander), default(View), propertyChanged: (bindable, oldValue, newValue)
-                       => ((Expander)bindable).SetContent((View)oldValue, (View)newValue));
+                       => ((Expander)bindable).SetContent());
 
                public static readonly BindableProperty ContentTemplateProperty = BindableProperty.Create(nameof(ContentTemplate), typeof(DataTemplate), typeof(Expander), default(DataTemplate), propertyChanged: (bindable, oldValue, newValue)
                        => ((Expander)bindable).SetContent(true));
@@ -45,7 +42,6 @@ namespace Xamarin.Forms
                public static readonly BindableProperty ForceUpdateSizeCommandProperty = BindableProperty.Create(nameof(ForceUpdateSizeCommand), typeof(ICommand), typeof(Expander), default(ICommand), BindingMode.OneWayToSource);
 
                DataTemplate _previousTemplate;
-               double _contentHeightRequest = -1;
                double _lastVisibleHeight = -1;
                double _previousWidth = -1;
                double _startHeight;
@@ -56,7 +52,7 @@ namespace Xamarin.Forms
 
                public Expander()
                {
-                       ExpanderLayout = new StackLayout { Spacing = Spacing };
+                       ExpanderLayout = new StackLayout { Spacing = 0 };
                        ForceUpdateSizeCommand = new Command(ForceUpdateSize);
                        InternalChildren.Add(ExpanderLayout);
                }
@@ -66,23 +62,30 @@ namespace Xamarin.Forms
                        if (isExperimentalFlagSet)
                                return;
 
-                       ExperimentalFlags.VerifyFlagEnabled(nameof(Markup), ExperimentalFlags.ExpanderExperimental, constructorHint, memberName);
+                       ExperimentalFlags.VerifyFlagEnabled(nameof(Expander), ExperimentalFlags.ExpanderExperimental, constructorHint, memberName);
 
                        isExperimentalFlagSet = true;
                }
 
                protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
                {
-                       VerifyExperimental();
+                       VerifyExperimental(nameof(Expander));
                        return base.OnMeasure(widthConstraint, heightConstraint);
                }
 
                StackLayout ExpanderLayout { get; }
 
-               public double Spacing
+               ContentView ContentHolder { get; set; }
+               
+               double ContentHeightRequest
                {
-                       get => (double)GetValue(SpacingProperty);
-                       set => SetValue(SpacingProperty, value);
+                       get
+                       {
+                               var heightRequest = Content.HeightRequest;
+                               if (heightRequest < 0 || !(Content is Layout layout))
+                                       return heightRequest;
+                               return heightRequest + layout.Padding.VerticalThickness;
+                       }
                }
 
                public View Header
@@ -182,60 +185,50 @@ namespace Xamarin.Forms
 
                void OnIsExpandedChanged(bool isBindingContextChanged = false)
                {
-                       if (Content == null || (!IsExpanded && !Content.IsVisible))
+                       if (ContentHolder == null || (!IsExpanded && !ContentHolder.IsVisible))
                        {
                                return;
                        }
 
-                       Content.SizeChanged -= OnContentSizeChanged;
-
-                       var isAnimationRunning = Content.AnimationIsRunning(ExpandAnimationName);
-                       Content.AbortAnimation(ExpandAnimationName);
+                       var isAnimationRunning = ContentHolder.AnimationIsRunning(ExpandAnimationName);
+                       ContentHolder.AbortAnimation(ExpandAnimationName);
 
-
-                       _startHeight = Content.IsVisible
-                               ? Max(Content.Height - (Content is Layout l ? l.Padding.Top + l.Padding.Bottom : 0), 0)
+                       _startHeight = ContentHolder.IsVisible
+                               ? Max(ContentHolder.Height, 0)
                                : 0;
 
                        if (IsExpanded)
                        {
-                               Content.IsVisible = true;
+                               ContentHolder.IsVisible = true;
                        }
 
-                       _endHeight = _contentHeightRequest >= 0
-                               ? _contentHeightRequest
+                       _endHeight = ContentHeightRequest >= 0
+                               ? ContentHeightRequest
                                : _lastVisibleHeight;
 
-                       var shouldInvokeAnimation = true;
-
                        if (IsExpanded)
                        {
                                if (_endHeight <= 0)
                                {
-                                       shouldInvokeAnimation = false;
-                                       Content.SizeChanged += OnContentSizeChanged;
-                                       Content.HeightRequest = -1;
+                                       ContentHolder.HeightRequest = -1;
+                                       _endHeight = ContentHolder.Measure(Width, double.PositiveInfinity).Request.Height;
+                                       ContentHolder.HeightRequest = 0;
                                }
                        }
                        else
                        {
-                               _lastVisibleHeight = _startHeight = _contentHeightRequest >= 0
-                                               ? _contentHeightRequest
+                               _lastVisibleHeight = _startHeight = ContentHeightRequest >= 0
+                                               ? ContentHeightRequest
                                                : !isAnimationRunning
-                                                       ? Content.Height - (Content is Layout layout
-                                                               ? layout.Padding.Top + layout.Padding.Bottom
-                                                               : 0)
+                                                       ? ContentHolder.Height
                                                        : _lastVisibleHeight;
                                _endHeight = 0;
                        }
 
                        _shouldIgnoreAnimation = isBindingContextChanged || Height < 0;
 
-                       if (shouldInvokeAnimation)
-                       {
                                InvokeAnimation();
                        }
-               }
 
                void SetHeader(View oldHeader)
                {
@@ -256,7 +249,7 @@ namespace Xamarin.Forms
                                                {
                                                        if (parent is Expander ancestorExpander)
                                                        {
-                                                               ancestorExpander.Content.HeightRequest = -1;
+                                                               ancestorExpander.ContentHolder.HeightRequest = -1;
                                                        }
                                                        parent = parent.Parent;
                                                }
@@ -279,23 +272,24 @@ namespace Xamarin.Forms
                        OnIsExpandedChanged(isBindingContextChanged);
                }
 
-               void SetContent(View oldContent, View newContent)
+               void SetContent()
                {
-                       if (oldContent != null)
+                       if (ContentHolder != null)
                        {
-                               oldContent.SizeChanged -= OnContentSizeChanged;
-                               ExpanderLayout.Children.Remove(oldContent);
+                               ContentHolder.AbortAnimation(ExpandAnimationName);
+                               ExpanderLayout.Children.Remove(ContentHolder);
+                               ContentHolder = null;
                        }
-                       if (newContent != null)
+                       if (Content != null)
                        {
-                               if (newContent is Layout layout)
+                               ContentHolder = new ContentView
                                {
-                                       layout.IsClippedToBounds = true;
-                               }
-                               _contentHeightRequest = newContent.HeightRequest;
-                               newContent.HeightRequest = 0;
-                               newContent.IsVisible = false;
-                               ExpanderLayout.Children.Add(newContent);
+                                       IsClippedToBounds = true,
+                                       IsVisible = false,
+                                       HeightRequest = 0,
+                                       Content = Content
+                               };
+                               ExpanderLayout.Children.Add(ContentHolder);
                        }
 
                        if (!_shouldIgnoreContentSetting)
@@ -319,18 +313,6 @@ namespace Xamarin.Forms
                        return (View)template?.CreateContent();
                }
 
-               void OnContentSizeChanged(object sender, EventArgs e)
-               {
-                       if (Content.Height <= 0)
-                       {
-                               return;
-                       }
-                       Content.SizeChanged -= OnContentSizeChanged;
-                       Content.HeightRequest = 0;
-                       _endHeight = Content.Height;
-                       InvokeAnimation();
-               }
-
                void InvokeAnimation()
                {
                        State = IsExpanded ? ExpanderState.Expanding : ExpanderState.Collapsing;
@@ -338,8 +320,8 @@ namespace Xamarin.Forms
                        if (_shouldIgnoreAnimation)
                        {
                                State = IsExpanded ? ExpanderState.Expanded : ExpanderState.Collapsed;
-                               Content.HeightRequest = _endHeight;
-                               Content.IsVisible = IsExpanded;
+                               ContentHolder.HeightRequest = _endHeight;
+                               ContentHolder.IsVisible = IsExpanded;
                                return;
                        }
 
@@ -356,8 +338,8 @@ namespace Xamarin.Forms
                                length = Max((uint)(length * (Abs(_endHeight - _startHeight) / _lastVisibleHeight)), 1);
                        }
 
-                       new Animation(v => Content.HeightRequest = v, _startHeight, _endHeight)
-                               .Commit(Content, ExpandAnimationName, 16, length, easing, (value, isInterrupted) =>
+                       new Animation(v => ContentHolder.HeightRequest = v, _startHeight, _endHeight)
+                               .Commit(ContentHolder, ExpandAnimationName, 16, length, easing, (value, isInterrupted) =>
                                {
                                        if (isInterrupted)
                                        {
@@ -365,7 +347,7 @@ namespace Xamarin.Forms
                                        }
                                        if (!IsExpanded)
                                        {
-                                               Content.IsVisible = false;
+                                               ContentHolder.IsVisible = false;
                                                State = ExpanderState.Collapsed;
                                                return;
                                        }
index e66c812..e4c1fe8 100644 (file)
@@ -18,6 +18,7 @@ namespace Xamarin.Forms
                internal const string MarkupExperimental = "Markup_Experimental";
                internal const string AppThemeExperimental = "AppTheme_Experimental";
                internal const string ExpanderExperimental = "Expander_Experimental";
+               internal const string RadioButtonExperimental = "RadioButton_Experimental";
 
                [EditorBrowsable(EditorBrowsableState.Never)]
                public static void VerifyFlagEnabled(
@@ -26,6 +27,11 @@ namespace Xamarin.Forms
                        string constructorHint = null,
                        [CallerMemberName] string memberName = "")
                {
+                       if (DesignMode.IsDesignModeEnabled)
+                       {
+                               return; 
+                       }
+
                        if (Device.Flags == null || !Device.Flags.Contains(flagName))
                        {
                                if (!String.IsNullOrEmpty(memberName))
index 98722d8..cf7d466 100644 (file)
@@ -2,7 +2,7 @@
 using System.Collections.Generic;
 using System.Linq;
 
-namespace Xamarin.Forms.Core
+namespace Xamarin.Forms
 {
        public class FontFile
        {
index b8f2b6a..b43b098 100644 (file)
@@ -2,6 +2,7 @@
 {
        public interface ISwipeViewController
        {
+               bool IsOpen { get; set; }
                void SendSwipeStarted(SwipeStartedEventArgs args);
                void SendSwipeChanging(SwipeChangingEventArgs args);
                void SendSwipeEnded(SwipeEndedEventArgs args);
index d8d2ec4..95b491a 100644 (file)
@@ -1,4 +1,5 @@
-using System.Collections;
+using System;
+using System.Collections;
 using System.Collections.Specialized;
 using Xamarin.Forms.Platform;
 
@@ -18,7 +19,7 @@ namespace Xamarin.Forms
                        => (((IndicatorView)bindable).IndicatorLayout as IndicatorStackLayout)?.ResetIndicatorCount((int)oldValue));
 
                public static readonly BindableProperty MaximumVisibleProperty = BindableProperty.Create(nameof(MaximumVisible), typeof(int), typeof(IndicatorView), int.MaxValue, propertyChanged: (bindable, oldValue, newValue)
-               => (((IndicatorView) bindable).IndicatorLayout as IndicatorStackLayout)?.ResetIndicators());
+               => (((IndicatorView)bindable).IndicatorLayout as IndicatorStackLayout)?.ResetIndicators());
 
                public static readonly BindableProperty IndicatorTemplateProperty = BindableProperty.Create(nameof(IndicatorTemplate), typeof(DataTemplate), typeof(IndicatorView), default(DataTemplate), propertyChanging: (bindable, oldValue, newValue)
                        => UpdateIndicatorLayout((IndicatorView)bindable, newValue));
index 302303e..23bdbd8 100644 (file)
@@ -2,7 +2,6 @@
 using System.Collections;
 using System.Collections.Generic;
 using System.Text;
-using Xamarin.Forms.PlatformConfiguration.TizenSpecific;
 
 namespace Xamarin.Forms.Internals
 {
@@ -46,23 +45,25 @@ namespace Xamarin.Forms.Internals
 
                internal static void PropagateFlowDirection(Element target, Element source)
                {
-                       IFlowDirectionController targetController = target as IFlowDirectionController;
-                       if (targetController == null)
+                       IFlowDirectionController controller = target as IFlowDirectionController;
+                       if (controller == null)
                                return;
 
-                       if (targetController.EffectiveFlowDirection.IsImplicit())
-                       {
                                var sourceController = source as IFlowDirectionController;
                                if (sourceController == null)
                                        return;
 
+                       if (controller.EffectiveFlowDirection.IsImplicit())
+                       {
                                var flowDirection = sourceController.EffectiveFlowDirection.ToFlowDirection();
 
-                               if (flowDirection != targetController.EffectiveFlowDirection.ToFlowDirection())
+                               if (flowDirection != controller.EffectiveFlowDirection.ToFlowDirection())
                                {
-                                       targetController.EffectiveFlowDirection = flowDirection.ToEffectiveFlowDirection();
+                                       controller.EffectiveFlowDirection = flowDirection.ToEffectiveFlowDirection();
                                }
                        }
+
+                       controller.EffectiveFlowDirection = controller.EffectiveFlowDirection;
                }
 
                internal static void SetFlowDirectionFromParent(Element child)
index 8b4877b..56c185c 100644 (file)
@@ -64,8 +64,7 @@ namespace Xamarin.Forms.Markup
                        { "Xamarin.Forms.UriImageSource", UriImageSource.UriProperty },
                        { "Xamarin.Forms.UriMediaSource", UriMediaSource.UriProperty },
                        { "Xamarin.Forms.UrlWebViewSource", UrlWebViewSource.UrlProperty },
-                       { "Xamarin.Forms.WebView", WebView.SourceProperty },
-                       { "Xamarin.Forms.AppThemeColor", AppThemeColor.DefaultProperty }
+                       { "Xamarin.Forms.WebView", WebView.SourceProperty }
                };
 
                static Dictionary<string, (BindableProperty, BindableProperty)> bindableObjectTypeDefaultCommandAndParameterProperties = new Dictionary<string, (BindableProperty, BindableProperty)>
index 4287390..49c3c04 100644 (file)
 
 namespace Xamarin.Forms
 {
-       public class OnAppTheme<T> : BindableObject
+       public class OnAppTheme<T> : BindingBase
        {
+               WeakReference<BindableObject> _weakTarget;
+               BindableProperty _targetProperty;
+               
                public OnAppTheme()
                {
-                       Application.Current.RequestedThemeChanged += RequestedThemeChanged;
+                       Application.Current.RequestedThemeChanged += ThemeChanged;
                }
 
-               public static readonly BindableProperty LightProperty = BindableProperty.Create(nameof(Light), typeof(T), typeof(OnAppTheme<T>), default(T), propertyChanged: (bo, __, ___) => UpdateActualValue(bo));
-
-               public T Light
+               void ThemeChanged(object sender, AppThemeChangedEventArgs e)
+               {
+                       Device.BeginInvokeOnMainThread(() => ApplyCore());
+               }
+               public new BindingMode Mode
                {
-                       get => (T)GetValue(LightProperty);
-                       set => SetValue(LightProperty, value);
+                       get => base.Mode;
+                       private set { }
+               }
+               internal override BindingBase Clone()
+               {
+                       return new OnAppTheme<T> { Light = Light, Dark = Dark, Default = Default };
                }
 
-               public static readonly BindableProperty DarkProperty = BindableProperty.Create(nameof(Dark), typeof(T), typeof(OnAppTheme<T>), default(T), propertyChanged: (bo, __, ___) => UpdateActualValue(bo));
+               internal override void Apply(bool fromTarget)
+               {
+                       base.Apply(fromTarget);
+                       ApplyCore();
+               }
 
-               public T Dark
+               internal override void Apply(object context, BindableObject bindObj, BindableProperty targetProperty, bool fromBindingContextChanged = false)
                {
-                       get => (T)GetValue(DarkProperty);
-                       set => SetValue(DarkProperty, value);
+                       _weakTarget = new WeakReference<BindableObject>(bindObj);
+                       _targetProperty = targetProperty;
+                       base.Apply(context, bindObj, targetProperty, fromBindingContextChanged);
+                       ApplyCore();
                }
+               void ApplyCore()
+               {
+                       if (_weakTarget == null || !_weakTarget.TryGetTarget(out var target))
+                               return;
 
-               public static readonly BindableProperty DefaultProperty = BindableProperty.Create(nameof(Default), typeof(T), typeof(OnAppTheme<T>), default(T), propertyChanged: (bo, __, ___) => UpdateActualValue(bo));
+                       target?.SetValueCore(_targetProperty, GetValue());
+               }
 
-               public T Default
+               T _light;
+               T _dark;
+               T _default;
+               bool _isLightSet;
+               bool _isDarkSet;
+               bool _isDefaultSet;
+
+               public T Light
                {
-                       get => (T)GetValue(DefaultProperty);
-                       set => SetValue(DefaultProperty, value);
+                       get => _light;
+                       set
+                       {
+                               _light = value;
+                               _isLightSet = true;
+                       }
                }
-
-               public static implicit operator T(OnAppTheme<T> onAppTheme)
+               public T Dark
                {
-                       switch (Application.Current?.RequestedTheme)
+                       get => _dark;
+                       set
                        {
-                               default:
-                               case OSAppTheme.Light:
-                                       return onAppTheme.IsSet(LightProperty) ? onAppTheme.Light : (onAppTheme.IsSet(DefaultProperty) ? onAppTheme.Default : default(T));
-                               case OSAppTheme.Dark:
-                                       return onAppTheme.IsSet(DarkProperty) ? onAppTheme.Dark : (onAppTheme.IsSet(DefaultProperty) ? onAppTheme.Default : default(T));
+                               _dark = value;
+                               _isDarkSet = true;
                        }
                }
-
-               private T _actualValue;
-               public T ActualValue
+               public T Default
                {
-                       get => _actualValue;
-                       private set
+                       get => _default;
+                       set
                        {
-                               _actualValue = value;
-                               OnPropertyChanged();
+                               _default = value;
+                               _isDefaultSet = true;
                        }
                }
 
-               static void UpdateActualValue(BindableObject bo)
+               public static implicit operator T(OnAppTheme<T> onAppTheme)
+               {
+                       return onAppTheme.GetValue();
+               }
+
+               public T Value => GetValue();
+
+               T GetValue()
                {
-                       var appThemeColor = bo as OnAppTheme<T>;
-                       switch (Application.Current?.RequestedTheme)
+                       switch (Application.Current.RequestedTheme)
                        {
                                default:
                                case OSAppTheme.Light:
-                                       appThemeColor.ActualValue = appThemeColor.IsSet(LightProperty) ? appThemeColor.Light : (appThemeColor.IsSet(DefaultProperty) ? appThemeColor.Default : default(T));
-                                       break;
+                                       return _isLightSet ? Light : (_isDefaultSet ? Default : default);
                                case OSAppTheme.Dark:
-                                       appThemeColor.ActualValue = appThemeColor.IsSet(DarkProperty) ? appThemeColor.Dark : (appThemeColor.IsSet(DefaultProperty) ? appThemeColor.Default : default(T));
-                                       break;
+                                       return _isDarkSet ? Dark : (_isDefaultSet ? Default : default);
                        }
                }
-
-               void RequestedThemeChanged(object sender, AppThemeChangedEventArgs e)
-               {
-                       UpdateActualValue(this);
-               }
        }
 }
\ No newline at end of file
index 14079d1..31c8d74 100644 (file)
@@ -1,5 +1,6 @@
 namespace Xamarin.Forms.PlatformConfiguration.TizenSpecific
 {
+       using System.ComponentModel;
        using FormsElement = Xamarin.Forms.Application;
 
        public static class Application
@@ -27,8 +28,7 @@
                        return config;
                }
 
-               public static readonly BindableProperty OverlayContentProperty
-                  = BindableProperty.CreateAttached("OverlayContent", typeof(View), typeof(FormsElement), default(View));
+               public static readonly BindableProperty OverlayContentProperty = BindableProperty.CreateAttached("OverlayContent", typeof(View), typeof(FormsElement), default(View));
 
                public static View GetOverlayContent(BindableObject application)
                {
                        SetOverlayContent(config.Element, value);
                        return config;
                }
+
+               public static readonly BindablePropertyKey ActiveBezelInteractionElementPropertyKey = BindableProperty.CreateAttachedReadOnly("ActiveBezelInteractionElement", typeof(Element), typeof(FormsElement), default(Element));
+
+               public static Element GetActiveBezelInteractionElement(BindableObject application)
+               {
+                       return (Element)application.GetValue(ActiveBezelInteractionElementPropertyKey.BindableProperty);
+               }
+
+               [EditorBrowsable(EditorBrowsableState.Never)]
+               public static void SetActiveBezelInteractionElement(BindableObject application, Element value)
+               {
+                       application.SetValue(ActiveBezelInteractionElementPropertyKey, value);
+               }
+
+               public static Element GetActiveBezelInteractionElement(this IPlatformElementConfiguration<Tizen, FormsElement> config)
+               {
+                       return GetActiveBezelInteractionElement(config.Element);
+               }
+
+               [EditorBrowsable(EditorBrowsableState.Never)]
+               public static IPlatformElementConfiguration<Tizen, FormsElement> SetActiveBezelInteractionElement(this IPlatformElementConfiguration<Tizen, FormsElement> config, Element value)
+               {
+                       SetActiveBezelInteractionElement(config.Element, value);
+                       return config;
+               }
        }
 }
index 1b663bd..93f42d6 100644 (file)
@@ -14,6 +14,8 @@ namespace Xamarin.Forms.PlatformConfiguration.TizenSpecific
                public const string CheckBox = "default";
                public const string Toggle = "toggle";
                public const string Favorite = "favorite";
+               public const string OnOff = "on&off";
+               public const string Small = "small";
        }
 
        public static class ProgressBarStyle
diff --git a/src/XSF/Xamarin.Forms.Core/PlatformConfiguration/TizenSpecific/Switch.cs b/src/XSF/Xamarin.Forms.Core/PlatformConfiguration/TizenSpecific/Switch.cs
new file mode 100644 (file)
index 0000000..7635ac9
--- /dev/null
@@ -0,0 +1,31 @@
+
+namespace Xamarin.Forms.PlatformConfiguration.TizenSpecific
+{
+       using FormsElement = Xamarin.Forms.Switch;
+
+       public static class Switch
+       {
+               public static readonly BindableProperty ColorProperty = BindableProperty.Create(nameof(Color), typeof(Color), typeof(FormsElement), Color.Default);
+       
+               public static Color GetColor(BindableObject element)
+               {
+                       return (Color)element.GetValue(ColorProperty);
+               }
+
+               public static void SetColor(BindableObject element, Color color)
+               {
+                       element.SetValue(ColorProperty, color);
+               }
+
+               public static Color GetColor(this IPlatformElementConfiguration<Tizen, FormsElement> config)
+               {
+                       return GetColor(config.Element);
+               }
+
+               public static IPlatformElementConfiguration<Tizen, FormsElement> SetColor(this IPlatformElementConfiguration<Tizen, FormsElement> config, Color color)
+               {
+                       SetColor(config.Element, color);
+                       return config;
+               }
+       }
+}
index 76e050a..b286eab 100644 (file)
@@ -1,6 +1,7 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
+using System.Runtime.CompilerServices;
 using Xamarin.Forms.Platform;
 
 namespace Xamarin.Forms
@@ -50,6 +51,24 @@ namespace Xamarin.Forms
                        _platformConfigurationRegistry = new Lazy<PlatformConfigurationRegistry<RadioButton>>(() => new PlatformConfigurationRegistry<RadioButton>(this));
                }
 
+
+               static bool isExperimentalFlagSet = false;
+               internal static void VerifyExperimental([CallerMemberName] string memberName = "", string constructorHint = null)
+               {
+                       if (isExperimentalFlagSet)
+                               return;
+
+                       ExperimentalFlags.VerifyFlagEnabled(nameof(RadioButton), ExperimentalFlags.RadioButtonExperimental, constructorHint, memberName);
+
+                       isExperimentalFlagSet = true;
+               }
+
+               protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
+               {
+                       VerifyExperimental(nameof(RadioButton));
+                       return base.OnMeasure(widthConstraint, heightConstraint);
+               }
+
                public new IPlatformElementConfiguration<T, RadioButton> On<T>() where T : IConfigPlatform
                {
                        return _platformConfigurationRegistry.Value.On<T>();
index 76cd873..ae486f7 100644 (file)
@@ -259,10 +259,10 @@ namespace Xamarin.Forms
                                OnPropertyChanged(VisualElement.FlowDirectionProperty.PropertyName);
                        }
                }
+
                bool IFlowDirectionController.ApplyEffectiveFlowDirectionToChildContainer => true;
                double IFlowDirectionController.Width => (Parent as VisualElement)?.Width ?? 0;
 
-
                internal virtual void ApplyQueryAttributes(IDictionary<string, string> query)
                {
                }
@@ -275,7 +275,7 @@ namespace Xamarin.Forms
                                DefaultFlyoutItemLayoutStyle,
                                FlyoutItem.LabelStyle,
                                FlyoutItem.ImageStyle,
-                               FlyoutItem.GridStyle };
+                               FlyoutItem.LayoutStyle };
 
                        if (source?.Classes != null)
                                foreach (var styleClass in source.Classes)
@@ -320,6 +320,7 @@ namespace Xamarin.Forms
                                        Class = DefaultFlyoutItemLayoutStyle,
                                };
 
+                               
                                var groups = new VisualStateGroupList();
 
                                var commonGroup = new VisualStateGroup();
@@ -383,11 +384,15 @@ namespace Xamarin.Forms
                                        defaultImageClass.Setters.Add(new Setter { Property = Image.MarginProperty, Value = new Thickness(12, 0, 12, 0) });
                                }
 
-                               image.SetBinding(Image.SourceProperty, iconBinding);
+                               Binding imageBinding = new Binding(iconBinding);
+                               defaultImageClass.Setters.Add(new Setter { Property = Image.SourceProperty, Value = imageBinding });
+
                                grid.Children.Add(image);
 
                                var label = new Label();
-                               label.SetBinding(Label.TextProperty, textBinding);
+                               Binding labelBinding = new Binding(textBinding);
+                               defaultLabelClass.Setters.Add(new Setter { Property = Label.TextProperty, Value = labelBinding });
+
                                grid.Children.Add(label, 1, 0);
 
                                if (Device.RuntimePlatform == Device.Android)
@@ -408,6 +413,12 @@ namespace Xamarin.Forms
                                        defaultLabelClass.Setters.Add(new Setter { Property = Label.HorizontalTextAlignmentProperty, Value = TextAlignment.Start });
                                }
 
+                               INameScope nameScope = new NameScope();
+                               NameScope.SetNameScope(grid, nameScope);
+                               nameScope.RegisterName("FlyoutItemLayout", grid);
+                               nameScope.RegisterName("FlyoutItemImage", image);
+                               nameScope.RegisterName("FlyoutItemLabel", label);
+
                                UpdateFlyoutItemStyles(grid, styleSelectable);
                                grid.Resources = new ResourceDictionary() { defaultGridClass, defaultLabelClass, defaultImageClass };
                                return grid;
index 41fbfd5..3574251 100644 (file)
@@ -8,6 +8,7 @@ using System.Runtime.CompilerServices;
 using System.Text;
 using System.Threading.Tasks;
 using Xamarin.Forms.Internals;
+using Xamarin.Forms.StyleSheets;
 
 namespace Xamarin.Forms
 {
@@ -58,39 +59,13 @@ namespace Xamarin.Forms
                        BindableProperty.CreateAttached("TitleView", typeof(View), typeof(Shell), null, propertyChanged: OnTitleViewChanged);
 
                public static readonly BindableProperty MenuItemTemplateProperty =
-                       BindableProperty.CreateAttached(nameof(MenuItemTemplate), typeof(DataTemplate), typeof(Shell), null, BindingMode.OneTime, defaultValueCreator: OnMenuItemTemplateCreate);
+                       BindableProperty.CreateAttached(nameof(MenuItemTemplate), typeof(DataTemplate), typeof(Shell), null, BindingMode.OneTime);
 
                public static DataTemplate GetMenuItemTemplate(BindableObject obj) => (DataTemplate)obj.GetValue(MenuItemTemplateProperty);
                public static void SetMenuItemTemplate(BindableObject obj, DataTemplate menuItemTemplate) => obj.SetValue(MenuItemTemplateProperty, menuItemTemplate);
 
                public static readonly BindableProperty ItemTemplateProperty =
-                       BindableProperty.CreateAttached(nameof(ItemTemplate), typeof(DataTemplate), typeof(Shell), null, BindingMode.OneTime, defaultValueCreator: OnItemTemplateCreator);
-
-               static object OnItemTemplateCreator(BindableObject bindable)
-               {
-                       return OnFlyoutItemTemplateCreate(bindable, "Title", "FlyoutIcon");
-               }
-
-               static object OnMenuItemTemplateCreate(BindableObject bindable)
-               {
-                       return OnFlyoutItemTemplateCreate(bindable, "Text", "Icon");
-               }
-
-               static object OnFlyoutItemTemplateCreate(BindableObject bindable, string textBinding, string iconBinding)
-               {
-                       if (bindable is BaseShellItem baseShellItem)
-                               return BaseShellItem.CreateDefaultFlyoutItemCell(baseShellItem, textBinding, iconBinding);
-
-                       if (bindable is MenuItem mi)
-                       {
-                               if (mi.Parent is BaseShellItem bsiMi)
-                                       return BaseShellItem.CreateDefaultFlyoutItemCell(bsiMi, textBinding, iconBinding);
-                               else
-                                       return null;
-                       }
-
-                       return BaseShellItem.CreateDefaultFlyoutItemCell(bindable as StyleSheets.IStyleSelectable, textBinding, iconBinding);
-               }
+                       BindableProperty.CreateAttached(nameof(ItemTemplate), typeof(DataTemplate), typeof(Shell), null, BindingMode.OneTime);
 
                public static DataTemplate GetItemTemplate(BindableObject obj) => (DataTemplate)obj.GetValue(ItemTemplateProperty);
                public static void SetItemTemplate(BindableObject obj, DataTemplate itemTemplate) => obj.SetValue(ItemTemplateProperty, itemTemplate);
@@ -229,6 +204,9 @@ namespace Xamarin.Forms
                DataTemplate IShellController.GetFlyoutItemDataTemplate(BindableObject bo)
                {
                        BindableProperty bp = null;
+                       string textBinding; 
+                       string iconBinding;
+                       IStyleSelectable styleClassSource = null;
 
                        if (bo is IMenuItemController)
                        {
@@ -238,18 +216,36 @@ namespace Xamarin.Forms
                                        bo = mi.Parent;
                                else if (bo is MenuShellItem msi && msi.MenuItem != null && msi.MenuItem.IsSet(bp))
                                        bo = msi.MenuItem;
+
+                               if (bo is MenuItem myStyle)
+                                       styleClassSource = myStyle;
+                               else if (bo is MenuShellItem msiStyle)
+                                       styleClassSource = msiStyle.MenuItem;
+
+                               textBinding = "Text";
+                               iconBinding = "Icon";
                        }
                        else
                        {
+                               styleClassSource = bo as IStyleSelectable;
                                bp = ItemTemplateProperty;
+                               textBinding = "Title";
+                               iconBinding = "FlyoutIcon";
                        }
 
                        if (bo.IsSet(bp))
+                       {
                                return (DataTemplate)bo.GetValue(bp);
+                       }
 
+                       if(IsSet(bp))
+                       {
                        return (DataTemplate)GetValue(bp);
                }
 
+                       return BaseShellItem.CreateDefaultFlyoutItemCell(styleClassSource, textBinding, iconBinding);
+               }
+
                event EventHandler IShellController.StructureChanged
                {
                        add { _structureChanged += value; }
@@ -428,7 +424,8 @@ namespace Xamarin.Forms
 
                        ProcessNavigated(new ShellNavigatedEventArgs(oldState, CurrentState, source));
                }
-               ReadOnlyCollection<ShellItem> IShellController.GetItems() => ((ShellItemCollection)Items).VisibleItems;
+               ReadOnlyCollection<ShellItem> IShellController.GetItems() =>
+                       new ReadOnlyCollection<ShellItem>(((ShellItemCollection)Items).VisibleItems.ToList());
 
                event NotifyCollectionChangedEventHandler IShellController.ItemsCollectionChanged
                {
@@ -1055,6 +1052,9 @@ namespace Xamarin.Forms
                        if (oldValue is ShellItem oldShellItem)
                                oldShellItem.SendDisappearing();
 
+                       if (newValue == null)
+                               return;
+
                        if (newValue is ShellItem newShellItem)
                                newShellItem.SendAppearing();
 
index 32143a4..9258619 100644 (file)
@@ -165,9 +165,17 @@ namespace Xamarin.Forms
                        get => _contentCache;
                        set
                        {
+                               if (_contentCache == value)
+                                       return;
+
+                               var oldCache = _contentCache;
                                _contentCache = value;
+                               if(oldCache != null)
+                                       OnChildRemoved(oldCache);
+
                                if (value != null && value.Parent != this)
                                {
+                                       _logicalChildren.Add(value);
                                        OnChildAdded(value);
                                }
 
@@ -201,7 +209,6 @@ namespace Xamarin.Forms
                                // deparent old item
                                if (oldValue is Page oldElement)
                                {
-                                       shellContent.OnChildRemoved(oldElement);
                                        shellContent.ContentCache = null;
                                }
 
@@ -209,7 +216,6 @@ namespace Xamarin.Forms
                                shellContent._logicalChildren.Clear();
                                if (newValue is Page newElement)
                                {
-                                       shellContent._logicalChildren.Add((Element)newValue);
                                        shellContent.ContentCache = newElement;
                                }
                                else if (newValue != null)
index c8bcb20..46adc74 100644 (file)
@@ -10,21 +10,50 @@ namespace Xamarin.Forms
        internal sealed class ShellContentCollection : IList<ShellContent>, INotifyCollectionChanged
        {
                public event NotifyCollectionChangedEventHandler VisibleItemsChanged;
+               public event NotifyCollectionChangedEventHandler VisibleItemsChangedInternal;
+               public ReadOnlyCollection<ShellContent> VisibleItems { get; }
+
                ObservableCollection<ShellContent> _inner = new ObservableCollection<ShellContent>();
                ObservableCollection<ShellContent> _visibleContents = new ObservableCollection<ShellContent>();
-
-               public ReadOnlyCollection<ShellContent> VisibleItems { get; }
+               bool _pauseCollectionChanged;
+               List<NotifyCollectionChangedEventArgs> _notifyCollectionChangedEventArgs;
 
                public ShellContentCollection()
                {
+                       _notifyCollectionChangedEventArgs = new List<NotifyCollectionChangedEventArgs>();
                        _inner.CollectionChanged += InnerCollectionChanged;
                        VisibleItems = new ReadOnlyCollection<ShellContent>(_visibleContents);
                        _visibleContents.CollectionChanged += (_, args) =>
                        {
-                               VisibleItemsChanged?.Invoke(VisibleItems, args);
+                               if(_pauseCollectionChanged)
+                               {
+                                       _notifyCollectionChangedEventArgs.Add(args);
+                                       return;
+                               }
+
+                               OnVisibleItemsChanged(args);
                        };
                }
 
+               void OnVisibleItemsChanged(NotifyCollectionChangedEventArgs args)
+               {
+                       VisibleItemsChangedInternal?.Invoke(VisibleItems, args);
+                               VisibleItemsChanged?.Invoke(VisibleItems, args);
+               }
+
+               void PauseCollectionChanged() => _pauseCollectionChanged = true;
+
+               void ResumeCollectionChanged()
+               {
+                       _pauseCollectionChanged = false;
+
+                       var pendingEvents = _notifyCollectionChangedEventArgs.ToList();
+                       _notifyCollectionChangedEventArgs.Clear();
+
+                       foreach(var args in pendingEvents)
+                               OnVisibleItemsChanged(args);
+               }
+
                void InnerCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
                {
                        if (e.NewItems != null)
@@ -67,15 +96,24 @@ namespace Xamarin.Forms
                        if (shellContent is IShellContentController controller)
                        {
                                // Assume incoming page will be visible
-                               if (controller.Page == null)
+                               if (controller.Page == null || controller.Page.IsVisible)
                                {
-                                       if (!_visibleContents.Contains(shellContent))
-                                               _visibleContents.Add(shellContent);
+                                       if (_visibleContents.Contains(shellContent))
+                                               return;
+
+                                       int visibleIndex = 0;
+                                       for (var i = 0; i < _inner.Count; i++)
+                                       {
+                                               var item = _inner[i];
+
+                                               if (item == shellContent)
+                                               {
+                                                       _visibleContents.Insert(visibleIndex, shellContent);
+                                                       break;
+                                               }
+
+                                               visibleIndex++;
                                }
-                               else if(controller.Page.IsVisible)
-                               {
-                                       if (!_visibleContents.Contains(shellContent))
-                                               _visibleContents.Add(shellContent);
                                }
                                else
                                {
@@ -105,7 +143,16 @@ namespace Xamarin.Forms
                public void Clear()
                {
                        var list = _inner.ToList();
+                       try
+                       {
+                               PauseCollectionChanged();
                        Removing(_inner);
+                       }
+                       finally
+                       {
+                               ResumeCollectionChanged();
+                       }
+
                        _inner.Clear();
 
                        CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, list));
index 6c8c55e..8d9a735 100644 (file)
@@ -6,6 +6,7 @@ using System.Threading.Tasks;
 using Xamarin.Forms.Internals;
 using System.ComponentModel;
 using System.Runtime.CompilerServices;
+using System.Linq;
 
 namespace Xamarin.Forms
 {
@@ -14,7 +15,7 @@ namespace Xamarin.Forms
        {
                public const string LabelStyle = "FlyoutItemLabelStyle";
                public const string ImageStyle = "FlyoutItemImageStyle";
-               public const string GridStyle = "FlyoutItemGridStyle";
+               public const string LayoutStyle = "FlyoutItemLayoutStyle";
 
                public FlyoutItem()
                {
@@ -83,7 +84,9 @@ namespace Xamarin.Forms
                        return accept;
                }
 
-               ReadOnlyCollection<ShellSection> IShellItemController.GetItems() => ((ShellSectionCollection)Items).VisibleItems;
+               // we want the list returned from here to remain point in time accurate
+               ReadOnlyCollection<ShellSection> IShellItemController.GetItems() => 
+                       new ReadOnlyCollection<ShellSection>(((ShellSectionCollection)Items).VisibleItems.ToList());
 
                event NotifyCollectionChangedEventHandler IShellItemController.ItemsCollectionChanged
                {
@@ -113,7 +116,28 @@ namespace Xamarin.Forms
 
                public ShellItem()
                {
-                       ShellItemController.ItemsCollectionChanged += (_, __) => SendStructureChanged();
+                       ShellItemController.ItemsCollectionChanged += (_, args) =>
+                       {
+
+                               if (args.OldItems != null)
+                               {
+                               foreach (Element item in args.OldItems)
+                               {
+                                       OnVisibleChildRemoved(item);
+                               }
+                               }
+
+                               if(args.NewItems != null)
+                               {
+                                       foreach (Element item in args.NewItems)
+                                       {
+                                               OnVisibleChildAdded(item);
+                                       }
+                               }
+
+                               SendStructureChanged();
+                       };
+
                        (Items as INotifyCollectionChanged).CollectionChanged += ItemsCollectionChanged;
 
                        _platformConfigurationRegistry = new Lazy<PlatformConfigurationRegistry<ShellItem>>(() => new PlatformConfigurationRegistry<ShellItem>(this));
@@ -127,11 +151,13 @@ namespace Xamarin.Forms
 
                public IList<ShellSection> Items => (IList<ShellSection>)GetValue(ItemsProperty);
 
+               internal bool IsVisibleItem => Parent is Shell shell && shell?.CurrentItem == this;
+
                internal override ReadOnlyCollection<Element> LogicalChildrenInternal => _logicalChildren ?? (_logicalChildren = new ReadOnlyCollection<Element>(_children));
 
                internal void SendStructureChanged()
                {
-                       if (Parent is Shell shell)
+                       if (Parent is Shell shell && IsVisibleItem)
                        {
                                shell.SendStructureChanged();
                        }
@@ -139,6 +165,11 @@ namespace Xamarin.Forms
 
                internal static ShellItem CreateFromShellSection(ShellSection shellSection)
                {
+                       if (shellSection.Parent != null)
+                       {
+                               return (ShellItem)shellSection.Parent;
+                       }
+
                        ShellItem result = null;
 
                        if (shellSection is Tab)
@@ -157,9 +188,6 @@ namespace Xamarin.Forms
                        return result;
                }
 
-#if DEBUG
-               [Obsolete("Please dont use this in core code... its SUPER hard to debug when this happens", true)]
-#endif
                public static implicit operator ShellItem(ShellSection shellSection)
                {
                        return CreateFromShellSection(shellSection);
@@ -180,19 +208,10 @@ namespace Xamarin.Forms
                        return result;
                }
 
-#if DEBUG
-               [Obsolete("Please dont use this in core code... its SUPER hard to debug when this happens", true)]
-#endif
                public static implicit operator ShellItem(ShellContent shellContent) => (ShellSection)shellContent;
 
-#if DEBUG
-               [Obsolete("Please dont use this in core code... its SUPER hard to debug when this happens", true)]
-#endif
                public static implicit operator ShellItem(TemplatedPage page) => (ShellSection)(ShellContent)page;
 
-#if DEBUG
-               [Obsolete("Please dont use this in core code... its SUPER hard to debug when this happens", true)]
-#endif
                public static implicit operator ShellItem(MenuItem menuItem) => new MenuShellItem(menuItem);
 
                public IPlatformElementConfiguration<T, ShellItem> On<T>() where T : IConfigPlatform
@@ -203,13 +222,23 @@ namespace Xamarin.Forms
                protected override void OnChildAdded(Element child)
                {
                        base.OnChildAdded(child);
-                       if (CurrentItem == null)
-                               SetValueFromRenderer(CurrentItemProperty, child);
+                       OnVisibleChildAdded(child);
                }
 
                protected override void OnChildRemoved(Element child)
                {
                        base.OnChildRemoved(child);
+                       OnVisibleChildRemoved(child);
+               }
+
+               void OnVisibleChildAdded(Element child)
+               {
+                       if (CurrentItem == null && ((IShellItemController)this).GetItems().Contains(child))
+                               SetValueFromRenderer(CurrentItemProperty, child);
+               }
+
+               void OnVisibleChildRemoved(Element child)
+               {
                        if (CurrentItem == child)
                        {
                                if (ShellItemController.GetItems().Count == 0)
@@ -225,18 +254,24 @@ namespace Xamarin.Forms
                                oldShellItem.SendDisappearing();
 
                        var shellItem = (ShellItem)bindable;
-                       if (shellItem.Parent is Shell parentShell && parentShell.CurrentItem == shellItem)
+
+                       if (newValue == null)
+                               return;
+
+                       if (shellItem.Parent is Shell)
                        {
                                if (newValue is BaseShellItem newShellItem)
                                        newShellItem.SendAppearing();
                        }
 
-                       if (shellItem.Parent is IShellController shell)
+                       if (shellItem.Parent is IShellController shell && shellItem.IsVisibleItem)
                        {
                                shell.UpdateCurrentState(ShellNavigationSource.ShellSectionChanged);
                        }
 
                        shellItem.SendStructureChanged();
+
+                       if(shellItem.IsVisibleItem)
                        ((IShellController)shellItem?.Parent)?.AppearanceChanged(shellItem, false);
                }
 
index f117c29..5ec63f8 100644 (file)
@@ -179,7 +179,9 @@ namespace Xamarin.Forms
                        SendUpdateCurrentState(ShellNavigationSource.Pop);
                }
 
-               ReadOnlyCollection<ShellContent> IShellSectionController.GetItems() => ((ShellContentCollection)Items).VisibleItems;
+               // we want the list returned from here to remain point in time accurate
+               ReadOnlyCollection<ShellContent> IShellSectionController.GetItems() 
+                       => new ReadOnlyCollection<ShellContent>(((ShellContentCollection)Items).VisibleItems.ToList());
 
                [Obsolete]
                [EditorBrowsable(EditorBrowsableState.Never)]
@@ -237,6 +239,26 @@ namespace Xamarin.Forms
                public ShellSection()
                {
                        (Items as INotifyCollectionChanged).CollectionChanged += ItemsCollectionChanged;
+
+                       ((ShellContentCollection)Items).VisibleItemsChangedInternal += (_, args) =>
+                       {
+                               if (args.OldItems != null)
+                               {
+                               foreach(Element item in args.OldItems)
+                               {
+                                       OnVisibleChildRemoved(item);
+                               }
+                               }
+
+                               if(args.NewItems != null)
+                               {
+                                       foreach (Element item in args.NewItems)
+                                       {
+                                               OnVisibleChildAdded(item);
+                                       }
+                               }
+                       };
+
                        Navigation = new NavigationImpl(this);
                }
 
@@ -272,6 +294,11 @@ namespace Xamarin.Forms
 
                internal static ShellSection CreateFromShellContent(ShellContent shellContent)
                {
+                       if(shellContent.Parent != null)
+                       {
+                               return (ShellSection)shellContent.Parent;
+                       }
+
                        var shellSection = new ShellSection();
 
                        var contentRoute = shellContent.Route;
@@ -292,17 +319,11 @@ namespace Xamarin.Forms
                        return CreateFromShellContent((ShellContent)page);
                }
 
-#if DEBUG
-               [Obsolete("Please dont use this in core code... its SUPER hard to debug when this happens", true)]
-#endif
                public static implicit operator ShellSection(ShellContent shellContent)
                {
                        return CreateFromShellContent(shellContent);
                }
 
-#if DEBUG
-               [Obsolete("Please dont use this in core code... its SUPER hard to debug when this happens", true)]
-#endif
                public static implicit operator ShellSection(TemplatedPage page)
                {
                        return (ShellSection)(ShellContent)page;
@@ -470,7 +491,7 @@ namespace Xamarin.Forms
 
                internal void SendStructureChanged()
                {
-                       if (Parent?.Parent is Shell shell)
+                       if (Parent?.Parent is Shell shell && IsVisibleSection)
                        {
                                shell.SendStructureChanged();
                        }
@@ -503,6 +524,17 @@ namespace Xamarin.Forms
                protected override void OnChildAdded(Element child)
                {
                        base.OnChildAdded(child);
+                       OnVisibleChildAdded(child);
+               }
+
+               protected override void OnChildRemoved(Element child)
+               {
+                       base.OnChildRemoved(child);
+                       OnVisibleChildRemoved(child);
+               }
+
+               void OnVisibleChildAdded(Element child)
+               {
                        if (CurrentItem == null && ((IShellSectionController)this).GetItems().Contains(child))
                                SetValueFromRenderer(CurrentItemProperty, child);
 
@@ -510,22 +542,18 @@ namespace Xamarin.Forms
                                UpdateDisplayedPage();
                }
 
-               protected override void OnChildRemoved(Element child)
+               void OnVisibleChildRemoved(Element child)
                {
-                       base.OnChildRemoved(child);
                        if (CurrentItem == child)
                        {
-                               var items = ShellSectionController.GetItems();
-                               if (items.Count == 0)
+                               var contentItems = ShellSectionController.GetItems();
+                               if (contentItems.Count == 0)
+                               {
                                        ClearValue(CurrentItemProperty);
+                               }
                                else
                                {
-                                       // We want to delay invoke this because the renderer may handle this instead
-                                       Device.BeginInvokeOnMainThread(() =>
-                                       {
-                                               if (CurrentItem == null)
-                                                       SetValueFromRenderer(CurrentItemProperty, items[0]);
-                                       });
+                                       SetValueFromRenderer(CurrentItemProperty, contentItems[0]);
                                }
                        }
 
@@ -800,14 +828,19 @@ namespace Xamarin.Forms
                        if (oldValue is ShellContent oldShellItem)
                                oldShellItem.SendDisappearing();
 
+                       if (newValue == null)
+                               return;
+
                        shellSection.PresentedPageAppearing();
 
-                       if (shellSection.Parent?.Parent is IShellController shell)
+                       if (shellSection.Parent?.Parent is IShellController shell && shellSection.IsVisibleSection)
                        {
                                shell.UpdateCurrentState(ShellNavigationSource.ShellSectionChanged);
                        }
 
                        shellSection.SendStructureChanged();
+
+                       if(shellSection.IsVisibleSection)
                        ((IShellController)shellSection?.Parent?.Parent)?.AppearanceChanged(shellSection, false);
 
                        shellSection.UpdateDisplayedPage();
index 252e712..23bcb88 100644 (file)
@@ -42,9 +42,11 @@ namespace Xamarin.Forms
 
        public class SwipeEndedEventArgs : BaseSwipeEventArgs
        {
-               public SwipeEndedEventArgs(SwipeDirection swipeDirection) : base(swipeDirection)
+               public SwipeEndedEventArgs(SwipeDirection swipeDirection, bool isOpen) : base(swipeDirection)
                {
-
+                       IsOpen = isOpen;
                }
+
+               public bool IsOpen { get; set; }
        }
 }
\ No newline at end of file
index c5b4dff..377059a 100644 (file)
@@ -64,6 +64,8 @@ namespace Xamarin.Forms
                        set { SetValue(BottomItemsProperty, value); }
                }
 
+               bool ISwipeViewController.IsOpen { get; set; }
+
                static void OnSwipeItemsChanged(BindableObject bindable, object oldValue, object newValue)
                {
                        ((SwipeView)bindable).UpdateSwipeItemsParent((SwipeItems)newValue);
index 056a248..219784f 100644 (file)
@@ -810,7 +810,7 @@ namespace Xamarin.Forms.Internals
                                        oldItems = new List<TemplatedItemsList<TView, TItem>>(e.OldItems.Count);
                                        for (var i = 0; i < e.OldItems.Count; i++)
                                        {
-                                               int index = e.OldStartingIndex + i;
+                                               int index = e.OldStartingIndex;
                                                TemplatedItemsList<TView, TItem> til = _groupedItems[index];
                                                til.CollectionChanged -= OnInnerCollectionChanged;
                                                oldItems.Add(til);
index ddd9935..ac31e1b 100644 (file)
@@ -224,7 +224,6 @@ namespace Xamarin.Forms
                        ((VisualElement)bindable).TabStopDefaultValueCreator();
 
                IFlowDirectionController FlowController => this;
-               IPropertyPropagationController PropertyPropagationController => this;
 
                public FlowDirection FlowDirection
                {
@@ -238,13 +237,21 @@ namespace Xamarin.Forms
                        get { return _effectiveFlowDirection; }
                        set
                        {
+                               SetEffectiveFlowDirection(value, true);
+                       }
+               }
+
+               void SetEffectiveFlowDirection(EffectiveFlowDirection value, bool fireFlowDirectionPropertyChanged)
+               {
                                if (value == _effectiveFlowDirection)
                                        return;
 
                                _effectiveFlowDirection = value;
                                InvalidateMeasureInternal(InvalidationTrigger.Undefined);
+
+                       if (fireFlowDirectionPropertyChanged)
                                OnPropertyChanged(FlowDirectionProperty.PropertyName);
-                       }
+
                }
 
                EffectiveFlowDirection IVisualElementController.EffectiveFlowDirection => FlowController.EffectiveFlowDirection;
@@ -274,7 +281,7 @@ namespace Xamarin.Forms
 
                internal VisualElement()
                {
-                       if (Device.Flags?.IndexOf(ExperimentalFlags.AppThemeExperimental) > 0)
+                       if (Application.Current != null)
                                Application.Current.RequestedThemeChanged += (s, a) => OnRequestedThemeChanged(a.RequestedTheme);
                }
 
@@ -843,6 +850,9 @@ namespace Xamarin.Forms
 
                internal void InvalidateStateTriggers(bool attach)
                {
+                       if (!this.HasVisualStateGroups())
+                               return;
+
                        var groups = (IList<VisualStateGroup>)GetValue(VisualStateManager.VisualStateGroupsProperty);
 
                        if (groups.Count == 0)
index f8d0b55..fd827d4 100644 (file)
@@ -20,7 +20,7 @@ namespace Xamarin.Forms
                public static readonly BindableProperty VisualStateGroupsProperty =
                        BindableProperty.CreateAttached("VisualStateGroups", typeof(VisualStateGroupList), typeof(VisualElement),
                                defaultValue: null, propertyChanged: VisualStateGroupsPropertyChanged,
-                               defaultValueCreator: bindable => new VisualStateGroupList { VisualElement = (VisualElement)bindable });
+                               defaultValueCreator: bindable => new VisualStateGroupList(true) { VisualElement = (VisualElement)bindable });
 
                static void VisualStateGroupsPropertyChanged(BindableObject bindable, object oldValue, object newValue)
                {
@@ -50,7 +50,7 @@ namespace Xamarin.Forms
 
                public static bool GoToState(VisualElement visualElement, string name)
                {
-                       if (!visualElement.IsSet(VisualStateGroupsProperty))
+                       if (!visualElement.HasVisualStateGroups())
                        {
                                return false;
                        }
@@ -98,7 +98,13 @@ namespace Xamarin.Forms
 
                public static bool HasVisualStateGroups(this VisualElement element)
                {
-                       return element.IsSet(VisualStateGroupsProperty);
+                       if (!element.IsSet(VisualStateGroupsProperty))
+                               return false;
+
+                       if (GetVisualStateGroups(element) is VisualStateGroupList vsgl)
+                               return !vsgl.IsDefault;
+
+                       return true;
                }
 
                internal static void UpdateStateTriggers(VisualElement visualElement)
@@ -116,6 +122,7 @@ namespace Xamarin.Forms
        public class VisualStateGroupList : IList<VisualStateGroup>
        {
                readonly IList<VisualStateGroup> _internalList;
+               internal bool IsDefault { get; private set; }
 
                // Used to check for duplicate names; we keep it around because it's cheaper to create it once and clear it
                // than to create one every time we need to validate
@@ -167,8 +174,13 @@ namespace Xamarin.Forms
                        }
                }
 
-               public VisualStateGroupList()
+               public VisualStateGroupList() : this(false)
                {
+               }
+
+               public VisualStateGroupList(bool isDefault)
+               {
+                       IsDefault = isDefault;
                        _internalList = new WatchAddList<VisualStateGroup>(ValidateAndNotify);
                }
 
@@ -179,6 +191,9 @@ namespace Xamarin.Forms
 
                void ValidateAndNotify(IList<VisualStateGroup> groups)
                {
+                       if(groups.Count > 0)
+                               IsDefault = false;
+
                        Validate(groups);
                        OnStatesChanged();
                }
index a48178f..e01d13c 100644 (file)
@@ -38,7 +38,7 @@ namespace Xamarin.Forms
 
                public static readonly BindableProperty CanGoForwardProperty = CanGoForwardPropertyKey.BindableProperty;
 
-               public static readonly BindableProperty CookiesProperty = BindableProperty.Create(nameof(Cookies), typeof(CookieContainer), typeof(WebView), default(string));
+               public static readonly BindableProperty CookiesProperty = BindableProperty.Create(nameof(Cookies), typeof(CookieContainer), typeof(WebView), null);
 
                readonly Lazy<PlatformConfigurationRegistry<WebView>> _platformConfigurationRegistry;
 
index 9a5b878..d29dac7 100644 (file)
@@ -165,7 +165,7 @@ namespace Xamarin.Forms.Platform.Tizen
                        if(content != null)
                        {
                                var renderer = Platform.GetOrCreateRenderer(content);
-                       (renderer as LayoutRenderer)?.RegisterOnLayoutUpdated();
+                               (renderer as LayoutRenderer)?.RegisterOnLayoutUpdated();
                                nativeView = renderer?.NativeView;
                        }
                        Forms.BaseLayout.SetPartContent("elm.swallow.overlay", nativeView);
index 37f93c8..10bb59f 100644 (file)
@@ -41,19 +41,6 @@ namespace Xamarin.Forms.Platform.Tizen.Native
                        }
                }
 
-               public TimeSpan Time
-               {
-                       get
-                       {
-                               return DateTime.TimeOfDay;
-                       }
-                       set
-                       {
-                               DateTime -= DateTime.TimeOfDay;
-                               DateTime += value;
-                       }
-               }
-
                protected virtual void UpdateMode()
                {
                        if (Mode == DateTimePickerMode.Date)
index 4b91f5f..e69aad1 100644 (file)
@@ -7,6 +7,8 @@ namespace Xamarin.Forms.Platform.Tizen.Native
        public class DateTimePickerDialog : Dialog, IDateTimeDialog
        {
                EvasObject _parent;
+               DateTimePicker _picker;
+
                /// <summary>
                /// Creates a dialog window.
                /// </summary>
@@ -16,23 +18,62 @@ namespace Xamarin.Forms.Platform.Tizen.Native
                        Initialize();
                }
 
-               public DateTimePicker Picker { get; protected set; }
+               /// <summary>
+               /// Gets or sets picker style
+               /// </summary>
+               public DateTimePickerMode Mode
+               {
+                       get => _picker.Mode;
+                       set => _picker.Mode = value;
+               }
 
                /// <summary>
-               /// Occurs when the date of this dialog has changed.
+               /// Gets or sets the upper boundary of the DateTime field.
                /// </summary>
-               public event EventHandler<DateChangedEventArgs> DateTimeChanged;
+               public DateTime MaximumDateTime
+               {
+                       get => _picker.MaximumDateTime;
+                       set => _picker.MaximumDateTime = value;
+               }
 
-               protected virtual DateTimePicker CreatePicker(EvasObject parent)
+               /// <summary>
+               /// Gets or sets the lower boundary of the DateTime field.
+               /// </summary>
+               public DateTime MinimumDateTime
+               {
+                       get => _picker.MinimumDateTime;
+                       set => _picker.MinimumDateTime = value;
+               }
+
+               /// <summary>
+               /// Gets or sets the current value of the DateTime field.
+               /// </summary>
+               public DateTime DateTime
                {
-                       return new DateTimePicker(parent);
+                       get => _picker.DateTime;
+                       set => _picker.DateTime = value;
                }
 
+               /// <summary>
+               /// Occurs when the date of this dialog has changed.
+               /// </summary>
+               public event EventHandler<DateChangedEventArgs> DateTimeChanged;
+
+               /// <summary>
+               /// Occurs when the picker dialog has opened.
+               /// </summary>
+               public event EventHandler PickerOpened;
+
+               /// <summary>
+               /// Occurs when the picker dialog has closed.
+               /// </summary>
+               public event EventHandler PickerClosed;
+
                void Initialize()
                {
-                       Picker = CreatePicker(_parent);
-                       Picker.Show();
-                       Content = Picker;
+                       _picker = new DateTimePicker(_parent);
+                       _picker.Show();
+                       Content = _picker;
 
                        //TODO need to add internationalization support
                        PositiveButton = new EButton(_parent) { Text = "Set" };
@@ -46,10 +87,17 @@ namespace Xamarin.Forms.Platform.Tizen.Native
                        NegativeButton.Clicked += (s, e) =>
                        {
                                Hide();
+                               PickerClosed?.Invoke(this, EventArgs.Empty);
                        };
                        BackButtonPressed += (object s, EventArgs e) =>
                        {
                                Hide();
+                               PickerClosed?.Invoke(this, EventArgs.Empty);
+                       };
+
+                       ShowAnimationFinished += (object s, EventArgs e) =>
+                       {
+                               PickerOpened?.Invoke(this, EventArgs.Empty);
                        };
 
                        // TODO This is Tizen TV Limitation.
@@ -60,7 +108,7 @@ namespace Xamarin.Forms.Platform.Tizen.Native
                                {
                                        if (e.KeyName == "Return")
                                        {
-                                               if (Picker != null && Picker.IsFocused)
+                                               if (_picker != null && _picker.IsFocused)
                                                {
                                                        Confirm();
                                                        e.Flags |= EvasEventFlag.OnHold;
@@ -72,8 +120,9 @@ namespace Xamarin.Forms.Platform.Tizen.Native
 
                void Confirm()
                {
-                       DateTimeChanged?.Invoke(this, new DateChangedEventArgs(Picker.DateTime));
+                       DateTimeChanged?.Invoke(this, new DateChangedEventArgs(_picker.DateTime));
                        Hide();
+                       PickerClosed?.Invoke(this, EventArgs.Empty);
                }
        }
 }
\ No newline at end of file
index 25eadac..c180ecd 100644 (file)
@@ -22,12 +22,6 @@ namespace Xamarin.Forms.Platform.Tizen.Native
                                _editfieldLayout.SetTheme("layout", "editfield", style);
                }
 
-               public event EventHandler TextBlockFocused;
-               public event EventHandler TextBlockUnfocused;
-
-               public event EventHandler LayoutFocused;
-               public event EventHandler LayoutUnfocused;
-
                public bool IsTextBlockFocused { get; private set; }
 
                public override EColor BackgroundColor
@@ -71,9 +65,9 @@ namespace Xamarin.Forms.Platform.Tizen.Native
                        IsTextBlockFocused = isFocused;
 
                        if (isFocused)
-                               TextBlockFocused?.Invoke(this, EventArgs.Empty);
+                               OnTextBlockFocused();
                        else
-                               TextBlockUnfocused?.Invoke(this, EventArgs.Empty);
+                               OnTextBlcokUnfocused();
                }
 
                public override ElmSharp.Size Measure(int availableWidth, int availableHeight)
@@ -136,12 +130,12 @@ namespace Xamarin.Forms.Platform.Tizen.Native
                        {
                                SetFocusOnTextBlock(false);
                                layout.SignalEmit("elm,state,unfocused", "");
-                               LayoutUnfocused?.Invoke(this, EventArgs.Empty);
+                               OnEntryLayoutUnfocused();
                        };
                        layout.Focused += (s, e) =>
                        {
                                layout.SignalEmit("elm,state,focused", "");
-                               LayoutFocused?.Invoke(this, EventArgs.Empty);
+                               OnEntryLayoutFocused();
                        };
 
                        layout.KeyDown += (s, e) =>
index 41a487c..141ca24 100644 (file)
@@ -67,6 +67,26 @@ namespace Xamarin.Forms.Platform.Tizen.Native
                public event EventHandler<TextChangedEventArgs> TextChanged;
 
                /// <summary>
+               /// Occurs when the text block get focused.
+               /// </summary>
+               public event EventHandler TextBlockFocused;
+
+               /// <summary>
+               /// Occurs when the text block loses focus
+               /// </summary>
+               public event EventHandler TextBlockUnfocused;
+
+               /// <summary>
+               /// Occurs when the layout of entry get focused.
+               /// </summary>
+               public event EventHandler EntryLayoutFocused;
+
+               /// <summary>
+               /// Occurs when the layout of entry loses focus
+               /// </summary>
+               public event EventHandler EntryLayoutUnfocused;
+
+               /// <summary>
                /// Gets or sets the text.
                /// </summary>
                /// <value>The text.</value>
@@ -79,6 +99,7 @@ namespace Xamarin.Forms.Platform.Tizen.Native
 
                        set
                        {
+
                                if (value != _span.Text)
                                {
                                        var old = _span.Text;
@@ -364,6 +385,26 @@ namespace Xamarin.Forms.Platform.Tizen.Native
 
                }
 
+               protected virtual void OnTextBlockFocused()
+               {
+                       TextBlockFocused?.Invoke(this, EventArgs.Empty);
+               }
+
+               protected virtual void OnTextBlcokUnfocused()
+               {
+                       TextBlockUnfocused?.Invoke(this, EventArgs.Empty);
+               }
+
+               protected virtual void OnEntryLayoutFocused()
+               {
+                       EntryLayoutFocused?.Invoke(this, EventArgs.Empty);
+               }
+
+               protected virtual void OnEntryLayoutUnfocused()
+               {
+                       EntryLayoutUnfocused?.Invoke(this, EventArgs.Empty);
+               }
+
                protected virtual void OnTextChanged(string oldValue, string newValue)
                {
                        TextChanged?.Invoke(this, new TextChangedEventArgs(oldValue, newValue));
index 1bc2d28..3a76c5d 100644 (file)
@@ -1,16 +1,19 @@
 using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using ElmSharp;
 
 namespace Xamarin.Forms.Platform.Tizen.Native
 {
        public interface IDateTimeDialog
        {
                string Title { get; set; }
-               DateTimePicker Picker { get; }
+               DateTimePickerMode Mode { get; set; }
+               DateTime MaximumDateTime { get; set; }
+               DateTime MinimumDateTime { get; set; }
+               DateTime DateTime { get; set; }
+
                event EventHandler<DateChangedEventArgs> DateTimeChanged;
+               event EventHandler PickerOpened;
+               event EventHandler PickerClosed;
+
                void Show();
                void Hide();
                void Unrealize();
index 965d826..5d82a7c 100644 (file)
@@ -25,5 +25,13 @@ namespace Xamarin.Forms.Platform.Tizen.Native
                Keyboard Keyboard { get; set; }
 
                event EventHandler<TextChangedEventArgs> TextChanged;
+
+               event EventHandler TextBlockFocused;
+
+               event EventHandler TextBlockUnfocused;
+
+               event EventHandler EntryLayoutFocused;
+
+               event EventHandler EntryLayoutUnfocused;
        }
 }
\ No newline at end of file
index e31b0b1..57968c6 100644 (file)
@@ -4,38 +4,45 @@ using ElmSharp.Wearable;
 
 namespace Xamarin.Forms.Platform.Tizen.Native.Watch
 {
-       public class WatchDateTimePicker : DateTimePicker
+       public class WatchDateTimePicker : CircleDateTimeSelector, IRotaryInteraction
        {
-               readonly CircleSurface _surface;
-               public WatchDateTimePicker(EvasObject parent, CircleSurface surface) : base()
+               DateTimePickerMode _mode;
+
+               public IRotaryActionWidget RotaryWidget => this;
+
+               public WatchDateTimePicker(EvasObject parent, CircleSurface surface) : base(parent, surface)
                {
-                       _surface = surface;
-                       Realize(parent);
                        UpdateMode();
                }
 
-               public CircleDateTimeSelector CircleSelector { get; private set; }
-
-               protected override void UpdateMode()
+               public DateTimePickerMode Mode
                {
-                       if (Mode == DateTimePickerMode.Date)
+                       get 
                        {
-                               Style = "datepicker/circle";
+                               return _mode;
                        }
-                       else
+                       set
                        {
-                               Style = "timepicker/circle";
+                               if (_mode != value)
+                       {
+                                       _mode = value;
+                                       UpdateMode();
+                               }
                        }
                }
 
-               protected override IntPtr CreateHandle(EvasObject parent)
+               protected virtual void UpdateMode()
                {
-                       CircleSelector = new CircleDateTimeSelector(parent, _surface);
-                       if (CircleSelector.RealHandle != CircleSelector.Handle)
+                       if (_mode == DateTimePickerMode.Date)
+                       {
+                               Style = "datepicker/circle";
+                               Format = "%d/%b/%Y";
+                       }
+                       else
                        {
-                               RealHandle = CircleSelector.RealHandle;
+                               Style = "timepicker/circle";
+                               Format = "%d/%b/%Y %I:%M %p";
                        }
-                       return CircleSelector.Handle;
                }
        }
 }
\ No newline at end of file
@@ -3,10 +3,11 @@ using ElmSharp;
 using ElmSharp.Wearable;
 using ELayout = ElmSharp.Layout;
 using EButton = ElmSharp.Button;
+using Specific = Xamarin.Forms.PlatformConfiguration.TizenSpecific.Application;
 
 namespace Xamarin.Forms.Platform.Tizen.Native.Watch
 {
-       public class WatchDataTimePickerDialog : Popup, IDateTimeDialog
+       public class WatchDateTimePickerDialog : Popup, IDateTimeDialog
        {
                ELayout _surfaceLayout;
                ELayout _datetimeLayout;
@@ -14,8 +15,9 @@ namespace Xamarin.Forms.Platform.Tizen.Native.Watch
                EButton _doneButton;
                Box _container;
                string _title;
+               WatchDateTimePicker _picker;
 
-               public WatchDataTimePickerDialog(EvasObject parent) : base(parent)
+               public WatchDateTimePickerDialog(EvasObject parent) : base(parent)
                {
                        AlignmentX = -1;
                        AlignmentY = -1;
@@ -36,9 +38,9 @@ namespace Xamarin.Forms.Platform.Tizen.Native.Watch
                        _datetimeLayout.SetTheme("layout", "circle", "datetime");
                        _surface = new CircleSurface(_surfaceLayout);
 
-                       WatchPicker = new WatchDateTimePicker(parent, _surface);
-                       WatchPicker.Show();
-                       _datetimeLayout.SetContent(WatchPicker);
+                       _picker = new WatchDateTimePicker(parent, _surface);
+                       _picker.Show();
+                       _datetimeLayout.SetContent(_picker);
 
                        _doneButton = new Button(parent)
                        {
@@ -48,13 +50,14 @@ namespace Xamarin.Forms.Platform.Tizen.Native.Watch
                        _datetimeLayout.SetPartContent("elm.swallow.btn", _doneButton);
                        _doneButton.Clicked += OnDoneClicked;
 
-                       ((IRotaryActionWidget)WatchPicker.CircleSelector).Activate();
+                       ActivateRotaryInteraction();
 
                        _datetimeLayout.Show();
                        _surfaceLayout.Show();
                        _container.Show();
 
                        SetContent(_container);
+                       ShowAnimationFinished += OnShowAnimationFinished;
                        BackButtonPressed += OnBackButtonPressed;
                }
 
@@ -68,10 +71,44 @@ namespace Xamarin.Forms.Platform.Tizen.Native.Watch
                        }
                }
 
-               public DateTimePicker Picker => WatchPicker;
-               protected WatchDateTimePicker WatchPicker { get; }
+               public DateTimePickerMode Mode
+               {
+                       get => _picker.Mode;
+                       set => _picker.Mode = value;
+               }
+
+               public DateTime MaximumDateTime
+               {
+                       get => _picker.MaximumDateTime;
+                       set => _picker.MaximumDateTime = value;
+               }
+
+               public DateTime MinimumDateTime
+               {
+                       get => _picker.MinimumDateTime;
+                       set => _picker.MinimumDateTime = value;
+               }
+
+               public DateTime DateTime
+               {
+                       get => _picker.DateTime;
+                       set => _picker.DateTime = value;
+               }
 
                public event EventHandler<DateChangedEventArgs> DateTimeChanged;
+               public event EventHandler PickerOpened;
+               public event EventHandler PickerClosed;
+
+               protected virtual void ActivateRotaryInteraction()
+               {
+                       if (_picker is IRotaryInteraction ri)
+                       {
+                               if (Specific.GetUseBezelInteraction(Application.Current))
+                               {
+                                       ri.RotaryWidget.Activate();
+                               }
+                       }
+               }
 
                void OnContainerLayout()
                {
@@ -82,14 +119,21 @@ namespace Xamarin.Forms.Platform.Tizen.Native.Watch
                void OnDoneClicked(object sender, EventArgs e)
                {
                        System.Console.WriteLine("Done clicked");
-                       System.Console.WriteLine("Picker.DateTime - {0} ", Picker.DateTime);
-                       DateTimeChanged?.Invoke(this, new DateChangedEventArgs(Picker.DateTime));
+                       System.Console.WriteLine("Picker.DateTime - {0} ", _picker.DateTime);
+                       DateTimeChanged?.Invoke(this, new DateChangedEventArgs(_picker.DateTime));
                        Hide();
+                       PickerClosed?.Invoke(this, EventArgs.Empty);
                }
 
                void OnBackButtonPressed(object sender, EventArgs e)
                {
                        Hide();
+                       PickerClosed?.Invoke(this, EventArgs.Empty);
+               }
+
+               void OnShowAnimationFinished(object sender, EventArgs e)
+               {
+                       PickerOpened?.Invoke(this, EventArgs.Empty);
                }
        }
-}
\ No newline at end of file
+}
index ee79e7b..2a11401 100644 (file)
@@ -15,6 +15,8 @@ namespace Xamarin.Forms.Platform.Tizen.Native.Watch
 
                public IntPtr CircleHandle => _circleGenList.CircleHandle;
 
+               public CircleGenList CircleGenList => _circleGenList;
+
                public CircleSurface CircleSurface => _surface;
 
                public IRotaryActionWidget RotaryWidget { get => this; }
@@ -34,13 +36,6 @@ namespace Xamarin.Forms.Platform.Tizen.Native.Watch
                        Scroller.Scrolled += OnScrolled;
                }
 
-               public override void AddSource(IEnumerable source, Cell beforeCell = null)
-               {
-                       base.AddSource(source, beforeCell);
-                       AddHeaderPadding();
-                       AddFooterPadding();
-               }
-
                public override void SetHeader(VisualElement header)
                {
                        if (_headerPadding != null)
index 506766e..3c953d5 100644 (file)
@@ -13,6 +13,8 @@ namespace Xamarin.Forms.Platform.Tizen.Native.Watch
 
                public CircleSurface CircleSurface => _surface;
 
+               public CircleScroller CircleScroller => _circleScroller;
+
                public IRotaryActionWidget RotaryWidget { get => this; }
 
                public WatchScroller(EvasObject parent, CircleSurface surface)
diff --git a/src/XSF/Xamarin.Forms.Platform.Tizen/Native/Watch/WatchSpinner.cs b/src/XSF/Xamarin.Forms.Platform.Tizen/Native/Watch/WatchSpinner.cs
new file mode 100644 (file)
index 0000000..00d6f09
--- /dev/null
@@ -0,0 +1,37 @@
+using System;
+using ElmSharp;
+using ElmSharp.Wearable;
+using TizenDotnetUtil = Tizen.Common.DotnetUtil;
+
+namespace Xamarin.Forms.Platform.Tizen.Native.Watch
+{
+       public class WatchSpinner : CircleSpinner, IRotaryInteraction
+       {
+               SmartEvent _wheelAppeared, _wheelDisappeared;
+
+               public event EventHandler WheelAppeared;
+
+               public event EventHandler WheelDisappeared;
+
+               public IRotaryActionWidget RotaryWidget { get => this; }
+
+               public WatchSpinner(EvasObject parent, CircleSurface surface) : base(parent, surface)
+               {
+                       Style = "circle";
+
+                       if (TizenDotnetUtil.TizenAPIVersion == 4)
+                       {
+                               _wheelAppeared = new ElmSharp.SmartEvent(this, "genlist,show");
+                               _wheelDisappeared = new ElmSharp.SmartEvent(this, "genlist,hide");
+                       }
+                       else
+                       {
+                               _wheelAppeared = new ElmSharp.SmartEvent(this, "list,show");
+                               _wheelDisappeared = new ElmSharp.SmartEvent(this, "list,hide");
+                       }
+
+                       _wheelAppeared.On += (s, e) => WheelAppeared?.Invoke(this, EventArgs.Empty);
+                       _wheelDisappeared.On += (s, e) => WheelDisappeared?.Invoke(this, EventArgs.Empty);
+               }
+       }
+}
\ No newline at end of file
index 3ae0ef5..6862754 100644 (file)
@@ -1,10 +1,12 @@
 using System;
 using Xamarin.Forms.Platform.Tizen.Native;
-using WatchDataTimePickerDialog = Xamarin.Forms.Platform.Tizen.Native.Watch.WatchDataTimePickerDialog;
+using WatchDateTimePickerDialog = Xamarin.Forms.Platform.Tizen.Native.Watch.WatchDateTimePickerDialog;
+using EEntry = ElmSharp.Entry;
+using Specific = Xamarin.Forms.PlatformConfiguration.TizenSpecific.Application;
 
 namespace Xamarin.Forms.Platform.Tizen
 {
-       public class DatePickerRenderer : ViewRenderer<DatePicker, EditfieldEntry>
+       public class DatePickerRenderer : ViewRenderer<DatePicker, EEntry>
        {
                //TODO need to add internationalization support
                const string DialogTitle = "Choose Date";
@@ -24,7 +26,7 @@ namespace Xamarin.Forms.Platform.Tizen
                {
                        if (Device.Idiom == TargetIdiom.Watch)
                        {
-                               return new WatchDataTimePickerDialog(Forms.NativeParent);
+                               return new WatchDateTimePickerDialog(Forms.NativeParent);
                        }
                        else
                        {
@@ -36,30 +38,49 @@ namespace Xamarin.Forms.Platform.Tizen
                {
                        if (Control == null)
                        {
-                               var entry = new Native.EditfieldEntry(Forms.NativeParent)
-                               {
-                                       IsSingleLine = true,
-                                       HorizontalTextAlignment = Native.TextAlignment.Center,
-                                       InputPanelShowByOnDemand = true,
-                               };
+                               var entry = CreateNativeControl();
                                entry.SetVerticalTextAlignment("elm.text", 0.5);
-                               entry.TextBlockFocused += OnTextBlockFocused;
                                SetNativeControl(entry);
 
+                               if (entry is IEntry ie)
+                               {
+                                       ie.TextBlockFocused += OnTextBlockFocused;
+                               }
+
                                _lazyDialog = new Lazy<IDateTimeDialog>(() =>
                                {
                                        var dialog = CreateDialog();
                                        dialog.Title = DialogTitle;
                                        dialog.DateTimeChanged += OnDateTimeChanged;
+                                       dialog.PickerOpened += OnPickerOpened;
+                                       dialog.PickerClosed += OnPickerClosed;
                                        return dialog;
                                });
                        }
                        base.OnElementChanged(e);
                }
 
+               protected virtual EEntry CreateNativeControl()
+               {
+                       return new Native.EditfieldEntry(Forms.NativeParent)
+                       {
+                               IsSingleLine = true,
+                               HorizontalTextAlignment = Native.TextAlignment.Center,
+                               InputPanelShowByOnDemand = true,
+                               IsEditable = false
+                       };
+               }
+
                protected override Size MinimumSize()
                {
-                       return Control.Measure(Control.MinimumWidth, Control.MinimumHeight).ToDP();
+                       if (Control is IMeasurable im)
+                       {
+                               return im.Measure(Control.MinimumWidth, Control.MinimumHeight).ToDP();
+                       }
+                       else
+                       {
+                               return base.MinimumSize();
+                       }
                }
 
                protected override void Dispose(bool disposing)
@@ -68,11 +89,16 @@ namespace Xamarin.Forms.Platform.Tizen
                        {
                                if (Control != null)
                                {
-                                       Control.TextBlockFocused -= OnTextBlockFocused;
+                                       if (Control is IEntry ie)
+                                       {
+                                               ie.TextBlockFocused -= OnTextBlockFocused;
+                                       }
                                }
                                if (_lazyDialog.IsValueCreated)
                                {
                                        _lazyDialog.Value.DateTimeChanged -= OnDateTimeChanged;
+                                       _lazyDialog.Value.PickerOpened += OnPickerOpened;
+                                       _lazyDialog.Value.PickerClosed += OnPickerClosed;
                                        _lazyDialog.Value.Unrealize();
                                }
                        }
@@ -86,44 +112,77 @@ namespace Xamarin.Forms.Platform.Tizen
                        if (Element.IsEnabled)
                        {
                                var dialog = _lazyDialog.Value;
-                               dialog.Picker.DateTime = Element.Date;
-                               dialog.Picker.MaximumDateTime = Element.MaximumDate;
-                               dialog.Picker.MinimumDateTime = Element.MinimumDate;
+                               dialog.DateTime = Element.Date;
+                               dialog.MaximumDateTime = Element.MaximumDate;
+                               dialog.MinimumDateTime = Element.MinimumDate;
                                // You need to call Show() after ui thread occupation because of EFL problem.
                                // Otherwise, the content of the popup will not receive focus.
                                Device.BeginInvokeOnMainThread(() => dialog.Show());
                        }
                }
 
-               void OnDateTimeChanged(object sender, Native.DateChangedEventArgs dcea)
+               protected virtual void OnDateTimeChanged(object sender, Native.DateChangedEventArgs dcea)
                {
                        Element.Date = dcea.NewDate;
                        Control.Text = dcea.NewDate.ToString(Element.Format);
                }
 
-               void UpdateDate()
+               protected virtual void UpdateDate()
                {
                        Control.Text = Element.Date.ToString(Element.Format);
                }
 
-               void UpdateTextColor()
+               protected virtual void UpdateTextColor()
                {
-                       Control.TextColor = Element.TextColor.ToNative();
+                       if (Control is IEntry ie)
+                       {
+                               ie.TextColor = Element.TextColor.ToNative();
+                       }
+               }
+
+               protected virtual void OnPickerOpened(object sender, EventArgs args)
+               {
+                       if (Specific.GetUseBezelInteraction(Application.Current))
+                       {
+                               // picker included in WatchDatePickedDialog has been activated, whenever the dialog is opend.
+                               Forms.RotaryFocusObject = Element;
+                               Specific.SetActiveBezelInteractionElement(Application.Current, Element);
+                       }
+               }
+
+               protected virtual void OnPickerClosed(object sender, EventArgs args)
+               {
+                       if (Specific.GetUseBezelInteraction(Application.Current))
+                       {
+                               if (Forms.RotaryFocusObject == Element)
+                                       Forms.RotaryFocusObject = null;
+                               if (Specific.GetActiveBezelInteractionElement(Application.Current) == Element)
+                                       Specific.SetActiveBezelInteractionElement(Application.Current, null);
+                       }
                }
 
                void UpdateFontSize()
                {
-                       Control.FontSize = Element.FontSize;
+                       if (Control is IEntry ie)
+                       {
+                               ie.FontSize = Element.FontSize;
+                       }
                }
 
                void UpdateFontFamily()
                {
-                       Control.FontFamily = Element.FontFamily.ToNativeFontFamily();
+                       if (Control is IEntry ie)
+                       {
+                               ie.FontFamily = Element.FontFamily;
+                       }
                }
 
                void UpdateFontAttributes()
                {
-                       Control.FontAttributes = Element.FontAttributes;
+                       if (Control is IEntry ie)
+                       {
+                               ie.FontAttributes = Element.FontAttributes;
+                       }
                }
        }
 }
\ No newline at end of file
index 6ac21a5..2e277d9 100644 (file)
@@ -1,8 +1,10 @@
 using System;
+using Xamarin.Forms.Platform.Tizen.Native;
+using EEntry = ElmSharp.Entry;
 
 namespace Xamarin.Forms.Platform.Tizen
 {
-       public class EditorRenderer : ViewRenderer<Editor, Native.Entry>
+       public class EditorRenderer : ViewRenderer<Editor, EEntry>
        {
                public EditorRenderer()
                {
@@ -23,32 +25,44 @@ namespace Xamarin.Forms.Platform.Tizen
                {
                        if (Control == null)
                        {
-                               // Multiline EditField style is only available on Mobile and TV profile
-                               var entry = Device.Idiom == TargetIdiom.Phone || Device.Idiom == TargetIdiom.TV ? new Native.EditfieldEntry(Forms.NativeParent, "multiline") : new Native.Entry(Forms.NativeParent)
-                               {
-                                       IsSingleLine = false,
-                               };
+                               var entry = CreateNativeControl();
                                entry.Focused += OnEntryFocused;
                                entry.Unfocused += OnEntryUnfocused;
-                               entry.TextChanged += OnTextChanged;
                                entry.Unfocused += OnCompleted;
                                entry.PrependMarkUpFilter(MaxLengthFilter);
-
+                               if (entry is IEntry ie)
+                               {
+                                       ie.TextChanged += OnTextChanged;
+                               }
                                SetNativeControl(entry);
                        }
                        base.OnElementChanged(e);
                }
 
+               protected virtual EEntry CreateNativeControl()
+               {
+                       // Multiline EditField style is only available on Mobile and TV profile
+                       var entry = Device.Idiom == TargetIdiom.Phone || Device.Idiom == TargetIdiom.TV ? new Native.EditfieldEntry(Forms.NativeParent, "multiline") : new Native.Entry(Forms.NativeParent)
+                       {
+                               IsSingleLine = false,
+                       };
+
+                       return entry;
+               }
+
                protected override void Dispose(bool disposing)
                {
                        if (disposing)
                        {
                                if (null != Control)
                                {
-                                       Control.TextChanged -= OnTextChanged;
                                        Control.BackButtonPressed -= OnCompleted;
                                        Control.Unfocused -= OnEntryUnfocused;
                                        Control.Focused -= OnEntryFocused;
+                                       if (Control is IEntry ie)
+                                       {
+                                               ie.TextChanged -= OnTextChanged;
+                                       }
                                }
                        }
                        base.Dispose(disposing);
@@ -59,9 +73,17 @@ namespace Xamarin.Forms.Platform.Tizen
                        return (Control as Native.IMeasurable).Measure(Control.MinimumWidth, Control.MinimumHeight).ToDP();
                }
 
+               protected virtual void UpdateTextColor()
+               {
+                       if (Control is IEntry ie)
+                       {
+                               ie.TextColor = Element.TextColor.ToNative();
+                       }
+               }
+
                void OnTextChanged(object sender, EventArgs e)
                {
-                       Element.SetValueFromRenderer(Editor.TextProperty, ((Native.Entry)sender).Text);
+                       Element.SetValueFromRenderer(Editor.TextProperty, Control.Text);
                }
 
                bool _isSendComplate = false;
@@ -99,31 +121,39 @@ namespace Xamarin.Forms.Platform.Tizen
                        }
                }
 
-               void UpdateTextColor()
-               {
-                       Control.TextColor = Element.TextColor.ToNative();
-               }
-
                void UpdateFontSize()
                {
-                       Control.FontSize = Element.FontSize;
+                       if (Control is IEntry ie)
+               {
+                               ie.FontSize = Element.FontSize;
+               }
                }
 
                void UpdateFontFamily()
                {
-                       Control.FontFamily = Element.FontFamily.ToNativeFontFamily();
+                       if (Control is IEntry ie)
+                       {
+                               ie.FontFamily = Element.FontFamily.ToNativeFontFamily();
+                       }
                }
 
                void UpdateFontAttributes()
                {
-                       Control.FontAttributes = Element.FontAttributes;
+                       if (Control is IEntry ie)
+                       {
+                               ie.FontAttributes = Element.FontAttributes;
+                       }
                }
 
                void UpdateKeyboard(bool initialize)
                {
                        if (initialize && Element.Keyboard == Keyboard.Default)
                                return;
-                       Control.UpdateKeyboard(Element.Keyboard, Element.IsSpellCheckEnabled, true);
+
+                       if (Control is IEntry ie)
+                       {
+                               ie.UpdateKeyboard(Element.Keyboard, Element.IsSpellCheckEnabled, true);
+                       }
                }
 
                void UpdateIsSpellCheckEnabled()
@@ -139,12 +169,18 @@ namespace Xamarin.Forms.Platform.Tizen
 
                void UpdatePlaceholder()
                {
-                       Control.Placeholder = Element.Placeholder;
+                       if (Control is IEntry ie)
+                       {
+                               ie.Placeholder = Element.Placeholder;
+                       }
                }
 
                void UpdatePlaceholderColor()
                {
-                       Control.PlaceholderColor = Element.PlaceholderColor.ToNative();
+                       if (Control is IEntry ie)
+                       {
+                               ie.PlaceholderColor = Element.PlaceholderColor.ToNative();
+                       }
                }
 
                string MaxLengthFilter(ElmSharp.Entry entry, string s)
index 94dfc14..3f69976 100644 (file)
@@ -246,16 +246,10 @@ namespace Xamarin.Forms.Platform.Tizen
 
                        public void Dispose()
                        {
-                               if (headerElement != null)
-                               {
                                        Control.SetHeader(headerElement);
-                               }
-                               if (footerElement != null)
-                               {
                                        Control.SetFooter(footerElement);
                                }
                        }
-               }
 
                /// <summary>
                /// This method is called whenever something changes in list view data model.
index 641a964..0f4622f 100644 (file)
@@ -72,6 +72,8 @@ namespace Xamarin.Forms.Platform.Tizen
                                        if (_moreOption.IsValueCreated)
                                        {
                                                _moreOption.Value.Clicked -= OnMoreOptionItemClicked;
+                                               _moreOption.Value.Closed -= SendMoreOptionClosed;
+                                               _moreOption.Value.Opened -= SendMoreOptionOpened;
                                                _moreOption.Value.Items.Clear();
                                                _moreOption.Value.Unrealize();
                                        }
@@ -114,6 +116,14 @@ namespace Xamarin.Forms.Platform.Tizen
                        return moreOptionItem;
                }
 
+               protected virtual void OnMoreOptionClosed()
+               {
+               }
+
+               protected virtual void OnMoreOptionOpened()
+               {
+               }
+
                void UpdateBackgroundImage(bool initialize)
                {
                        if (initialize && Element.BackgroundImageSource.IsNullOrEmpty())
@@ -141,12 +151,24 @@ namespace Xamarin.Forms.Platform.Tizen
                MoreOption CreateMoreOption()
                {
                        var moreOption = new MoreOption(_page);
-                       moreOption.Clicked += OnMoreOptionItemClicked;
                        _page.Children.Add(moreOption);
                        moreOption.Show();
+                       moreOption.Clicked += OnMoreOptionItemClicked;
+                       moreOption.Closed += SendMoreOptionClosed;
+                       moreOption.Opened += SendMoreOptionOpened;
                        return moreOption;
                }
 
+               void SendMoreOptionClosed(object sender, EventArgs e)
+               {
+                       OnMoreOptionClosed();
+               }
+
+               void SendMoreOptionOpened(object sender, EventArgs e)
+               {
+                       OnMoreOptionOpened();
+               }
+
                void OnToolbarCollectionChanged(object sender, EventArgs eventArgs)
                {
                        if (Element.ToolbarItems.Count > 0 || _moreOption.IsValueCreated)
index cf75da3..33094f7 100644 (file)
@@ -3,10 +3,11 @@ using System.Collections.Generic;
 using Xamarin.Forms.Platform.Tizen.Native;
 using Xamarin.Forms.Platform.Tizen.Native.Watch;
 using ElmSharp;
+using EEntry = ElmSharp.Entry;
 
 namespace Xamarin.Forms.Platform.Tizen
 {
-       public class PickerRenderer : ViewRenderer<Picker, EditfieldEntry>
+       public class PickerRenderer : ViewRenderer<Picker, EEntry>
        {
                List _list;
                Dialog _dialog;
@@ -29,11 +30,14 @@ namespace Xamarin.Forms.Platform.Tizen
                        {
                                if (Control != null)
                                {
-                                       Control.TextBlockFocused -= OnTextBlockFocused;
+                                       if (Control is IEntry ie)
+                                       {
+                                               ie.TextBlockFocused -= OnTextBlockFocused;
                                        if (Device.Idiom == TargetIdiom.TV)
                                        {
-                                               Control.LayoutFocused -= OnLayoutFocused;
-                                               Control.LayoutUnfocused -= OnLayoutUnfocused;
+                                                       ie.EntryLayoutFocused -= OnLayoutFocused;
+                                                       ie.EntryLayoutUnfocused -= OnLayoutUnfocused;
+                                               }
                                        }
                                        CleanView();
                                }
@@ -45,70 +49,102 @@ namespace Xamarin.Forms.Platform.Tizen
                {
                        if (Control == null)
                        {
-                               var entry = new EditfieldEntry(Forms.NativeParent)
-                               {
-                                       IsSingleLine = true,
-                                       InputPanelShowByOnDemand = true,
-                               };
+                               var entry = CreateNativeControl();
                                entry.SetVerticalTextAlignment("elm.text", 0.5);
-                               entry.HorizontalTextAlignment = Native.TextAlignment.Center;
-                               entry.TextBlockFocused += OnTextBlockFocused;
+                               if (entry is IEntry ie)
+                               {
+                                       ie.TextBlockFocused += OnTextBlockFocused;
 
                                if (Device.Idiom == TargetIdiom.TV)
                                {
-                                       entry.LayoutFocused += OnLayoutFocused;
-                                       entry.LayoutUnfocused += OnLayoutUnfocused;
+                                               ie.EntryLayoutFocused += OnLayoutFocused;
+                                               ie.EntryLayoutUnfocused += OnLayoutUnfocused;
+                                       }
                                }
-
                                SetNativeControl(entry);
                        }
                        base.OnElementChanged(e);
                }
 
-               void UpdateSelectedIndex()
+               protected virtual EEntry CreateNativeControl()
+               {
+                       return new EditfieldEntry(Forms.NativeParent)
+                       {
+                               IsSingleLine = true,
+                               InputPanelShowByOnDemand = true,
+                               IsEditable = false,
+                               HorizontalTextAlignment = Native.TextAlignment.Center
+                       };
+               }
+
+               protected virtual void UpdateSelectedIndex()
                {
                        Control.Text = (Element.SelectedIndex == -1 || Element.Items == null ?
                                "" : Element.Items[Element.SelectedIndex]);
                }
 
-               void UpdateTextColor()
+               protected virtual void UpdateTitleColor()
+               {
+                       if (Control is IEntry ie)
+                       {
+                               ie.PlaceholderColor = Element.TitleColor.ToNative();
+                       }
+               }
+
+               protected virtual void UpdateTextColor()
                {
-                       Control.TextColor = Element.TextColor.ToNative();
+                       if (Control is IEntry ie)
+                       {
+                               ie.TextColor = Element.TextColor.ToNative();
+                       }
                }
 
                void UpdateFontSize()
                {
-                       Control.FontSize = Element.FontSize;
+                       if (Control is IEntry ie)
+                       {
+                               ie.FontSize = Element.FontSize;
+                       }
                }
 
                void UpdateFontFamily()
                {
-                       Control.FontFamily = Element.FontFamily;
+                       if (Control is IEntry ie)
+                       {
+                               ie.FontFamily = Element.FontFamily;
+                       }
                }
 
                void UpdateFontAttributes()
                {
-                       Control.FontAttributes = Element.FontAttributes;
+                       if (Control is IEntry ie)
+                       {
+                               ie.FontAttributes = Element.FontAttributes;
+                       }
                }
 
                void UpdateTitle()
                {
-                       Control.Placeholder = Element.Title;
+                       if (Control is IEntry ie)
+                       {
+                               ie.Placeholder = Element.Title;
                }
-
-               void UpdateTitleColor()
-               {
-                       Control.PlaceholderColor = Element.TitleColor.ToNative();
                }
 
                void OnLayoutFocused(object sender, EventArgs e)
                {
-                       Control.FontSize = Control.FontSize * 1.5;
+                       if (Control is IEntry ie)
+                       {
+                               ie.FontSize = ie.FontSize * 1.5;
+                       }
                }
 
                void OnLayoutUnfocused(object sender, EventArgs e)
                {
-                       Control.FontSize = Control.FontSize / 1.5;
+                       if (Control is IEntry ie)
+                       {
+                               ie.FontSize = ie.FontSize / 1.5;
+                       }
                }
 
                void OnTextBlockFocused(object sender, EventArgs e)
index 1350948..beb5b02 100644 (file)
@@ -1,5 +1,6 @@
 using System;
 using ElmSharp;
+using Xamarin.Forms.Platform.Tizen.Native.Watch;
 
 namespace Xamarin.Forms.Platform.Tizen
 {
@@ -18,15 +19,27 @@ namespace Xamarin.Forms.Platform.Tizen
                {
                        if (Control == null)
                        {
-                               SetNativeControl(new Spinner(Forms.NativeParent)
-                               {
-                                       IsEditable = false,
-                               });
+                               SetNativeControl(CreateNativeControl());
                                Control.ValueChanged += OnValueChanged;
                        }
                        base.OnElementChanged(e);
                }
 
+               protected virtual Spinner CreateNativeControl()
+               {
+                       if (Device.Idiom == TargetIdiom.Watch)
+                       {
+                               return new WatchSpinner(Forms.NativeParent.Parent, Forms.CircleSurface);
+                       }
+                       else
+                       {
+                               return new Spinner(Forms.NativeParent)
+                               {
+                                       IsEditable = false
+                               };
+                       }
+               }
+
                protected override void Dispose(bool disposing)
                {
                        if (disposing)
@@ -39,7 +52,7 @@ namespace Xamarin.Forms.Platform.Tizen
                        base.Dispose(disposing);
                }
 
-               void OnValueChanged(object sender, EventArgs e)
+               protected virtual void OnValueChanged(object sender, EventArgs e)
                {
                        double newValue = Control.Value;
                        ((IElementController)Element).SetValueFromRenderer(Stepper.ValueProperty, newValue);
@@ -85,4 +98,4 @@ namespace Xamarin.Forms.Platform.Tizen
                        Control.Step = Element.Increment;
                }
        }
-}
\ No newline at end of file
+}
index a86c415..02ff944 100644 (file)
@@ -187,7 +187,7 @@ namespace Xamarin.Forms.Platform.Tizen
                                _itemsRenderer = null;
                        }
 
-                       ((ISwipeViewController)Element).SendSwipeEnded(new SwipeEndedEventArgs(SwipeDirection));
+                       ((ISwipeViewController)Element).SendSwipeEnded(new SwipeEndedEventArgs(SwipeDirection, DrawerState == SwipeDrawerState.Opend));
                        DrawerState = SwipeDrawerState.Closed;
                        SwipeDirection = 0;
                }
index 1002f4c..4fe4300 100644 (file)
@@ -2,6 +2,7 @@ using System;
 using ElmSharp;
 using Xamarin.Forms.PlatformConfiguration.TizenSpecific;
 using Specific = Xamarin.Forms.PlatformConfiguration.TizenSpecific.VisualElement;
+using SpecificSwitch = Xamarin.Forms.PlatformConfiguration.TizenSpecific.Switch;
 using EColor = ElmSharp.Color;
 
 namespace Xamarin.Forms.Platform.Tizen
@@ -18,6 +19,7 @@ namespace Xamarin.Forms.Platform.Tizen
                        _onColorPart = _isTV ? "slider_on" : Device.Idiom == TargetIdiom.Watch ? "outer_bg_on" : "bg_on";
                        RegisterPropertyHandler(Switch.IsToggledProperty, HandleToggled);
                        RegisterPropertyHandler(Switch.OnColorProperty, UpdateOnColor);
+                       RegisterPropertyHandler(SpecificSwitch.ColorProperty, UpdateColor);
                }
 
                protected override void OnElementChanged(ElementChangedEventArgs<Switch> e)
@@ -58,6 +60,8 @@ namespace Xamarin.Forms.Platform.Tizen
                                case SwitchStyle.Toggle:
                                case SwitchStyle.Favorite:
                                case SwitchStyle.CheckBox:
+                               case SwitchStyle.OnOff:
+                               case SwitchStyle.Small:
                                        Control.Style = style;
                                        break;
                                default:
@@ -67,17 +71,16 @@ namespace Xamarin.Forms.Platform.Tizen
                        ((IVisualElementController)Element).NativeSizeChanged();
                }
 
-               void OnStateChanged(object sender, EventArgs e)
+               protected virtual void UpdateColor()
                {
-                       Element.SetValueFromRenderer(Switch.IsToggledProperty, Control.IsChecked);
-               }
-
-               void HandleToggled()
+                       var color = SpecificSwitch.GetColor(Element);
+                       if (color != Color.Default)
                {
-                       Control.IsChecked = Element.IsToggled;
+                               Control.Color = color.ToNative();
+               }
                }
 
-               void UpdateOnColor(bool initialize)
+               protected void UpdateOnColor(bool initialize)
                {
                        if (initialize && Element.OnColor.IsDefault)
                                return;
@@ -96,5 +99,16 @@ namespace Xamarin.Forms.Platform.Tizen
                                        Control.SetPartColor("slider_focused_on", color);
                        }
                }
+
+               void OnStateChanged(object sender, EventArgs e)
+               {
+                       Element.SetValueFromRenderer(Switch.IsToggledProperty, Control.IsChecked);
+               }
+
+               void HandleToggled()
+               {
+                       Control.IsChecked = Element.IsToggled;
+               }
+
        }
 }
\ No newline at end of file
index d8b85af..be607e4 100644 (file)
@@ -1,19 +1,22 @@
 using System;
 using System.Globalization;
 using Xamarin.Forms.Platform.Tizen.Native;
-using WatchDataTimePickerDialog = Xamarin.Forms.Platform.Tizen.Native.Watch.WatchDataTimePickerDialog;
+using WatchDateTimePickerDialog = Xamarin.Forms.Platform.Tizen.Native.Watch.WatchDateTimePickerDialog;
+using EEntry = ElmSharp.Entry;
+using Specific = Xamarin.Forms.PlatformConfiguration.TizenSpecific.Application;
 
 namespace Xamarin.Forms.Platform.Tizen
 {
-       public class TimePickerRenderer : ViewRenderer<TimePicker, EditfieldEntry>
+       public class TimePickerRenderer : ViewRenderer<TimePicker, EEntry>
        {
                //TODO need to add internationalization support
                const string DialogTitle = "Choose Time";
                static readonly string s_defaultFormat = CultureInfo.CurrentCulture.DateTimeFormat.ShortTimePattern;
 
-               TimeSpan _time = DateTime.Now.TimeOfDay;
                Lazy<IDateTimeDialog> _lazyDialog;
 
+               protected TimeSpan Time = DateTime.Now.TimeOfDay;
+
                public TimePickerRenderer()
                {
                        RegisterPropertyHandler(TimePicker.FormatProperty, UpdateFormat);
@@ -28,7 +31,7 @@ namespace Xamarin.Forms.Platform.Tizen
                {
                        if (Device.Idiom == TargetIdiom.Watch)
                        {
-                               return new WatchDataTimePickerDialog(Forms.NativeParent);
+                               return new WatchDateTimePickerDialog(Forms.NativeParent);
                        }
                        else
                        {
@@ -40,38 +43,55 @@ namespace Xamarin.Forms.Platform.Tizen
                {
                        if (Control == null)
                        {
-                               var entry = new Native.EditfieldEntry(Forms.NativeParent)
-                               {
-                                       IsSingleLine = true,
-                                       HorizontalTextAlignment = Native.TextAlignment.Center,
-                                       InputPanelShowByOnDemand = true,
-                               };
+                               var entry = CreateNativeControl();
                                entry.SetVerticalTextAlignment("elm.text", 0.5);
-                               entry.TextBlockFocused += OnTextBlockFocused;
                                SetNativeControl(entry);
 
+                               if (entry is IEntry ie)
+                               {
+                                       ie.TextBlockFocused += OnTextBlockFocused;
+                               }
+
                                _lazyDialog = new Lazy<IDateTimeDialog>(() => {
                                        var dialog = CreateDialog();
-                                       dialog.Picker.Mode = DateTimePickerMode.Time;
+                                       dialog.Mode = DateTimePickerMode.Time;
                                        dialog.Title = DialogTitle;
                                        dialog.DateTimeChanged += OnDialogTimeChanged;
+                                       dialog.PickerOpened += OnPickerOpened;
+                                       dialog.PickerClosed += OnPickerClosed;
                                        return dialog;
                                });
                        }
                        base.OnElementChanged(e);
                }
 
+               protected virtual EEntry CreateNativeControl()
+               {
+                       return new Native.EditfieldEntry(Forms.NativeParent)
+                       {
+                               IsSingleLine = true,
+                               HorizontalTextAlignment = Native.TextAlignment.Center,
+                               InputPanelShowByOnDemand = true,
+                               IsEditable = false
+                       };
+               }
+
                protected override void Dispose(bool disposing)
                {
                        if (disposing)
                        {
                                if (Control != null)
                                {
-                                       Control.TextBlockFocused -= OnTextBlockFocused;
+                                       if (Control is IEntry ie)
+                                       {
+                                               ie.TextBlockFocused -= OnTextBlockFocused;
+                                       }
                                }
                                if (_lazyDialog.IsValueCreated)
                                {
                                        _lazyDialog.Value.DateTimeChanged -= OnDialogTimeChanged;
+                                       _lazyDialog.Value.PickerOpened -= OnPickerOpened;
+                                       _lazyDialog.Value.PickerClosed -= OnPickerClosed;
                                        _lazyDialog.Value.Unrealize();
                                }
                        }
@@ -81,7 +101,14 @@ namespace Xamarin.Forms.Platform.Tizen
 
                protected override Size MinimumSize()
                {
-                       return Control.Measure(Control.MinimumWidth, Control.MinimumHeight).ToDP();
+                       if ( Control is IMeasurable im)
+                       {
+                               return im.Measure(Control.MinimumWidth, Control.MinimumHeight).ToDP();
+                       }
+                       else
+                       {
+                               return base.MinimumSize();
+                       }
                }
 
                void OnTextBlockFocused(object o, EventArgs e)
@@ -91,7 +118,9 @@ namespace Xamarin.Forms.Platform.Tizen
                        if (Element.IsEnabled)
                        {
                                var dialog = _lazyDialog.Value;
-                               dialog.Picker.Time = Element.Time;
+                               dialog.DateTime -= dialog.DateTime.TimeOfDay;
+                               dialog.DateTime += Element.Time;
+
                                // You need to call Show() after ui thread occupation because of EFL problem.
                                // Otherwise, the content of the popup will not receive focus.
                                Device.BeginInvokeOnMainThread(() => dialog.Show());
@@ -108,37 +137,68 @@ namespace Xamarin.Forms.Platform.Tizen
                {
                        UpdateTimeAndFormat();
                }
-
-               void UpdateTextColor()
+               protected virtual void UpdateTextColor()
                {
-                       Control.TextColor = Element.TextColor.ToNative();
+                       if (Control is IEntry ie)
+                       {
+                               ie.TextColor = Element.TextColor.ToNative();
+                       }
                }
 
                void UpdateTime()
                {
-                       _time = Element.Time;
+                       Time = Element.Time;
                        UpdateTimeAndFormat();
                }
 
                void UpdateFontSize()
                {
-                       Control.FontSize = Element.FontSize;
+                       if (Control is IEntry ie)
+                       {
+                               ie.FontSize = Element.FontSize;
+                       }
                }
 
                void UpdateFontFamily()
                {
-                       Control.FontFamily = Element.FontFamily.ToNativeFontFamily();
+                       if (Control is IEntry ie)
+                       {
+                               ie.FontFamily = Element.FontFamily;
+                       }
                }
 
                void UpdateFontAttributes()
                {
-                       Control.FontAttributes = Element.FontAttributes;
+                       if (Control is IEntry ie)
+                       {
+                               ie.FontAttributes = Element.FontAttributes;
+                       }
+               }
+               protected virtual void OnPickerOpened(object sender, EventArgs args)
+               {
+                       if (Specific.GetUseBezelInteraction(Application.Current))
+                       {
+                               // picker included in WatchDatePickedDialog has been activated, whenever the dialog is opend.
+                               Forms.RotaryFocusObject = Element;
+                               Specific.SetActiveBezelInteractionElement(Application.Current, Element);
+                       }
+               }
+
+               protected virtual void OnPickerClosed(object sender, EventArgs args)
+               {
+                       if (Specific.GetUseBezelInteraction(Application.Current))
+                       {
+                               if (Forms.RotaryFocusObject == Element)
+                                       Forms.RotaryFocusObject = null;
+                               if (Specific.GetActiveBezelInteractionElement(Application.Current) == Element)
+                                       Specific.SetActiveBezelInteractionElement(Application.Current, null);
+                       }
                }
 
-               void UpdateTimeAndFormat()
+               protected virtual void UpdateTimeAndFormat()
                {
                        // Xamarin using DateTime formatting (https://developer.xamarin.com/api/property/Xamarin.Forms.TimePicker.Format/)
-                       Control.Text = new DateTime(_time.Ticks).ToString(Element.Format ?? s_defaultFormat);
+                       Control.Text = new DateTime(Time.Ticks).ToString(Element.Format ?? s_defaultFormat);
                }
        }
 }
\ No newline at end of file
index 3577ceb..f5d0b5a 100644 (file)
@@ -118,12 +118,15 @@ namespace Xamarin.Forms.Platform.Tizen
                                        {
                                                ri.RotaryWidget?.Activate();
                                                Forms.RotaryFocusObject = Element;
+                                               Specific.SetActiveBezelInteractionElement(Application.Current, Element);
                                        }
                                        else
                                        {
                                                ri.RotaryWidget?.Deactivate();
                                                if (Forms.RotaryFocusObject == Element)
                                                        Forms.RotaryFocusObject = null;
+                                               if (Specific.GetActiveBezelInteractionElement(Application.Current) == Element)
+                                                       Specific.SetActiveBezelInteractionElement(Application.Current, null);
                                        }
                                }
                        }
index 0baa595..41c1562 100644 (file)
@@ -1,8 +1,6 @@
 using ElmSharp;
 using System;
 using System.Collections.Generic;
-using System.Linq;
-using Xamarin.Forms;
 
 namespace Xamarin.Forms.Platform.Tizen.Watch
 {
@@ -48,11 +46,21 @@ namespace Xamarin.Forms.Platform.Tizen.Watch
                        base.Dispose(disposing);
                }
 
+               protected virtual NavigationView CreateNavigationView(EvasObject parent)
+               {
+                       return new NavigationView(parent);
+               }
+
+               protected virtual NavigationDrawer CreateNavigationDrawer(EvasObject parent)
+               {
+                       return new NavigationDrawer(parent);
+               }
+
                void InitializeComponent()
                {
                        if (_drawer == null)
                        {
-                               _drawer = new NavigationDrawer(Forms.NativeParent);
+                               _drawer = CreateNavigationDrawer(Forms.NativeParent);
                                _drawer.IsOpen = Element.FlyoutIsPresented;
                                _drawer.Toggled += OnNavigationDrawerToggled;
                                SetNativeView(_drawer);
@@ -94,13 +102,12 @@ namespace Xamarin.Forms.Platform.Tizen.Watch
                                return;
                        }
 
-                       _navigationView = new NavigationView(Forms.NativeParent)
-                       {
-                               AlignmentX = -1,
-                               AlignmentY = -1,
-                               WeightX = 1,
-                               WeightY = 1,
-                       };
+                       _navigationView = CreateNavigationView(Forms.NativeParent);
+                       _navigationView.AlignmentX = -1;
+                       _navigationView.AlignmentY = -1;
+                       _navigationView.WeightX = 1;
+                       _navigationView.WeightY = 1;
+
                        _navigationView.Show();
                        _navigationView.ItemSelected += OnMenuItemSelected;
 
index ef203b2..9736782 100644 (file)
@@ -22,6 +22,8 @@ namespace Xamarin.Forms.Xaml
                                markupExtension = new OnPlatformExtension();
                        else if (match == "OnIdiom")
                                markupExtension = new OnIdiomExtension();
+                       else if (match == "OnAppTheme")
+                               markupExtension = new OnAppThemeExtension();
                        else if (match == "DataTemplate")
                                markupExtension = new DataTemplateExtension();
                        else
index 8bb51b1..0df0215 100644 (file)
@@ -1,46 +1,50 @@
 using System;
-using System.ComponentModel;
 using System.Globalization;
 using System.Reflection;
-using System.Runtime.CompilerServices;
 
 namespace Xamarin.Forms.Xaml
 {
        [ContentProperty(nameof(Default))]
-       public class OnAppThemeExtension : IMarkupExtension, INotifyPropertyChanged
+       public class OnAppThemeExtension : IMarkupExtension<BindingBase>
        {
                public OnAppThemeExtension()
                {
-                       ExperimentalFlags.VerifyFlagEnabled(nameof(AppThemeColor), ExperimentalFlags.AppThemeExperimental, nameof(OnAppThemeExtension));
+                       ExperimentalFlags.VerifyFlagEnabled(nameof(OnAppThemeExtension), ExperimentalFlags.AppThemeExperimental, nameof(OnAppThemeExtension));
 
                        Application.Current.RequestedThemeChanged += RequestedThemeChanged;
                }
 
-               public event PropertyChangedEventHandler PropertyChanged;
-
-               protected void OnPropertyChanged([CallerMemberName] string propName = null)
-                       => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
-
                public object Default { get; set; }
                public object Light { get; set; }
                public object Dark { get; set; }
+               public object Value     { get; private set;     }
+
+               public IValueConverter Converter { get; set; }
+               public object ConverterParameter { get; set; }
+
+               public object ProvideValue(IServiceProvider serviceProvider)
+               {
+                       return (this as IMarkupExtension<BindingBase>).ProvideValue(serviceProvider);
+               }
 
-               private object _value;
-               public object Value
+               object GetValue()
                {
-                       get => _value;
-                       private set
+                       switch (Application.Current?.RequestedTheme)
                        {
-                               _value = value;
-                               OnPropertyChanged();
+                               default:
+                               case OSAppTheme.Light:
+                                       return Light ?? Default;
+                               case OSAppTheme.Dark:
+                                       return Dark ?? Default;
                        }
                }
 
-               public IValueConverter Converter { get; set; }
-
-               public object ConverterParameter { get; set; }
+               void RequestedThemeChanged(object sender, AppThemeChangedEventArgs e)
+               {
+                       Value = GetValue();
+               }
 
-               public object ProvideValue(IServiceProvider serviceProvider)
+               BindingBase IMarkupExtension<BindingBase>.ProvideValue(IServiceProvider serviceProvider)
                {
                        if (Default == null
                                && Light == null
@@ -66,13 +70,15 @@ namespace Xamarin.Forms.Xaml
                                                          ?? pi?.PropertyType
                                                          ?? throw new InvalidOperationException("Cannot determine property to provide the value for.");
 
-                       var value = GetValue();
-                       var info = propertyType.GetTypeInfo();
-                       if (value == null && info.IsValueType)
-                               Value = Activator.CreateInstance(propertyType);
-
                        if (Converter != null)
-                               Value = Converter.Convert(value, propertyType, ConverterParameter, CultureInfo.CurrentUICulture);
+                       {
+                               var light = Converter.Convert(Light, propertyType, ConverterParameter, CultureInfo.CurrentUICulture);
+
+                               var dark = Converter.Convert(Dark, propertyType, ConverterParameter, CultureInfo.CurrentUICulture);
+                               var def = Converter.Convert(Dark, propertyType, ConverterParameter, CultureInfo.CurrentUICulture);
+
+                               return new OnAppTheme<object> { Light = light, Dark = dark, Default = def };
+                       }
 
                        var converterProvider = serviceProvider?.GetService<IValueConverterProvider>();
                        if (converterProvider != null)
@@ -103,37 +109,39 @@ namespace Xamarin.Forms.Xaml
                                        }
                                }
 
-                               Value = converterProvider.Convert(value, propertyType, minforetriever, serviceProvider);
+                               var light = converterProvider.Convert(Light, propertyType, minforetriever, serviceProvider);
+
+                               var dark = converterProvider.Convert(Dark, propertyType, minforetriever, serviceProvider);
+                               var def = converterProvider.Convert(Dark, propertyType, minforetriever, serviceProvider);
+
+                               return new OnAppTheme<object> { Light = light, Dark = dark, Default = def };
                        }
                        if (converterProvider != null)
-                               Value = converterProvider.Convert(value, propertyType, () => pi, serviceProvider);
+                       {
+                               var light = converterProvider.Convert(Light, propertyType, () => pi, serviceProvider);
 
-                       var ret = value.ConvertTo(propertyType, () => pi, serviceProvider, out Exception exception);
-                       if (exception != null)
-                               throw exception;
-                       Value = ret;
+                               var dark = converterProvider.Convert(Dark, propertyType, () => pi, serviceProvider);
+                               var def = converterProvider.Convert(Default, propertyType, () => pi, serviceProvider);
 
-                       if (!(value is Binding))
-                               return new Binding(nameof(Value), source: this);
-                       else
-                               return ret;
-               }
-
-               object GetValue()
-               {
-                       switch (Application.Current?.RequestedTheme)
-                       {
-                               default:
-                               case OSAppTheme.Light:
-                                       return Light ?? Default;
-                               case OSAppTheme.Dark:
-                                       return Dark ?? Default;
+                               return new OnAppTheme<object> { Light = light, Dark = dark, Default = def };
                        }
-               }
 
-               void RequestedThemeChanged(object sender, AppThemeChangedEventArgs e)
-               {
-                       Value = GetValue();
+                       var lightConverted = Light.ConvertTo(propertyType, () => pi, serviceProvider, out Exception lightException);
+                       
+                       if (lightException != null)
+                               throw lightException;
+
+                       var darkConverted = Dark.ConvertTo(propertyType, () => pi, serviceProvider, out Exception darkException);
+
+                       if (darkException != null)
+                               throw darkException;
+
+                       var defaultConverted = Dark.ConvertTo(propertyType, () => pi, serviceProvider, out Exception defaultException);
+
+                       if (defaultException != null)
+                               throw defaultException;
+
+                       return new OnAppTheme<object> { Light = Light, Dark = Dark, Default = defaultConverted };
                }
        }
 }
\ No newline at end of file