54bc675fc58fd2579ebad9f4636524cb5b73bb42
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / internal / XamlBinding / Interactivity / PropertyCondition.cs
1 using System;
2 using System.ComponentModel;
3 using System.Reflection;
4 using Tizen.NUI.Binding;
5
6 namespace Tizen.NUI.Xaml
7 {
8         [ProvideCompiled("Tizen.NUI.Xaml.Core.XamlC.PassthroughValueProvider")]
9         [AcceptEmptyServiceProvider]
10         internal sealed class PropertyCondition : Condition, IValueProvider
11         {
12                 readonly BindableProperty _stateProperty;
13
14                 BindableProperty _property;
15                 object _triggerValue;
16
17                 public PropertyCondition()
18                 {
19                         _stateProperty = BindableProperty.CreateAttached("State", typeof(bool), typeof(PropertyCondition), false, propertyChanged: OnStatePropertyChanged);
20                 }
21
22                 public BindableProperty Property
23                 {
24                         get { return _property; }
25                         set
26                         {
27                                 if (_property == value)
28                                         return;
29                                 if (IsSealed)
30                                         throw new InvalidOperationException("Can not change Property once the Trigger has been applied.");
31                                 _property = value;
32
33                                 //convert the value
34                                 if (_property != null && s_valueConverter != null)
35                                 {
36                                         Func<MemberInfo> minforetriever = () => Property.DeclaringType.GetRuntimeProperty(Property.PropertyName);
37                                         Value = s_valueConverter.Convert(Value, Property.ReturnType, minforetriever, null);
38                                 }
39                         }
40                 }
41
42                 public object Value
43                 {
44                         get { return _triggerValue; }
45                         set
46                         {
47                                 if (_triggerValue == value)
48                                         return;
49                                 if (IsSealed)
50                                         throw new InvalidOperationException("Can not change Value once the Trigger has been applied.");
51
52                                 //convert the value
53                                 if (_property != null && s_valueConverter != null)
54                                 {
55                                         Func<MemberInfo> minforetriever = () => Property.DeclaringType.GetRuntimeProperty(Property.PropertyName);
56                                         value = s_valueConverter.Convert(value, Property.ReturnType, minforetriever, null);
57                                 }
58                                 _triggerValue = value;
59                         }
60                 }
61
62                 object IValueProvider.ProvideValue(IServiceProvider serviceProvider)
63                 {
64                         //This is no longer required
65                         return this;
66                 }
67
68                 internal override bool GetState(BindableObject bindable)
69                 {
70                         return (bool)bindable.GetValue(_stateProperty);
71                 }
72
73                 static IValueConverterProvider s_valueConverter = DependencyService.Get<IValueConverterProvider>();
74
75                 internal override void SetUp(BindableObject bindable)
76                 {
77                         object newvalue = bindable.GetValue(Property);
78                         bool newState = (newvalue == Value) || (newvalue != null && newvalue.Equals(Value));
79                         bindable.SetValue(_stateProperty, newState);
80                         bindable.PropertyChanged += OnAttachedObjectPropertyChanged;
81                 }
82
83                 internal override void TearDown(BindableObject bindable)
84                 {
85                         bindable.ClearValue(_stateProperty);
86                         bindable.PropertyChanged -= OnAttachedObjectPropertyChanged;
87                 }
88
89                 void OnAttachedObjectPropertyChanged(object sender, PropertyChangedEventArgs e)
90                 {
91                         var bindable = (BindableObject)sender;
92                         var oldState = (bool)bindable.GetValue(_stateProperty);
93
94                         if (Property == null)
95                                 return;
96                         if (e.PropertyName != Property.PropertyName)
97                                 return;
98                         object newvalue = bindable.GetValue(Property);
99                         bool newstate = (newvalue == Value) || (newvalue != null && newvalue.Equals(Value));
100                         if (oldState != newstate)
101                                 bindable.SetValue(_stateProperty, newstate);
102                 }
103
104                 void OnStatePropertyChanged(BindableObject bindable, object oldValue, object newValue)
105                 {
106                         if ((bool)oldValue == (bool)newValue)
107                                 return;
108
109                         ConditionChanged?.Invoke(bindable, (bool)oldValue, (bool)newValue);
110                 }
111         }
112 }