[NUI] TCSACR-226 code change (#1032)
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / public / Layouting / AbsoluteLayout.cs
1 /* Copyright (c) 2019 Samsung Electronics Co., Ltd.
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  *
15  */
16 using System;
17 using Tizen.NUI.BaseComponents;
18
19 namespace Tizen.NUI
20 {
21     /// <summary>
22     /// [Draft] This class implements a absolute layout, allowing explicit positioning of children.
23     ///  Positions are from the top left of the layout and can be set using the Actor::Property::POSITION and alike.
24     /// </summary>
25     public class AbsoluteLayout : LayoutGroup
26     {
27         /// <summary>
28         /// Struct to store Measured states of height and width.
29         /// </summary>
30         private struct HeightAndWidthState
31         {
32             public MeasuredSize.StateType widthState;
33             public MeasuredSize.StateType heightState;
34
35             public HeightAndWidthState( MeasuredSize.StateType width, MeasuredSize.StateType height)
36             {
37                 widthState = width;
38                 heightState = height;
39             }
40         }
41
42         /// <summary>
43         /// [Draft] Constructor
44         /// </summary>
45         /// <since_tizen> 6 </since_tizen>
46         public AbsoluteLayout()
47         {
48         }
49
50         /// <summary>
51         /// Measure the layout and its content to determine the measured width and the measured height.<br />
52         /// </summary>
53         /// <param name="widthMeasureSpec">horizontal space requirements as imposed by the parent.</param>
54         /// <param name="heightMeasureSpec">vertical space requirements as imposed by the parent.</param>
55         /// <since_tizen> 6 </since_tizen>
56         protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
57         {
58             float totalHeight = 0.0f;
59             float totalWidth = 0.0f;
60
61             HeightAndWidthState childState = new HeightAndWidthState(MeasuredSize.StateType.MeasuredSizeOK,
62                                                                      MeasuredSize.StateType.MeasuredSizeOK);
63
64             float minPositionX = 0.0f;
65             float minPositionY = 0.0f;
66             float maxPositionX = 0.0f;
67             float maxPositionY = 0.0f;
68
69             // measure children
70             foreach( LayoutItem childLayout in LayoutChildren )
71             {
72                 if (childLayout != null)
73                 {
74                     // Get size of child
75                     MeasureChild( childLayout, widthMeasureSpec, heightMeasureSpec );
76                     float childWidth = childLayout.MeasuredWidth.Size.AsDecimal();
77                     float childHeight = childLayout.MeasuredHeight.Size.AsDecimal();
78
79                     // Determine the width and height needed by the children using their given position and size.
80                     // Children could overlap so find the left most and right most child.
81                     Position2D childPosition = childLayout.Owner.Position2D;
82                     float childLeft = childPosition.X;
83                     float childTop = childPosition.Y;
84
85                     minPositionX = Math.Min( minPositionX, childLeft );
86                     maxPositionX = Math.Max( maxPositionX, childLeft + childWidth );
87                     // Children could overlap so find the highest and lowest child.
88                     minPositionY = Math.Min( minPositionY, childTop );
89                     maxPositionY = Math.Max( maxPositionY, childTop + childHeight );
90
91                     // Store current width and height needed to contain all children.
92                     totalWidth = maxPositionX - minPositionX;
93                     totalHeight = maxPositionY - minPositionY;
94
95                     if (childLayout.MeasuredWidth.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
96                     {
97                         childState.widthState = MeasuredSize.StateType.MeasuredSizeTooSmall;
98                     }
99                     if (childLayout.MeasuredWidth.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
100                     {
101                         childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall;
102                     }
103                 }
104             }
105
106
107             MeasuredSize widthSizeAndState = ResolveSizeAndState(new LayoutLength(totalWidth), widthMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK);
108             MeasuredSize heightSizeAndState = ResolveSizeAndState(new LayoutLength(totalHeight), heightMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK);
109             totalWidth = widthSizeAndState.Size.AsDecimal();
110             totalHeight = heightSizeAndState.Size.AsDecimal();
111
112             // Ensure layout respects it's given minimum size
113             totalWidth = Math.Max( totalWidth, SuggestedMinimumWidth.AsDecimal() );
114             totalHeight = Math.Max( totalHeight, SuggestedMinimumHeight.AsDecimal() );
115
116             widthSizeAndState.State = childState.widthState;
117             heightSizeAndState.State = childState.heightState;
118
119             SetMeasuredDimensions( ResolveSizeAndState( new LayoutLength(totalWidth), widthMeasureSpec, childState.widthState ),
120                                    ResolveSizeAndState( new LayoutLength(totalHeight), heightMeasureSpec, childState.heightState ) );
121         }
122
123         /// <summary>
124         /// Assign a size and position to each of its children.<br />
125         /// </summary>
126         /// <param name="changed">This is a new size or position for this layout.</param>
127         /// <param name="left">Left position, relative to parent.</param>
128         /// <param name="top"> Top position, relative to parent.</param>
129         /// <param name="right">Right position, relative to parent.</param>
130         /// <param name="bottom">Bottom position, relative to parent.</param>
131         /// <since_tizen> 6 </since_tizen>
132         protected override void OnLayout(bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom)
133         {
134             // Absolute layout positions it's children at their Actor positions.
135             // Children could overlap or spill outside the parent, as is the nature of absolute positions.
136             foreach( LayoutItem childLayout in LayoutChildren )
137             {
138                 if( childLayout != null )
139                 {
140                     LayoutLength childWidth = childLayout.MeasuredWidth.Size;
141                     LayoutLength childHeight = childLayout.MeasuredHeight.Size;
142
143                     Position2D childPosition = childLayout.Owner.Position2D;
144
145                     LayoutLength childLeft = new LayoutLength(childPosition.X);
146                     LayoutLength childTop = new LayoutLength(childPosition.Y);
147
148                     childLayout.Layout( childLeft, childTop, childLeft + childWidth, childTop + childHeight );
149                 }
150             }
151         }
152     }
153
154 } // namespace