Merge pull request #506 from andrewcsmith/patch-2
[supercollider.git] / HelpSource / Guides / GUI-Layout-Management.schelp
blob29c995dfb701f09c21180733f7c74eb06ef3d2d8
1 title:: Layout Management
2 summary:: Using layout classes to manage distribution of child views within parents
3 categories:: GUI>Layout
4 related:: Classes/HLayout, Classes/VLayout, Classes/GridLayout, Classes/StackLayout
6 The purpose of layouts is to distribute the amount of space given to the view on which they are installed among the children of that view. Each subclass of QLayout has a specific pattern of space distribution (a line, a 2D grid, etc.). See their documentation for details.
8 A layout is installed on a view to manage the space the view occupies and distribute it among its child views. These child views can in turn have other layouts installed, managing the space given to them. But a layout can also manage other layouts directly - one layout can directly occupy a place in another layout's distribution pattern. A basic unit on which a layout operates is therefore abstractly called an item and can be a view or another layout.
10 note::
11 While layouts can form a hierachy on their own, in terms of view hierarchy all views managed by those layouts are direct children of the view on which the top layout is installed.
14 The following is an example of a VLayout, organizing a series of TextFields in a vertical line, and its last item is a HLayout, organizing a series of Buttons in a horizontal line.
16 code::
18 w = Window(bounds:Rect(200,200,200,200)).layout_(
19         VLayout(
20                 TextField(), TextField(), TextField(),
21                 HLayout( Button(), Button(), Button() )
22         )
23 ).front;
28 section:: How a layout does its job
30 A layout does its job by resizing and moving items within the parent view to form a specific distribution pattern, in accord with items' own size preferences and constraints, and with the common sense of what makes the GUI useful.
32 To explain how the layout operates, let's first take a look at intrinsic size preferences and constraints of views:
35 subsection:: Intrinsic view sizes
37 Every view intrinsically has a strong::preferred size:: and a strong::minimum size::, returned by link::Classes/View#-sizeHint:: and link::Classes/View#-minSizeHint::, respectively. The preferred size is a suitable size for the view to comfortably draw itself, display its contents and allow interaction, while the minimum size is the absolute minimum that the view needs to properly draw itself (including its contents). Both may change when the view's contents change; for example, most views that display some text will report a different code::sizeHint:: when the text changes (unless the text is scrollable).
39 A view takes on its preferred size at construction, if the 'bounds' argument is omitted. However, there is usually no way to set the text on a view at construction, so the size it automatically gets will not reflect the changes in text done after construction. You can remedy that by resizing the view to its code::sizeHint:: after the text has been set - but the strong::purpose of layouts:: (explained below) is exactly to do that automatically for you. Here is an example of manually using the code::sizeHint:::
41 code::
42 // Create a Window with a StaticText
44 w=Window().alwaysOnTop_(true);
45 t=StaticText(w);
46 w.front;
49 // There's no text set yet. Post the sizeHint of StaticText:
50 t.sizeHint
52 // Set the text, and post the sizeHint again:
53 t.string_("This is a looooooong text");
54 t.sizeHint
56 // Adjust the size to the sizeHint:
57 t.bounds = t.bounds.size_(t.sizeHint);
59 // Now you can see the whole text
62 As their names suggest, code::sizeHint:: and code::minSizeHint:: are only hints, and do not prevent one from setting a different size. You can, however, set a strong::hard limit:: on the size using link::Classes/View#-minSize::, link::Classes/View#-maxSize:: and similar methods:
64 code::
65 x=View(bounds:Rect(30,30,100,100)).alwaysOnTop_(true).front;
67 // Set the minimum size limit:
68 x.minSize = Size(200,200);
70 // The view automatically resized to the minimum size.
71 // Now try to shrink it back:
72 x.resizeTo(100,100);
74 // The view did not allow a smaller size than minSize.
77 subsection:: Automatic and dynamic space distribution
79 A layout strong::automatically:: distributes its space among its items, possibly in strong::unequal:: parts, based on the intrinsic preferences and constraints of views described above. Moreover, views also have intrinsic preferences as to whether they profit from being extended horizontally or vertically, or whether they prefer their size to be fixed in a certain direction. This is also taken into account by a layout.
81 A layout works strong::dynamically::, meaning that it redistributes the space whenever the amount of it changes (the view on which it is installed or the parent layout is resized), whenever items are added or removed, and whenever the size constraints and preferences of items change. The latter may happen for instance when a property of a view that affects its appearance is changed.
83 A layout will affect space distribution strong::up the layout hierarchy:: - it will define its own constraints and preferences according to its distribution pattern as well as the sum of constraints and preferences of its items. Ultimately, this means that the user's ability to resize a window will be limited by size constraints determined on the basis of window's contents.
85 For example: in a HLayout (a layout organizing items in a horizontal line) containing a Button and a TextField, the Button will be given a fixed amount of width according to the text it displays, while the TextField will be given all the width that is left. The other Button in the example code below will occupy all the width of the window, since there is no other item competing for that particular space. Note that both Button and TextField have an instrinsically fixed height and so their height never changes when resizing the window. The size constraints also limit the minimum size that the window can be resized to.
87 code::
89 w = Window.new(bounds:Rect(100,100,300,80)).layout_(
90         VLayout (
91                 HLayout(
92                         Button().states_([["Super"]]),
93                         TextField().string_("Collider")
94                 ),
95                 Button().states_([["SuperCollider"]])
96         )
97 ).front;
101 section:: User customization
103 subsection:: Stretch factors
105 Layouts typically allow the user to override their default distribution policy by assigning stretch factors to items or aspects of the layout's distribution pattern.
107 code::
109 w = Window.new(bounds:Rect(100,100,400,80)).layout_(
110         HLayout(
111                 [Button().states_([["Super"]]), stretch:1],
112                 TextField().string_("Collider")
113         )
114 ).front;
118 subsection:: Size constraints
120 The user can override a view's intrinsic size constraints and preferences that the layout will take into account, by placing a hard-limit on a view's size, as described above.
122 code::
124 w = Window.new(bounds:Rect(100,100,300,300)).layout_(
125         VLayout(
126                 TextField().string_("Super").minHeight_(80),
127                 TextField().string_("Collider").maxWidth_(150)
128         )
129 ).front;
133 subsection:: Alignment
135 The combination of size constraints and preferences of all items in a layout hierarchy may result in a larger amount of space given to an item than its own constraints allow. In that case the item will only grow up to its maximum allowed size, and its position within its extra available space may be controlled by user by assigning alignment to an item.
137 code::
139 w = Window.new.layout_(
140         HLayout(
141                 [Button.new.states_([["Super"]]), align:\bottom],
142                 TextView(),
143                 [Button.new.states_([["Collider"]]), align:\top]
144         )
145 ).front;
150 section:: View vs. layout hierachies
152 A layout starts to operate on the space that a view occupies from the moment it is installed on that view on. However, it will not automatically affect child views that where created before the layout was. For views to be managed by a layout they have to be created as children of a view after the layout has been installed on it, or they have to be explicitely inserted into the layout via layout's constructor or its instance methods for this purpose.
154 subsection:: View constructed with a parent
156 When a view is created with another view as parent it will implicitely become subject to the management of the parent's layout - it will be inserted into the layout in some default way. However, layouts like link::Classes/GridLayout:: have a complex space distribution pattern and so you will need to use their dedicated methods to specify exactly what place in the layout's distribution pattern a view will occupy.
158 subsection:: View explicitely inserted into a layout
160 A view can also be constructed with no parent given; after it is explicitely inserted into a layout via the layout's constructor or an instance method, it will automatically become a child of the view on which the layout is or will be installed. In case the layout occupies place directly in another layout, the view will become a child of the view on wich the topmost layout is installed.