[dali_1.0.1] Merge branch 'tizen'
[platform/core/uifw/dali-toolkit.git] / docs / content / programming-guide / size-negotiation.h
1 /*! \page size-negotiation Size Negotiation
2  *
3 <h2 class="pg">Overview</h2>
4
5 Size negotiation provides the ability for controls to be resized without the application having to set a size.
6 A parent control can resize itself according to its children. Each control can provide hints to using policies for the width and height.
7 Controls will be relaid just once and only when requested to, rather than relaid out several times when different properties are set.
8 Using size negotiation avoids the need for using size constraints to resize children, which would need to be calculated in the update
9 thread every time even minor changes occur.
10
11 This topic covers size policies, deriving from ControlImpl, size policy examples and the size negotiation algorithm.
12
13 <h2 class="pg">Size Policies</h2>
14
15 Each control has a policy for both width and height:
16 - <b>Fixed:</b> The size is fixed to the size set by the application. If no size is set, then the size is fixed to the <i>natural</i> size of the control.
17 - <b>Mininum:</b> The size can grow and shrink but cannot be smaller than the <i>minimum</i> size specified.
18 - <b>Maximum:</b> The size can grow and shrink but cannot be larger than the <i>maximum</i> size specified.
19 - <b>Range:</b> The size can grow or shrink but within the <i>minimum</i> and <i>maximum</i> sizes specified.
20 - <b>Flexible:</b> The size of the control can grow or shrink as required without any limits.
21
22 Currently, by default, controls use a fixed size policy for width and height. If one dimension is set, and the other dimension is set to zero, then the latter
23 dimension is assumed to have a non fixed policy.
24
25 <h2 class="pg">Deriving from ControlImpl</h2>
26
27 The size negotiation utilises several methods to work out the best size of a control. The default behaviour is in the ControlImpl class.
28 The following methods can be overridden.
29 @code Vector3 GetNaturalSize() @endcode
30 This method should return the natural size of the control. This can be dependent on the control's children or the control may decide to have a fixed size.
31
32 @code float GetHeightForWidth( float width ) @endcode
33 This method should return the height it needs to be when given a certain width.
34
35 @code float GetWidthForHeight( float height ) @endcode
36 This method should return the width it needs to be when given a certain height.
37
38 All these methods can be overridden by deriving classes. This allows each control to dictate what size it would like to be. If you want the default behaviour,
39 then you do not have to override these methods. A parent control can call the child's methods to determine its size if it needs to.
40
41 <h2 class="pg">Size Policies and Virtual Methods</h2>
42
43 The table below shows the methods that are called when certain width and height policies are in place.
44
45 <table>
46   <tr>
47     <td></td>
48     <td><b>Fixed Height</b></td>
49     <td><b>Height Not Fixed (All other policies)</b></td>
50   </tr>
51   <tr>
52     <td><b>Fixed Width</b></td>
53     <td>
54     - Use size set by application
55     - If only height set by application
56       - Use height set by application
57       - Use <b>GetWidthForHeight()</b> for width
58     - If only width set by application
59       - Use width set by application
60       - Use <b>GetHeightForWidth()</b> for height
61     - If not set, then get size by calling <b>GetNaturalSize()</b>
62     </td>
63     <td>
64     - Use width set by application
65     - Use allocated width if not set
66       - Ensure it satisfies our width policy
67       - Adjust if required
68     - Use <b>GetHeightForWidth()</b> for height
69     - Ensure height satisfies our height policy
70       - Adjust if required
71     </td>
72   </tr>
73   <tr>
74     <td><b>Width Not Fixed (All other policies)</b></td>
75     <td>
76     - Use height set by application
77     - Use allocated height if not set
78       - Ensure it satisfies our height policy
79       - Adjust if required
80     - Use <b>GetWidthForHeight()</b> for width
81     - Ensure width satisfies our width policy
82       - Adjust if required
83     </td>
84     <td>
85     - Constrain the allocated width and height according to the two policies
86     </td>
87   </tr>
88 </table>
89
90 <h2 class="pg">Size Policy Examples</h2>
91
92 <h3 class="pg">Policy: Fixed Width and Height (1)</h3>
93
94 <table border=0 cellpadding=10><tr>
95 <td>
96 \image html FixedWidthHeight.png
97 </td>
98 <td>
99 The application/control has set the following settings:
100 - <b>SetSize:</b> 200 x 300
101 - <b>Natural Size:</b> 400 x 400
102 - <b>Width To Height Ratio:</b> 1 to 1
103 - <b>Width Policy:</b> Fixed
104 - <b>Height Policy:</b> Fixed
105 - <b>ParentOrigin:</b> TopLeft
106 - <b>AnchorPoint:</b> TopLeft
107
108 Control methods called:
109 - None
110
111 Result
112 - <b>Allocated size:</b> 200 x 300
113 </td>
114 </tr></table>
115
116 <h3 class="pg">Policy: Fixed Width and Height (2)</h3>
117
118 <table border=0 cellpadding=10><tr>
119 <td>
120 \image html FixedWidthHeight2.png
121 </td>
122 <td>
123 The application/control has set the following settings:
124 - <b>SetSize:</b> 0 x 0 (No size set)
125 - <b>Natural Size:</b> 400 x 400
126 - <b>Width To Height Ratio:</b> 1 to 1
127 - <b>Width Policy:</b> Fixed
128 - <b>Height Policy:</b> Fixed
129 - <b>ParentOrigin:</b> TopLeft
130 - <b>AnchorPoint:</b> TopLeft
131
132 Control methods called:
133 - GetNaturalSize() = 400 x 400
134
135 Result
136 - <b>Allocated size:</b> 400 x 400
137 </td>
138 </tr></table>
139
140 <h3 class="pg">Policy: Flexible Width and Height</h3>
141
142 <table border=0 cellpadding=10><tr>
143 <td>
144 \image html FlexibleWidthHeight.png
145 </td>
146 <td>
147 The application/control has set the following settings:
148 - <b>SetSize:</b> 200 x 300
149 - <b>Natural Size:</b> 400 x 400
150 - <b>Width To Height Ratio:</b> 1 to 1
151 - <b>Width Policy:</b> Flexible
152 - <b>Height Policy:</b> Flexible
153 - <b>ParentOrigin:</b> TopLeft
154 - <b>AnchorPoint:</b> TopLeft
155
156 Control methods called:
157 - None
158
159 Result
160 - <b>Allocated size:</b> 480 x 800  (Assume stage size 480 x 800)
161 </td>
162 </tr></table>
163
164 <h3 class="pg">Policy: Fixed Width and Flexible Height (1)</h3>
165
166 <table border=0 cellpadding=10><tr>
167 <td>
168 \image html FixedWidthFlexibleHeight.png
169 </td>
170 <td>
171 The application/control has set the following settings:
172 - <b>SetSize:</b> 200 x 300
173 - <b>Natural Size:</b> 400 x 400
174 - <b>Width To Height Ratio:</b> 1 to 1
175 - <b>Width Policy:</b> Fixed
176 - <b>Height Policy:</b> Flexible
177 - <b>ParentOrigin:</b> TopLeft
178 - <b>AnchorPoint:</b> TopLeft
179
180 Control methods called:
181 - GetHeightForWidth( 200 ) = 200
182
183 Result
184 - <b>Allocated size:</b> 200 x 200
185 </td>
186 </tr></table>
187
188 <h3 class="pg">Policy: Fixed Width and Flexible Height (2)</h3>
189
190 <table border=0 cellpadding=10><tr>
191 <td>
192 \image html FixedWidthFlexibleHeight.png
193 </td>
194 <td>
195 The application/control has set the following settings:
196 - <b>SetSize:</b> 200 x 0 (No height set)
197 - <b>Natural Size:</b> 400 x 400
198 - <b>Width To Height Ratio:</b> 1 to 1
199 - <b>Width Policy:</b> Fixed
200 - <b>Height Policy:</b> Flexible
201 - <b>ParentOrigin:</b> TopLeft
202 - <b>AnchorPoint:</b> TopLeft
203
204 Control methods called:
205 - GetHeightForWidth( 200 ) = 200
206
207 Result
208 - <b>Allocated size:</b> 200 x 200
209 </td>
210 </tr></table>
211
212 <h3 class="pg">Policy: Fixed Width and Flexible Height (3)</h3>
213
214 If the control did not have the GetHeightForWidth() method, then the <i>size set</i> is used to calculate the ratio.
215
216 <table border=0 cellpadding=10><tr>
217 <td>
218 \image html FixedWidthFlexibleHeight2.png
219 </td>
220 <td>
221 The application/control has set the following settings:
222 - <b>SetSize:</b> 200 x 0 (No height set)
223 - <b>Natural Size:</b> 400 x 400
224 - <b>Width To Height Ratio:</b> Not set
225 - <b>Width Policy:</b> Fixed
226 - <b>Height Policy:</b> Flexible
227 - <b>ParentOrigin:</b> TopLeft
228 - <b>AnchorPoint:</b> TopLeft
229
230 Control methods called:
231 - GetHeightForWidth( 200 ) = 200  <i>(Unable to calculate ratio using size set)</i>
232
233 Result
234 - <b>Allocated size:</b> 200 x 800  <i>(Allocate entire height)</i>
235 </td>
236 </tr></table>
237
238 <h3 class="pg">Policy: Fixed Width and Flexible Height (4)</h3>
239
240 <table border=0 cellpadding=10><tr>
241 <td>
242 \image html FlexibleWidthHeight.png
243 </td>
244 <td>
245 The application/control has set the following settings:
246 - <b>SetSize:</b> 0 x 0 (No size set)
247 - <b>Natural Size:</b> 400 x 400
248 - <b>Width To Height Ratio:</b> 1 to 1
249 - <b>Width Policy:</b> Fixed
250 - <b>Height Policy:</b> Flexible
251 - <b>ParentOrigin:</b> TopLeft
252 - <b>AnchorPoint:</b> TopLeft
253
254 Control methods called:
255 - GetHeightForWidth( 0 ) = 0
256
257 Result
258 - <b>Allocated size:</b> 480 x 800  <i>(Allocate entire size)</i>
259 </td>
260 </tr></table>
261
262 <h3 class="pg">Policy: Flexible Width and Fixed Height (1)</h3>
263
264 <table border=0 cellpadding=10><tr>
265 <td>
266 \image html FlexibleWidthFixedHeight.png
267 </td>
268 <td>
269 The application/control has set the following settings:
270 - <b>SetSize:</b> 0 x 300 (No width set)
271 - <b>Natural Size:</b> 400 x 400
272 - <b>Width To Height Ratio:</b> 1 to 1
273 - <b>Width Policy:</b> Flexible
274 - <b>Height Policy:</b> Fixed
275 - <b>ParentOrigin:</b> TopLeft
276 - <b>AnchorPoint:</b> TopLeft
277
278 Control methods called:
279 - GetWidthForHeight( 300 ) = 300
280
281 Result
282 - <b>Allocated size:</b> 300 x 300
283 </td>
284 </tr></table>
285
286 <h3 class="pg">Policy: Flexible Width and Fixed Height (2)</h3>
287
288 If the control did not have the GetWidthForHeight() method, then the <i>size set</i> is used to calculate the ratio.
289
290 <table border=0 cellpadding=10><tr>
291 <td>
292 \image html FlexibleWidthFixedHeight2.png
293 </td>
294 <td>
295 The application/control has set the following settings:
296 - <b>SetSize:</b> 0 x 300 (No width set)
297 - <b>Natural Size:</b> 400 x 400
298 - <b>Width To Height Ratio:</b> Not set
299 - <b>Width Policy:</b> Flexible
300 - <b>Height Policy:</b> Fixed
301 - <b>ParentOrigin:</b> TopLeft
302 - <b>AnchorPoint:</b> TopLeft
303
304 Control methods called:
305 - GetWidthForHeight( 300 ) = 0  <i>(Unable to calculate ratio using size set)</i>
306
307 Result
308 - <b>Allocated size:</b> 480 x 300  <i>(Allocate entire width)</i>
309 </td>
310 </tr></table>
311
312 <h2 class="pg">The Size Negotiation Algorithm</h2>
313
314 <h3 class="pg">The Algorithm</h3>
315
316 -# The algorithm starts at the stage
317   - All top level controls are found and offered the size of the stage
318   - The control negotiates the size offered by using the policy rules to determine the size that it should be allocated
319   - The control is then set to that allocated size
320 -# The control is responsible for setting the sizes of all its children
321   - Can set a size on an Actor
322   - Or can call relayout on a Control directly
323 -# Children that a control does not handle, the control can add to a container so that the top-level algorithm delas with it instead
324   - The control should call Relayout with the child and size of itself as parameters
325
326 <table border=0 cellpadding=10><tr>
327 <td>
328 \image html Algorithm1.png
329 </td>
330 <td>
331 \image html Algorithm2.png
332 </td>
333 </tr></table>
334
335 <h3 class="pg">A closer look at Control A</h3>
336
337 Taking a closer look at Control A we see in this example that children should share the width equally and that the height of Control A
338 is the maximum height of the children.
339
340 <table border=0 cellpadding=10><tr>
341 <td>
342 \image html Algorithm3.png
343 </td>
344 <td>
345 <table border=0 cellpadding=10><tr>
346 <td>
347 \image html Algorithm4.png
348 </td>
349 </tr></table>
350 </td>
351 </tr></table>
352
353 @code
354 class ControlA : public Control
355 {
356   ...
357 private:
358   // Data
359   Actor mActorC; // Container to store children
360   TextView mControlD; // Some text we want to display
361   ImageActor mActorD; // An image
362 };
363 @endcode
364
365 @code
366 Vector3 ControlA::GetNaturalSize()
367 {
368   // Width is total of ControlD and ActorD
369   // Height is max of ControlD and ActorD
370   // Don't care about the Depth
371   Vector3 naturalSize;  // Initialised to (0.0f, 0.0f, 0.0f)
372
373   if ( mControlD )
374   {
375     // We know ControlD is a control, so just ask its natural size
376     naturalSize = mControlD.GetNaturalSize();
377   }
378
379   if ( mActorD )
380   {
381     // We know ActorD is an ImageActor, we can get the image's natural size
382     Image image = mActorD.GetImage();
383     naturalSize.width += image.GetWidth;
384     naturalSize.height = std::max( naturalSize.height, image.GetHeight() );
385   }
386
387   return naturalSize;
388 }
389 @endcode
390
391 GetHeightForWidth() and GetWidthForHeight() can be created in a similar manner.
392
393 @code
394 void ControlA::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
395 {
396   // Width to be shared between ControlD and ActorD
397   Vector2 childSize( size.width * 0.5f, size.height );
398
399   if ( mActorC )
400   {
401     // ActorC is the same size as ControlA
402     mActorC.SetSize( size );
403   }
404
405   if ( mControlD )
406   {
407     Relayout( mControlD, childSize );
408     // Can add more complex calculations to preserve aspect ratio etc.
409   }
410
411   if ( mActorD )
412   {
413     mActorD.SetSize( childSize );
414     // Can add more complex calculations to preserve aspect ratio etc.
415   }
416 }
417 @endcode
418
419 The allocated layout is as follows.
420 <table border=0 cellpadding=10><tr>
421 <td>
422 \image html Algorithm8.png
423 </td>
424 </tr></table>
425
426 <h3 class="pg">A closer look at Control B</h3>
427
428 In this example we have the following requirements:
429 - Control B creates a small border around its children
430 - Control B just allocates whatever its given to its children (minus the border)
431 - Actor E is a simple container actor and contains one control (Control E)
432 - Control B is not aware of the actors it contains
433
434 <table border=0 cellpadding=10><tr>
435 <td>
436 \image html Algorithm9.png
437 </td>
438 <td>
439 \image html Algorithm10.png
440 </td>
441 </tr></table>
442
443 @code
444 void ControlA::OnRelaidOut( Vector2 size, ActorSizeContainer& container )
445 {
446   // Width of children is our size minus border
447   Vector3 childSize( size.width - mBorder.width * 2.0f,
448                      size.height - mBorder.height * 2.0f );
449
450   // Our children should be set to the childSize
451   ActorContainer children( Self().GetChildren() );
452   for ( ActorIter iter = children.begin(), endIter = children.end();
453         iter != endIter;
454         ++iter )
455   {
456     Relayout( *iter, childSize, container );
457   }
458 }
459 @endcode
460
461 The Relayout method will add ControlB's children to the size negotiation algorithm container where the child's size will be negotiated. Control E's
462 size will be negotiated with the childSize as the allocation.
463
464 *
465 */