New size negotiation
[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, also known as layout management, is responsible for allocating sizes to all actors on the stage based on rules of dependency between
6 the actors. Requests for relayout on actors are collected during the frame with the actual relayout performed at the end of the frame.
7
8 This document details how to use the size negotiation API and is intended for application writters.
9
10 The topics covered are:
11 - Dimensions
12 - Resize policies
13 - Actor
14 - Debugging
15
16 <h2 class="pg">Dimensions</h2>
17
18 The notion of width and height is generalised into the concept of a Dimension. Several methods take a Dimension parameter.
19
20 The Dimension enum specifies the available dimensions as bitfields:
21 - WIDTH
22 - HEIGHT
23
24 If a method can process width and height at the same time then the ALL_DIMENSIONS mask can be specified.
25
26 <h2 class="pg">Resize Policies</h2>
27
28 <h3>Policies</h3>
29 The ResizePolicy enum specifies a range of options for controlling the way actors resize. These are powerful rules that enable much automatic
30 resizing behaviour. They are as following:
31
32 - FIXED: This is the option to use when you want the specific definite size as set by SetPreferredSize
33 - USE_NATURAL_SIZE: Use this option for objects such as images or text to get their natural size e.g. The dimensions of the image, or the size of the text without wrapping. Also use this on TableViews when the size of the table is dependent on its children.
34 - FILL_TO_PARENT: Size will fill up to the size of its parent's size, taking a size factor into account to allow proportionate filling
35 - FIT_TO_CHILDREN: Size will scale around the size of the actor's children. E.g. A popup's height may resize itself around it's contents.
36 - DIMENSION_DEPENDENCY: This covers rules such as width-for-height and height-for-width. You specify that one dimension depends on another.
37
38 \image html size-negotiation/ResizePolicies.png
39
40 <h2 class="pg">Actor</h2>
41
42 This section details how an actor may be used with size negotiation.
43
44 <h3>Enabling Size Negotiation</h3>
45
46 The first thing to do is to specify whether you want an actor to be included or excluded from the relayout process. The following method is used to enable or disable the relayout
47 for an individual actor.
48 @code void SetRelayoutEnabled( bool enabled ) @endcode
49 Text and image actors have relayout enabled by default, while a plain Actor is disabled. Be aware that if desiring to use an Actor in relayout
50 then relayout needs to be explicitly enabled first.
51
52 <h3>Specifying Size Policies</h3>
53
54 The next step is to specify how an actor will be size negotiated. The resize policies for an actor may be specified by the following method:
55 @code void SetResizePolicy( ResizePolicy policy, Dimension dimension ) @endcode
56 It is common to specifiy different policies for the different dimensions of width and height to achive different layouts. Different actors have
57 different resize policies specified by default. For example ImageActors are set to use USE_NATURAL_SIZE.
58
59 The following example code snippet shows rootActor having its width policy set to FILL_TO_PARENT and its height policy set to FIT_TO_CHILDREN.
60 It has an ImageActor added to it with an explicit call to USE_NATURAL_SIZE in both dimensions called on it. This will make an actor that will
61 fill up the space of its parent in the width dimension and fit to its child in the height dimension. As the image actor child is using natural size
62 the height of the root actor will fit to the height of the child image.
63
64 @code
65 Actor rootActor = Actor::New();
66 rootActor.SetRelayoutEnabled( true );
67 rootActor.SetResizePolicy( FILL_TO_PARENT, WIDTH );
68 rootActor.SetResizePolicy( FIT_TO_CHILDREN, HEIGHT );
69 ImageActor image = ImageActor::New( Image::New( MY_IMAGE_PATH ) );
70 image.SetResizePolicy( USE_NATURAL_SIZE, ALL_DIMENSIONS );
71 rootActor.Add( image );
72 @endcode
73
74 The following images show the before and after layouts for this code example.
75
76 Before:
77 \image html size-negotiation/SizeNegotiationExample_Before.png
78 After:
79 \image html size-negotiation/SizeNegotiationExample_After.png
80
81 This example shows an actor rootActor set to expand to its parent's width and contract/expand around its child's height. The child image actor
82 is set to natural size which means it will display at the acutal size of the image.
83
84 To specify that a dimension has a dependency on another dimension use the following method. Calling this method will automatically set the resize policy to be DIMENSION_DEPENDENCY
85 for the given dimension.
86 @code void SetDimensionDependency( Dimension dimension, Dimension dependency ) @endcode
87 For example if dimension is HEIGHT and dependency is WIDTH then there is a height-for-width dependency in effect. The classic use case for this
88 is a text view that wraps its text. The following example snippet shows a text view that expands its width to the size of its parent, wraps its
89 contents and then determines its height based on the width.
90 @code
91 TextView text = TextView::New( "Example" );
92 text.SetMultilinePolicy( SplitByWord );
93 text.SetResizePolicy( FILL_TO_PARENT, WIDTH );
94 text.SetDimensionDependency( HEIGHT, WIDTH );
95 @endcode
96
97 <h3>Specifying Sizes and Size Limits</h3>
98
99 When wanting a specific fixed size for an actor then specify the resize policy to be FIXED and set the desired, or preferred size using the following method.
100 This method is to be used instead of SetSize when wishing to specify a size for an actor being size negotiated.
101 @code void SetPreferredSize( const Vector2& size ) @endcode
102 If only one dimension is FIXED then the other value in the size parameter will be ignored, so it is safe to set it to zero.
103
104 To constrain the final negotiated size of an actor, set the following for minimum and maximum sizes respectively.
105 @code
106 void SetMinimumSize( const Vector2& size )
107 void SetMaximumSize( const Vector2& size )
108 @endcode
109
110 <h3>Altering Negotiated Size</h3>
111
112 The following method specifies a size mode to use. Use one of: USE_OWN_SIZE, SIZE_RELATIVE_TO_PARENT or SIZE_FIXED_OFFSET_FROM_PARENT. SIZE_RELATIVE_TO_PARENT will
113 scale the image relative to it's parent size when the resize policy of FILL_TO_PARENT is in effect. While SIZE_FIXED_OFFSET_FROM_PARENT will
114 add an offset to this parent size, for example when wanting an image to act as a border around its parent.
115 @code void SetSizeMode( const SizeMode mode ) @endcode
116
117 Use the following with SetSizeMode to specify either the size relative to parent or the fixed offset to apply.
118 @code void SetSizeModeFactor( const Vector3& factor ) @endcode
119
120 When an actor is required to maintain the aspect ratio of its natural size the following method can be used. This is useful for size negotiating images
121 to ensure they maintain their aspect ratio while still fitting within the bounds they have been allocated. This can be one of USE_SIZE_SET, FIT_WITH_ASPECT_RATIO
122 or FILL_WITH_ASPECT_RATIO. The first is the default. The second will fit the actor within the bounds it has been allocated while maintaining aspect ratio. The
123 third will fill all available space, potentially overflowing its bounds, while maintaining apsect ratio.
124 @code void SetSizeScalePolicy( SizeScalePolicy policy ) @endcode
125
126 <h3>Using Actors in Containers</h3>
127
128 When laying out actors in containers such as TableView it is useful to be able to specify padding that surrounds the actor. E.g. You may
129 want some white space around an image actor placed in a table cell. The padding specifies the left, right, bottom and top padding values.
130 @code void SetPadding( const Padding& padding ) @endcode
131
132 <h2 class="pg">An Example</h2>
133
134 This section shows a more complex example of how to configure size negotiation. It creates a popup and adds a table view to it with a text view,
135 an image and a sub-table. The sub-table contains a checkbox and another text view.
136 @code
137 mPopup = CreatePopup();
138 mPopup.SetTitle( "Warning" );
139
140 // Content
141 Toolkit::TableView content = Toolkit::TableView::New( 2, 2 );
142 content.SetResizePolicy( FILL_TO_PARENT, WIDTH );
143 content.SetResizePolicy( USE_NATURAL_SIZE, HEIGHT );
144 content.SetFitHeight( 0 );
145 content.SetFitHeight( 1 );
146 content.SetPadding( Padding( 20.0f, 20.0f, 20.0f, 0.0f ) );
147
148 // Text
149 Toolkit::TextView text = Toolkit::TextView::New();
150 text.SetText( "Do you really want to quit?" );
151 text.SetMultilinePolicy( Toolkit::TextView::SplitByWord );
152 text.SetWidthExceedPolicy( Toolkit::TextView::Split );
153 text.SetLineJustification( Toolkit::TextView::Left );
154 text.SetResizePolicy( FILL_TO_PARENT, WIDTH );
155 text.SetDimensionDependency( HEIGHT, WIDTH );
156
157 content.AddChild( text, Toolkit::TableView::CellPosition( 0, 0 ) );
158
159 // Image
160 ImageActor image = ImageActor::New( ResourceImage::New( IMAGE1 ) );
161 image.SetResizePolicy( FILL_TO_PARENT, WIDTH );
162 image.SetDimensionDependency( HEIGHT, WIDTH );
163 image.SetPadding( Padding( 20.0f, 0.0f, 0.0f, 0.0f ) );
164 content.AddChild( image, Toolkit::TableView::CellPosition( 0, 1 ) );
165
166 // Checkbox and text
167 Toolkit::TableView root = Toolkit::TableView::New( 1, 2 );
168 root.SetResizePolicy( FILL_TO_PARENT, WIDTH );
169 root.SetResizePolicy( USE_NATURAL_SIZE, HEIGHT );
170 root.SetFitHeight( 0 );
171 root.SetFitWidth( 0 );
172 root.SetPadding( Padding( 0.0f, 0.0f, 0.0f, 20.0f ) );
173
174 Dali::Image unchecked = Dali::ResourceImage::New( CHECKBOX_UNCHECKED_IMAGE );
175 Dali::Image checked = Dali::ResourceImage::New( CHECKBOX_CHECKED_IMAGE );
176 Toolkit::CheckBoxButton checkBox = Toolkit::CheckBoxButton::New();
177 checkBox.SetBackgroundImage( unchecked );
178 checkBox.SetSelectedImage( checked );
179 checkBox.SetPreferredSize( Vector2( 48, 48 ) );
180 checkBox.SetResizePolicy( FIXED, ALL_DIMENSIONS );
181
182 root.AddChild( checkBox, Toolkit::TableView::CellPosition( 0, 0 ) );
183
184 Toolkit::TextView text2 = Toolkit::TextView::New();
185 text2.SetText( "Don't show again" );
186 text2.SetLineJustification( Toolkit::TextView::Left );
187 text2.SetPadding( Padding( 20.0f, 0.0f, 0.0f, 10.0f ) );
188
189 root.AddChild( text2, Toolkit::TableView::CellPosition( 0, 1 ) );
190
191 content.AddChild( root, Toolkit::TableView::CellPosition( 1, 0, 0, 2 ) );  // Column span 2
192
193 mPopup.Add( content );
194 @endcode
195
196 The resulting popup with additional buttons added is shown below.
197 \image html size-negotiation/Popup.png
198
199 The key things to pick out from this example are the use of the size negotiation API.
200 The content table view is set to FILL_TO_PARENT for its width and USE_NATURAL_SIZE for its height. This will result
201 in the table view expanding its width to fit the available space in the popup while also expanding/contracting its
202 height based on the size of the contents in its cells.
203 @code
204 content.SetResizePolicy( FILL_TO_PARENT, WIDTH );
205 content.SetResizePolicy( USE_NATURAL_SIZE, HEIGHT );
206 @endcode
207 To add a little space around the left, right and bottom of the table view, some padding is added.
208 @code
209 content.SetPadding( Padding( 20.0f, 20.0f, 20.0f, 0.0f ) );
210 @endcode
211 The first text view has its width set to FILL_TO_PARENT and its height has a dimension dependency on its width. This
212 will result in a text view that fills up its width to available space in the table cell and then then calculates its
213 height based on its new width. The table view will then fit its height taking the height of the text view into account.
214 @code
215 text.SetResizePolicy( FILL_TO_PARENT, WIDTH );
216 text.SetDimensionDependency( HEIGHT, WIDTH );
217 @endcode
218 The image view performs a similar relayout. It fits its width to the size of the cell and calculates its height based on the new
219 width. Some padding is added to the left of it as well to center it more.
220 @code
221 image.SetResizePolicy( FILL_TO_PARENT, WIDTH );
222 image.SetDimensionDependency( HEIGHT, WIDTH );
223 image.SetPadding( Padding( 20.0f, 0.0f, 0.0f, 0.0f ) );
224 @endcode
225 The sub table view is similar as well in that it expands its width to the size of its cell. When it is added to the table view it
226 will span two columns. Its height is set to natural size so that it will grow or shrink based on its children cells. Note that for
227 a container like table view, USE_NATURAL_SIZE acts in a similar manner to FIT_TO_CHILDREN in that the size of the container could
228 grow or shrink based on the sizes of the child actors.
229 @code
230 root.SetResizePolicy( FILL_TO_PARENT, WIDTH );
231 root.SetResizePolicy( USE_NATURAL_SIZE, HEIGHT );
232 @endcode
233 The checkbox is set to have a fixed size.
234 @code
235 checkBox.SetResizePolicy( FIXED, ALL_DIMENSIONS );
236 @endcode
237 The second text view has not specified a resize policy so will use its default of USE_NATURAL_SIZE.
238
239 <h2 class="pg">Debugging</h2>
240
241 When constructing large scenes using interacting resize policies it is useful to be able to debug the relayout process. The following sections
242 describe a pitfall to avoid when creating scenes and a way to print debug output about the actors.
243
244 <h3>Infinite Dependency Loops</h3>
245 Despite the power of the resize rules there is one pitfall to be aware of: infinite dependency loops. The most simplest form of this is
246 shown by a parent actor with resize policy set to FIT_TO_CHILDREN with a child that has a resize policy of FILL_TO_PARENT. Who should
247 determine the size in this case? A more complex loop occurs when DIMENSION_DEPENDENCY comes into play. Say a parent has a width policy
248 of DIMENSION_DEPENDENCY with height and a height policy of FIT_TO_CHILDREN. The parent has a single child with a height policy DIMENSION_DEPENDENCY
249 with width. If the child's width policy is FILL_TO_PARENT then a loop will occur. These are two simple examples but the loops could occur
250 over larger spreads of parent child relationships. These loops are detected by the relayout algorithm with the result being that actors will
251 receive zero sizes. These loops are not common but are still something to watch out for.
252
253 <h3 class="pg">Inspecting Actor Relayout Properties</h3>
254 To get a print out of the stage hierarchy before and after negotiation, with a list of actors that were negotiated set the LOG_RELAYOUT_CONTROLLER environment variable to 3,true.
255
256 E.g. On desktop run:
257
258 $  LOG_RELAYOUT_CONTROLLER=3,true dali-demo
259
260 Example output from the logging is as follows:
261
262 PushButton, OKAY_BUTTON - Pos: [185, 0, 0.1] Size: [165, 76, 76], Dirty: (FALSE,FALSE), Negotiated: (TRUE,TRUE), Enabled: TRUE, (0x1649850)
263
264 The format is as follows:
265
266 [Actor type], [Actor name] – Pos:[X, Y, Z] Size[WIDTH, HEIGHT, DEPTH], Dirty:(WIDTH, HEIGHT), Negotiated: (WIDTH, HEIGHT), Enabled: BOOLEAN, (Object address)
267 - <i>Actor type</i>: The type name of the actor E.g. PushButton
268 - <i>Actor name</i>: The name set on the actor with SetName(). Useful for debugging.
269 - <i>Pos</i>: The position of the actor
270 - <i>Size</i>: The current size of the actor. Check this to see if the actor has been negotiated correctly.
271 - <i>Dirty</i>: Booleans to say if the width or height has been marked as dirty by the relayout dirty flag propagation algorithm
272 - <i>Negotiated</i>: Booleans to say if the width or height has been negotiated by the size negotiation algorithm
273 - <i>Enabled</i>: Boolean to say if the actor is enabled for size negotitation
274 - <i>Object address</i>: The address of the actor object in memory
275 *
276 */