* 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)
-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
using System.Threading.Tasks;
using Xamarin.Forms.Internals;
using Xamarin.Forms.Platform;
-using System.Diagnostics;
-using Xamarin.Forms.Core;
namespace Xamarin.Forms
{
if (_mainPage != null)
{
InternalChildren.Remove(_mainPage);
+
_mainPage.Parent = null;
}
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;
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
public enum EffectiveFlowDirection
{
RightToLeft = 1 << 0,
- Explicit = 1 << 1,
+ Explicit = 1 << 1
}
}
\ No newline at end of file
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));
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;
public Expander()
{
- ExpanderLayout = new StackLayout { Spacing = Spacing };
+ ExpanderLayout = new StackLayout { Spacing = 0 };
ForceUpdateSizeCommand = new Command(ForceUpdateSize);
InternalChildren.Add(ExpanderLayout);
}
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
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)
{
{
if (parent is Expander ancestorExpander)
{
- ancestorExpander.Content.HeightRequest = -1;
+ ancestorExpander.ContentHolder.HeightRequest = -1;
}
parent = parent.Parent;
}
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)
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;
if (_shouldIgnoreAnimation)
{
State = IsExpanded ? ExpanderState.Expanded : ExpanderState.Collapsed;
- Content.HeightRequest = _endHeight;
- Content.IsVisible = IsExpanded;
+ ContentHolder.HeightRequest = _endHeight;
+ ContentHolder.IsVisible = IsExpanded;
return;
}
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)
{
}
if (!IsExpanded)
{
- Content.IsVisible = false;
+ ContentHolder.IsVisible = false;
State = ExpanderState.Collapsed;
return;
}
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(
string constructorHint = null,
[CallerMemberName] string memberName = "")
{
+ if (DesignMode.IsDesignModeEnabled)
+ {
+ return;
+ }
+
if (Device.Flags == null || !Device.Flags.Contains(flagName))
{
if (!String.IsNullOrEmpty(memberName))
using System.Collections.Generic;
using System.Linq;
-namespace Xamarin.Forms.Core
+namespace Xamarin.Forms
{
public class FontFile
{
{
public interface ISwipeViewController
{
+ bool IsOpen { get; set; }
void SendSwipeStarted(SwipeStartedEventArgs args);
void SendSwipeChanging(SwipeChangingEventArgs args);
void SendSwipeEnded(SwipeEndedEventArgs args);
-using System.Collections;
+using System;
+using System.Collections;
using System.Collections.Specialized;
using Xamarin.Forms.Platform;
=> (((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));
using System.Collections;
using System.Collections.Generic;
using System.Text;
-using Xamarin.Forms.PlatformConfiguration.TizenSpecific;
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)
{ "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)>
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
namespace Xamarin.Forms.PlatformConfiguration.TizenSpecific
{
+ using System.ComponentModel;
using FormsElement = Xamarin.Forms.Application;
public static class Application
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;
+ }
}
}
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
--- /dev/null
+
+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;
+ }
+ }
+}
using System;
using System.Collections;
using System.Collections.Generic;
+using System.Runtime.CompilerServices;
using Xamarin.Forms.Platform;
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>();
OnPropertyChanged(VisualElement.FlowDirectionProperty.PropertyName);
}
}
+
bool IFlowDirectionController.ApplyEffectiveFlowDirectionToChildContainer => true;
double IFlowDirectionController.Width => (Parent as VisualElement)?.Width ?? 0;
-
internal virtual void ApplyQueryAttributes(IDictionary<string, string> query)
{
}
DefaultFlyoutItemLayoutStyle,
FlyoutItem.LabelStyle,
FlyoutItem.ImageStyle,
- FlyoutItem.GridStyle };
+ FlyoutItem.LayoutStyle };
if (source?.Classes != null)
foreach (var styleClass in source.Classes)
Class = DefaultFlyoutItemLayoutStyle,
};
+
var groups = new VisualStateGroupList();
var commonGroup = new VisualStateGroup();
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)
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;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms.Internals;
+using Xamarin.Forms.StyleSheets;
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);
DataTemplate IShellController.GetFlyoutItemDataTemplate(BindableObject bo)
{
BindableProperty bp = null;
+ string textBinding;
+ string iconBinding;
+ IStyleSelectable styleClassSource = null;
if (bo is IMenuItemController)
{
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; }
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
{
if (oldValue is ShellItem oldShellItem)
oldShellItem.SendDisappearing();
+ if (newValue == null)
+ return;
+
if (newValue is ShellItem newShellItem)
newShellItem.SendAppearing();
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);
}
// deparent old item
if (oldValue is Page oldElement)
{
- shellContent.OnChildRemoved(oldElement);
shellContent.ContentCache = null;
}
shellContent._logicalChildren.Clear();
if (newValue is Page newElement)
{
- shellContent._logicalChildren.Add((Element)newValue);
shellContent.ContentCache = newElement;
}
else if (newValue != null)
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)
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
{
public void Clear()
{
var list = _inner.ToList();
+ try
+ {
+ PauseCollectionChanged();
Removing(_inner);
+ }
+ finally
+ {
+ ResumeCollectionChanged();
+ }
+
_inner.Clear();
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, list));
using Xamarin.Forms.Internals;
using System.ComponentModel;
using System.Runtime.CompilerServices;
+using System.Linq;
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()
{
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
{
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));
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();
}
internal static ShellItem CreateFromShellSection(ShellSection shellSection)
{
+ if (shellSection.Parent != null)
+ {
+ return (ShellItem)shellSection.Parent;
+ }
+
ShellItem result = null;
if (shellSection is Tab)
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);
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
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)
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);
}
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)]
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);
}
internal static ShellSection CreateFromShellContent(ShellContent shellContent)
{
+ if(shellContent.Parent != null)
+ {
+ return (ShellSection)shellContent.Parent;
+ }
+
var shellSection = new ShellSection();
var contentRoute = shellContent.Route;
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;
internal void SendStructureChanged()
{
- if (Parent?.Parent is Shell shell)
+ if (Parent?.Parent is Shell shell && IsVisibleSection)
{
shell.SendStructureChanged();
}
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);
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]);
}
}
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();
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
set { SetValue(BottomItemsProperty, value); }
}
+ bool ISwipeViewController.IsOpen { get; set; }
+
static void OnSwipeItemsChanged(BindableObject bindable, object oldValue, object newValue)
{
((SwipeView)bindable).UpdateSwipeItemsParent((SwipeItems)newValue);
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);
((VisualElement)bindable).TabStopDefaultValueCreator();
IFlowDirectionController FlowController => this;
- IPropertyPropagationController PropertyPropagationController => this;
public FlowDirection FlowDirection
{
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;
internal VisualElement()
{
- if (Device.Flags?.IndexOf(ExperimentalFlags.AppThemeExperimental) > 0)
+ if (Application.Current != null)
Application.Current.RequestedThemeChanged += (s, a) => OnRequestedThemeChanged(a.RequestedTheme);
}
internal void InvalidateStateTriggers(bool attach)
{
+ if (!this.HasVisualStateGroups())
+ return;
+
var groups = (IList<VisualStateGroup>)GetValue(VisualStateManager.VisualStateGroupsProperty);
if (groups.Count == 0)
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)
{
public static bool GoToState(VisualElement visualElement, string name)
{
- if (!visualElement.IsSet(VisualStateGroupsProperty))
+ if (!visualElement.HasVisualStateGroups())
{
return false;
}
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)
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
}
}
- public VisualStateGroupList()
+ public VisualStateGroupList() : this(false)
{
+ }
+
+ public VisualStateGroupList(bool isDefault)
+ {
+ IsDefault = isDefault;
_internalList = new WatchAddList<VisualStateGroup>(ValidateAndNotify);
}
void ValidateAndNotify(IList<VisualStateGroup> groups)
{
+ if(groups.Count > 0)
+ IsDefault = false;
+
Validate(groups);
OnStatesChanged();
}
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;
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);
}
}
- public TimeSpan Time
- {
- get
- {
- return DateTime.TimeOfDay;
- }
- set
- {
- DateTime -= DateTime.TimeOfDay;
- DateTime += value;
- }
- }
-
protected virtual void UpdateMode()
{
if (Mode == DateTimePickerMode.Date)
public class DateTimePickerDialog : Dialog, IDateTimeDialog
{
EvasObject _parent;
+ DateTimePicker _picker;
+
/// <summary>
/// Creates a dialog window.
/// </summary>
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" };
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.
{
if (e.KeyName == "Return")
{
- if (Picker != null && Picker.IsFocused)
+ if (_picker != null && _picker.IsFocused)
{
Confirm();
e.Flags |= EvasEventFlag.OnHold;
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
_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
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)
{
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) =>
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>
set
{
+
if (value != _span.Text)
{
var old = _span.Text;
}
+ 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));
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();
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
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
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;
EButton _doneButton;
Box _container;
string _title;
+ WatchDateTimePicker _picker;
- public WatchDataTimePickerDialog(EvasObject parent) : base(parent)
+ public WatchDateTimePickerDialog(EvasObject parent) : base(parent)
{
AlignmentX = -1;
AlignmentY = -1;
_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)
{
_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;
}
}
}
- 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()
{
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
+}
public IntPtr CircleHandle => _circleGenList.CircleHandle;
+ public CircleGenList CircleGenList => _circleGenList;
+
public CircleSurface CircleSurface => _surface;
public IRotaryActionWidget RotaryWidget { get => this; }
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)
public CircleSurface CircleSurface => _surface;
+ public CircleScroller CircleScroller => _circleScroller;
+
public IRotaryActionWidget RotaryWidget { get => this; }
public WatchScroller(EvasObject parent, CircleSurface surface)
--- /dev/null
+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
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";
{
if (Device.Idiom == TargetIdiom.Watch)
{
- return new WatchDataTimePickerDialog(Forms.NativeParent);
+ return new WatchDateTimePickerDialog(Forms.NativeParent);
}
else
{
{
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)
{
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();
}
}
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
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()
{
{
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);
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;
}
}
- 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()
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)
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.
if (_moreOption.IsValueCreated)
{
_moreOption.Value.Clicked -= OnMoreOptionItemClicked;
+ _moreOption.Value.Closed -= SendMoreOptionClosed;
+ _moreOption.Value.Opened -= SendMoreOptionOpened;
_moreOption.Value.Items.Clear();
_moreOption.Value.Unrealize();
}
return moreOptionItem;
}
+ protected virtual void OnMoreOptionClosed()
+ {
+ }
+
+ protected virtual void OnMoreOptionOpened()
+ {
+ }
+
void UpdateBackgroundImage(bool initialize)
{
if (initialize && Element.BackgroundImageSource.IsNullOrEmpty())
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)
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;
{
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();
}
{
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)
using System;
using ElmSharp;
+using Xamarin.Forms.Platform.Tizen.Native.Watch;
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)
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);
Control.Step = Element.Increment;
}
}
-}
\ No newline at end of file
+}
_itemsRenderer = null;
}
- ((ISwipeViewController)Element).SendSwipeEnded(new SwipeEndedEventArgs(SwipeDirection));
+ ((ISwipeViewController)Element).SendSwipeEnded(new SwipeEndedEventArgs(SwipeDirection, DrawerState == SwipeDrawerState.Opend));
DrawerState = SwipeDrawerState.Closed;
SwipeDirection = 0;
}
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
_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)
case SwitchStyle.Toggle:
case SwitchStyle.Favorite:
case SwitchStyle.CheckBox:
+ case SwitchStyle.OnOff:
+ case SwitchStyle.Small:
Control.Style = style;
break;
default:
((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;
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
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);
{
if (Device.Idiom == TargetIdiom.Watch)
{
- return new WatchDataTimePickerDialog(Forms.NativeParent);
+ return new WatchDateTimePickerDialog(Forms.NativeParent);
}
else
{
{
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();
}
}
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)
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());
{
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
{
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);
}
}
}
using ElmSharp;
using System;
using System.Collections.Generic;
-using System.Linq;
-using Xamarin.Forms;
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);
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;
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
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
?? 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)
}
}
- 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