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