]> git.saurik.com Git - wxWidgets.git/blame - src/xrc/xh_sizer.cpp
ensure that GetEditControl() returns something even if label editing was started...
[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
78d14f80 38
172541f6
VS
39//-----------------------------------------------------------------------------
40// wxSizerXmlHandler
41//-----------------------------------------------------------------------------
78d14f80 42
0d077b41 43IMPLEMENT_DYNAMIC_CLASS(wxSizerXmlHandler, wxXmlResourceHandler)
78d14f80 44
f80ea77b 45wxSizerXmlHandler::wxSizerXmlHandler()
ed2fbeb8
WS
46 :wxXmlResourceHandler(),
47 m_isInside(false),
48 m_isGBS(false),
49 m_parentSizer(NULL)
78d14f80 50{
544fee32
VS
51 XRC_ADD_STYLE(wxHORIZONTAL);
52 XRC_ADD_STYLE(wxVERTICAL);
78d14f80
VS
53
54 // and flags
544fee32
VS
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);
78d14f80 64
544fee32
VS
65 XRC_ADD_STYLE(wxGROW);
66 XRC_ADD_STYLE(wxEXPAND);
67 XRC_ADD_STYLE(wxSHAPED);
68 XRC_ADD_STYLE(wxSTRETCH_NOT);
78d14f80 69
544fee32
VS
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);
f80ea77b 80
c66b63e5 81 XRC_ADD_STYLE(wxFIXED_MINSIZE);
a575238f 82 XRC_ADD_STYLE(wxRESERVE_SPACE_EVEN_IF_HIDDEN);
63b37a4e
VZ
83
84 // wxWrapSizer-specific flags
85 XRC_ADD_STYLE(wxEXTEND_LAST_ON_EACH_LINE);
86 XRC_ADD_STYLE(wxREMOVE_LEADING_SPACES);
78d14f80
VS
87}
88
89
90
0d077b41
RD
91bool wxSizerXmlHandler::CanHandle(wxXmlNode *node)
92{
93 return ( (!m_isInside && IsSizerNode(node)) ||
94 (m_isInside && IsOfClass(node, wxT("sizeritem"))) ||
f80ea77b 95 (m_isInside && IsOfClass(node, wxT("spacer")))
0d077b41
RD
96 );
97}
98
f80ea77b 99
0d077b41 100wxObject* wxSizerXmlHandler::DoCreateResource()
f80ea77b 101{
78d14f80 102 if (m_class == wxT("sizeritem"))
0d077b41 103 return Handle_sizeritem();
f80ea77b 104
78d14f80 105 else if (m_class == wxT("spacer"))
0d077b41
RD
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"))) ||
13a38887
VZ
121 (IsOfClass(node, wxT("wxGridBagSizer"))) ||
122 (IsOfClass(node, wxT("wxWrapSizer")));
0d077b41
RD
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();
f80ea77b 138
0d077b41
RD
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;
f80ea77b
WS
143 m_isInside = false;
144 if (!IsSizerNode(n)) m_parentSizer = NULL;
0d077b41
RD
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);
f80ea77b 153
0d077b41 154 if (sizer)
a50cf60e 155 sitem->AssignSizer(sizer);
0d077b41 156 else if (wnd)
a50cf60e 157 sitem->AssignWindow(wnd);
f80ea77b 158 else
0d077b41
RD
159 wxLogError(wxT("Error in resource."));
160
1eba2193
RD
161 // finally, set other wxSizerItem attributes
162 SetSizerItemAttributes(sitem);
163
0d077b41
RD
164 AddSizerItem(sitem);
165 return item;
166 }
167 else /*n == NULL*/
78d14f80 168 {
0d077b41 169 wxLogError(wxT("Error in resource: no window/sizer/spacer within sizeritem object."));
78d14f80
VS
170 return NULL;
171 }
0d077b41
RD
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);
a50cf60e 181 sitem->AssignSpacer(GetSize());
f80ea77b 182 AddSizerItem(sitem);
0d077b41
RD
183 return NULL;
184}
185
78d14f80 186
0d077b41
RD
187wxObject* wxSizerXmlHandler::Handle_sizer()
188{
189 wxSizer *sizer = NULL;
f80ea77b 190
0d077b41 191 wxXmlNode *parentNode = m_node->GetParent();
78d14f80 192
0d077b41 193 wxCHECK_MSG(m_parentSizer != NULL ||
0a904ad4 194 (parentNode && parentNode->GetType() == wxXML_ELEMENT_NODE &&
35386afc
VZ
195 m_parentAsWindow), NULL,
196 wxT("Sizer must have a window parent node"));
78d14f80 197
0d077b41
RD
198 if (m_class == wxT("wxBoxSizer"))
199 sizer = Handle_wxBoxSizer();
200
627ddac9 201#if wxUSE_STATBOX
0d077b41
RD
202 else if (m_class == wxT("wxStaticBoxSizer"))
203 sizer = Handle_wxStaticBoxSizer();
627ddac9 204#endif
f80ea77b 205
0d077b41
RD
206 else if (m_class == wxT("wxGridSizer"))
207 sizer = Handle_wxGridSizer();
f80ea77b 208
0d077b41
RD
209 else if (m_class == wxT("wxFlexGridSizer"))
210 sizer = Handle_wxFlexGridSizer();
78d14f80 211
0d077b41
RD
212 else if (m_class == wxT("wxGridBagSizer"))
213 sizer = Handle_wxGridBagSizer();
78d14f80 214
13a38887 215 else if (m_class == wxT("wxWrapSizer"))
63b37a4e 216 sizer = Handle_wxWrapSizer();
13a38887 217
641c5f1a
VZ
218 if ( !sizer )
219 {
220 wxLogError(_T("Failed to create size of class \"%s\""), m_class.c_str());
221 return NULL;
222 }
f80ea77b 223
0d077b41
RD
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;
0d077b41
RD
231
232 // set new state
233 m_parentSizer = sizer;
f80ea77b 234 m_isInside = true;
0d077b41 235 m_isGBS = (m_class == wxT("wxGridBagSizer"));
f80ea77b
WS
236
237 CreateChildren(m_parent, true/*only this handler*/);
0d077b41
RD
238
239 // restore state
0d077b41
RD
240 m_isInside = old_ins;
241 m_parentSizer = old_par;
242
243 if (m_parentSizer == NULL) // setup window:
244 {
0d077b41
RD
245 m_parentAsWindow->SetSizer(sizer);
246
247 wxXmlNode *nd = m_node;
248 m_node = parentNode;
249 if (GetSize() == wxDefaultSize)
5e1a9f05
VS
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 }
0d077b41
RD
260 m_node = nd;
261
ea813d91
VS
262 if (m_parentAsWindow->IsTopLevel())
263 {
0d077b41 264 sizer->SetSizeHints(m_parentAsWindow);
ea813d91 265 }
0d077b41 266 }
f80ea77b 267
0d077b41
RD
268 return sizer;
269}
270
271
272wxSizer* wxSizerXmlHandler::Handle_wxBoxSizer()
273{
274 return new wxBoxSizer(GetStyle(wxT("orient"), wxHORIZONTAL));
f80ea77b
WS
275}
276
627ddac9 277#if wxUSE_STATBOX
0d077b41
RD
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}
627ddac9 289#endif // wxUSE_STATBOX
f80ea77b 290
0d077b41
RD
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{
f80ea77b 300 wxFlexGridSizer *sizer =
0d077b41
RD
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{
f80ea77b 311 wxGridBagSizer *sizer =
0d077b41
RD
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
13a38887
VZ
318wxSizer* wxSizerXmlHandler::Handle_wxWrapSizer()
319{
63b37a4e 320 wxWrapSizer *sizer = new wxWrapSizer(GetStyle("orient"), GetStyle("flag"));
13a38887
VZ
321 return sizer;
322}
0d077b41
RD
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);
78d14f80 342 }
78d14f80
VS
343 }
344}
345
346
0d077b41
RD
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}
78d14f80 354
0d077b41
RD
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))
1eba2193 380 sitem->SetMinSize(sz);
0d077b41
RD
381 sz = GetSize(wxT("ratio"));
382 if (!(sz == wxDefaultSize))
383 sitem->SetRatio(sz);
f80ea77b 384
0d077b41
RD
385 if (m_isGBS)
386 {
387 wxGBSizerItem* gbsitem = (wxGBSizerItem*)sitem;
ea0d8ca6
RD
388 gbsitem->SetPos(GetGBPos(wxT("cellpos")));
389 gbsitem->SetSpan(GetGBSpan(wxT("cellspan")));
f80ea77b 390 }
86909f4c
VZ
391
392 // record the id of the item, if any, for use by XRCSIZERITEM()
393 sitem->SetId(GetID());
0d077b41
RD
394}
395
396void wxSizerXmlHandler::AddSizerItem(wxSizerItem* sitem)
78d14f80 397{
0d077b41
RD
398 if (m_isGBS)
399 ((wxGridBagSizer*)m_parentSizer)->Add((wxGBSizerItem*)sitem);
400 else
401 m_parentSizer->Add(sitem);
78d14f80 402}
f80ea77b 403
172541f6
VS
404
405
406//-----------------------------------------------------------------------------
407// wxStdDialogButtonSizerXmlHandler
408//-----------------------------------------------------------------------------
dd47af27 409#if wxUSE_BUTTON
172541f6
VS
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}
dd47af27 471#endif // wxUSE_BUTTON
172541f6 472
621be1ec 473#endif // wxUSE_XRC