Fix nested layout issue
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / devel-api / layouting / measure-spec.h
1 #ifndef DALI_TOOLKIT_LAYOUTING_MEASURE_SPEC_H
2 #define DALI_TOOLKIT_LAYOUTING_MEASURE_SPEC_H
3
4 /*
5  * Copyright (c) 2018 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 #include <dali/public-api/common/dali-common.h>
21 #include <dali-toolkit/devel-api/layouting/layout-length.h>
22
23 #include <sstream>
24
25 namespace Dali
26 {
27 namespace Toolkit
28 {
29
30 /**
31  * A MeasureSpec is used during the Measure pass by a LayoutGroup to inform it's children
32  * how to be measured. For instance, it may measure a child with an exact width and an unspecified
33  * height in order to determine height for width.
34  */
35 class DALI_IMPORT_API MeasureSpec
36 {
37 public:
38   using IntType = LayoutLength::IntType;
39
40   enum class Mode
41   {
42     UNSPECIFIED, ///< This is used by a parent to determine the desired dimension of a child layout.
43     EXACTLY, /** This is used by a parent to impose an exact size on the child. The child must use
44                  this size, and guarantee that all of its descendants will fit within this size */
45     AT_MOST /** This is used by the parent to impose a maximum size on the child. The child must guarantee
46              * that it and all of it's descendants will fit within this size. */
47   };
48
49   MeasureSpec( LayoutLength measureSpec, MeasureSpec::Mode mode )
50   : mSize( measureSpec.mValue ),
51     mMode( mode )
52   {
53   }
54
55   MeasureSpec( IntType measureSpec )
56   : mSize( measureSpec ),
57     mMode( Mode::UNSPECIFIED )
58   {
59   }
60
61   ~MeasureSpec() = default;
62
63   MeasureSpec& operator=( const MeasureSpec& rhs )
64   {
65     if( this != &rhs )
66     {
67       this->mSize = rhs.mSize;
68       this->mMode = rhs.mMode;
69     }
70     return *this;
71   }
72
73   bool operator==( MeasureSpec value )
74   {
75     return mSize == value.mSize;
76   }
77
78   bool operator!=( MeasureSpec value )
79   {
80     return mSize != value.mSize;
81   }
82
83   /**
84    * @brief Get the mode of the measure spec.
85    *
86    * @return The mode of the measure spec
87    */
88   MeasureSpec::Mode GetMode() const
89   {
90     return mMode;
91   }
92
93   /**
94    * @brief Get the size of the measure spec
95    *
96    * @return the size of the measure spec
97    */
98   IntType GetSize() const
99   {
100     return mSize;
101   }
102
103   /**
104    * @brief Adjust the measure size by the given delta.
105    *
106    * Used only for EXACT and AT_MOST modes.
107    * @param[in] measureSpec the measure spec to adjust
108    * @param[in] delta A positive or negative value to adjust the measure spec by.
109    *
110    * @note if the adjusted size is negative, it is zeroed.
111    * @return A new measure spec with the adjusted values.
112    */
113   static MeasureSpec Adjust( MeasureSpec measureSpec, int delta )
114   {
115     auto mode = measureSpec.GetMode();
116     auto size = measureSpec.GetSize();
117
118     if( mode == MeasureSpec::Mode::UNSPECIFIED )
119     {
120       return MeasureSpec( size, MeasureSpec::Mode::UNSPECIFIED );
121     }
122
123     if( delta < 0 && measureSpec.mSize < static_cast<IntType>(abs(delta)) )
124     {
125       size = 0;
126     }
127     else
128     {
129       size += delta;
130     }
131     return MeasureSpec( size, mode );
132   }
133
134 public:
135   IntType  mSize; ///< The specified size
136   Mode     mMode; ///< The measure mode
137 };
138
139 inline std::ostream& operator<< (std::ostream& o, const MeasureSpec& measureSpec )
140 {
141   return o << ( (measureSpec.GetMode() == MeasureSpec::Mode::UNSPECIFIED ? "Unspecified"
142                  : (measureSpec.GetMode() == MeasureSpec::Mode::EXACTLY ? "Exactly":"At most" ) ) )
143            << " " << measureSpec.GetSize();
144 }
145
146 } //namespace Toolkit
147 } //namespace Dali
148
149
150 #endif // DALI_TOOLKIT_LAYOUTING_MEASURE_SPEC_H