]> git.saurik.com Git - wxWidgets.git/blob - src/xrc/xh_sizer.cpp
extracted wxWrapSizer in separate files and somewhat improved it (heavily modified...
[wxWidgets.git] / src / xrc / xh_sizer.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/xrc/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 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
13
14 #ifdef __BORLANDC__
15 #pragma hdrstop
16 #endif
17
18 #if wxUSE_XRC
19
20 #include "wx/xrc/xh_sizer.h"
21
22 #ifndef WX_PRECOMP
23 #include "wx/log.h"
24 #include "wx/panel.h"
25 #include "wx/statbox.h"
26 #include "wx/sizer.h"
27 #include "wx/frame.h"
28 #include "wx/dialog.h"
29 #include "wx/button.h"
30 #include "wx/scrolwin.h"
31 #endif
32
33 #include "wx/gbsizer.h"
34 #include "wx/wrapsizer.h"
35 #include "wx/notebook.h"
36 #include "wx/tokenzr.h"
37
38
39 //-----------------------------------------------------------------------------
40 // wxSizerXmlHandler
41 //-----------------------------------------------------------------------------
42
43 IMPLEMENT_DYNAMIC_CLASS(wxSizerXmlHandler, wxXmlResourceHandler)
44
45 wxSizerXmlHandler::wxSizerXmlHandler()
46 :wxXmlResourceHandler(),
47 m_isInside(false),
48 m_isGBS(false),
49 m_parentSizer(NULL)
50 {
51 XRC_ADD_STYLE(wxHORIZONTAL);
52 XRC_ADD_STYLE(wxVERTICAL);
53
54 // and flags
55 XRC_ADD_STYLE(wxLEFT);
56 XRC_ADD_STYLE(wxRIGHT);
57 XRC_ADD_STYLE(wxTOP);
58 XRC_ADD_STYLE(wxBOTTOM);
59 XRC_ADD_STYLE(wxNORTH);
60 XRC_ADD_STYLE(wxSOUTH);
61 XRC_ADD_STYLE(wxEAST);
62 XRC_ADD_STYLE(wxWEST);
63 XRC_ADD_STYLE(wxALL);
64
65 XRC_ADD_STYLE(wxGROW);
66 XRC_ADD_STYLE(wxEXPAND);
67 XRC_ADD_STYLE(wxSHAPED);
68 XRC_ADD_STYLE(wxSTRETCH_NOT);
69
70 XRC_ADD_STYLE(wxALIGN_CENTER);
71 XRC_ADD_STYLE(wxALIGN_CENTRE);
72 XRC_ADD_STYLE(wxALIGN_LEFT);
73 XRC_ADD_STYLE(wxALIGN_TOP);
74 XRC_ADD_STYLE(wxALIGN_RIGHT);
75 XRC_ADD_STYLE(wxALIGN_BOTTOM);
76 XRC_ADD_STYLE(wxALIGN_CENTER_HORIZONTAL);
77 XRC_ADD_STYLE(wxALIGN_CENTRE_HORIZONTAL);
78 XRC_ADD_STYLE(wxALIGN_CENTER_VERTICAL);
79 XRC_ADD_STYLE(wxALIGN_CENTRE_VERTICAL);
80
81 XRC_ADD_STYLE(wxFIXED_MINSIZE);
82 XRC_ADD_STYLE(wxRESERVE_SPACE_EVEN_IF_HIDDEN);
83 }
84
85
86
87 bool wxSizerXmlHandler::CanHandle(wxXmlNode *node)
88 {
89 return ( (!m_isInside && IsSizerNode(node)) ||
90 (m_isInside && IsOfClass(node, wxT("sizeritem"))) ||
91 (m_isInside && IsOfClass(node, wxT("spacer")))
92 );
93 }
94
95
96 wxObject* wxSizerXmlHandler::DoCreateResource()
97 {
98 if (m_class == wxT("sizeritem"))
99 return Handle_sizeritem();
100
101 else if (m_class == wxT("spacer"))
102 return Handle_spacer();
103
104 else
105 return Handle_sizer();
106 }
107
108
109
110
111 bool wxSizerXmlHandler::IsSizerNode(wxXmlNode *node)
112 {
113 return (IsOfClass(node, wxT("wxBoxSizer"))) ||
114 (IsOfClass(node, wxT("wxStaticBoxSizer"))) ||
115 (IsOfClass(node, wxT("wxGridSizer"))) ||
116 (IsOfClass(node, wxT("wxFlexGridSizer"))) ||
117 (IsOfClass(node, wxT("wxGridBagSizer"))) ||
118 (IsOfClass(node, wxT("wxWrapSizer")));
119 }
120
121
122 wxObject* wxSizerXmlHandler::Handle_sizeritem()
123 {
124 // find the item to be managed by this sizeritem
125 wxXmlNode *n = GetParamNode(wxT("object"));
126 if ( !n )
127 n = GetParamNode(wxT("object_ref"));
128
129 // did we find one?
130 if (n)
131 {
132 // create a sizer item for it
133 wxSizerItem* sitem = MakeSizerItem();
134
135 // now fetch the item to be managed
136 bool old_gbs = m_isGBS;
137 bool old_ins = m_isInside;
138 wxSizer *old_par = m_parentSizer;
139 m_isInside = false;
140 if (!IsSizerNode(n)) m_parentSizer = NULL;
141 wxObject *item = CreateResFromNode(n, m_parent, NULL);
142 m_isInside = old_ins;
143 m_parentSizer = old_par;
144 m_isGBS = old_gbs;
145
146 // and figure out what type it is
147 wxSizer *sizer = wxDynamicCast(item, wxSizer);
148 wxWindow *wnd = wxDynamicCast(item, wxWindow);
149
150 if (sizer)
151 sitem->AssignSizer(sizer);
152 else if (wnd)
153 sitem->AssignWindow(wnd);
154 else
155 wxLogError(wxT("Error in resource."));
156
157 // finally, set other wxSizerItem attributes
158 SetSizerItemAttributes(sitem);
159
160 AddSizerItem(sitem);
161 return item;
162 }
163 else /*n == NULL*/
164 {
165 wxLogError(wxT("Error in resource: no window/sizer/spacer within sizeritem object."));
166 return NULL;
167 }
168 }
169
170
171 wxObject* wxSizerXmlHandler::Handle_spacer()
172 {
173 wxCHECK_MSG(m_parentSizer, NULL, wxT("Incorrect syntax of XRC resource: spacer not within sizer!"));
174
175 wxSizerItem* sitem = MakeSizerItem();
176 SetSizerItemAttributes(sitem);
177 sitem->AssignSpacer(GetSize());
178 AddSizerItem(sitem);
179 return NULL;
180 }
181
182
183 wxObject* wxSizerXmlHandler::Handle_sizer()
184 {
185 wxSizer *sizer = NULL;
186
187 wxXmlNode *parentNode = m_node->GetParent();
188
189 wxCHECK_MSG(m_parentSizer != NULL ||
190 (parentNode && parentNode->GetType() == wxXML_ELEMENT_NODE &&
191 m_parentAsWindow), NULL,
192 wxT("Sizer must have a window parent node"));
193
194 if (m_class == wxT("wxBoxSizer"))
195 sizer = Handle_wxBoxSizer();
196
197 #if wxUSE_STATBOX
198 else if (m_class == wxT("wxStaticBoxSizer"))
199 sizer = Handle_wxStaticBoxSizer();
200 #endif
201
202 else if (m_class == wxT("wxGridSizer"))
203 sizer = Handle_wxGridSizer();
204
205 else if (m_class == wxT("wxFlexGridSizer"))
206 sizer = Handle_wxFlexGridSizer();
207
208 else if (m_class == wxT("wxGridBagSizer"))
209 sizer = Handle_wxGridBagSizer();
210
211 else if (m_class == wxT("wxWrapSizer"))
212 sizer = Handle_wxGridBagSizer();
213
214 if ( !sizer )
215 {
216 wxLogError(_T("Failed to create size of class \"%s\""), m_class.c_str());
217 return NULL;
218 }
219
220 wxSize minsize = GetSize(wxT("minsize"));
221 if (!(minsize == wxDefaultSize))
222 sizer->SetMinSize(minsize);
223
224 // save state
225 wxSizer *old_par = m_parentSizer;
226 bool old_ins = m_isInside;
227
228 // set new state
229 m_parentSizer = sizer;
230 m_isInside = true;
231 m_isGBS = (m_class == wxT("wxGridBagSizer"));
232
233 CreateChildren(m_parent, true/*only this handler*/);
234
235 // restore state
236 m_isInside = old_ins;
237 m_parentSizer = old_par;
238
239 if (m_parentSizer == NULL) // setup window:
240 {
241 m_parentAsWindow->SetSizer(sizer);
242
243 wxXmlNode *nd = m_node;
244 m_node = parentNode;
245 if (GetSize() == wxDefaultSize)
246 {
247 if ( wxDynamicCast(m_parentAsWindow, wxScrolledWindow) != NULL )
248 {
249 sizer->FitInside(m_parentAsWindow);
250 }
251 else
252 {
253 sizer->Fit(m_parentAsWindow);
254 }
255 }
256 m_node = nd;
257
258 if (m_parentAsWindow->IsTopLevel())
259 {
260 sizer->SetSizeHints(m_parentAsWindow);
261 }
262 }
263
264 return sizer;
265 }
266
267
268 wxSizer* wxSizerXmlHandler::Handle_wxBoxSizer()
269 {
270 return new wxBoxSizer(GetStyle(wxT("orient"), wxHORIZONTAL));
271 }
272
273 #if wxUSE_STATBOX
274 wxSizer* wxSizerXmlHandler::Handle_wxStaticBoxSizer()
275 {
276 return new wxStaticBoxSizer(
277 new wxStaticBox(m_parentAsWindow,
278 GetID(),
279 GetText(wxT("label")),
280 wxDefaultPosition, wxDefaultSize,
281 0/*style*/,
282 GetName()),
283 GetStyle(wxT("orient"), wxHORIZONTAL));
284 }
285 #endif // wxUSE_STATBOX
286
287 wxSizer* wxSizerXmlHandler::Handle_wxGridSizer()
288 {
289 return new wxGridSizer(GetLong(wxT("rows")), GetLong(wxT("cols")),
290 GetDimension(wxT("vgap")), GetDimension(wxT("hgap")));
291 }
292
293
294 wxSizer* wxSizerXmlHandler::Handle_wxFlexGridSizer()
295 {
296 wxFlexGridSizer *sizer =
297 new wxFlexGridSizer(GetLong(wxT("rows")), GetLong(wxT("cols")),
298 GetDimension(wxT("vgap")), GetDimension(wxT("hgap")));
299 SetGrowables(sizer, wxT("growablerows"), true);
300 SetGrowables(sizer, wxT("growablecols"), false);
301 return sizer;
302 }
303
304
305 wxSizer* wxSizerXmlHandler::Handle_wxGridBagSizer()
306 {
307 wxGridBagSizer *sizer =
308 new wxGridBagSizer(GetDimension(wxT("vgap")), GetDimension(wxT("hgap")));
309 SetGrowables(sizer, wxT("growablerows"), true);
310 SetGrowables(sizer, wxT("growablecols"), false);
311 return sizer;
312 }
313
314 wxSizer* wxSizerXmlHandler::Handle_wxWrapSizer()
315 {
316 wxWrapSizer *sizer = new wxWrapSizer(GetStyle("orient"), wxHORIZONTAL);
317 return sizer;
318 }
319
320
321
322 void wxSizerXmlHandler::SetGrowables(wxFlexGridSizer* sizer,
323 const wxChar* param,
324 bool rows)
325 {
326 wxStringTokenizer tkn;
327 unsigned long l;
328 tkn.SetString(GetParamValue(param), wxT(","));
329 while (tkn.HasMoreTokens())
330 {
331 if (!tkn.GetNextToken().ToULong(&l))
332 wxLogError(wxT("growable[rows|cols] must be comma-separated list of row numbers"));
333 else {
334 if (rows)
335 sizer->AddGrowableRow(l);
336 else
337 sizer->AddGrowableCol(l);
338 }
339 }
340 }
341
342
343 wxGBPosition wxSizerXmlHandler::GetGBPos(const wxString& param)
344 {
345 wxSize sz = GetSize(param);
346 if (sz.x < 0) sz.x = 0;
347 if (sz.y < 0) sz.y = 0;
348 return wxGBPosition(sz.x, sz.y);
349 }
350
351 wxGBSpan wxSizerXmlHandler::GetGBSpan(const wxString& param)
352 {
353 wxSize sz = GetSize(param);
354 if (sz.x < 1) sz.x = 1;
355 if (sz.y < 1) sz.y = 1;
356 return wxGBSpan(sz.x, sz.y);
357 }
358
359
360
361 wxSizerItem* wxSizerXmlHandler::MakeSizerItem()
362 {
363 if (m_isGBS)
364 return new wxGBSizerItem();
365 else
366 return new wxSizerItem();
367 }
368
369 void wxSizerXmlHandler::SetSizerItemAttributes(wxSizerItem* sitem)
370 {
371 sitem->SetProportion(GetLong(wxT("option"))); // Should this check for "proportion" too?
372 sitem->SetFlag(GetStyle(wxT("flag")));
373 sitem->SetBorder(GetDimension(wxT("border")));
374 wxSize sz = GetSize(wxT("minsize"));
375 if (!(sz == wxDefaultSize))
376 sitem->SetMinSize(sz);
377 sz = GetSize(wxT("ratio"));
378 if (!(sz == wxDefaultSize))
379 sitem->SetRatio(sz);
380
381 if (m_isGBS)
382 {
383 wxGBSizerItem* gbsitem = (wxGBSizerItem*)sitem;
384 gbsitem->SetPos(GetGBPos(wxT("cellpos")));
385 gbsitem->SetSpan(GetGBSpan(wxT("cellspan")));
386 }
387
388 // record the id of the item, if any, for use by XRCSIZERITEM()
389 sitem->SetId(GetID());
390 }
391
392 void wxSizerXmlHandler::AddSizerItem(wxSizerItem* sitem)
393 {
394 if (m_isGBS)
395 ((wxGridBagSizer*)m_parentSizer)->Add((wxGBSizerItem*)sitem);
396 else
397 m_parentSizer->Add(sitem);
398 }
399
400
401
402 //-----------------------------------------------------------------------------
403 // wxStdDialogButtonSizerXmlHandler
404 //-----------------------------------------------------------------------------
405 #if wxUSE_BUTTON
406
407 IMPLEMENT_DYNAMIC_CLASS(wxStdDialogButtonSizerXmlHandler, wxXmlResourceHandler)
408
409 wxStdDialogButtonSizerXmlHandler::wxStdDialogButtonSizerXmlHandler()
410 : m_isInside(false), m_parentSizer(NULL)
411 {
412 }
413
414 wxObject *wxStdDialogButtonSizerXmlHandler::DoCreateResource()
415 {
416 if (m_class == wxT("wxStdDialogButtonSizer"))
417 {
418 wxASSERT( !m_parentSizer );
419
420 wxSizer *s = m_parentSizer = new wxStdDialogButtonSizer;
421 m_isInside = true;
422
423 CreateChildren(m_parent, true/*only this handler*/);
424
425 m_parentSizer->Realize();
426
427 m_isInside = false;
428 m_parentSizer = NULL;
429
430 return s;
431 }
432 else // m_class == "button"
433 {
434 wxASSERT( m_parentSizer );
435
436 // find the item to be managed by this sizeritem
437 wxXmlNode *n = GetParamNode(wxT("object"));
438 if ( !n )
439 n = GetParamNode(wxT("object_ref"));
440
441 // did we find one?
442 if (n)
443 {
444 wxObject *item = CreateResFromNode(n, m_parent, NULL);
445 wxButton *button = wxDynamicCast(item, wxButton);
446
447 if (button)
448 m_parentSizer->AddButton(button);
449 else
450 wxLogError(wxT("Error in resource - expected button."));
451
452 return item;
453 }
454 else /*n == NULL*/
455 {
456 wxLogError(wxT("Error in resource: no button within wxStdDialogButtonSizer."));
457 return NULL;
458 }
459 }
460 }
461
462 bool wxStdDialogButtonSizerXmlHandler::CanHandle(wxXmlNode *node)
463 {
464 return (!m_isInside && IsOfClass(node, wxT("wxStdDialogButtonSizer"))) ||
465 (m_isInside && IsOfClass(node, wxT("button")));
466 }
467 #endif // wxUSE_BUTTON
468
469 #endif // wxUSE_XRC