[NUI] Improve performance in theme and styles (#2704)
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / BaseComponents / Style / ViewStyle.cs
1 /*
2  * Copyright(c) 2021 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 System.Collections.Generic;
20 using Tizen.NUI.Binding;
21
22 namespace Tizen.NUI.BaseComponents
23 {
24     /// <summary>
25     /// The base class for Children attributes in Components.
26     /// </summary>
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 partial class ViewStyle : BindableObject, IDisposable
30     {
31         private bool disposed = false;
32         private bool? focusable;
33         private bool? positionUsesPivotPoint;
34         private Position parentOrigin;
35         private Position pivotPoint;
36         private Position position;
37         private Rotation orientation;
38         private DrawModeType? drawMode;
39         private Vector3 sizeModeFactor;
40         private ResizePolicyType? widthResizePolicy;
41         private ResizePolicyType? heightResizePolicy;
42         private bool? widthForHeight;
43         private bool? heightForWidth;
44         private Extents padding;
45         private Size2D minimumSize;
46         private Size2D maximumSize;
47         private ClippingModeType? clippingMode;
48         private Size size;
49         private Extents margin;
50         private bool? themeChangeSensitive;
51         private float? cornerRadius;
52
53         private Selector<ImageShadow> imageShadow;
54         private Selector<Shadow> boxShadow;
55         private Selector<string> backgroundImageSelector;
56         private Selector<float?> opacitySelector;
57         private Selector<Color> backgroundColorSelector;
58         private Selector<Rectangle> backgroundImageBorderSelector;
59         private Selector<Color> colorSelector;
60         private VisualTransformPolicyType? cornerRadiusPolicy;
61
62         static ViewStyle() { }
63
64         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
65         [EditorBrowsable(EditorBrowsableState.Never)]
66         public ViewStyle() { }
67
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 ViewStyle(ViewStyle viewAttributes)
71         {
72             CopyFrom(viewAttributes);
73         }
74
75         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
76         [EditorBrowsable(EditorBrowsableState.Never)]
77         public Selector<string> BackgroundImage
78         {
79             get
80             {
81                 Selector<string> image = (Selector<string>)GetValue(BackgroundImageSelectorProperty);
82                 return (null != image) ? image : backgroundImageSelector = new Selector<string>();
83             }
84             set => SetValue(BackgroundImageSelectorProperty, value);
85         }
86
87         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
88         [EditorBrowsable(EditorBrowsableState.Never)]
89         public bool? Focusable
90         {
91             get => (bool?)GetValue(FocusableProperty);
92             set => SetValue(FocusableProperty, value);
93         }
94
95         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
96         [Obsolete("Deprecated. Please use Size instead.")]
97         [EditorBrowsable(EditorBrowsableState.Never)]
98         public Size2D Size2D
99         {
100             get => (Size2D)GetValue(Size2DProperty);
101             set => SetValue(Size2DProperty, value);
102         }
103
104         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
105         [EditorBrowsable(EditorBrowsableState.Never)]
106         public Selector<float?> Opacity
107         {
108             get
109             {
110                 Selector<float?> opacity = (Selector<float?>)GetValue(OpacitySelectorProperty);
111                 return (null != opacity) ? opacity : opacitySelector = new Selector<float?>();
112             }
113             set => SetValue(OpacitySelectorProperty, value);
114         }
115
116         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
117         [Obsolete("Deprecated. Please use Position instead.")]
118         [EditorBrowsable(EditorBrowsableState.Never)]
119         public Position2D Position2D
120         {
121             get => (Position2D)GetValue(Position2DProperty);
122             set => SetValue(Position2DProperty, value);
123         }
124
125         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
126         [EditorBrowsable(EditorBrowsableState.Never)]
127         public bool? PositionUsesPivotPoint
128         {
129             get => (bool?)GetValue(PositionUsesPivotPointProperty);
130             set => SetValue(PositionUsesPivotPointProperty, value);
131         }
132
133         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
134         [EditorBrowsable(EditorBrowsableState.Never)]
135         public Position ParentOrigin
136         {
137             get => (Position)GetValue(ParentOriginProperty);
138             set => SetValue(ParentOriginProperty, value);
139         }
140
141         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
142         [EditorBrowsable(EditorBrowsableState.Never)]
143         public Position PivotPoint
144         {
145             get => (Position)GetValue(PivotPointProperty);
146             set => SetValue(PivotPointProperty, value);
147         }
148
149         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
150         [EditorBrowsable(EditorBrowsableState.Never)]
151         public float? SizeWidth
152         {
153             get => (float?)GetValue(SizeWidthProperty);
154             set => SetValue(SizeWidthProperty, value);
155         }
156
157         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
158         [EditorBrowsable(EditorBrowsableState.Never)]
159         public float? SizeHeight
160         {
161             get => (float?)GetValue(SizeHeightProperty);
162             set => SetValue(SizeHeightProperty, value);
163         }
164
165         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
166         [EditorBrowsable(EditorBrowsableState.Never)]
167         public Position Position
168         {
169             get => (Position)GetValue(PositionProperty);
170             set => SetValue(PositionProperty, value);
171         }
172
173         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
174         [EditorBrowsable(EditorBrowsableState.Never)]
175         public float? PositionX
176         {
177             get => (float?)GetValue(PositionXProperty);
178             set => SetValue(PositionXProperty, value);
179         }
180
181         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
182         [EditorBrowsable(EditorBrowsableState.Never)]
183         public float? PositionY
184         {
185             get => (float?)GetValue(PositionYProperty);
186             set => SetValue(PositionYProperty, value);
187         }
188
189         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
190         [EditorBrowsable(EditorBrowsableState.Never)]
191         public Rotation Orientation
192         {
193             get => (Rotation)GetValue(OrientationProperty);
194             set => SetValue(OrientationProperty, value);
195         }
196
197         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
198         [EditorBrowsable(EditorBrowsableState.Never)]
199         public DrawModeType? DrawMode
200         {
201             get => (DrawModeType?)GetValue(DrawModeProperty);
202             set => SetValue(DrawModeProperty, value);
203         }
204
205         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
206         [EditorBrowsable(EditorBrowsableState.Never)]
207         public Vector3 SizeModeFactor
208         {
209             get => (Vector3)GetValue(SizeModeFactorProperty);
210             set => SetValue(SizeModeFactorProperty, value);
211         }
212
213         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
214         [EditorBrowsable(EditorBrowsableState.Never)]
215         public ResizePolicyType? WidthResizePolicy
216         {
217             get => (ResizePolicyType?)GetValue(WidthResizePolicyProperty);
218             set => SetValue(WidthResizePolicyProperty, value);
219         }
220
221         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
222         [EditorBrowsable(EditorBrowsableState.Never)]
223         public ResizePolicyType? HeightResizePolicy
224         {
225             get => (ResizePolicyType?)GetValue(HeightResizePolicyProperty);
226             set => SetValue(HeightResizePolicyProperty, value);
227         }
228
229         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
230         [EditorBrowsable(EditorBrowsableState.Never)]
231         public bool? WidthForHeight
232         {
233             get => (bool?)GetValue(WidthForHeightProperty);
234             set => SetValue(WidthForHeightProperty, value);
235         }
236
237         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
238         [EditorBrowsable(EditorBrowsableState.Never)]
239         public bool? HeightForWidth
240         {
241             get => (bool?)GetValue(HeightForWidthProperty);
242             set => SetValue(HeightForWidthProperty, value);
243         }
244
245         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
246         [EditorBrowsable(EditorBrowsableState.Never)]
247         public Extents Padding
248         {
249             get => (Extents)GetValue(PaddingProperty) ?? (padding = new Extents());
250             set => SetValue(PaddingProperty, value);
251         }
252
253         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
254         [EditorBrowsable(EditorBrowsableState.Never)]
255         public Size2D MinimumSize
256         {
257             get => (Size2D)GetValue(MinimumSizeProperty);
258             set => SetValue(MinimumSizeProperty, value);
259         }
260
261         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
262         [EditorBrowsable(EditorBrowsableState.Never)]
263         public Size2D MaximumSize
264         {
265             get => (Size2D)GetValue(MaximumSizeProperty);
266             set => SetValue(MaximumSizeProperty, value);
267         }
268
269         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
270         [EditorBrowsable(EditorBrowsableState.Never)]
271         public ClippingModeType? ClippingMode
272         {
273             get => (ClippingModeType?)GetValue(ClippingModeProperty);
274             set => SetValue(ClippingModeProperty, value);
275         }
276
277         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
278         [EditorBrowsable(EditorBrowsableState.Never)]
279         public Size Size
280         {
281             get => (Size)GetValue(SizeProperty);
282             set => SetValue(SizeProperty, value);
283         }
284
285         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
286         [EditorBrowsable(EditorBrowsableState.Never)]
287         public Extents Margin
288         {
289             get => (Extents)GetValue(MarginProperty) ?? (margin = new Extents());
290             set => SetValue(MarginProperty, value);
291         }
292
293         /// <summary> View BackgroundColor </summary>
294         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
295         [EditorBrowsable(EditorBrowsableState.Never)]
296         public Selector<Color> BackgroundColor
297         {
298             get
299             {
300                 Selector<Color> color = (Selector<Color>)GetValue(BackgroundColorSelectorProperty);
301                 return (null != color) ? color : backgroundColorSelector = new Selector<Color>();
302             }
303             set => SetValue(BackgroundColorSelectorProperty, value);
304         }
305
306         /// <summary>
307         /// Color
308         /// </summary>
309         [EditorBrowsable(EditorBrowsableState.Never)]
310         public Selector<Color> Color
311         {
312             get => (Selector<Color>)GetValue(ColorSelectorProperty) ?? (colorSelector = new Selector<Color>());
313             set => SetValue(ColorSelectorProperty, value);
314         }
315
316         /// <summary>View BackgroundBorder</summary>
317         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
318         [EditorBrowsable(EditorBrowsableState.Never)]
319         public Selector<Rectangle> BackgroundImageBorder
320         {
321             get
322             {
323                 Selector<Rectangle> border = (Selector<Rectangle>)GetValue(BackgroundImageBorderSelectorProperty);
324                 return (null != border) ? border : backgroundImageBorderSelector = new Selector<Rectangle>();
325             }
326             set => SetValue(BackgroundImageBorderSelectorProperty, value);
327         }
328
329         /// <summary>
330         /// Describes a shadow as an image for a View.
331         /// It is null by default.
332         /// </summary>
333         /// <remarks>
334         /// If BoxShadow is not null, the ImageShadow value will be ignored.
335         /// </remarks>
336         [EditorBrowsable(EditorBrowsableState.Never)]
337         public Selector<ImageShadow> ImageShadow
338         {
339             get => (Selector<ImageShadow>)GetValue(ImageShadowSelectorProperty);
340             set => SetValue(ImageShadowSelectorProperty, value);
341         }
342
343         /// <summary>
344         /// Describes a box shaped shadow drawing for a View.
345         /// It is null by default.
346         /// </summary>
347         [EditorBrowsable(EditorBrowsableState.Never)]
348         public Selector<Shadow> BoxShadow
349         {
350             get => (Selector<Shadow>)GetValue(BoxShadowSelectorProperty);
351             set => SetValue(BoxShadowSelectorProperty, value);
352         }
353
354         /// <summary>
355         /// The radius for the rounded corners of the View
356         /// </summary>
357         [EditorBrowsable(EditorBrowsableState.Never)]
358         public float? CornerRadius
359         {
360             get => (float?)GetValue(CornerRadiusProperty);
361             set => SetValue(CornerRadiusProperty, value);
362         }
363
364         /// <summary>
365         /// Whether the CornerRadius property value is relative (percentage [0.0f to 1.0f] of the view size) or absolute (in world units).
366         /// It is absolute by default.
367         /// When the policy is relative, the corner radius is relative to the smaller of the view's width and height.
368         /// </summary>
369         [EditorBrowsable(EditorBrowsableState.Never)]
370         public VisualTransformPolicyType? CornerRadiusPolicy
371         {
372             get => (VisualTransformPolicyType?)GetValue(CornerRadiusPolicyProperty);
373             set => SetValue(CornerRadiusPolicyProperty, value);
374         }
375
376         /// <summary>
377         /// The ThemeChangeSensitive value of the View.
378         /// </summary>
379         [EditorBrowsable(EditorBrowsableState.Never)]
380         public bool? ThemeChangeSensitive
381         {
382             get => (bool?)GetValue(ThemeChangeSensitiveProperty);
383             set => SetValue(ThemeChangeSensitiveProperty, value);
384         }
385
386
387         /// <summary>
388         /// Allow null properties when merging it into other Theme.
389         /// If the value is true, the null properties reset target properties of the other ViewStyle with same key when merge.
390         /// It is used in <seealso cref="Theme.Merge(string)"/>, <seealso cref="Theme.Merge(Theme)"/>.
391         /// It is also used in <seealso cref="Theme.GetStyle(string)"/> when the Theme has a parent and needs to merge.
392         /// Please note that it is false by default.
393         /// </summary>
394         [EditorBrowsable(EditorBrowsableState.Never)]
395         public bool SolidNull { get; set; } = false;
396
397         /// <summary>
398         /// HashSet of dirty properties. Internal use only.
399         /// </summary>
400         internal HashSet<BindableProperty> DirtyProperties { get; private set; }
401
402         /// <summary>
403         /// Set style's bindable properties from the view.
404         /// </summary>
405         /// <param name="view">The view that includes property data.</param>
406         [EditorBrowsable(EditorBrowsableState.Never)]
407         public virtual void CopyPropertiesFromView(View view)
408         {
409             if (view == null) return;
410
411             BindableProperty.GetBindablePropertysOfType(GetType(), out var styleProperties);
412             BindableProperty.GetBindablePropertysOfType(view.GetType(), out var viewProperties);
413
414
415             if (styleProperties == null || viewProperties == null) return;
416
417             foreach (var stylePropertyItem in styleProperties)
418             {
419                 viewProperties.TryGetValue(stylePropertyItem.Key, out var viewProperty);
420
421                 if (viewProperty == null) continue;
422
423                 SetValue(stylePropertyItem.Value, view.GetValue(viewProperty));
424             }
425         }
426
427         /// <summary>Create a cloned ViewStyle.</summary>
428         [EditorBrowsable(EditorBrowsableState.Never)]
429         public ViewStyle Clone()
430         {
431             var cloned = CreateInstance();
432             cloned.CopyFrom(this);
433
434             return cloned;
435         }
436
437         /// <summary>Create a cloned ViewStyle.</summary>
438         [EditorBrowsable(EditorBrowsableState.Never)]
439         public void Merge(ViewStyle other)
440         {
441             CopyFrom(other);
442         }
443
444         /// <summary>
445         /// Release instance.
446         /// </summary>
447         [EditorBrowsable(EditorBrowsableState.Never)]
448         public void Dispose()
449         {
450             Dispose(true);
451             global::System.GC.SuppressFinalize(this);
452         }
453
454         /// <summary>Copy properties of other ViewStyle to this.</summary>
455         /// <param name="other">The other BindableProperty merge to this.</param>
456         [EditorBrowsable(EditorBrowsableState.Never)]
457         public override void CopyFrom(BindableObject other)
458         {
459             var source = other as ViewStyle;
460
461             if (source == null || source.DirtyProperties == null || source.DirtyProperties.Count == 0)
462             {
463                 return;
464             }
465
466             BindableProperty.GetBindablePropertysOfType(GetType(), out var thisBindableProperties);
467
468             if (thisBindableProperties == null)
469             {
470                 return;
471             }
472
473             foreach (var sourceProperty in source.DirtyProperties)
474             {
475                 var sourceValue = source.GetValue(sourceProperty);
476
477                 if (sourceValue == null)
478                 {
479                     continue;
480                 }
481
482                 thisBindableProperties.TryGetValue(sourceProperty.PropertyName, out var destinationProperty);
483
484                 if (destinationProperty != null)
485                 {
486                     SetValue(destinationProperty, sourceValue);
487                 }
488             }
489         }
490
491         /// <summary>
492         /// Release instance.
493         /// </summary>
494         [EditorBrowsable(EditorBrowsableState.Never)]
495         protected virtual void Dispose(bool disposing)
496         {
497             if (disposed)
498             {
499                 return;
500             }
501
502             if (disposing)
503             {
504                 // Dispose managed state (managed objects).
505                 margin?.Dispose();
506                 maximumSize?.Dispose();
507                 minimumSize?.Dispose();
508                 orientation?.Dispose();
509                 padding?.Dispose();
510                 parentOrigin?.Dispose();
511                 pivotPoint?.Dispose();
512                 position?.Dispose();
513                 size?.Dispose();
514                 sizeModeFactor?.Dispose();
515             }
516
517             disposed = true;
518         }
519
520         /// <summary>
521         /// Method that is called when a bound property is changed.
522         /// </summary>
523         [EditorBrowsable(EditorBrowsableState.Never)]
524         protected override void OnPropertyChangedWithData(BindableProperty property)
525         {
526             base.OnPropertyChangedWithData(property);
527
528             if (property != null)
529             {
530                 (DirtyProperties ?? (DirtyProperties = new HashSet<BindableProperty>())).Add(property);
531             }
532         }
533
534         internal ViewStyle CreateInstance()
535         {
536             return (ViewStyle)Activator.CreateInstance(GetType());
537         }
538     }
539 }