1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/xrc/xh_sizer.cpp
3 // Purpose: XRC resource for wxBoxSizer
4 // Author: Vaclav Slavik
7 // Copyright: (c) 2000 Vaclav Slavik
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
20 #include "wx/xrc/xh_sizer.h"
25 #include "wx/statbox.h"
28 #include "wx/dialog.h"
29 #include "wx/button.h"
30 #include "wx/scrolwin.h"
33 #include "wx/gbsizer.h"
34 #include "wx/wrapsizer.h"
35 #include "wx/notebook.h"
36 #include "wx/tokenzr.h"
39 //-----------------------------------------------------------------------------
41 //-----------------------------------------------------------------------------
43 IMPLEMENT_DYNAMIC_CLASS(wxSizerXmlHandler
, wxXmlResourceHandler
)
45 wxSizerXmlHandler::wxSizerXmlHandler()
46 :wxXmlResourceHandler(),
51 XRC_ADD_STYLE(wxHORIZONTAL
);
52 XRC_ADD_STYLE(wxVERTICAL
);
55 XRC_ADD_STYLE(wxLEFT
);
56 XRC_ADD_STYLE(wxRIGHT
);
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
);
65 XRC_ADD_STYLE(wxGROW
);
66 XRC_ADD_STYLE(wxEXPAND
);
67 XRC_ADD_STYLE(wxSHAPED
);
68 XRC_ADD_STYLE(wxSTRETCH_NOT
);
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
);
81 XRC_ADD_STYLE(wxFIXED_MINSIZE
);
82 XRC_ADD_STYLE(wxRESERVE_SPACE_EVEN_IF_HIDDEN
);
84 // this flag doesn't do anything any more but we can just ignore its
85 // occurrences in the old resource files instead of raising a fuss because
87 AddStyle("wxADJUST_MINSIZE", 0);
89 // wxWrapSizer-specific flags
90 XRC_ADD_STYLE(wxEXTEND_LAST_ON_EACH_LINE
);
91 XRC_ADD_STYLE(wxREMOVE_LEADING_SPACES
);
96 bool wxSizerXmlHandler::CanHandle(wxXmlNode
*node
)
98 return ( (!m_isInside
&& IsSizerNode(node
)) ||
99 (m_isInside
&& IsOfClass(node
, wxT("sizeritem"))) ||
100 (m_isInside
&& IsOfClass(node
, wxT("spacer")))
105 wxObject
* wxSizerXmlHandler::DoCreateResource()
107 if (m_class
== wxT("sizeritem"))
108 return Handle_sizeritem();
110 else if (m_class
== wxT("spacer"))
111 return Handle_spacer();
114 return Handle_sizer();
120 bool wxSizerXmlHandler::IsSizerNode(wxXmlNode
*node
)
122 return (IsOfClass(node
, wxT("wxBoxSizer"))) ||
123 (IsOfClass(node
, wxT("wxStaticBoxSizer"))) ||
124 (IsOfClass(node
, wxT("wxGridSizer"))) ||
125 (IsOfClass(node
, wxT("wxFlexGridSizer"))) ||
126 (IsOfClass(node
, wxT("wxGridBagSizer"))) ||
127 (IsOfClass(node
, wxT("wxWrapSizer")));
131 wxObject
* wxSizerXmlHandler::Handle_sizeritem()
133 // find the item to be managed by this sizeritem
134 wxXmlNode
*n
= GetParamNode(wxT("object"));
136 n
= GetParamNode(wxT("object_ref"));
141 // create a sizer item for it
142 wxSizerItem
* sitem
= MakeSizerItem();
144 // now fetch the item to be managed
145 bool old_gbs
= m_isGBS
;
146 bool old_ins
= m_isInside
;
147 wxSizer
*old_par
= m_parentSizer
;
149 if (!IsSizerNode(n
)) m_parentSizer
= NULL
;
150 wxObject
*item
= CreateResFromNode(n
, m_parent
, NULL
);
151 m_isInside
= old_ins
;
152 m_parentSizer
= old_par
;
155 // and figure out what type it is
156 wxSizer
*sizer
= wxDynamicCast(item
, wxSizer
);
157 wxWindow
*wnd
= wxDynamicCast(item
, wxWindow
);
160 sitem
->AssignSizer(sizer
);
162 sitem
->AssignWindow(wnd
);
164 ReportError(n
, "unexpected item in sizer");
166 // finally, set other wxSizerItem attributes
167 SetSizerItemAttributes(sitem
);
174 ReportError("no window/sizer/spacer within sizeritem object");
180 wxObject
* wxSizerXmlHandler::Handle_spacer()
182 if ( !m_parentSizer
)
184 ReportError("spacer only allowed inside a sizer");
188 wxSizerItem
* sitem
= MakeSizerItem();
189 SetSizerItemAttributes(sitem
);
190 sitem
->AssignSpacer(GetSize());
196 wxObject
* wxSizerXmlHandler::Handle_sizer()
198 wxSizer
*sizer
= NULL
;
199 wxFlexGridSizer
*flexsizer
= NULL
;
201 wxXmlNode
*parentNode
= m_node
->GetParent();
203 if ( !m_parentSizer
&&
204 (!parentNode
|| parentNode
->GetType() != wxXML_ELEMENT_NODE
||
207 ReportError("sizer must have a window parent");
211 if (m_class
== wxT("wxBoxSizer"))
212 sizer
= Handle_wxBoxSizer();
214 else if (m_class
== wxT("wxStaticBoxSizer"))
215 sizer
= Handle_wxStaticBoxSizer();
217 else if (m_class
== wxT("wxGridSizer"))
219 if ( !ValidateGridSizerChildren() )
221 sizer
= Handle_wxGridSizer();
223 else if (m_class
== wxT("wxFlexGridSizer"))
225 flexsizer
= Handle_wxFlexGridSizer();
228 else if (m_class
== wxT("wxGridBagSizer"))
230 flexsizer
= Handle_wxGridBagSizer();
233 else if (m_class
== wxT("wxWrapSizer"))
235 sizer
= Handle_wxWrapSizer();
239 ReportError(wxString::Format("unknown sizer class \"%s\"", m_class
));
242 // creation of sizer failed for some (already reported) reason, so exit:
246 wxSize minsize
= GetSize(wxT("minsize"));
247 if (!(minsize
== wxDefaultSize
))
248 sizer
->SetMinSize(minsize
);
251 wxSizer
*old_par
= m_parentSizer
;
252 bool old_ins
= m_isInside
;
255 m_parentSizer
= sizer
;
257 m_isGBS
= (m_class
== wxT("wxGridBagSizer"));
259 CreateChildren(m_parent
, true/*only this handler*/);
261 // set growable rows and cols for sizers which support this
264 SetGrowables(flexsizer
, wxT("growablerows"), true);
265 SetGrowables(flexsizer
, wxT("growablecols"), false);
269 m_isInside
= old_ins
;
270 m_parentSizer
= old_par
;
272 if (m_parentSizer
== NULL
) // setup window:
274 m_parentAsWindow
->SetSizer(sizer
);
276 wxXmlNode
*nd
= m_node
;
278 if (GetSize() == wxDefaultSize
)
280 if ( wxDynamicCast(m_parentAsWindow
, wxScrolledWindow
) != NULL
)
282 sizer
->FitInside(m_parentAsWindow
);
286 sizer
->Fit(m_parentAsWindow
);
291 if (m_parentAsWindow
->IsTopLevel())
293 sizer
->SetSizeHints(m_parentAsWindow
);
301 wxSizer
* wxSizerXmlHandler::Handle_wxBoxSizer()
303 return new wxBoxSizer(GetStyle(wxT("orient"), wxHORIZONTAL
));
307 wxSizer
* wxSizerXmlHandler::Handle_wxStaticBoxSizer()
309 return new wxStaticBoxSizer(
310 new wxStaticBox(m_parentAsWindow
,
312 GetText(wxT("label")),
313 wxDefaultPosition
, wxDefaultSize
,
316 GetStyle(wxT("orient"), wxHORIZONTAL
));
318 #endif // wxUSE_STATBOX
320 wxSizer
* wxSizerXmlHandler::Handle_wxGridSizer()
322 return new wxGridSizer(GetLong(wxT("rows")), GetLong(wxT("cols")),
323 GetDimension(wxT("vgap")), GetDimension(wxT("hgap")));
327 wxFlexGridSizer
* wxSizerXmlHandler::Handle_wxFlexGridSizer()
329 if ( !ValidateGridSizerChildren() )
331 return new wxFlexGridSizer(GetLong(wxT("rows")), GetLong(wxT("cols")),
332 GetDimension(wxT("vgap")), GetDimension(wxT("hgap")));
336 wxGridBagSizer
* wxSizerXmlHandler::Handle_wxGridBagSizer()
338 if ( !ValidateGridSizerChildren() )
340 return new wxGridBagSizer(GetDimension(wxT("vgap")), GetDimension(wxT("hgap")));
343 wxSizer
* wxSizerXmlHandler::Handle_wxWrapSizer()
345 wxWrapSizer
*sizer
= new wxWrapSizer(GetStyle("orient"), GetStyle("flag"));
350 bool wxSizerXmlHandler::ValidateGridSizerChildren()
352 int rows
= GetLong("rows");
353 int cols
= GetLong("cols");
357 // fixed number of cells, need to verify children count
359 for ( wxXmlNode
*n
= m_node
->GetChildren(); n
; n
= n
->GetNext() )
361 if ( n
->GetType() == wxXML_ELEMENT_NODE
&&
362 (n
->GetName() == "object" || n
->GetName() == "object_ref") )
368 if ( children
> rows
* cols
)
374 "too many children in grid sizer: %d > %d x %d"
375 " (consider omitting the number of rows or columns)",
389 void wxSizerXmlHandler::SetGrowables(wxFlexGridSizer
* sizer
,
394 sizer
->CalcRowsCols(nrows
, ncols
);
395 const int nslots
= rows
? nrows
: ncols
;
397 wxStringTokenizer tkn
;
398 tkn
.SetString(GetParamValue(param
), wxT(","));
400 while (tkn
.HasMoreTokens())
403 if (!tkn
.GetNextToken().ToULong(&l
))
408 "value must be comma-separated list of row numbers"
413 if ( (int)l
>= nslots
)
420 "invalid %s index %d: must be less than %d",
421 rows
? "row" : "column",
427 // ignore incorrect value, still try to process the rest
432 sizer
->AddGrowableRow(l
);
434 sizer
->AddGrowableCol(l
);
439 wxGBPosition
wxSizerXmlHandler::GetGBPos(const wxString
& param
)
441 wxSize sz
= GetSize(param
);
442 if (sz
.x
< 0) sz
.x
= 0;
443 if (sz
.y
< 0) sz
.y
= 0;
444 return wxGBPosition(sz
.x
, sz
.y
);
447 wxGBSpan
wxSizerXmlHandler::GetGBSpan(const wxString
& param
)
449 wxSize sz
= GetSize(param
);
450 if (sz
.x
< 1) sz
.x
= 1;
451 if (sz
.y
< 1) sz
.y
= 1;
452 return wxGBSpan(sz
.x
, sz
.y
);
457 wxSizerItem
* wxSizerXmlHandler::MakeSizerItem()
460 return new wxGBSizerItem();
462 return new wxSizerItem();
465 void wxSizerXmlHandler::SetSizerItemAttributes(wxSizerItem
* sitem
)
467 sitem
->SetProportion(GetLong(wxT("option"))); // Should this check for "proportion" too?
468 sitem
->SetFlag(GetStyle(wxT("flag")));
469 sitem
->SetBorder(GetDimension(wxT("border")));
470 wxSize sz
= GetSize(wxT("minsize"));
471 if (!(sz
== wxDefaultSize
))
472 sitem
->SetMinSize(sz
);
473 sz
= GetSize(wxT("ratio"));
474 if (!(sz
== wxDefaultSize
))
479 wxGBSizerItem
* gbsitem
= (wxGBSizerItem
*)sitem
;
480 gbsitem
->SetPos(GetGBPos(wxT("cellpos")));
481 gbsitem
->SetSpan(GetGBSpan(wxT("cellspan")));
484 // record the id of the item, if any, for use by XRCSIZERITEM()
485 sitem
->SetId(GetID());
488 void wxSizerXmlHandler::AddSizerItem(wxSizerItem
* sitem
)
491 ((wxGridBagSizer
*)m_parentSizer
)->Add((wxGBSizerItem
*)sitem
);
493 m_parentSizer
->Add(sitem
);
498 //-----------------------------------------------------------------------------
499 // wxStdDialogButtonSizerXmlHandler
500 //-----------------------------------------------------------------------------
503 IMPLEMENT_DYNAMIC_CLASS(wxStdDialogButtonSizerXmlHandler
, wxXmlResourceHandler
)
505 wxStdDialogButtonSizerXmlHandler::wxStdDialogButtonSizerXmlHandler()
506 : m_isInside(false), m_parentSizer(NULL
)
510 wxObject
*wxStdDialogButtonSizerXmlHandler::DoCreateResource()
512 if (m_class
== wxT("wxStdDialogButtonSizer"))
514 wxASSERT( !m_parentSizer
);
516 wxSizer
*s
= m_parentSizer
= new wxStdDialogButtonSizer
;
519 CreateChildren(m_parent
, true/*only this handler*/);
521 m_parentSizer
->Realize();
524 m_parentSizer
= NULL
;
528 else // m_class == "button"
530 wxASSERT( m_parentSizer
);
532 // find the item to be managed by this sizeritem
533 wxXmlNode
*n
= GetParamNode(wxT("object"));
535 n
= GetParamNode(wxT("object_ref"));
540 wxObject
*item
= CreateResFromNode(n
, m_parent
, NULL
);
541 wxButton
*button
= wxDynamicCast(item
, wxButton
);
544 m_parentSizer
->AddButton(button
);
546 ReportError(n
, "expected wxButton");
552 ReportError("no button within wxStdDialogButtonSizer");
558 bool wxStdDialogButtonSizerXmlHandler::CanHandle(wxXmlNode
*node
)
560 return (!m_isInside
&& IsOfClass(node
, wxT("wxStdDialogButtonSizer"))) ||
561 (m_isInside
&& IsOfClass(node
, wxT("button")));
563 #endif // wxUSE_BUTTON