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