Added wxSizerItem::SetMinSize that calls m_window->SetSizeHints if not
[wxWidgets.git] / src / xrc / xh_sizer.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: xh_sizer.cpp
3 // Purpose: XRC resource for wxBoxSizer
4 // Author: Vaclav Slavik
5 // Created: 2000/03/21
6 // RCS-ID: $Id$
7 // Copyright: (c) 2000 Vaclav Slavik
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 #ifdef __GNUG__
12 #pragma implementation "xh_sizer.h"
13 #endif
14
15 // For compilers that support precompilation, includes "wx.h".
16 #include "wx/wxprec.h"
17
18 #ifdef __BORLANDC__
19 #pragma hdrstop
20 #endif
21
22 #include "wx/xrc/xh_sizer.h"
23 #include "wx/sizer.h"
24 #include "wx/gbsizer.h"
25 #include "wx/log.h"
26 #include "wx/statbox.h"
27 #include "wx/notebook.h"
28 #include "wx/panel.h"
29 #include "wx/tokenzr.h"
30
31
32
33 IMPLEMENT_DYNAMIC_CLASS(wxSizerXmlHandler, wxXmlResourceHandler)
34
35
36
37 wxSizerXmlHandler::wxSizerXmlHandler()
38 : wxXmlResourceHandler(),
39 m_isInside(FALSE),
40 m_isGBS(FALSE),
41 m_parentSizer(NULL)
42 {
43 XRC_ADD_STYLE(wxHORIZONTAL);
44 XRC_ADD_STYLE(wxVERTICAL);
45
46 // and flags
47 XRC_ADD_STYLE(wxLEFT);
48 XRC_ADD_STYLE(wxRIGHT);
49 XRC_ADD_STYLE(wxTOP);
50 XRC_ADD_STYLE(wxBOTTOM);
51 XRC_ADD_STYLE(wxNORTH);
52 XRC_ADD_STYLE(wxSOUTH);
53 XRC_ADD_STYLE(wxEAST);
54 XRC_ADD_STYLE(wxWEST);
55 XRC_ADD_STYLE(wxALL);
56
57 XRC_ADD_STYLE(wxGROW);
58 XRC_ADD_STYLE(wxEXPAND);
59 XRC_ADD_STYLE(wxSHAPED);
60 XRC_ADD_STYLE(wxSTRETCH_NOT);
61
62 XRC_ADD_STYLE(wxALIGN_CENTER);
63 XRC_ADD_STYLE(wxALIGN_CENTRE);
64 XRC_ADD_STYLE(wxALIGN_LEFT);
65 XRC_ADD_STYLE(wxALIGN_TOP);
66 XRC_ADD_STYLE(wxALIGN_RIGHT);
67 XRC_ADD_STYLE(wxALIGN_BOTTOM);
68 XRC_ADD_STYLE(wxALIGN_CENTER_HORIZONTAL);
69 XRC_ADD_STYLE(wxALIGN_CENTRE_HORIZONTAL);
70 XRC_ADD_STYLE(wxALIGN_CENTER_VERTICAL);
71 XRC_ADD_STYLE(wxALIGN_CENTRE_VERTICAL);
72
73 XRC_ADD_STYLE(wxADJUST_MINSIZE);
74 XRC_ADD_STYLE(wxFIXED_MINSIZE);
75 }
76
77
78
79 bool wxSizerXmlHandler::CanHandle(wxXmlNode *node)
80 {
81 return ( (!m_isInside && IsSizerNode(node)) ||
82 (m_isInside && IsOfClass(node, wxT("sizeritem"))) ||
83 (m_isInside && IsOfClass(node, wxT("spacer")))
84 );
85 }
86
87
88 wxObject* wxSizerXmlHandler::DoCreateResource()
89 {
90 if (m_class == wxT("sizeritem"))
91 return Handle_sizeritem();
92
93 else if (m_class == wxT("spacer"))
94 return Handle_spacer();
95
96 else
97 return Handle_sizer();
98 }
99
100
101
102
103 bool wxSizerXmlHandler::IsSizerNode(wxXmlNode *node)
104 {
105 return (IsOfClass(node, wxT("wxBoxSizer"))) ||
106 (IsOfClass(node, wxT("wxStaticBoxSizer"))) ||
107 (IsOfClass(node, wxT("wxGridSizer"))) ||
108 (IsOfClass(node, wxT("wxFlexGridSizer"))) ||
109 (IsOfClass(node, wxT("wxGridBagSizer")));
110 }
111
112
113 wxObject* wxSizerXmlHandler::Handle_sizeritem()
114 {
115 // find the item to be managed by this sizeritem
116 wxXmlNode *n = GetParamNode(wxT("object"));
117 if ( !n )
118 n = GetParamNode(wxT("object_ref"));
119
120 // did we find one?
121 if (n)
122 {
123 // create a sizer item for it
124 wxSizerItem* sitem = MakeSizerItem();
125
126 // now fetch the item to be managed
127 bool old_gbs = m_isGBS;
128 bool old_ins = m_isInside;
129 wxSizer *old_par = m_parentSizer;
130 m_isInside = FALSE;
131 if (!IsSizerNode(n)) m_parentSizer = NULL;
132 wxObject *item = CreateResFromNode(n, m_parent, NULL);
133 m_isInside = old_ins;
134 m_parentSizer = old_par;
135 m_isGBS = old_gbs;
136
137 // and figure out what type it is
138 wxSizer *sizer = wxDynamicCast(item, wxSizer);
139 wxWindow *wnd = wxDynamicCast(item, wxWindow);
140
141 if (sizer)
142 sitem->SetSizer(sizer);
143 else if (wnd)
144 sitem->SetWindow(wnd);
145 else
146 wxLogError(wxT("Error in resource."));
147
148 // finally, set other wxSizerItem attributes
149 SetSizerItemAttributes(sitem);
150
151 AddSizerItem(sitem);
152 return item;
153 }
154 else /*n == NULL*/
155 {
156 wxLogError(wxT("Error in resource: no window/sizer/spacer within sizeritem object."));
157 return NULL;
158 }
159 }
160
161
162 wxObject* wxSizerXmlHandler::Handle_spacer()
163 {
164 wxCHECK_MSG(m_parentSizer, NULL, wxT("Incorrect syntax of XRC resource: spacer not within sizer!"));
165
166 wxSizerItem* sitem = MakeSizerItem();
167 SetSizerItemAttributes(sitem);
168 sitem->SetSpacer(GetSize());
169 AddSizerItem(sitem);
170 return NULL;
171 }
172
173
174 wxObject* wxSizerXmlHandler::Handle_sizer()
175 {
176 wxSizer *sizer = NULL;
177
178 wxXmlNode *parentNode = m_node->GetParent();
179
180 wxCHECK_MSG(m_parentSizer != NULL ||
181 (parentNode && parentNode->GetType() == wxXML_ELEMENT_NODE &&
182 m_parentAsWindow != NULL &&
183 (m_parentAsWindow->IsKindOf(CLASSINFO(wxPanel)) ||
184 m_parentAsWindow->IsKindOf(CLASSINFO(wxFrame)) ||
185 m_parentAsWindow->IsKindOf(CLASSINFO(wxDialog)))
186 ), NULL,
187 wxT("Incorrect use of sizer: parent is not 'wxDialog', 'wxFrame' or 'wxPanel'."));
188
189 if (m_class == wxT("wxBoxSizer"))
190 sizer = Handle_wxBoxSizer();
191
192 else if (m_class == wxT("wxStaticBoxSizer"))
193 sizer = Handle_wxStaticBoxSizer();
194
195 else if (m_class == wxT("wxGridSizer"))
196 sizer = Handle_wxGridSizer();
197
198 else if (m_class == wxT("wxFlexGridSizer"))
199 sizer = Handle_wxFlexGridSizer();
200
201 else if (m_class == wxT("wxGridBagSizer"))
202 sizer = Handle_wxGridBagSizer();
203
204
205 wxSize minsize = GetSize(wxT("minsize"));
206 if (!(minsize == wxDefaultSize))
207 sizer->SetMinSize(minsize);
208
209 // save state
210 wxSizer *old_par = m_parentSizer;
211 bool old_ins = m_isInside;
212
213 // set new state
214 m_parentSizer = sizer;
215 m_isInside = TRUE;
216 m_isGBS = (m_class == wxT("wxGridBagSizer"));
217
218 CreateChildren(m_parent, TRUE/*only this handler*/);
219
220 // restore state
221 m_isInside = old_ins;
222 m_parentSizer = old_par;
223
224 if (m_parentSizer == NULL) // setup window:
225 {
226 m_parentAsWindow->SetAutoLayout(TRUE);
227 m_parentAsWindow->SetSizer(sizer);
228
229 wxXmlNode *nd = m_node;
230 m_node = parentNode;
231 if (GetSize() == wxDefaultSize)
232 sizer->Fit(m_parentAsWindow);
233 m_node = nd;
234
235 if (m_parentAsWindow->GetWindowStyle() & (wxRESIZE_BOX | wxRESIZE_BORDER))
236 sizer->SetSizeHints(m_parentAsWindow);
237 }
238
239 return sizer;
240 }
241
242
243 wxSizer* wxSizerXmlHandler::Handle_wxBoxSizer()
244 {
245 return new wxBoxSizer(GetStyle(wxT("orient"), wxHORIZONTAL));
246 }
247
248 wxSizer* wxSizerXmlHandler::Handle_wxStaticBoxSizer()
249 {
250 return new wxStaticBoxSizer(
251 new wxStaticBox(m_parentAsWindow,
252 GetID(),
253 GetText(wxT("label")),
254 wxDefaultPosition, wxDefaultSize,
255 0/*style*/,
256 GetName()),
257 GetStyle(wxT("orient"), wxHORIZONTAL));
258 }
259
260 wxSizer* wxSizerXmlHandler::Handle_wxGridSizer()
261 {
262 return new wxGridSizer(GetLong(wxT("rows")), GetLong(wxT("cols")),
263 GetDimension(wxT("vgap")), GetDimension(wxT("hgap")));
264 }
265
266
267 wxSizer* wxSizerXmlHandler::Handle_wxFlexGridSizer()
268 {
269 wxFlexGridSizer *sizer =
270 new wxFlexGridSizer(GetLong(wxT("rows")), GetLong(wxT("cols")),
271 GetDimension(wxT("vgap")), GetDimension(wxT("hgap")));
272 SetGrowables(sizer, wxT("growablerows"), true);
273 SetGrowables(sizer, wxT("growablecols"), false);
274 return sizer;
275 }
276
277
278 wxSizer* wxSizerXmlHandler::Handle_wxGridBagSizer()
279 {
280 wxGridBagSizer *sizer =
281 new wxGridBagSizer(GetDimension(wxT("vgap")), GetDimension(wxT("hgap")));
282 SetGrowables(sizer, wxT("growablerows"), true);
283 SetGrowables(sizer, wxT("growablecols"), false);
284 return sizer;
285 }
286
287
288
289
290 void wxSizerXmlHandler::SetGrowables(wxFlexGridSizer* sizer,
291 const wxChar* param,
292 bool rows)
293 {
294 wxStringTokenizer tkn;
295 unsigned long l;
296 tkn.SetString(GetParamValue(param), wxT(","));
297 while (tkn.HasMoreTokens())
298 {
299 if (!tkn.GetNextToken().ToULong(&l))
300 wxLogError(wxT("growable[rows|cols] must be comma-separated list of row numbers"));
301 else {
302 if (rows)
303 sizer->AddGrowableRow(l);
304 else
305 sizer->AddGrowableCol(l);
306 }
307 }
308 }
309
310
311 wxGBPosition wxSizerXmlHandler::GetGBPos(const wxString& param)
312 {
313 wxSize sz = GetSize(param);
314 if (sz.x < 0) sz.x = 0;
315 if (sz.y < 0) sz.y = 0;
316 return wxGBPosition(sz.x, sz.y);
317 }
318
319 wxGBSpan wxSizerXmlHandler::GetGBSpan(const wxString& param)
320 {
321 wxSize sz = GetSize(param);
322 if (sz.x < 1) sz.x = 1;
323 if (sz.y < 1) sz.y = 1;
324 return wxGBSpan(sz.x, sz.y);
325 }
326
327
328
329 wxSizerItem* wxSizerXmlHandler::MakeSizerItem()
330 {
331 if (m_isGBS)
332 return new wxGBSizerItem();
333 else
334 return new wxSizerItem();
335 }
336
337 void wxSizerXmlHandler::SetSizerItemAttributes(wxSizerItem* sitem)
338 {
339 sitem->SetProportion(GetLong(wxT("option"))); // Should this check for "proportion" too?
340 sitem->SetFlag(GetStyle(wxT("flag")));
341 sitem->SetBorder(GetDimension(wxT("border")));
342 wxSize sz = GetSize(wxT("minsize"));
343 if (!(sz == wxDefaultSize))
344 sitem->SetMinSize(sz);
345 sz = GetSize(wxT("ratio"));
346 if (!(sz == wxDefaultSize))
347 sitem->SetRatio(sz);
348
349 if (m_isGBS)
350 {
351 wxGBSizerItem* gbsitem = (wxGBSizerItem*)sitem;
352 gbsitem->SetPos(GetGBPos(wxT("cellpos")));
353 gbsitem->SetSpan(GetGBSpan(wxT("cellspan")));
354 }
355 }
356
357 void wxSizerXmlHandler::AddSizerItem(wxSizerItem* sitem)
358 {
359 if (m_isGBS)
360 ((wxGridBagSizer*)m_parentSizer)->Add((wxGBSizerItem*)sitem);
361 else
362 m_parentSizer->Add(sitem);
363 }
364
365
366
367
368
369
370
371
372
373