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