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