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