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