[NUI] Support Shadow Size Extents (#1334)
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / BaseComponents / Style / Selector.cs
1 /*
2  * Copyright(c) 2019 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 using System.ComponentModel;
18 using Tizen.NUI.Binding;
19 using Tizen.NUI.Components;
20
21 namespace Tizen.NUI.BaseComponents
22 {
23     /// <summary>
24     /// Selector class, which is related by Control State, it is base class for other Selector.
25     /// </summary>
26     /// <since_tizen> 6 </since_tizen>
27     /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
28     [EditorBrowsable(EditorBrowsableState.Never)]
29     public class Selector<T> : BindableObject
30     {
31         /// <since_tizen> 6 </since_tizen>
32         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
33         public static implicit operator Selector<T>(T value)
34         {
35             Selector<T> selector = new Selector<T>();
36             selector.All = value;
37             return selector;
38         }
39
40         /// Default Contructor
41         [EditorBrowsable(EditorBrowsableState.Never)]
42         public Selector()
43         {
44         }
45
46         /// Contructor with T
47         [EditorBrowsable(EditorBrowsableState.Never)]
48         public Selector(T value) : this()
49         {
50             All = value;
51         }
52
53         /// <summary>
54         /// All State.
55         /// </summary>
56         /// <since_tizen> 6 </since_tizen>
57         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
58         [EditorBrowsable(EditorBrowsableState.Never)]
59         public T All
60         {
61             get;
62             set;
63         }
64         /// <summary>
65         /// Normal State.
66         /// </summary>
67         /// <since_tizen> 6 </since_tizen>
68         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
69         [EditorBrowsable(EditorBrowsableState.Never)]
70         public T Normal
71         {
72             get;
73             set;
74         }
75         /// <summary>
76         /// Pressed State.
77         /// </summary>
78         /// <since_tizen> 6 </since_tizen>
79         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
80         [EditorBrowsable(EditorBrowsableState.Never)]
81         public T Pressed
82         {
83             get;
84             set;
85         }
86         /// <summary>
87         /// Focused State.
88         /// </summary>
89         /// <since_tizen> 6 </since_tizen>
90         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
91         [EditorBrowsable(EditorBrowsableState.Never)]
92         public T Focused
93         {
94             get;
95             set;
96         }
97         /// <summary>
98         /// Selected State.
99         /// </summary>
100         /// <since_tizen> 6 </since_tizen>
101         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
102         [EditorBrowsable(EditorBrowsableState.Never)]
103         public T Selected
104         {
105             get;
106             set;
107         }
108         /// <summary>
109         /// Disabled State.
110         /// </summary>
111         /// <since_tizen> 6 </since_tizen>
112         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
113         [EditorBrowsable(EditorBrowsableState.Never)]
114         public T Disabled
115         {
116             get;
117             set;
118         }
119         /// <summary>
120         /// DisabledFocused State.
121         /// </summary>
122         /// <since_tizen> 6 </since_tizen>
123         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
124         [EditorBrowsable(EditorBrowsableState.Never)]
125         public T DisabledFocused
126         {
127             get;
128             set;
129         }
130         /// <summary>
131         /// SelectedFocused State.
132         /// </summary>
133         /// <since_tizen> 6 </since_tizen>
134         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
135         public T SelectedFocused
136         {
137             get;
138             set;
139         }
140         /// <summary>
141         /// DisabledSelected State.
142         /// </summary>
143         /// <since_tizen> 6 </since_tizen>
144         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
145         [EditorBrowsable(EditorBrowsableState.Never)]
146         public T DisabledSelected
147         {
148             get;
149             set;
150         }
151         /// <summary>
152         /// Other State.
153         /// </summary>
154         /// <since_tizen> 6 </since_tizen>
155         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
156         [EditorBrowsable(EditorBrowsableState.Never)]
157         public T Other
158         {
159             get;
160             set;
161         }
162         /// <summary>
163         /// Get value by State.
164         /// </summary>
165         /// <since_tizen> 6 </since_tizen>
166         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
167         [EditorBrowsable(EditorBrowsableState.Never)]
168         public T GetValue(ControlStates state)
169         {
170             if(All != null)
171             {
172                 return All;
173             }
174             switch(state)
175             {
176                 case ControlStates.Normal:
177                     return Normal != null? Normal : Other;
178                 case ControlStates.Focused:
179                     return Focused != null? Focused : Other;
180                 case ControlStates.Pressed:
181                     return Pressed != null? Pressed : Other;
182                 case ControlStates.Disabled:
183                     return Disabled != null? Disabled : Other;
184                 case ControlStates.Selected:
185                     return Selected != null? Selected : Other;
186                 case ControlStates.DisabledFocused:
187                     return DisabledFocused != null? DisabledFocused : Other;
188                 case ControlStates.DisabledSelected:
189                     return DisabledSelected != null? DisabledSelected : Other;
190                 case ControlStates.SelectedFocused:
191                     return SelectedFocused != null ? SelectedFocused : Other;
192                 default:
193                     return Other;
194             }
195         }
196         /// <summary>
197         /// Clone function.
198         /// </summary>
199         /// <since_tizen> 6 </since_tizen>
200         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
201         [EditorBrowsable(EditorBrowsableState.Never)]
202         public void Clone(Selector<T> selector)
203         {
204             All = selector.All;
205             Normal = selector.Normal;
206             Focused = selector.Focused;
207             Pressed = selector.Pressed;
208             Disabled = selector.Disabled;
209             Selected = selector.Selected;
210             DisabledSelected = selector.DisabledSelected;
211             DisabledFocused = selector.DisabledFocused;
212             SelectedFocused = selector.SelectedFocused;
213             Other = selector.Other;
214         }
215
216         internal void Clone<U>(Selector<U> other) where U : T, Tizen.NUI.Internal.ICloneable
217         {
218             // TODO Apply constraint to the Selector (not to Clone method)
219
220             All = (T)(other.All)?.Clone();
221             Normal = (T)(other.Normal)?.Clone();
222             Focused = (T)(other.Focused)?.Clone();
223             Pressed = (T)(other.Pressed)?.Clone();
224             Disabled = (T)(other.Disabled)?.Clone();
225             Selected = (T)(other.Selected)?.Clone();
226             DisabledSelected = (T)(other.DisabledSelected)?.Clone();
227             DisabledFocused = (T)(other.DisabledFocused)?.Clone();
228             SelectedFocused = (T)(other.SelectedFocused)?.Clone();
229             Other = (T)(other.Other)?.Clone();
230         }
231     }
232
233     /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
234     [EditorBrowsable(EditorBrowsableState.Never)]
235     public class TriggerableSelector<T> : Selector<T>
236     {
237         public TriggerableSelector(View view, BindableProperty bindableProperty)
238         {
239             targetView = view;
240             targetBindableProperty = bindableProperty;
241             view.ControlStateChangeEvent += OnViewControlState;
242         }
243
244         /// <summary>
245         /// Clone function.
246         /// </summary>
247         /// <since_tizen> 6 </since_tizen>
248         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
249         [EditorBrowsable(EditorBrowsableState.Never)]
250         public new void Clone(Selector<T> selector)
251         {
252             base.Clone(selector);
253
254             if (null != targetView && null != GetValue(targetView.ControlState))
255             {
256                 targetView.SetValue(targetBindableProperty, GetValue(targetView.ControlState));
257             }
258         }
259
260         private void OnViewControlState(View obj, ControlStates state)
261         {
262             if (null != obj && null != GetValue(state))
263             {
264                 obj.SetValue(targetBindableProperty, GetValue(state));
265             }
266         }
267
268         private View targetView;
269         private BindableProperty targetBindableProperty;
270     }
271
272     /// <summary>
273     /// A class that helps binding a non-selector property in View to selector property in ViewStyle.
274     /// </summary>
275     internal class ViewSelector<T> where T : class, Tizen.NUI.Internal.ICloneable
276     {
277         private Selector<T> selector;
278         private View view;
279         private View.ControlStateChangesDelegate controlStateChanged;
280
281         internal ViewSelector(View view, View.ControlStateChangesDelegate controlStateChanged)
282         {
283             if (view == null || controlStateChanged == null)
284             {
285                 throw new global::System.ArgumentNullException();
286             }
287             this.view = view;
288             this.controlStateChanged = controlStateChanged;
289             this.selector = null;
290         }
291
292         internal T GetValue()
293         {
294             return selector == null ? null : selector.GetValue(view.ControlState);
295         }
296
297         internal void Clone(object value)
298         {
299             bool hadMultiValue = HasMultiValue();
300             var type = value?.GetType();
301
302             if (type == typeof(T))
303             {
304                 selector = new Selector<T>();
305                 selector.All = (T)((T)value).Clone();
306             }
307             else if (type == typeof(Selector<T>))
308             {
309                 selector = new Selector<T>();
310                 selector.Clone<T>((Selector<T>)value);
311             }
312             else
313             {
314                 selector = null;
315             }
316
317             if (hadMultiValue != HasMultiValue())
318             {
319                 if (hadMultiValue) view.ControlStateChangeEvent -= controlStateChanged;
320                 else view.ControlStateChangeEvent += controlStateChanged;
321             }
322         }
323
324         internal void Clear()
325         {
326             if (HasMultiValue())
327             {
328                 view.ControlStateChangeEvent -= controlStateChanged;
329             }
330             selector = null;
331         }
332
333         internal bool IsEmpty()
334         {
335             return selector == null;
336         }
337
338         private bool HasMultiValue()
339         {
340             return (selector != null && selector.All == null);
341         }
342     }
343
344     internal static class SelectorHelper<T> where T : class, Tizen.NUI.Internal.ICloneable
345     {
346         /// <summary>
347         /// For the object type of T or Selector T, convert it to Selector T and return the cloned one.
348         /// Otherwise, return null. <br/>
349         /// </summary>
350         static internal Selector<T> Clone(object value)
351         {
352             var type = value?.GetType();
353
354             if (type == typeof(Selector<T>))
355             {
356                 var result = new Selector<T>();
357                 result.Clone<T>((Selector<T>)value);
358                 return result;
359             }
360
361             if (type == typeof(T))
362             {
363                 return new Selector<T>((T)((T)value).Clone());
364             }
365
366             return null;
367         }
368
369         /// <summary>
370         /// For the object type of T or Selector T, convert it to T and return the cloned one.
371         /// Otherwise, return null. <br/>
372         /// </summary>
373         static internal T Clone(object value, View view)
374         {
375             var type = value?.GetType();
376
377             if (type == typeof(T))
378             {
379                 return (T)((T)value).Clone();
380             }
381
382             if (type == typeof(Selector<T>) && view != null)
383             {
384                 Selector<T> selector = (Selector<T>)value;
385                 T valueInState = selector.GetValue(view.ControlState);
386
387                 return (T)valueInState?.Clone();
388             }
389
390             return null;
391         }
392     }
393 }