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