[NUI] Integreation from dalihub (#988)
[platform/core/csapi/tizenfx.git] / src / Tizen.NUI / src / internal / 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     internal 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         public AbsoluteLayout()
46         {
47         }
48
49         protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
50         {
51             float totalHeight = 0.0f;
52             float totalWidth = 0.0f;
53
54             HeightAndWidthState childState = new HeightAndWidthState(MeasuredSize.StateType.MeasuredSizeOK,
55                                                                      MeasuredSize.StateType.MeasuredSizeOK);
56
57             float minPositionX = 0.0f;
58             float minPositionY = 0.0f;
59             float maxPositionX = 0.0f;
60             float maxPositionY = 0.0f;
61
62             // measure children
63             foreach( LayoutItem childLayout in _children )
64             {
65                 if (childLayout != null)
66                 {
67                     // Get size of child
68                     MeasureChild( childLayout, widthMeasureSpec, heightMeasureSpec );
69                     float childWidth = childLayout.MeasuredWidth.Size.AsDecimal();
70                     float childHeight = childLayout.MeasuredHeight.Size.AsDecimal();
71
72                     // Determine the width and height needed by the children using their given position and size.
73                     // Children could overlap so find the left most and right most child.
74                     Position2D childPosition = childLayout.Owner.Position2D;
75                     float childLeft = childPosition.X;
76                     float childTop = childPosition.Y;
77
78                     minPositionX = Math.Min( minPositionX, childLeft );
79                     maxPositionX = Math.Max( maxPositionX, childLeft + childWidth );
80                     // Children could overlap so find the highest and lowest child.
81                     minPositionY = Math.Min( minPositionY, childTop );
82                     maxPositionY = Math.Max( maxPositionY, childTop + childHeight );
83
84                     // Store current width and height needed to contain all children.
85                     totalWidth = maxPositionX - minPositionX;
86                     totalHeight = maxPositionY - minPositionY;
87
88                     if (childLayout.MeasuredWidthAndState.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
89                     {
90                         childState.widthState = MeasuredSize.StateType.MeasuredSizeTooSmall;
91                     }
92                     if (childLayout.MeasuredWidthAndState.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
93                     {
94                         childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall;
95                     }
96                 }
97             }
98
99
100             MeasuredSize widthSizeAndState = ResolveSizeAndState(new LayoutLength(totalWidth), widthMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK);
101             MeasuredSize heightSizeAndState = ResolveSizeAndState(new LayoutLength(totalHeight), heightMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK);
102             totalWidth = widthSizeAndState.Size.AsDecimal();
103             totalHeight = heightSizeAndState.Size.AsDecimal();
104
105             // Ensure layout respects it's given minimum size
106             totalWidth = Math.Max( totalWidth, SuggestedMinimumWidth.AsDecimal() );
107             totalHeight = Math.Max( totalHeight, SuggestedMinimumHeight.AsDecimal() );
108
109             widthSizeAndState.State = childState.widthState;
110             heightSizeAndState.State = childState.heightState;
111
112             SetMeasuredDimensions( ResolveSizeAndState( new LayoutLength(totalWidth), widthMeasureSpec, childState.widthState ),
113                                    ResolveSizeAndState( new LayoutLength(totalHeight), heightMeasureSpec, childState.heightState ) );
114         }
115
116         protected override void OnLayout(bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom)
117         {
118             // Absolute layout positions it's children at their Actor positions.
119             // Children could overlap or spill outside the parent, as is the nature of absolute positions.
120             foreach( LayoutItem childLayout in _children )
121             {
122                 if( childLayout != null )
123                 {
124                     LayoutLength childWidth = childLayout.MeasuredWidth.Size;
125                     LayoutLength childHeight = childLayout.MeasuredHeight.Size;
126
127                     Position2D childPosition = childLayout.Owner.Position2D;
128
129                     LayoutLength childLeft = new LayoutLength(childPosition.X);
130                     LayoutLength childTop = new LayoutLength(childPosition.Y);
131
132                     childLayout.Layout( childLeft, childTop, childLeft + childWidth, childTop + childHeight );
133                 }
134             }
135         }
136     }
137
138 } // namespace