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