[NUI] Apply CornerRadius to View (#1463)
[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;
18 using System.ComponentModel;
19 using Tizen.NUI.Binding;
20 using Tizen.NUI.Components;
21
22 namespace Tizen.NUI.BaseComponents
23 {
24     /// <summary>
25     /// Selector class, which is related by Control State, it is base class for other Selector.
26     /// </summary>
27     /// <since_tizen> 6 </since_tizen>
28     /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
29     [EditorBrowsable(EditorBrowsableState.Never)]
30     public class Selector<T> : BindableObject
31     {
32         /// <since_tizen> 6 </since_tizen>
33         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
34         public static implicit operator Selector<T>(T value)
35         {
36             Selector<T> selector = new Selector<T>();
37             selector.All = value;
38             return selector;
39         }
40
41         /// Default Contructor
42         [EditorBrowsable(EditorBrowsableState.Never)]
43         public Selector()
44         {
45         }
46
47         /// Contructor with T
48         [EditorBrowsable(EditorBrowsableState.Never)]
49         public Selector(T value) : this()
50         {
51             All = value;
52         }
53
54         /// <summary>
55         /// All State.
56         /// </summary>
57         /// <since_tizen> 6 </since_tizen>
58         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
59         [EditorBrowsable(EditorBrowsableState.Never)]
60         public T All
61         {
62             get;
63             set;
64         }
65         /// <summary>
66         /// Normal State.
67         /// </summary>
68         /// <since_tizen> 6 </since_tizen>
69         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
70         [EditorBrowsable(EditorBrowsableState.Never)]
71         public T Normal
72         {
73             get;
74             set;
75         }
76         /// <summary>
77         /// Pressed State.
78         /// </summary>
79         /// <since_tizen> 6 </since_tizen>
80         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
81         [EditorBrowsable(EditorBrowsableState.Never)]
82         public T Pressed
83         {
84             get;
85             set;
86         }
87         /// <summary>
88         /// Focused State.
89         /// </summary>
90         /// <since_tizen> 6 </since_tizen>
91         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
92         [EditorBrowsable(EditorBrowsableState.Never)]
93         public T Focused
94         {
95             get;
96             set;
97         }
98         /// <summary>
99         /// Selected State.
100         /// </summary>
101         /// <since_tizen> 6 </since_tizen>
102         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
103         [EditorBrowsable(EditorBrowsableState.Never)]
104         public T Selected
105         {
106             get;
107             set;
108         }
109         /// <summary>
110         /// Disabled State.
111         /// </summary>
112         /// <since_tizen> 6 </since_tizen>
113         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
114         [EditorBrowsable(EditorBrowsableState.Never)]
115         public T Disabled
116         {
117             get;
118             set;
119         }
120         /// <summary>
121         /// DisabledFocused State.
122         /// </summary>
123         /// <since_tizen> 6 </since_tizen>
124         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
125         [EditorBrowsable(EditorBrowsableState.Never)]
126         public T DisabledFocused
127         {
128             get;
129             set;
130         }
131         /// <summary>
132         /// SelectedFocused State.
133         /// </summary>
134         /// <since_tizen> 6 </since_tizen>
135         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
136         public T SelectedFocused
137         {
138             get;
139             set;
140         }
141         /// <summary>
142         /// DisabledSelected State.
143         /// </summary>
144         /// <since_tizen> 6 </since_tizen>
145         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
146         [EditorBrowsable(EditorBrowsableState.Never)]
147         public T DisabledSelected
148         {
149             get;
150             set;
151         }
152         /// <summary>
153         /// Other State.
154         /// </summary>
155         /// <since_tizen> 6 </since_tizen>
156         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
157         [EditorBrowsable(EditorBrowsableState.Never)]
158         public T Other
159         {
160             get;
161             set;
162         }
163         /// <summary>
164         /// Get value by State.
165         /// </summary>
166         /// <since_tizen> 6 </since_tizen>
167         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
168         [EditorBrowsable(EditorBrowsableState.Never)]
169         public T GetValue(ControlStates state)
170         {
171             if(All != null)
172             {
173                 return All;
174             }
175             switch(state)
176             {
177                 case ControlStates.Normal:
178                     return Normal != null? Normal : Other;
179                 case ControlStates.Focused:
180                     return Focused != null? Focused : Other;
181                 case ControlStates.Pressed:
182                     return Pressed != null? Pressed : Other;
183                 case ControlStates.Disabled:
184                     return Disabled != null? Disabled : Other;
185                 case ControlStates.Selected:
186                     return Selected != null? Selected : Other;
187                 case ControlStates.DisabledFocused:
188                     return DisabledFocused != null? DisabledFocused : Other;
189                 case ControlStates.DisabledSelected:
190                     return DisabledSelected != null? DisabledSelected : Other;
191                 case ControlStates.SelectedFocused:
192                     return SelectedFocused != null ? SelectedFocused : Other;
193                 default:
194                     return Other;
195             }
196         }
197         /// <summary>
198         /// Clone function.
199         /// </summary>
200         /// <since_tizen> 6 </since_tizen>
201         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
202         [EditorBrowsable(EditorBrowsableState.Never)]
203         public void Clone(Selector<T> selector)
204         {
205             All = selector.All;
206             Normal = selector.Normal;
207             Focused = selector.Focused;
208             Pressed = selector.Pressed;
209             Disabled = selector.Disabled;
210             Selected = selector.Selected;
211             DisabledSelected = selector.DisabledSelected;
212             DisabledFocused = selector.DisabledFocused;
213             SelectedFocused = selector.SelectedFocused;
214             Other = selector.Other;
215         }
216
217         internal void Clone<U>(Selector<U> other) where U : T, Tizen.NUI.Internal.ICloneable
218         {
219             // TODO Apply constraint to the Selector (not to Clone method)
220
221             All = (T)(other.All)?.Clone();
222             Normal = (T)(other.Normal)?.Clone();
223             Focused = (T)(other.Focused)?.Clone();
224             Pressed = (T)(other.Pressed)?.Clone();
225             Disabled = (T)(other.Disabled)?.Clone();
226             Selected = (T)(other.Selected)?.Clone();
227             DisabledSelected = (T)(other.DisabledSelected)?.Clone();
228             DisabledFocused = (T)(other.DisabledFocused)?.Clone();
229             SelectedFocused = (T)(other.SelectedFocused)?.Clone();
230             Other = (T)(other.Other)?.Clone();
231         }
232     }
233
234     /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
235     [EditorBrowsable(EditorBrowsableState.Never)]
236     public class TriggerableSelector<T> : Selector<T>
237     {
238         public TriggerableSelector(View view, BindableProperty bindableProperty)
239         {
240             targetView = view;
241             targetBindableProperty = bindableProperty;
242             view.ControlStateChangeEvent += OnViewControlState;
243         }
244
245         /// <summary>
246         /// Clone function.
247         /// </summary>
248         /// <since_tizen> 6 </since_tizen>
249         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
250         [EditorBrowsable(EditorBrowsableState.Never)]
251         public new void Clone(Selector<T> selector)
252         {
253             base.Clone(selector);
254
255             if (null != targetView && null != GetValue(targetView.ControlState))
256             {
257                 targetView.SetValue(targetBindableProperty, GetValue(targetView.ControlState));
258             }
259         }
260
261         private void OnViewControlState(View obj, ControlStates state)
262         {
263             if (null != obj && null != GetValue(state))
264             {
265                 obj.SetValue(targetBindableProperty, GetValue(state));
266             }
267         }
268
269         private View targetView;
270         private BindableProperty targetBindableProperty;
271     }
272
273     /// <summary>
274     /// A class that helps binding a non-selector property in View to selector property in ViewStyle.
275     /// </summary>
276     internal class ViewSelector<T>
277     {
278         protected Selector<T> selector;
279         protected View view;
280         protected View.ControlStateChangesDelegate controlStateChanged;
281
282         internal ViewSelector(View view, View.ControlStateChangesDelegate controlStateChanged)
283         {
284             if (view == null || controlStateChanged == null)
285             {
286                 throw new global::System.ArgumentNullException();
287             }
288             this.view = view;
289             this.controlStateChanged = controlStateChanged;
290             this.selector = null;
291         }
292
293         internal T GetValue()
294         {
295             return selector == null ? default(T) : selector.GetValue(view.ControlState);
296         }
297
298         internal void Set(object value)
299         {
300             bool hadMultiValue = HasMultiValue();
301             var type = value?.GetType();
302
303             if (type == typeof(T))
304             {
305                 CopyValueToSelector((T)value);
306             }
307             else if (type == typeof(Selector<T>))
308             {
309                 CopySelectorToSelector((Selector<T>)value);
310             }
311             else if (type == Nullable.GetUnderlyingType(typeof(T)))
312             {
313                 CopyValueToSelector((T)value);
314             }
315             else
316             {
317                 selector = null;
318             }
319
320             if (hadMultiValue != HasMultiValue())
321             {
322                 if (hadMultiValue) view.ControlStateChangeEvent -= controlStateChanged;
323                 else view.ControlStateChangeEvent += controlStateChanged;
324             }
325         }
326
327         protected virtual void CopyValueToSelector(T value)
328         {
329             selector = new Selector<T>();
330             selector.All = value;
331         }
332
333         protected virtual void CopySelectorToSelector(Selector<T> value)
334         {
335             selector = new Selector<T>();
336             selector.Clone(value);
337         }
338
339         internal void Clear()
340         {
341             if (HasMultiValue())
342             {
343                 view.ControlStateChangeEvent -= controlStateChanged;
344             }
345             selector = null;
346         }
347
348         internal bool IsEmpty()
349         {
350             return selector == null;
351         }
352
353         protected bool HasMultiValue()
354         {
355             return (selector != null && selector.All == null);
356         }
357     }
358
359     /// <summary>
360     /// ViewSelector class for ICloneable type
361     /// </summary>
362     internal class CloneableViewSelector<T> : ViewSelector<T> where T : Tizen.NUI.Internal.ICloneable
363     {
364         internal CloneableViewSelector(View view, View.ControlStateChangesDelegate controlStateChanged) : base(view, controlStateChanged)
365         {
366         }
367
368         protected override void CopyValueToSelector(T value)
369         {
370             selector = new Selector<T>();
371             selector.All = (T)((T)value).Clone();
372         }
373
374         protected override void CopySelectorToSelector(Selector<T> value)
375         {
376             selector = new Selector<T>();
377             selector.Clone<T>((Selector<T>)value);
378         }
379     }
380
381     internal static class SelectorHelper
382     {
383         /// <summary>
384         /// For the object type of T or Selector T, convert it to Selector T and return the cloned one.
385         /// Otherwise, return null. <br/>
386         /// </summary>
387         static internal Selector<T> CopyCloneable<T>(object value) where T : class, Tizen.NUI.Internal.ICloneable
388         {
389             var type = value?.GetType();
390
391             if (type == typeof(Selector<T>))
392             {
393                 var result = new Selector<T>();
394                 result.Clone<T>((Selector<T>)value);
395                 return result;
396             }
397
398             if (type == typeof(T))
399             {
400                 return new Selector<T>((T)((T)value).Clone());
401             }
402
403             return null;
404         }
405
406         /// <summary>
407         /// For the value type of T or Selector T, convert it to Selector T and return the cloned one.
408         /// Otherwise, return null. <br/>
409         /// </summary>
410         static internal Selector<T> CopyValue<T>(object value)
411         {
412             var type = value?.GetType();
413
414             if (type == typeof(Selector<T>))
415             {
416                 var result = new Selector<T>();
417                 result.Clone((Selector<T>)value);
418                 return result;
419             }
420
421             if (type == typeof(T))
422             {
423                 return new Selector<T>((T)value);
424             }
425
426             return null;
427         }
428     }
429 }