[NUI] Update theme system
[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 of style attributes for a view.
26     /// </summary>
27     /// <since_tizen> 9 </since_tizen>
28     public partial class ViewStyle : BindableObject, IDisposable
29     {
30         private bool disposed = false;
31         private bool? focusable;
32         private bool? positionUsesPivotPoint;
33         private Position parentOrigin;
34         private Position pivotPoint;
35         private Position position;
36         private Rotation orientation;
37         private DrawModeType? drawMode;
38         private Vector3 sizeModeFactor;
39         private ResizePolicyType? widthResizePolicy;
40         private ResizePolicyType? heightResizePolicy;
41         private bool? widthForHeight;
42         private bool? heightForWidth;
43         private Extents padding;
44         private Size2D minimumSize;
45         private Size2D maximumSize;
46         private ClippingModeType? clippingMode;
47         private Size size;
48         private Extents margin;
49         private bool? themeChangeSensitive;
50         private Vector4 cornerRadius;
51         private float? borderlineWidth;
52         private Color borderlineColor;
53         private float? borderlineOffset;
54
55         private Selector<ImageShadow> imageShadow;
56         private Selector<Shadow> boxShadow;
57         private Selector<string> backgroundImageSelector;
58         private Selector<float?> opacitySelector;
59         private Selector<Color> backgroundColorSelector;
60         private Selector<Rectangle> backgroundImageBorderSelector;
61         private Selector<Color> colorSelector;
62         private VisualTransformPolicyType? cornerRadiusPolicy;
63
64         static ViewStyle() { }
65
66         /// <summary>
67         /// Create an empty style instance.
68         /// </summary>
69         /// <since_tizen> 9 </since_tizen>
70         public ViewStyle() { }
71
72         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
73         [EditorBrowsable(EditorBrowsableState.Never)]
74         public ViewStyle(ViewStyle viewAttributes)
75         {
76             CopyFrom(viewAttributes);
77         }
78
79         /// <summary>
80         /// The flag that is used when creating a component with this style.
81         /// If the value is true, it will include default component style defined in the default theme.
82         /// </summary>
83         [EditorBrowsable(EditorBrowsableState.Never)]
84         public bool IncludeDefaultStyle { get; set; } = false;
85
86         /// <summary>
87         /// Gets or sets the image resource url of the background of view.
88         /// The mutually exclusive with "BackgroundColor". Setting it overwrites existing "BackgroundColor".
89         /// </summary>
90         /// <since_tizen> 9 </since_tizen>
91         public Selector<string> BackgroundImage
92         {
93             get
94             {
95                 Selector<string> image = (Selector<string>)GetValue(BackgroundImageProperty);
96                 return (null != image) ? image : backgroundImageSelector = new Selector<string>();
97             }
98             set => SetValue(BackgroundImageProperty, value);
99         }
100
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 bool? Focusable
104         {
105             get => (bool?)GetValue(FocusableProperty);
106             set => SetValue(FocusableProperty, value);
107         }
108
109         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
110         [Obsolete("Deprecated. Please use Size instead.")]
111         [EditorBrowsable(EditorBrowsableState.Never)]
112         public Size2D Size2D
113         {
114             get => (Size2D)GetValue(Size2DProperty);
115             set => SetValue(Size2DProperty, value);
116         }
117
118         /// <summary>
119         /// Defines view's opacity value.
120         /// </summary>
121         /// <since_tizen> 9 </since_tizen>
122         public Selector<float?> Opacity
123         {
124             get
125             {
126                 Selector<float?> opacity = (Selector<float?>)GetValue(OpacityProperty);
127                 return (null != opacity) ? opacity : opacitySelector = new Selector<float?>();
128             }
129             set => SetValue(OpacityProperty, value);
130         }
131
132         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
133         [Obsolete("Deprecated. Please use Position instead.")]
134         [EditorBrowsable(EditorBrowsableState.Never)]
135         public Position2D Position2D
136         {
137             get => (Position2D)GetValue(Position2DProperty);
138             set => SetValue(Position2DProperty, value);
139         }
140
141         /// <summary>
142         /// Determines whether the pivot point should be used to determine the position of the view.
143         /// </summary>
144         /// <since_tizen> 9 </since_tizen>
145         public bool? PositionUsesPivotPoint
146         {
147             get => (bool?)GetValue(PositionUsesPivotPointProperty);
148             set => SetValue(PositionUsesPivotPointProperty, value);
149         }
150
151         /// <summary>
152         /// Gets or sets the origin of a view within its parent's area.<br />
153         /// This is expressed in unit coordinates, such that (0.0, 0.0, 0.5) is the top-left corner of the parent, and (1.0, 1.0, 0.5) is the bottom-right corner.<br />
154         /// The default parent-origin is ParentOrigin.TopLeft (0.0, 0.0, 0.5).<br />
155         /// A view's position is the distance between this origin and the view's anchor-point.<br />
156         /// </summary>
157         /// <since_tizen> 9 </since_tizen>
158         public Position ParentOrigin
159         {
160             get => (Position)GetValue(ParentOriginProperty);
161             set => SetValue(ParentOriginProperty, value);
162         }
163
164         /// <summary>
165         /// Gets or sets the pivot point of a view.<br />
166         /// This is expressed in unit coordinates, such that (0.0, 0.0, 0.5) is the top-left corner of the view, and (1.0, 1.0, 0.5) is the bottom-right corner.<br />
167         /// The default pivot point is PivotPoint.Center (0.5, 0.5, 0.5).<br />
168         /// A view position is the distance between its parent origin and this pivot point.<br />
169         /// A view's orientation is the rotation from its default orientation, the rotation is centered around its pivot point.<br />
170         /// </summary>
171         /// <since_tizen> 9 </since_tizen>
172         public Position PivotPoint
173         {
174             get => (Position)GetValue(PivotPointProperty);
175             set => SetValue(PivotPointProperty, value);
176         }
177
178         /// <summary>
179         /// Gets or sets the width of the view.
180         /// </summary>
181         /// <since_tizen> 9 </since_tizen>
182         public float? SizeWidth
183         {
184             get => (float?)GetValue(SizeWidthProperty);
185             set => SetValue(SizeWidthProperty, value);
186         }
187
188         /// <summary>
189         /// Gets or sets the height of the view.
190         /// </summary>
191         /// <since_tizen> 9 </since_tizen>
192         public float? SizeHeight
193         {
194             get => (float?)GetValue(SizeHeightProperty);
195             set => SetValue(SizeHeightProperty, value);
196         }
197
198         /// <summary>
199         /// Gets or sets the position of the view.
200         /// </summary>
201         /// <since_tizen> 9 </since_tizen>
202         public Position Position
203         {
204             get => (Position)GetValue(PositionProperty);
205             set => SetValue(PositionProperty, value);
206         }
207
208         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
209         [EditorBrowsable(EditorBrowsableState.Never)]
210         public float? PositionX
211         {
212             get => (float?)GetValue(PositionXProperty);
213             set => SetValue(PositionXProperty, value);
214         }
215
216         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
217         [EditorBrowsable(EditorBrowsableState.Never)]
218         public float? PositionY
219         {
220             get => (float?)GetValue(PositionYProperty);
221             set => SetValue(PositionYProperty, value);
222         }
223
224         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
225         [EditorBrowsable(EditorBrowsableState.Never)]
226         public Rotation Orientation
227         {
228             get => (Rotation)GetValue(OrientationProperty);
229             set => SetValue(OrientationProperty, value);
230         }
231
232         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
233         [EditorBrowsable(EditorBrowsableState.Never)]
234         public DrawModeType? DrawMode
235         {
236             get => (DrawModeType?)GetValue(DrawModeProperty);
237             set => SetValue(DrawModeProperty, value);
238         }
239
240         /// <summary>
241         /// Gets or sets the relative to parent size factor of the view.<br />
242         /// This factor is only used when ResizePolicyType is set to either: ResizePolicyType.SizeRelativeToParent or ResizePolicyType.SizeFixedOffsetFromParent.<br />
243         /// This view's size is set to the view's size multiplied by or added to this factor, depending on ResizePolicyType.<br />
244         /// </summary>
245         /// <since_tizen> 9 </since_tizen>
246         [Obsolete("Deprecated. Since Tizen.NUI.ResizePolicyType is deprecated, OnSetResizePolicy is no longer supported. Instead, please use parent view having Tizen.NUI.RelativeLayout as its Layout.")]
247         public Vector3 SizeModeFactor
248         {
249             get => (Vector3)GetValue(SizeModeFactorProperty);
250             set => SetValue(SizeModeFactorProperty, value);
251         }
252
253         /// <summary>
254         /// Gets or sets the width resize policy to be used.
255         /// </summary>
256         /// <since_tizen> 9 </since_tizen>
257         [Obsolete("Deprecated. Please set Tizen.NUI.View.Layout and use Tizen.NUI.View.WidthSpecification instead.")]
258         public ResizePolicyType? WidthResizePolicy
259         {
260             get => (ResizePolicyType?)GetValue(WidthResizePolicyProperty);
261             set => SetValue(WidthResizePolicyProperty, value);
262         }
263
264         /// <summary>
265         /// Gets or sets the height resize policy to be used.
266         /// </summary>
267         /// <since_tizen> 9 </since_tizen>
268         [Obsolete("Deprecated. Please set Tizen.NUI.View.Layout and use Tizen.NUI.View.HeightSpecification instead.")]
269         public ResizePolicyType? HeightResizePolicy
270         {
271             get => (ResizePolicyType?)GetValue(HeightResizePolicyProperty);
272             set => SetValue(HeightResizePolicyProperty, value);
273         }
274
275         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
276         [EditorBrowsable(EditorBrowsableState.Never)]
277         public bool? WidthForHeight
278         {
279             get => (bool?)GetValue(WidthForHeightProperty);
280             set => SetValue(WidthForHeightProperty, value);
281         }
282
283         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
284         [EditorBrowsable(EditorBrowsableState.Never)]
285         public bool? HeightForWidth
286         {
287             get => (bool?)GetValue(HeightForWidthProperty);
288             set => SetValue(HeightForWidthProperty, value);
289         }
290
291         /// <summary>
292         /// Gets or sets the padding for use in layout.
293         /// </summary>
294         /// <since_tizen> 9 </since_tizen>
295         public Extents Padding
296         {
297             get => (Extents)GetValue(PaddingProperty) ?? (padding = new Extents());
298             set => SetValue(PaddingProperty, value);
299         }
300
301         /// <summary>
302         /// Gets or sets the minimum size the view can be assigned in size negotiation.
303         /// </summary>
304         /// <since_tizen> 9 </since_tizen>
305         public Size2D MinimumSize
306         {
307             get => (Size2D)GetValue(MinimumSizeProperty);
308             set => SetValue(MinimumSizeProperty, value);
309         }
310
311         /// <summary>
312         /// Gets or sets the maximum size the view can be assigned in size negotiation.
313         /// </summary>
314         /// <since_tizen> 9 </since_tizen>
315         public Size2D MaximumSize
316         {
317             get => (Size2D)GetValue(MaximumSizeProperty);
318             set => SetValue(MaximumSizeProperty, value);
319         }
320
321         /// This will be public opened in tizen_6.0 after ACR done. Before ACR, need to be hidden as inhouse API.
322         [EditorBrowsable(EditorBrowsableState.Never)]
323         public ClippingModeType? ClippingMode
324         {
325             get => (ClippingModeType?)GetValue(ClippingModeProperty);
326             set => SetValue(ClippingModeProperty, value);
327         }
328
329         /// <summary>
330         /// Sets the size of a view for the width, the height, and the depth.
331         /// </summary>
332         /// <since_tizen> 9 </since_tizen>
333         public Size Size
334         {
335             get => (Size)GetValue(SizeProperty);
336             set => SetValue(SizeProperty, value);
337         }
338
339         /// <summary>
340         /// Gets or sets the Margin for use in layout.
341         /// </summary>
342         /// <since_tizen> 9 </since_tizen>
343         public Extents Margin
344         {
345             get => (Extents)GetValue(MarginProperty) ?? (margin = new Extents());
346             set => SetValue(MarginProperty, value);
347         }
348
349         /// <summary>
350         /// Gets or sets the color of the background of view.
351         /// The mutually exclusive with "BackgroundImage". Setting it overwrites existing "BackgroundImage".
352         /// </summary>
353         /// <since_tizen> 9 </since_tizen>
354         public Selector<Color> BackgroundColor
355         {
356             get
357             {
358                 Selector<Color> color = (Selector<Color>)GetValue(BackgroundColorProperty);
359                 return (null != color) ? color : backgroundColorSelector = new Selector<Color>();
360             }
361             set => SetValue(BackgroundColorProperty, value);
362         }
363
364         /// <summary>
365         /// Color
366         /// </summary>
367         [EditorBrowsable(EditorBrowsableState.Never)]
368         public Selector<Color> Color
369         {
370             get => (Selector<Color>)GetValue(ColorProperty) ?? (colorSelector = new Selector<Color>());
371             set => SetValue(ColorProperty, value);
372         }
373
374         /// <summary>View BackgroundBorder</summary>
375         /// This will be public opened in tizen_5.5 after ACR done. Before ACR, need to be hidden as inhouse API.
376         [EditorBrowsable(EditorBrowsableState.Never)]
377         public Selector<Rectangle> BackgroundImageBorder
378         {
379             get
380             {
381                 Selector<Rectangle> border = (Selector<Rectangle>)GetValue(BackgroundImageBorderProperty);
382                 return (null != border) ? border : backgroundImageBorderSelector = new Selector<Rectangle>();
383             }
384             set => SetValue(BackgroundImageBorderProperty, value);
385         }
386
387         /// <summary>
388         /// Describes a shadow as an image for a View.
389         /// It is null by default.
390         /// </summary>
391         /// <remarks>
392         /// If BoxShadow is not null, the ImageShadow value will be ignored.
393         /// </remarks>
394         [EditorBrowsable(EditorBrowsableState.Never)]
395         public Selector<ImageShadow> ImageShadow
396         {
397             get => (Selector<ImageShadow>)GetValue(ImageShadowProperty);
398             set => SetValue(ImageShadowProperty, value);
399         }
400
401         /// <summary>
402         /// Describes a box shaped shadow drawing for a View.
403         /// </summary>
404         /// <since_tizen> 9 </since_tizen>
405         public Selector<Shadow> BoxShadow
406         {
407             get => (Selector<Shadow>)GetValue(BoxShadowProperty);
408             set => SetValue(BoxShadowProperty, value);
409         }
410
411         /// <summary>
412         /// The radius for the rounded corners of the View.
413         /// The values in Vector4 are used in clockwise order from top-left to bottom-left : Vector4(top-left-corner, top-right-corner, bottom-right-corner, bottom-left-corner).
414         /// </summary>
415         /// <since_tizen> 9 </since_tizen>
416         public Vector4 CornerRadius
417         {
418             get => (Vector4)GetValue(CornerRadiusProperty);
419             set => SetValue(CornerRadiusProperty, value);
420         }
421
422         /// <summary>
423         /// Whether the CornerRadius property value is relative (percentage [0.0f to 1.0f] of the view size) or absolute (in world units).
424         /// It is absolute by default.
425         /// When the policy is relative, the corner radius is relative to the smaller of the view's width and height.
426         /// </summary>
427         /// <since_tizen> 9 </since_tizen>
428         public VisualTransformPolicyType? CornerRadiusPolicy
429         {
430             get => (VisualTransformPolicyType?)GetValue(CornerRadiusPolicyProperty);
431             set => SetValue(CornerRadiusPolicyProperty, value);
432         }
433
434         /// <summary>
435         /// The width for the borderline of the View.
436         /// </summary>
437         [EditorBrowsable(EditorBrowsableState.Never)]
438         public float? BorderlineWidth
439         {
440             get => (float?)GetValue(BorderlineWidthProperty);
441             set => SetValue(BorderlineWidthProperty, value);
442         }
443
444         /// <summary>
445         /// The color for the borderline of the View.
446         /// </summary>
447         [EditorBrowsable(EditorBrowsableState.Never)]
448         public Color BorderlineColor
449         {
450             get => (Color)GetValue(BorderlineColorProperty);
451             set => SetValue(BorderlineColorProperty, value);
452         }
453
454         /// <summary>
455         /// The Relative offset for the borderline of the View.
456         /// recommand [-1.0f to 1.0f] range.
457         /// If -1.0f, borderline draw inside of View.
458         /// If 1.0f, borderline draw outside of View.
459         /// If 0.0f, borderline draw half at inside and half at outside.
460         /// </summary>
461         [EditorBrowsable(EditorBrowsableState.Never)]
462         public float? BorderlineOffset
463         {
464             get => (float?)GetValue(BorderlineOffsetProperty);
465             set => SetValue(BorderlineOffsetProperty, value);
466         }
467
468         /// <summary>
469         /// The ThemeChangeSensitive value of the View.
470         /// </summary>
471         [EditorBrowsable(EditorBrowsableState.Never)]
472         public bool? ThemeChangeSensitive
473         {
474             get => (bool?)GetValue(ThemeChangeSensitiveProperty);
475             set => SetValue(ThemeChangeSensitiveProperty, value);
476         }
477
478
479         /// <summary>
480         /// Allow null properties when merging it into other Theme.
481         /// If the value is true, the null properties reset target properties of the other ViewStyle with same key when merge.
482         /// It is used in <seealso cref="Theme.Merge(string)"/>, <seealso cref="Theme.Merge(Theme)"/>.
483         /// It is also used in <seealso cref="Theme.GetStyle(string)"/> when the Theme has a parent and needs to merge.
484         /// Please note that it is false by default.
485         /// </summary>
486         [EditorBrowsable(EditorBrowsableState.Never)]
487         public bool SolidNull { get; set; } = false;
488
489         /// <summary>
490         /// HashSet of dirty properties. Internal use only.
491         /// </summary>
492         internal HashSet<BindableProperty> DirtyProperties { get; private set; }
493
494         /// <summary>Create a cloned ViewStyle.</summary>
495         [EditorBrowsable(EditorBrowsableState.Never)]
496         public ViewStyle Clone()
497         {
498             var cloned = CreateInstance();
499             cloned.CopyFrom(this);
500
501             return cloned;
502         }
503
504         /// <summary>
505         /// Release instance.
506         /// </summary>
507         /// <since_tizen> 9 </since_tizen>
508         public void Dispose()
509         {
510             Dispose(true);
511             global::System.GC.SuppressFinalize(this);
512         }
513
514         /// <inheritdoc/>
515         [EditorBrowsable(EditorBrowsableState.Never)]
516         public override void CopyFrom(BindableObject other)
517         {
518             var source = other as ViewStyle;
519
520             if (source == null || source.DirtyProperties == null || source.DirtyProperties.Count == 0)
521             {
522                 return;
523             }
524
525             BindableProperty.GetBindablePropertysOfType(GetType(), out var thisBindableProperties);
526
527             if (thisBindableProperties == null)
528             {
529                 return;
530             }
531
532             foreach (var sourceProperty in source.DirtyProperties)
533             {
534                 var sourceValue = source.GetValue(sourceProperty);
535
536                 if (sourceValue == null)
537                 {
538                     continue;
539                 }
540
541                 thisBindableProperties.TryGetValue(sourceProperty.PropertyName, out var destinationProperty);
542
543                 if (destinationProperty != null)
544                 {
545                     SetValue(destinationProperty, sourceValue);
546                 }
547             }
548
549             IncludeDefaultStyle = source.IncludeDefaultStyle;
550         }
551
552         /// <summary>
553         /// Release instance.
554         /// </summary>
555         /// <param name="disposing"> If it true, the method has been called by a user's code. Otherwise the method has been called by the finalizer. </param>
556         /// <since_tizen> 9 </since_tizen>
557         protected virtual void Dispose(bool disposing)
558         {
559             if (disposed)
560             {
561                 return;
562             }
563
564             if (disposing)
565             {
566                 // Dispose managed state (managed objects).
567                 margin?.Dispose();
568                 maximumSize?.Dispose();
569                 minimumSize?.Dispose();
570                 orientation?.Dispose();
571                 padding?.Dispose();
572                 parentOrigin?.Dispose();
573                 pivotPoint?.Dispose();
574                 position?.Dispose();
575                 size?.Dispose();
576                 sizeModeFactor?.Dispose();
577                 cornerRadius?.Dispose();
578                 borderlineColor?.Dispose();
579             }
580
581             disposed = true;
582         }
583
584         /// <summary>
585         /// Method that is called when a bound property is changed.
586         /// </summary>
587         [EditorBrowsable(EditorBrowsableState.Never)]
588         protected override void OnPropertyChangedWithData(BindableProperty property)
589         {
590             base.OnPropertyChangedWithData(property);
591
592             if (property != null)
593             {
594                 (DirtyProperties ?? (DirtyProperties = new HashSet<BindableProperty>())).Add(property);
595             }
596         }
597
598         internal ViewStyle CreateInstance()
599         {
600             return (ViewStyle)Activator.CreateInstance(GetType());
601         }
602
603         /// <summary>Merge other style into the current style without creating new one.</summary>
604         [EditorBrowsable(EditorBrowsableState.Never)]
605         internal void MergeDirectly(ViewStyle other)
606         {
607             CopyFrom(other);
608         }
609     }
610
611     /// <summary> Extension methods for ViewStyle class.</summary>
612     [EditorBrowsable(EditorBrowsableState.Never)]
613     public static class ViewStyleExtension
614     {
615         /// <summary>Merge two styles into the new one.</summary>
616         /// <exception cref="ArgumentException">Thrown when failed because of an invalid parameter.</exception>
617         [EditorBrowsable(EditorBrowsableState.Never)]
618         public static TOut Merge<TOut>(this TOut value, TOut other) where TOut : Tizen.NUI.BaseComponents.ViewStyle
619         {
620             var newStyle = value.Clone() as TOut;
621
622             newStyle?.CopyFrom(other);
623
624             return newStyle;
625         }
626     }
627 }