]>
Commit | Line | Data |
---|---|---|
15b6757b | 1 | ///////////////////////////////////////////////////////////////////////////// |
d54cf7ff | 2 | // Name: constraints.h |
15b6757b FM |
3 | // Purpose: topic overview |
4 | // Author: wxWidgets team | |
5 | // RCS-ID: $Id$ | |
6 | // Licence: wxWindows license | |
7 | ///////////////////////////////////////////////////////////////////////////// | |
8 | ||
9 | /*! | |
36c9828f | 10 | |
d54cf7ff | 11 | @page overview_constraints Constraints overview |
36c9828f | 12 | |
98ba1eee | 13 | Classes: wxLayoutConstraints, wxIndividualLayoutConstraint. |
d54cf7ff FM |
14 | |
15 | @note Constraints are now deprecated and you should use sizers instead (see wxSizer). | |
16 | ||
15b6757b FM |
17 | Objects of class wxLayoutConstraint can be associated with a window to define |
18 | the way it is laid out, with respect to its siblings or the parent. | |
d54cf7ff | 19 | |
15b6757b FM |
20 | The class consists of the following eight constraints of class wxIndividualLayoutConstraint, |
21 | some or all of which should be accessed directly to set the appropriate | |
22 | constraints. | |
36c9828f | 23 | |
15b6757b FM |
24 | @b left: represents the left hand edge of the window |
25 | @b right: represents the right hand edge of the window | |
26 | @b top: represents the top edge of the window | |
27 | @b bottom: represents the bottom edge of the window | |
28 | @b width: represents the width of the window | |
29 | @b height: represents the height of the window | |
30 | @b centreX: represents the horizontal centre point of the window | |
31 | @b centreY: represents the vertical centre point of the window | |
36c9828f | 32 | |
15b6757b FM |
33 | The constraints are initially set to have the relationship wxUnconstrained, |
34 | which means that their values should be calculated by looking at known constraints. | |
35 | To calculate the position and size of the control, the layout algorithm needs to | |
36 | know exactly 4 constraints (as it has 4 numbers to calculate from them), so you | |
37 | should always set exactly 4 of the constraints from the above table. | |
d54cf7ff | 38 | |
15b6757b FM |
39 | If you want the controls height or width to have the default value, you may use |
40 | a special value for the constraint: wxAsIs. If the constraint is wxAsIs, the | |
41 | dimension will not be changed which is useful for the dialog controls which | |
42 | often have the default size (e.g. the buttons whose size is determined by their | |
43 | label). | |
d54cf7ff FM |
44 | |
45 | The constrains calculation is done in wxWindow::Layout function which evaluates | |
46 | constraints. To call it you can either call wxWindow::SetAutoLayout if the parent | |
47 | window is a frame, panel or a dialog to tell default OnSize handlers to call Layout | |
15b6757b | 48 | automatically whenever the window size changes, or override OnSize and call |
98ba1eee | 49 | Layout yourself (note that you do have to call wxWindow::Layout yourself if the parent |
d54cf7ff FM |
50 | window is not a frame, panel or dialog). |
51 | ||
52 | @li @ref overview_constraints_layout | |
53 | @li @ref overview_constraints_examples | |
54 | ||
36c9828f | 55 | |
d54cf7ff | 56 | <hr> |
36c9828f | 57 | |
d54cf7ff FM |
58 | |
59 | @section overview_constraints_layout Constraint layout: more details | |
36c9828f | 60 | |
15b6757b FM |
61 | By default, windows do not have a wxLayoutConstraints object. In this case, much layout |
62 | must be done explicitly, by performing calculations in OnSize members, except | |
63 | for the case of frames that have exactly one subwindow (not counting toolbar and | |
64 | statusbar which are also positioned by the frame automatically), where wxFrame::OnSize | |
65 | takes care of resizing the child to always fill the frame. | |
d54cf7ff | 66 | |
15b6757b FM |
67 | To avoid the need for these rather awkward calculations, the user can create |
68 | a wxLayoutConstraints object and associate it with a window with wxWindow::SetConstraints. | |
69 | This object contains a constraint for each of the window edges, two for the centre point, | |
70 | and two for the window size. By setting some or all of these constraints appropriately, | |
71 | the user can achieve quite complex layout by defining relationships between windows. | |
d54cf7ff FM |
72 | |
73 | In wxWidgets, each window can be constrained relative to either its @e siblings | |
74 | on the same window, or the @e parent. The layout algorithm | |
15b6757b | 75 | therefore operates in a top-down manner, finding the correct layout for |
d54cf7ff FM |
76 | the children of a window, then the layout for the grandchildren, and so on. |
77 | ||
78 | Note that this differs markedly from native Motif layout, where | |
15b6757b FM |
79 | constraints can ripple upwards and can eventually change the frame |
80 | window or dialog box size. We assume in wxWidgets that the @e user is | |
81 | always 'boss' and specifies the size of the outer window, to which | |
82 | subwindows must conform. Obviously, this might be a limitation in some | |
83 | circumstances, but it suffices for most situations, and the | |
84 | simplification avoids some of the nightmarish problems associated with | |
85 | programming Motif. | |
d54cf7ff | 86 | |
15b6757b FM |
87 | When the user sets constraints, many of the constraints for windows |
88 | edges and dimensions remain unconstrained. For a given window, | |
89 | the wxWindow::Layout algorithm first resets all constraints | |
d54cf7ff FM |
90 | in all children to have unknown edge or dimension values, and then iterates |
91 | through the constraints, evaluating them. For unconstrained edges and dimensions, | |
92 | it tries to find the value using known relationships that always hold. For example, | |
15b6757b FM |
93 | an unconstrained @e width may be calculated from the @e left and @e right edges, if |
94 | both are currently known. For edges and dimensions with user-supplied constraints, these | |
95 | constraints are evaluated if the inputs of the constraint are known. | |
d54cf7ff | 96 | |
36c9828f | 97 | The algorithm stops when all child edges and dimension are known (success), or |
15b6757b FM |
98 | there are unknown edges or dimensions but there has been no change in this cycle (failure). |
99 | It then sets all the window positions and sizes according to the values it has found. | |
100 | Because the algorithm is iterative, the order in which constraints are considered is | |
101 | irrelevant, however you may reduce the number of iterations (and thus speed up | |
102 | the layout calculations) by creating the controls in such order that as many | |
103 | constraints as possible can be calculated during the first iteration. For example, if | |
104 | you have 2 buttons which you'd like to position in the lower right corner, it is | |
105 | slightly more efficient to first create the second button and specify that its | |
106 | right border IsSameAs(parent, wxRight) and then create the first one by | |
107 | specifying that it should be LeftOf() the second one than to do in a more | |
108 | natural left-to-right order. | |
36c9828f | 109 | |
36c9828f FM |
110 | |
111 | ||
d54cf7ff FM |
112 | @section overview_constraints_examples Window layout examples |
113 | ||
114 | @subsection overview_constraints_example1 Example 1: subwindow layout | |
36c9828f | 115 | |
15b6757b FM |
116 | This example specifies a panel and a window side by side, |
117 | with a text subwindow below it. | |
36c9828f | 118 | |
15b6757b | 119 | @code |
98ba1eee FM |
120 | frame->panel = new wxPanel(frame, -1, wxPoint(0, 0), wxSize(1000, 500), 0); |
121 | frame->scrollWindow = new MyScrolledWindow(frame, -1, wxPoint(0, 0), wxSize(400, 400), wxRETAINED); | |
122 | frame->text_window = new MyTextWindow(frame, -1, wxPoint(0, 250), wxSize(400, 250)); | |
36c9828f | 123 | |
15b6757b FM |
124 | // Set constraints for panel subwindow |
125 | wxLayoutConstraints *c1 = new wxLayoutConstraints; | |
36c9828f | 126 | |
98ba1eee FM |
127 | c1->left.SameAs (frame, wxLeft); |
128 | c1->top.SameAs (frame, wxTop); | |
129 | c1->right.PercentOf (frame, wxWidth, 50); | |
130 | c1->height.PercentOf (frame, wxHeight, 50); | |
36c9828f | 131 | |
98ba1eee | 132 | frame->panel->SetConstraints(c1); |
36c9828f | 133 | |
15b6757b FM |
134 | // Set constraints for scrollWindow subwindow |
135 | wxLayoutConstraints *c2 = new wxLayoutConstraints; | |
36c9828f | 136 | |
98ba1eee FM |
137 | c2->left.SameAs (frame->panel, wxRight); |
138 | c2->top.SameAs (frame, wxTop); | |
139 | c2->right.SameAs (frame, wxRight); | |
140 | c2->height.PercentOf (frame, wxHeight, 50); | |
36c9828f | 141 | |
98ba1eee | 142 | frame->scrollWindow->SetConstraints(c2); |
36c9828f | 143 | |
15b6757b FM |
144 | // Set constraints for text subwindow |
145 | wxLayoutConstraints *c3 = new wxLayoutConstraints; | |
98ba1eee FM |
146 | c3->left.SameAs (frame, wxLeft); |
147 | c3->top.Below (frame->panel); | |
148 | c3->right.SameAs (frame, wxRight); | |
149 | c3->bottom.SameAs (frame, wxBottom); | |
36c9828f | 150 | |
98ba1eee | 151 | frame->text_window->SetConstraints(c3); |
15b6757b | 152 | @endcode |
36c9828f FM |
153 | |
154 | ||
d54cf7ff | 155 | @subsection overview_constraints_example2 Example 2: panel item layout |
36c9828f | 156 | |
15b6757b FM |
157 | This example sizes a button width to 80 percent of the panel width, and centres |
158 | it horizontally. A listbox and multitext item are placed below it. The listbox | |
159 | takes up 40 percent of the panel width, and the multitext item takes up | |
160 | the remainder of the width. Margins of 5 pixels are used. | |
36c9828f | 161 | |
15b6757b | 162 | @code |
d54cf7ff | 163 | // Create some panel items |
98ba1eee | 164 | wxButton *btn1 = new wxButton(frame->panel, ->1, "A button") ; |
36c9828f | 165 | |
15b6757b | 166 | wxLayoutConstraints *b1 = new wxLayoutConstraints; |
98ba1eee FM |
167 | b1->centreX.SameAs (frame->panel, wxCentreX); |
168 | b1->top.SameAs (frame->panel, wxTop, 5); | |
169 | b1->width.PercentOf (frame->panel, wxWidth, 80); | |
170 | b1->height.PercentOf (frame->panel, wxHeight, 10); | |
171 | btn1->SetConstraints(b1); | |
36c9828f | 172 | |
98ba1eee FM |
173 | wxListBox *list = new wxListBox(frame->panel, ->1, "A list", |
174 | wxPoint(->1, ->1), wxSize(200, 100)); | |
36c9828f | 175 | |
15b6757b | 176 | wxLayoutConstraints *b2 = new wxLayoutConstraints; |
98ba1eee FM |
177 | b2->top.Below (btn1, 5); |
178 | b2->left.SameAs (frame->panel, wxLeft, 5); | |
179 | b2->width.PercentOf (frame->panel, wxWidth, 40); | |
180 | b2->bottom.SameAs (frame->panel, wxBottom, 5); | |
181 | list->SetConstraints(b2); | |
36c9828f | 182 | |
98ba1eee FM |
183 | wxTextCtrl *mtext = new wxTextCtrl(frame->panel, ->1, "Multiline text", "Some text", |
184 | wxPoint(->1, ->1), wxSize(150, 100), wxTE_MULTILINE); | |
36c9828f | 185 | |
15b6757b | 186 | wxLayoutConstraints *b3 = new wxLayoutConstraints; |
98ba1eee FM |
187 | b3->top.Below (btn1, 5); |
188 | b3->left.RightOf (list, 5); | |
189 | b3->right.SameAs (frame->panel, wxRight, 5); | |
190 | b3->bottom.SameAs (frame->panel, wxBottom, 5); | |
191 | mtext->SetConstraints(b3); | |
15b6757b | 192 | @endcode |
36c9828f | 193 | |
d54cf7ff | 194 | */ |
36c9828f | 195 |