]> git.saurik.com Git - wxWidgets.git/blame - src/xrc/xh_sizer.cpp
avoiding reentrancy problems and congestion
[wxWidgets.git] / src / xrc / xh_sizer.cpp
CommitLineData
78d14f80 1/////////////////////////////////////////////////////////////////////////////
1c067fe3 2// Name: src/xrc/xh_sizer.cpp
b5d6954b 3// Purpose: XRC resource for wxBoxSizer
78d14f80
VS
4// Author: Vaclav Slavik
5// Created: 2000/03/21
6// RCS-ID: $Id$
7// Copyright: (c) 2000 Vaclav Slavik
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
f80ea77b 10
78d14f80
VS
11// For compilers that support precompilation, includes "wx.h".
12#include "wx/wxprec.h"
13
14#ifdef __BORLANDC__
15 #pragma hdrstop
16#endif
17
621be1ec 18#if wxUSE_XRC
a1e4ec87 19
78d14f80 20#include "wx/xrc/xh_sizer.h"
e4db172a
WS
21
22#ifndef WX_PRECOMP
23 #include "wx/log.h"
8e609c82 24 #include "wx/panel.h"
876cd6f7 25 #include "wx/statbox.h"
ed2fbeb8 26 #include "wx/sizer.h"
4107600f
MW
27 #include "wx/frame.h"
28 #include "wx/dialog.h"
29 #include "wx/button.h"
5e1a9f05 30 #include "wx/scrolwin.h"
e4db172a
WS
31#endif
32
0d077b41 33#include "wx/gbsizer.h"
13a38887 34#include "wx/wrapsizer.h"
78d14f80
VS
35#include "wx/notebook.h"
36#include "wx/tokenzr.h"
37
df27f1dc 38#include "wx/xml/xml.h"
78d14f80 39
172541f6
VS
40//-----------------------------------------------------------------------------
41// wxSizerXmlHandler
42//-----------------------------------------------------------------------------
78d14f80 43
0d077b41 44IMPLEMENT_DYNAMIC_CLASS(wxSizerXmlHandler, wxXmlResourceHandler)
78d14f80 45
f80ea77b 46wxSizerXmlHandler::wxSizerXmlHandler()
ed2fbeb8
WS
47 :wxXmlResourceHandler(),
48 m_isInside(false),
49 m_isGBS(false),
50 m_parentSizer(NULL)
78d14f80 51{
544fee32
VS
52 XRC_ADD_STYLE(wxHORIZONTAL);
53 XRC_ADD_STYLE(wxVERTICAL);
78d14f80
VS
54
55 // and flags
544fee32
VS
56 XRC_ADD_STYLE(wxLEFT);
57 XRC_ADD_STYLE(wxRIGHT);
58 XRC_ADD_STYLE(wxTOP);
59 XRC_ADD_STYLE(wxBOTTOM);
60 XRC_ADD_STYLE(wxNORTH);
61 XRC_ADD_STYLE(wxSOUTH);
62 XRC_ADD_STYLE(wxEAST);
63 XRC_ADD_STYLE(wxWEST);
64 XRC_ADD_STYLE(wxALL);
78d14f80 65
544fee32
VS
66 XRC_ADD_STYLE(wxGROW);
67 XRC_ADD_STYLE(wxEXPAND);
68 XRC_ADD_STYLE(wxSHAPED);
69 XRC_ADD_STYLE(wxSTRETCH_NOT);
78d14f80 70
544fee32
VS
71 XRC_ADD_STYLE(wxALIGN_CENTER);
72 XRC_ADD_STYLE(wxALIGN_CENTRE);
73 XRC_ADD_STYLE(wxALIGN_LEFT);
74 XRC_ADD_STYLE(wxALIGN_TOP);
75 XRC_ADD_STYLE(wxALIGN_RIGHT);
76 XRC_ADD_STYLE(wxALIGN_BOTTOM);
77 XRC_ADD_STYLE(wxALIGN_CENTER_HORIZONTAL);
78 XRC_ADD_STYLE(wxALIGN_CENTRE_HORIZONTAL);
79 XRC_ADD_STYLE(wxALIGN_CENTER_VERTICAL);
80 XRC_ADD_STYLE(wxALIGN_CENTRE_VERTICAL);
f80ea77b 81
c66b63e5 82 XRC_ADD_STYLE(wxFIXED_MINSIZE);
a575238f 83 XRC_ADD_STYLE(wxRESERVE_SPACE_EVEN_IF_HIDDEN);
63b37a4e 84
249259e7
VZ
85 // this flag doesn't do anything any more but we can just ignore its
86 // occurrences in the old resource files instead of raising a fuss because
87 // of it
88 AddStyle("wxADJUST_MINSIZE", 0);
89
63b37a4e
VZ
90 // wxWrapSizer-specific flags
91 XRC_ADD_STYLE(wxEXTEND_LAST_ON_EACH_LINE);
92 XRC_ADD_STYLE(wxREMOVE_LEADING_SPACES);
78d14f80
VS
93}
94
95
96
0d077b41
RD
97bool wxSizerXmlHandler::CanHandle(wxXmlNode *node)
98{
99 return ( (!m_isInside && IsSizerNode(node)) ||
100 (m_isInside && IsOfClass(node, wxT("sizeritem"))) ||
f80ea77b 101 (m_isInside && IsOfClass(node, wxT("spacer")))
0d077b41
RD
102 );
103}
104
f80ea77b 105
0d077b41 106wxObject* wxSizerXmlHandler::DoCreateResource()
f80ea77b 107{
78d14f80 108 if (m_class == wxT("sizeritem"))
0d077b41 109 return Handle_sizeritem();
f80ea77b 110
78d14f80 111 else if (m_class == wxT("spacer"))
0d077b41
RD
112 return Handle_spacer();
113
114 else
115 return Handle_sizer();
116}
117
118
40730ad1
VZ
119wxSizer* wxSizerXmlHandler::DoCreateSizer(const wxString& name)
120{
121 if (name == wxT("wxBoxSizer"))
122 return Handle_wxBoxSizer();
123#if wxUSE_STATBOX
124 else if (name == wxT("wxStaticBoxSizer"))
125 return Handle_wxStaticBoxSizer();
126#endif
127 else if (name == wxT("wxGridSizer"))
128 {
129 if ( !ValidateGridSizerChildren() )
130 return NULL;
131 return Handle_wxGridSizer();
132 }
133 else if (name == wxT("wxFlexGridSizer"))
134 {
135 return Handle_wxFlexGridSizer();
136 }
137 else if (name == wxT("wxGridBagSizer"))
138 {
139 return Handle_wxGridBagSizer();
140 }
141 else if (name == wxT("wxWrapSizer"))
142 {
143 return Handle_wxWrapSizer();
144 }
145
146 ReportError(wxString::Format("unknown sizer class \"%s\"", name));
147 return NULL;
148}
149
0d077b41
RD
150
151
40730ad1 152bool wxSizerXmlHandler::IsSizerNode(wxXmlNode *node) const
0d077b41
RD
153{
154 return (IsOfClass(node, wxT("wxBoxSizer"))) ||
155 (IsOfClass(node, wxT("wxStaticBoxSizer"))) ||
156 (IsOfClass(node, wxT("wxGridSizer"))) ||
157 (IsOfClass(node, wxT("wxFlexGridSizer"))) ||
13a38887
VZ
158 (IsOfClass(node, wxT("wxGridBagSizer"))) ||
159 (IsOfClass(node, wxT("wxWrapSizer")));
0d077b41
RD
160}
161
162
163wxObject* wxSizerXmlHandler::Handle_sizeritem()
164{
165 // find the item to be managed by this sizeritem
166 wxXmlNode *n = GetParamNode(wxT("object"));
167 if ( !n )
168 n = GetParamNode(wxT("object_ref"));
169
170 // did we find one?
171 if (n)
172 {
173 // create a sizer item for it
174 wxSizerItem* sitem = MakeSizerItem();
f80ea77b 175
0d077b41
RD
176 // now fetch the item to be managed
177 bool old_gbs = m_isGBS;
178 bool old_ins = m_isInside;
179 wxSizer *old_par = m_parentSizer;
f80ea77b
WS
180 m_isInside = false;
181 if (!IsSizerNode(n)) m_parentSizer = NULL;
0d077b41
RD
182 wxObject *item = CreateResFromNode(n, m_parent, NULL);
183 m_isInside = old_ins;
184 m_parentSizer = old_par;
185 m_isGBS = old_gbs;
186
187 // and figure out what type it is
188 wxSizer *sizer = wxDynamicCast(item, wxSizer);
189 wxWindow *wnd = wxDynamicCast(item, wxWindow);
f80ea77b 190
0d077b41 191 if (sizer)
a50cf60e 192 sitem->AssignSizer(sizer);
0d077b41 193 else if (wnd)
a50cf60e 194 sitem->AssignWindow(wnd);
f80ea77b 195 else
819559b2 196 ReportError(n, "unexpected item in sizer");
0d077b41 197
1eba2193
RD
198 // finally, set other wxSizerItem attributes
199 SetSizerItemAttributes(sitem);
200
0d077b41
RD
201 AddSizerItem(sitem);
202 return item;
203 }
204 else /*n == NULL*/
78d14f80 205 {
819559b2 206 ReportError("no window/sizer/spacer within sizeritem object");
78d14f80
VS
207 return NULL;
208 }
0d077b41
RD
209}
210
211
212wxObject* wxSizerXmlHandler::Handle_spacer()
213{
07acc3cc
VZ
214 if ( !m_parentSizer )
215 {
819559b2 216 ReportError("spacer only allowed inside a sizer");
07acc3cc
VZ
217 return NULL;
218 }
0d077b41
RD
219
220 wxSizerItem* sitem = MakeSizerItem();
221 SetSizerItemAttributes(sitem);
a50cf60e 222 sitem->AssignSpacer(GetSize());
f80ea77b 223 AddSizerItem(sitem);
0d077b41
RD
224 return NULL;
225}
226
78d14f80 227
0d077b41
RD
228wxObject* wxSizerXmlHandler::Handle_sizer()
229{
0d077b41 230 wxXmlNode *parentNode = m_node->GetParent();
78d14f80 231
07acc3cc
VZ
232 if ( !m_parentSizer &&
233 (!parentNode || parentNode->GetType() != wxXML_ELEMENT_NODE ||
234 !m_parentAsWindow) )
235 {
819559b2 236 ReportError("sizer must have a window parent");
07acc3cc
VZ
237 return NULL;
238 }
78d14f80 239
40730ad1
VZ
240 // Create the sizer of the appropriate class.
241 wxSizer * const sizer = DoCreateSizer(m_class);
f80ea77b 242
afc0db8c
VS
243 // creation of sizer failed for some (already reported) reason, so exit:
244 if ( !sizer )
245 return NULL;
246
0d077b41
RD
247 wxSize minsize = GetSize(wxT("minsize"));
248 if (!(minsize == wxDefaultSize))
249 sizer->SetMinSize(minsize);
250
251 // save state
252 wxSizer *old_par = m_parentSizer;
253 bool old_ins = m_isInside;
0d077b41
RD
254
255 // set new state
256 m_parentSizer = sizer;
f80ea77b 257 m_isInside = true;
0d077b41 258 m_isGBS = (m_class == wxT("wxGridBagSizer"));
f80ea77b 259
ff1aede6
VZ
260 wxObject* parent = m_parent;
261#if wxUSE_STATBOX
262 // wxStaticBoxSizer's child controls should be parented by the box itself,
263 // not its parent.
264 wxStaticBoxSizer* const stsizer = wxDynamicCast(sizer, wxStaticBoxSizer);
265 if ( stsizer )
266 parent = stsizer->GetStaticBox();
267#endif // wxUSE_STATBOX
268
269 CreateChildren(parent, true/*only this handler*/);
0d077b41 270
5dd238c6 271 // set growable rows and cols for sizers which support this
40730ad1 272 if ( wxFlexGridSizer *flexsizer = wxDynamicCast(sizer, wxFlexGridSizer) )
5dd238c6 273 {
5a3eee0d 274 SetFlexibleMode(flexsizer);
5dd238c6
VZ
275 SetGrowables(flexsizer, wxT("growablerows"), true);
276 SetGrowables(flexsizer, wxT("growablecols"), false);
277 }
278
0d077b41 279 // restore state
0d077b41
RD
280 m_isInside = old_ins;
281 m_parentSizer = old_par;
282
283 if (m_parentSizer == NULL) // setup window:
284 {
0d077b41
RD
285 m_parentAsWindow->SetSizer(sizer);
286
287 wxXmlNode *nd = m_node;
288 m_node = parentNode;
289 if (GetSize() == wxDefaultSize)
5e1a9f05
VS
290 {
291 if ( wxDynamicCast(m_parentAsWindow, wxScrolledWindow) != NULL )
292 {
293 sizer->FitInside(m_parentAsWindow);
294 }
295 else
296 {
297 sizer->Fit(m_parentAsWindow);
298 }
299 }
0d077b41
RD
300 m_node = nd;
301
ea813d91
VS
302 if (m_parentAsWindow->IsTopLevel())
303 {
0d077b41 304 sizer->SetSizeHints(m_parentAsWindow);
ea813d91 305 }
0d077b41 306 }
f80ea77b 307
0d077b41
RD
308 return sizer;
309}
310
311
312wxSizer* wxSizerXmlHandler::Handle_wxBoxSizer()
313{
314 return new wxBoxSizer(GetStyle(wxT("orient"), wxHORIZONTAL));
f80ea77b
WS
315}
316
627ddac9 317#if wxUSE_STATBOX
0d077b41
RD
318wxSizer* wxSizerXmlHandler::Handle_wxStaticBoxSizer()
319{
320 return new wxStaticBoxSizer(
321 new wxStaticBox(m_parentAsWindow,
322 GetID(),
323 GetText(wxT("label")),
324 wxDefaultPosition, wxDefaultSize,
325 0/*style*/,
326 GetName()),
327 GetStyle(wxT("orient"), wxHORIZONTAL));
328}
627ddac9 329#endif // wxUSE_STATBOX
f80ea77b 330
0d077b41
RD
331wxSizer* wxSizerXmlHandler::Handle_wxGridSizer()
332{
333 return new wxGridSizer(GetLong(wxT("rows")), GetLong(wxT("cols")),
334 GetDimension(wxT("vgap")), GetDimension(wxT("hgap")));
335}
336
337
5dd238c6 338wxFlexGridSizer* wxSizerXmlHandler::Handle_wxFlexGridSizer()
0d077b41 339{
afc0db8c
VS
340 if ( !ValidateGridSizerChildren() )
341 return NULL;
5dd238c6
VZ
342 return new wxFlexGridSizer(GetLong(wxT("rows")), GetLong(wxT("cols")),
343 GetDimension(wxT("vgap")), GetDimension(wxT("hgap")));
0d077b41
RD
344}
345
346
1808bb47 347wxGridBagSizer* wxSizerXmlHandler::Handle_wxGridBagSizer()
0d077b41 348{
afc0db8c
VS
349 if ( !ValidateGridSizerChildren() )
350 return NULL;
5dd238c6 351 return new wxGridBagSizer(GetDimension(wxT("vgap")), GetDimension(wxT("hgap")));
0d077b41
RD
352}
353
13a38887
VZ
354wxSizer* wxSizerXmlHandler::Handle_wxWrapSizer()
355{
63b37a4e 356 wxWrapSizer *sizer = new wxWrapSizer(GetStyle("orient"), GetStyle("flag"));
13a38887
VZ
357 return sizer;
358}
0d077b41
RD
359
360
afc0db8c
VS
361bool wxSizerXmlHandler::ValidateGridSizerChildren()
362{
363 int rows = GetLong("rows");
364 int cols = GetLong("cols");
365
366 if ( rows && cols )
367 {
368 // fixed number of cells, need to verify children count
369 int children = 0;
370 for ( wxXmlNode *n = m_node->GetChildren(); n; n = n->GetNext() )
371 {
372 if ( n->GetType() == wxXML_ELEMENT_NODE &&
373 (n->GetName() == "object" || n->GetName() == "object_ref") )
374 {
375 children++;
376 }
377 }
378
379 if ( children > rows * cols )
380 {
381 ReportError
382 (
383 wxString::Format
384 (
385 "too many children in grid sizer: %d > %d x %d"
386 " (consider omitting the number of rows or columns)",
387 children,
388 cols,
389 rows
390 )
391 );
392 return false;
393 }
394 }
395
396 return true;
397}
398
0d077b41 399
5a3eee0d
VZ
400void wxSizerXmlHandler::SetFlexibleMode(wxFlexGridSizer* fsizer)
401{
402 if (HasParam(wxT("flexibledirection")))
403 {
404 wxString dir = GetParamValue(wxT("flexibledirection"));
405
406 if (dir == wxT("wxVERTICAL"))
407 fsizer->SetFlexibleDirection(wxVERTICAL);
408 else if (dir == wxT("wxHORIZONTAL"))
409 fsizer->SetFlexibleDirection(wxHORIZONTAL);
410 else if (dir == wxT("wxBOTH"))
411 fsizer->SetFlexibleDirection(wxBOTH);
412 else
413 {
414 ReportParamError
415 (
416 wxT("flexibledirection"),
417 wxString::Format("unknown direction \"%s\"", dir)
418 );
419 }
420 }
421
422 if (HasParam(wxT("nonflexiblegrowmode")))
423 {
424 wxString mode = GetParamValue(wxT("nonflexiblegrowmode"));
425
426 if (mode == wxT("wxFLEX_GROWMODE_NONE"))
427 fsizer->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_NONE);
428 else if (mode == wxT("wxFLEX_GROWMODE_SPECIFIED"))
429 fsizer->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
430 else if (mode == wxT("wxFLEX_GROWMODE_ALL"))
431 fsizer->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_ALL);
432 else
433 {
434 ReportParamError
435 (
436 wxT("nonflexiblegrowmode"),
437 wxString::Format("unknown grow mode \"%s\"", mode)
438 );
439 }
440 }
441}
442
443
0d077b41
RD
444void wxSizerXmlHandler::SetGrowables(wxFlexGridSizer* sizer,
445 const wxChar* param,
446 bool rows)
447{
afc0db8c
VS
448 int nrows, ncols;
449 sizer->CalcRowsCols(nrows, ncols);
450 const int nslots = rows ? nrows : ncols;
451
0d077b41 452 wxStringTokenizer tkn;
0d077b41 453 tkn.SetString(GetParamValue(param), wxT(","));
afc0db8c 454
0d077b41
RD
455 while (tkn.HasMoreTokens())
456 {
5a3eee0d
VZ
457 wxString propStr;
458 wxString idxStr = tkn.GetNextToken().BeforeFirst(wxT(':'), &propStr);
459
460 unsigned long li;
461 if (!idxStr.ToULong(&li))
5dd238c6 462 {
819559b2
VS
463 ReportParamError
464 (
465 param,
5a3eee0d 466 "value must be a comma-separated list of numbers"
819559b2 467 );
5dd238c6 468 break;
78d14f80 469 }
5dd238c6 470
5a3eee0d
VZ
471 unsigned long lp = 0;
472 if (!propStr.empty())
473 {
474 if (!propStr.ToULong(&lp))
475 {
476 ReportParamError
477 (
478 param,
479 "value must be a comma-separated list of numbers"
480 );
481 break;
482 }
483 }
484
485 const int n = static_cast<int>(li);
f33a5bc6 486 if ( n >= nslots )
afc0db8c
VS
487 {
488 ReportParamError
489 (
490 param,
491 wxString::Format
492 (
493 "invalid %s index %d: must be less than %d",
494 rows ? "row" : "column",
f33a5bc6 495 n,
afc0db8c
VS
496 nslots
497 )
498 );
499
500 // ignore incorrect value, still try to process the rest
501 continue;
502 }
503
5dd238c6 504 if (rows)
5a3eee0d 505 sizer->AddGrowableRow(n, static_cast<int>(lp));
5dd238c6 506 else
5a3eee0d 507 sizer->AddGrowableCol(n, static_cast<int>(lp));
78d14f80
VS
508 }
509}
510
511
0d077b41
RD
512wxGBPosition wxSizerXmlHandler::GetGBPos(const wxString& param)
513{
514 wxSize sz = GetSize(param);
515 if (sz.x < 0) sz.x = 0;
516 if (sz.y < 0) sz.y = 0;
517 return wxGBPosition(sz.x, sz.y);
518}
78d14f80 519
0d077b41
RD
520wxGBSpan wxSizerXmlHandler::GetGBSpan(const wxString& param)
521{
522 wxSize sz = GetSize(param);
523 if (sz.x < 1) sz.x = 1;
524 if (sz.y < 1) sz.y = 1;
525 return wxGBSpan(sz.x, sz.y);
526}
527
528
529
530wxSizerItem* wxSizerXmlHandler::MakeSizerItem()
531{
532 if (m_isGBS)
533 return new wxGBSizerItem();
534 else
535 return new wxSizerItem();
536}
537
538void wxSizerXmlHandler::SetSizerItemAttributes(wxSizerItem* sitem)
539{
540 sitem->SetProportion(GetLong(wxT("option"))); // Should this check for "proportion" too?
541 sitem->SetFlag(GetStyle(wxT("flag")));
542 sitem->SetBorder(GetDimension(wxT("border")));
543 wxSize sz = GetSize(wxT("minsize"));
544 if (!(sz == wxDefaultSize))
1eba2193 545 sitem->SetMinSize(sz);
0d077b41
RD
546 sz = GetSize(wxT("ratio"));
547 if (!(sz == wxDefaultSize))
548 sitem->SetRatio(sz);
f80ea77b 549
0d077b41
RD
550 if (m_isGBS)
551 {
552 wxGBSizerItem* gbsitem = (wxGBSizerItem*)sitem;
ea0d8ca6
RD
553 gbsitem->SetPos(GetGBPos(wxT("cellpos")));
554 gbsitem->SetSpan(GetGBSpan(wxT("cellspan")));
f80ea77b 555 }
86909f4c
VZ
556
557 // record the id of the item, if any, for use by XRCSIZERITEM()
558 sitem->SetId(GetID());
0d077b41
RD
559}
560
561void wxSizerXmlHandler::AddSizerItem(wxSizerItem* sitem)
78d14f80 562{
0d077b41
RD
563 if (m_isGBS)
564 ((wxGridBagSizer*)m_parentSizer)->Add((wxGBSizerItem*)sitem);
565 else
566 m_parentSizer->Add(sitem);
78d14f80 567}
f80ea77b 568
172541f6
VS
569
570
571//-----------------------------------------------------------------------------
572// wxStdDialogButtonSizerXmlHandler
573//-----------------------------------------------------------------------------
dd47af27 574#if wxUSE_BUTTON
172541f6
VS
575
576IMPLEMENT_DYNAMIC_CLASS(wxStdDialogButtonSizerXmlHandler, wxXmlResourceHandler)
577
578wxStdDialogButtonSizerXmlHandler::wxStdDialogButtonSizerXmlHandler()
579 : m_isInside(false), m_parentSizer(NULL)
580{
581}
582
583wxObject *wxStdDialogButtonSizerXmlHandler::DoCreateResource()
584{
585 if (m_class == wxT("wxStdDialogButtonSizer"))
586 {
587 wxASSERT( !m_parentSizer );
588
589 wxSizer *s = m_parentSizer = new wxStdDialogButtonSizer;
590 m_isInside = true;
591
592 CreateChildren(m_parent, true/*only this handler*/);
593
594 m_parentSizer->Realize();
595
596 m_isInside = false;
597 m_parentSizer = NULL;
598
599 return s;
600 }
601 else // m_class == "button"
602 {
603 wxASSERT( m_parentSizer );
604
605 // find the item to be managed by this sizeritem
606 wxXmlNode *n = GetParamNode(wxT("object"));
607 if ( !n )
608 n = GetParamNode(wxT("object_ref"));
609
610 // did we find one?
611 if (n)
612 {
613 wxObject *item = CreateResFromNode(n, m_parent, NULL);
614 wxButton *button = wxDynamicCast(item, wxButton);
615
616 if (button)
617 m_parentSizer->AddButton(button);
618 else
819559b2 619 ReportError(n, "expected wxButton");
172541f6
VS
620
621 return item;
622 }
623 else /*n == NULL*/
624 {
819559b2 625 ReportError("no button within wxStdDialogButtonSizer");
172541f6
VS
626 return NULL;
627 }
628 }
629}
630
631bool wxStdDialogButtonSizerXmlHandler::CanHandle(wxXmlNode *node)
632{
633 return (!m_isInside && IsOfClass(node, wxT("wxStdDialogButtonSizer"))) ||
634 (m_isInside && IsOfClass(node, wxT("button")));
635}
dd47af27 636#endif // wxUSE_BUTTON
172541f6 637
621be1ec 638#endif // wxUSE_XRC