X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/819559b2ac7d2250097ce0b1d9d443164752be09..07aaf32633ecf18ec3edfbb41793a112914792d0:/src/xrc/xh_sizer.cpp diff --git a/src/xrc/xh_sizer.cpp b/src/xrc/xh_sizer.cpp index 060d3bbbcd..b0dd955f44 100644 --- a/src/xrc/xh_sizer.cpp +++ b/src/xrc/xh_sizer.cpp @@ -35,6 +35,7 @@ #include "wx/notebook.h" #include "wx/tokenzr.h" +#include "wx/xml/xml.h" //----------------------------------------------------------------------------- // wxSizerXmlHandler @@ -115,9 +116,40 @@ wxObject* wxSizerXmlHandler::DoCreateResource() } +wxSizer* wxSizerXmlHandler::DoCreateSizer(const wxString& name) +{ + if (name == wxT("wxBoxSizer")) + return Handle_wxBoxSizer(); +#if wxUSE_STATBOX + else if (name == wxT("wxStaticBoxSizer")) + return Handle_wxStaticBoxSizer(); +#endif + else if (name == wxT("wxGridSizer")) + { + if ( !ValidateGridSizerChildren() ) + return NULL; + return Handle_wxGridSizer(); + } + else if (name == wxT("wxFlexGridSizer")) + { + return Handle_wxFlexGridSizer(); + } + else if (name == wxT("wxGridBagSizer")) + { + return Handle_wxGridBagSizer(); + } + else if (name == wxT("wxWrapSizer")) + { + return Handle_wxWrapSizer(); + } + + ReportError(wxString::Format("unknown sizer class \"%s\"", name)); + return NULL; +} + -bool wxSizerXmlHandler::IsSizerNode(wxXmlNode *node) +bool wxSizerXmlHandler::IsSizerNode(wxXmlNode *node) const { return (IsOfClass(node, wxT("wxBoxSizer"))) || (IsOfClass(node, wxT("wxStaticBoxSizer"))) || @@ -195,9 +227,6 @@ wxObject* wxSizerXmlHandler::Handle_spacer() wxObject* wxSizerXmlHandler::Handle_sizer() { - wxSizer *sizer = NULL; - wxFlexGridSizer *flexsizer = NULL; - wxXmlNode *parentNode = m_node->GetParent(); if ( !m_parentSizer && @@ -208,32 +237,12 @@ wxObject* wxSizerXmlHandler::Handle_sizer() return NULL; } - if (m_class == wxT("wxBoxSizer")) - sizer = Handle_wxBoxSizer(); -#if wxUSE_STATBOX - else if (m_class == wxT("wxStaticBoxSizer")) - sizer = Handle_wxStaticBoxSizer(); -#endif - else if (m_class == wxT("wxGridSizer")) - sizer = Handle_wxGridSizer(); - else if (m_class == wxT("wxFlexGridSizer")) - { - flexsizer = Handle_wxFlexGridSizer(); - sizer = flexsizer; - } - else if (m_class == wxT("wxGridBagSizer")) - { - flexsizer = Handle_wxGridBagSizer(); - sizer = flexsizer; - } - else if (m_class == wxT("wxWrapSizer")) - sizer = Handle_wxWrapSizer(); + // Create the sizer of the appropriate class. + wxSizer * const sizer = DoCreateSizer(m_class); + // creation of sizer failed for some (already reported) reason, so exit: if ( !sizer ) - { - ReportError(wxString::Format("unknown sizer class \"%s\"", m_class)); return NULL; - } wxSize minsize = GetSize(wxT("minsize")); if (!(minsize == wxDefaultSize)) @@ -248,11 +257,21 @@ wxObject* wxSizerXmlHandler::Handle_sizer() m_isInside = true; m_isGBS = (m_class == wxT("wxGridBagSizer")); - CreateChildren(m_parent, true/*only this handler*/); + wxObject* parent = m_parent; +#if wxUSE_STATBOX + // wxStaticBoxSizer's child controls should be parented by the box itself, + // not its parent. + wxStaticBoxSizer* const stsizer = wxDynamicCast(sizer, wxStaticBoxSizer); + if ( stsizer ) + parent = stsizer->GetStaticBox(); +#endif // wxUSE_STATBOX + + CreateChildren(parent, true/*only this handler*/); // set growable rows and cols for sizers which support this - if ( flexsizer ) + if ( wxFlexGridSizer *flexsizer = wxDynamicCast(sizer, wxFlexGridSizer) ) { + SetFlexibleMode(flexsizer); SetGrowables(flexsizer, wxT("growablerows"), true); SetGrowables(flexsizer, wxT("growablecols"), false); } @@ -318,6 +337,8 @@ wxSizer* wxSizerXmlHandler::Handle_wxGridSizer() wxFlexGridSizer* wxSizerXmlHandler::Handle_wxFlexGridSizer() { + if ( !ValidateGridSizerChildren() ) + return NULL; return new wxFlexGridSizer(GetLong(wxT("rows")), GetLong(wxT("cols")), GetDimension(wxT("vgap")), GetDimension(wxT("hgap"))); } @@ -325,6 +346,8 @@ wxFlexGridSizer* wxSizerXmlHandler::Handle_wxFlexGridSizer() wxGridBagSizer* wxSizerXmlHandler::Handle_wxGridBagSizer() { + if ( !ValidateGridSizerChildren() ) + return NULL; return new wxGridBagSizer(GetDimension(wxT("vgap")), GetDimension(wxT("hgap"))); } @@ -335,30 +358,153 @@ wxSizer* wxSizerXmlHandler::Handle_wxWrapSizer() } +bool wxSizerXmlHandler::ValidateGridSizerChildren() +{ + int rows = GetLong("rows"); + int cols = GetLong("cols"); + + if ( rows && cols ) + { + // fixed number of cells, need to verify children count + int children = 0; + for ( wxXmlNode *n = m_node->GetChildren(); n; n = n->GetNext() ) + { + if ( n->GetType() == wxXML_ELEMENT_NODE && + (n->GetName() == "object" || n->GetName() == "object_ref") ) + { + children++; + } + } + + if ( children > rows * cols ) + { + ReportError + ( + wxString::Format + ( + "too many children in grid sizer: %d > %d x %d" + " (consider omitting the number of rows or columns)", + children, + cols, + rows + ) + ); + return false; + } + } + + return true; +} + + +void wxSizerXmlHandler::SetFlexibleMode(wxFlexGridSizer* fsizer) +{ + if (HasParam(wxT("flexibledirection"))) + { + wxString dir = GetParamValue(wxT("flexibledirection")); + + if (dir == wxT("wxVERTICAL")) + fsizer->SetFlexibleDirection(wxVERTICAL); + else if (dir == wxT("wxHORIZONTAL")) + fsizer->SetFlexibleDirection(wxHORIZONTAL); + else if (dir == wxT("wxBOTH")) + fsizer->SetFlexibleDirection(wxBOTH); + else + { + ReportParamError + ( + wxT("flexibledirection"), + wxString::Format("unknown direction \"%s\"", dir) + ); + } + } + + if (HasParam(wxT("nonflexiblegrowmode"))) + { + wxString mode = GetParamValue(wxT("nonflexiblegrowmode")); + + if (mode == wxT("wxFLEX_GROWMODE_NONE")) + fsizer->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_NONE); + else if (mode == wxT("wxFLEX_GROWMODE_SPECIFIED")) + fsizer->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED); + else if (mode == wxT("wxFLEX_GROWMODE_ALL")) + fsizer->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_ALL); + else + { + ReportParamError + ( + wxT("nonflexiblegrowmode"), + wxString::Format("unknown grow mode \"%s\"", mode) + ); + } + } +} + void wxSizerXmlHandler::SetGrowables(wxFlexGridSizer* sizer, const wxChar* param, bool rows) { + int nrows, ncols; + sizer->CalcRowsCols(nrows, ncols); + const int nslots = rows ? nrows : ncols; + wxStringTokenizer tkn; - unsigned long l; tkn.SetString(GetParamValue(param), wxT(",")); + while (tkn.HasMoreTokens()) { - if (!tkn.GetNextToken().ToULong(&l)) + wxString propStr; + wxString idxStr = tkn.GetNextToken().BeforeFirst(wxT(':'), &propStr); + + unsigned long li; + if (!idxStr.ToULong(&li)) { ReportParamError ( param, - "value must be comma-separated list of row numbers" + "value must be a comma-separated list of numbers" ); break; } + unsigned long lp = 0; + if (!propStr.empty()) + { + if (!propStr.ToULong(&lp)) + { + ReportParamError + ( + param, + "value must be a comma-separated list of numbers" + ); + break; + } + } + + const int n = static_cast(li); + if ( n >= nslots ) + { + ReportParamError + ( + param, + wxString::Format + ( + "invalid %s index %d: must be less than %d", + rows ? "row" : "column", + n, + nslots + ) + ); + + // ignore incorrect value, still try to process the rest + continue; + } + if (rows) - sizer->AddGrowableRow(l); + sizer->AddGrowableRow(n, static_cast(lp)); else - sizer->AddGrowableCol(l); + sizer->AddGrowableCol(n, static_cast(lp)); } }