From 819559b2ac7d2250097ce0b1d9d443164752be09 Mon Sep 17 00:00:00 2001 From: =?utf8?q?V=C3=A1clav=20Slav=C3=ADk?= Date: Sun, 15 Mar 2009 10:29:14 +0000 Subject: [PATCH] better XRC errors reporting: report location of the error and use unified formatting git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@59556 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/xrc/xmlres.h | 14 +++ interface/wx/xrc/xmlres.h | 81 ++++++++++++++++ src/xrc/xh_bmpcbox.cpp | 3 +- src/xrc/xh_choicbk.cpp | 6 +- src/xrc/xh_collpane.cpp | 4 +- src/xrc/xh_listbk.cpp | 6 +- src/xrc/xh_mdi.cpp | 2 +- src/xrc/xh_menu.cpp | 8 +- src/xrc/xh_notbk.cpp | 6 +- src/xrc/xh_propdlg.cpp | 6 +- src/xrc/xh_sizer.cpp | 21 ++-- src/xrc/xh_split.cpp | 2 +- src/xrc/xh_statbar.cpp | 12 ++- src/xrc/xh_toolb.cpp | 36 ++++--- src/xrc/xh_treebk.cpp | 9 +- src/xrc/xh_wizrd.cpp | 2 +- src/xrc/xmladv.cpp | 7 +- src/xrc/xmlres.cpp | 195 +++++++++++++++++++++++++++++++++----- 18 files changed, 348 insertions(+), 72 deletions(-) diff --git a/include/wx/xrc/xmlres.h b/include/wx/xrc/xmlres.h index c324aec930..c130d915cf 100644 --- a/include/wx/xrc/xmlres.h +++ b/include/wx/xrc/xmlres.h @@ -261,6 +261,13 @@ public: { return GetResourceNodeAndLocation(name, wxString(), true); } protected: + // reports input error at position 'context' + void ReportError(wxXmlNode *context, const wxString& message); + + // override this in derived class to customize errors reporting + virtual void DoReportError(const wxString& xrcFile, wxXmlNode *position, + const wxString& message); + // Scans the resources list for unloaded files and loads them. Also reloads // files that have been modified since last loading. bool UpdateResources(); @@ -529,6 +536,13 @@ protected: #if wxUSE_FILESYSTEM wxFileSystem& GetCurFileSystem() { return m_resource->GetCurFileSystem(); } #endif + + // reports input error at position 'context' + void ReportError(wxXmlNode *context, const wxString& message); + // reports input error at m_node + void ReportError(const wxString& message); + // reports input error when parsing parameter with given name + void ReportParamError(const wxString& param, const wxString& message); }; diff --git a/interface/wx/xrc/xmlres.h b/interface/wx/xrc/xmlres.h index 590b51ac30..5bd3bce792 100644 --- a/interface/wx/xrc/xmlres.h +++ b/interface/wx/xrc/xmlres.h @@ -334,6 +334,60 @@ public: hasn't been found in the list of loaded resources. */ bool Unload(const wxString& filename); + +protected: + /** + Reports error in XRC resources to the user. + + Any errors in XRC input files should be reported using this method + (or its wxXmlResourceHandler::ReportError() equivalent). Unlike + wxLogError(), this method presents the error to the user in a more + usable form. In particular, the output is compiler-like and contains + information about the exact location of the error. + + @param context XML node the error occurred in or relates to. This can + be @NULL, but should be the most specific node possible, + as its line number is what is reported to the user. + @param message Text of the error message. This string should always + be in English (i.e. not wrapped in _()). It shouldn't + be a sentence -- it should start with lower-case letter + and shouldn't have a trailing period or exclamation + point. + + @since 2.9.0 + + @see wxXmlResourceHandler::ReportError(), DoReportError() + */ + void ReportError(wxXmlNode *context, const wxString& message); + + /** + Implementation of XRC resources errors reporting. + + This method is called by ReportError() and shouldn't be called + directly; use ReportError() or wxXmlResourceHandler::ReportError() + to log errors. + + Default implementation uses wxLogError(). + + @param xrcFile File the error occurred in or empty string if it + couldn't be determined. + @param position XML node where the error occurred or @NULL if it + couldn't be determined. + @param message Text of the error message. See ReportError() + documentation for details of the string's format. + + @note + You may override this method in a derived class to customize errors + reporting. If you do so, you'll need to either use the derived class + in all your code or call wxXmlResource::Set() to change the global + wxXmlResource instance to your class. + + @since 2.9.0 + + @see ReportError() + */ + virtual void DoReportError(const wxString& xrcFile, wxXmlNode *position, + const wxString& message); }; @@ -544,5 +598,32 @@ protected: Sets common window options. */ void SetupWindow(wxWindow* wnd); + + /** + Reports error in XRC resources to the user. + + See wxXmlResource::ReportError() for more information. + + @since 2.9.0 + */ + void ReportError(wxXmlNode *context, const wxString& message); + + /** + Like ReportError(wxXmlNode*, const wxString&), but uses the node + of currently processed object (m_node) as the context. + + @since 2.9.0 + */ + void ReportError(const wxString& message); + + /** + Like ReportError(wxXmlNode*, const wxString&), but uses the node + of parameter @a param of the currently processed object as the context. + This is convenience function for reporting errors in particular + parameters. + + @since 2.9.0 + */ + void ReportParamError(const wxString& param, const wxString& message); }; diff --git a/src/xrc/xh_bmpcbox.cpp b/src/xrc/xh_bmpcbox.cpp index 464f75b79f..43936df9dd 100644 --- a/src/xrc/xh_bmpcbox.cpp +++ b/src/xrc/xh_bmpcbox.cpp @@ -44,8 +44,7 @@ wxObject *wxBitmapComboBoxXmlHandler::DoCreateResource() { if ( !m_combobox ) { - wxLogError(_("XRC syntex error: ownerdrawnitem only allowed within " - " a bitmapcombobox!")); + ReportError("ownerdrawnitem only allowed within a wxBitmapComboBox"); return NULL; } diff --git a/src/xrc/xh_choicbk.cpp b/src/xrc/xh_choicbk.cpp index 5b8aff619e..4b8390db17 100644 --- a/src/xrc/xh_choicbk.cpp +++ b/src/xrc/xh_choicbk.cpp @@ -86,12 +86,14 @@ wxObject *wxChoicebookXmlHandler::DoCreateResource() } } else - wxLogError(wxT("Error in resource.")); + { + ReportError(n, "choicebookpage child must be a window"); + } return wnd; } else { - wxLogError(wxT("Error in resource: no control within choicebook's tag.")); + ReportError("choicebookpage must have a window child"); return NULL; } } diff --git a/src/xrc/xh_collpane.cpp b/src/xrc/xh_collpane.cpp index bad9bcd9df..93ab13c397 100644 --- a/src/xrc/xh_collpane.cpp +++ b/src/xrc/xh_collpane.cpp @@ -54,7 +54,7 @@ wxObject *wxCollapsiblePaneXmlHandler::DoCreateResource() } else { - wxLogError(wxT("Error in resource: no control within collapsible pane's tag.")); + ReportError("no control within panewindow"); return NULL; } } @@ -65,7 +65,7 @@ wxObject *wxCollapsiblePaneXmlHandler::DoCreateResource() wxString label = GetParamValue(wxT("label")); if (label.empty()) { - wxLogError(wxT("Error in resource: empty label for wxCollapsiblePane")); + ReportParamError("label", "label cannot be empty"); return NULL; } diff --git a/src/xrc/xh_listbk.cpp b/src/xrc/xh_listbk.cpp index 36138404de..470be509ba 100644 --- a/src/xrc/xh_listbk.cpp +++ b/src/xrc/xh_listbk.cpp @@ -86,12 +86,14 @@ wxObject *wxListbookXmlHandler::DoCreateResource() } } else - wxLogError(wxT("Error in resource.")); + { + ReportError(n, "listbookpage child must be a window"); + } return wnd; } else { - wxLogError(wxT("Error in resource: no control within listbook's tag.")); + ReportError("listbookpage must have a window child"); return NULL; } } diff --git a/src/xrc/xh_mdi.cpp b/src/xrc/xh_mdi.cpp index 95fa08e21e..f6fea842dd 100644 --- a/src/xrc/xh_mdi.cpp +++ b/src/xrc/xh_mdi.cpp @@ -88,7 +88,7 @@ wxWindow *wxMdiXmlHandler::CreateFrame() if ( !mdiParent ) { - wxLogError(wxT("Parent of wxMDIChildFrame must be wxMDIParentFrame.")); + ReportError("parent of wxMDIChildFrame must be wxMDIParentFrame"); return NULL; } diff --git a/src/xrc/xh_menu.cpp b/src/xrc/xh_menu.cpp index fe700cdd5c..f6cc1963f1 100644 --- a/src/xrc/xh_menu.cpp +++ b/src/xrc/xh_menu.cpp @@ -91,9 +91,11 @@ wxObject *wxMenuXmlHandler::DoCreateResource() { if ( kind != wxITEM_NORMAL ) { - wxLogWarning(_("XRC syntax error: a menu item can't have " - "both \"radio\" and \"checkable\" " - "properties, ignoring the former.")); + ReportParamError + ( + "checkable", + "menu item can't have both and properties" + ); } kind = wxITEM_CHECK; diff --git a/src/xrc/xh_notbk.cpp b/src/xrc/xh_notbk.cpp index 01a280ef26..2908984fbf 100644 --- a/src/xrc/xh_notbk.cpp +++ b/src/xrc/xh_notbk.cpp @@ -89,12 +89,14 @@ wxObject *wxNotebookXmlHandler::DoCreateResource() } } else - wxLogError(wxT("Error in resource.")); + { + ReportError(n, "notebookpage child must be a window"); + } return wnd; } else { - wxLogError(wxT("Error in resource: no control within notebook's tag.")); + ReportError("notebookpage must have a window child"); return NULL; } } diff --git a/src/xrc/xh_propdlg.cpp b/src/xrc/xh_propdlg.cpp index 96bd4e2a23..0dd4f168f8 100644 --- a/src/xrc/xh_propdlg.cpp +++ b/src/xrc/xh_propdlg.cpp @@ -89,12 +89,14 @@ wxObject *wxPropertySheetDialogXmlHandler::DoCreateResource() } } else - wxLogError(wxT("Error in resource.")); + { + ReportError(n, "propertysheetpage child must be a window"); + } return wnd; } else { - wxLogError(wxT("Error in resource: no control within wxPropertySheetDialog's tag.")); + ReportError("propertysheetpage must have a window child"); return NULL; } } diff --git a/src/xrc/xh_sizer.cpp b/src/xrc/xh_sizer.cpp index fb21758c0b..060d3bbbcd 100644 --- a/src/xrc/xh_sizer.cpp +++ b/src/xrc/xh_sizer.cpp @@ -161,7 +161,7 @@ wxObject* wxSizerXmlHandler::Handle_sizeritem() else if (wnd) sitem->AssignWindow(wnd); else - wxLogError(wxT("Error in resource.")); + ReportError(n, "unexpected item in sizer"); // finally, set other wxSizerItem attributes SetSizerItemAttributes(sitem); @@ -171,7 +171,7 @@ wxObject* wxSizerXmlHandler::Handle_sizeritem() } else /*n == NULL*/ { - wxLogError(wxT("Error in resource: no window/sizer/spacer within sizeritem object.")); + ReportError("no window/sizer/spacer within sizeritem object"); return NULL; } } @@ -181,8 +181,7 @@ wxObject* wxSizerXmlHandler::Handle_spacer() { if ( !m_parentSizer ) { - wxLogError(_("XRC syntax error: \"spacer\" only allowed inside a " - "sizer")); + ReportError("spacer only allowed inside a sizer"); return NULL; } @@ -205,7 +204,7 @@ wxObject* wxSizerXmlHandler::Handle_sizer() (!parentNode || parentNode->GetType() != wxXML_ELEMENT_NODE || !m_parentAsWindow) ) { - wxLogError(_("XRC syntax error: sizer must have a window parent.")); + ReportError("sizer must have a window parent"); return NULL; } @@ -232,7 +231,7 @@ wxObject* wxSizerXmlHandler::Handle_sizer() if ( !sizer ) { - wxLogError(_T("Failed to create size of class \"%s\""), m_class.c_str()); + ReportError(wxString::Format("unknown sizer class \"%s\"", m_class)); return NULL; } @@ -348,7 +347,11 @@ void wxSizerXmlHandler::SetGrowables(wxFlexGridSizer* sizer, { if (!tkn.GetNextToken().ToULong(&l)) { - wxLogError(wxT("growable[rows|cols] must be comma-separated list of row numbers")); + ReportParamError + ( + param, + "value must be comma-separated list of row numbers" + ); break; } @@ -467,13 +470,13 @@ wxObject *wxStdDialogButtonSizerXmlHandler::DoCreateResource() if (button) m_parentSizer->AddButton(button); else - wxLogError(wxT("Error in resource - expected button.")); + ReportError(n, "expected wxButton"); return item; } else /*n == NULL*/ { - wxLogError(wxT("Error in resource: no button within wxStdDialogButtonSizer.")); + ReportError("no button within wxStdDialogButtonSizer"); return NULL; } } diff --git a/src/xrc/xh_split.cpp b/src/xrc/xh_split.cpp index fd21911808..e14300f4f9 100644 --- a/src/xrc/xh_split.cpp +++ b/src/xrc/xh_split.cpp @@ -87,7 +87,7 @@ wxObject *wxSplitterWindowXmlHandler::DoCreateResource() } if (win1 == NULL) - wxLogError(wxT("wxSplitterWindow node must contain at least one window.")); + ReportError("wxSplitterWindow node must contain at least one window"); bool horizontal = (GetParamValue(wxT("orientation")) != wxT("vertical")); if (win1 && win2) diff --git a/src/xrc/xh_statbar.cpp b/src/xrc/xh_statbar.cpp index fe14c250d7..0df6782e19 100644 --- a/src/xrc/xh_statbar.cpp +++ b/src/xrc/xh_statbar.cpp @@ -79,7 +79,17 @@ wxObject *wxStatusBarXmlHandler::DoCreateResource() else if (first == wxT("wxSB_RAISED")) style[i] = wxSB_RAISED; else if (!first.empty()) - wxLogError(wxT("Error in resource, unknown statusbar field style: ") + first); + { + ReportParamError + ( + "styles", + wxString::Format + ( + "unknown status bar field style \"%s\"", + first + ) + ); + } if(styles.Find(wxT(','))) styles.Remove(0, styles.Find(wxT(',')) + 1); diff --git a/src/xrc/xh_toolb.cpp b/src/xrc/xh_toolb.cpp index b6f518d4af..2d19946e33 100644 --- a/src/xrc/xh_toolb.cpp +++ b/src/xrc/xh_toolb.cpp @@ -57,8 +57,7 @@ wxObject *wxToolBarXmlHandler::DoCreateResource() { if ( !m_toolbar ) { - wxLogError(_("XRC syntax error: \"tool\" only allowed inside a " - "toolbar")); + ReportError("tool only allowed inside a wxToolBar"); return NULL; } @@ -70,9 +69,11 @@ wxObject *wxToolBarXmlHandler::DoCreateResource() { if ( kind != wxITEM_NORMAL ) { - wxLogWarning(_("XRC syntax error: tool can't have both " - "\"radio\" and \"toggle\" properties, " - "ignoring the former.")); + ReportParamError + ( + "toggle", + "tool can't have both and properties" + ); } kind = wxITEM_CHECK; @@ -85,9 +86,11 @@ wxObject *wxToolBarXmlHandler::DoCreateResource() { if ( kind != wxITEM_NORMAL ) { - wxLogWarning(_("XRC syntax error: drop-down tool can't have " - "neither \"radio\" nor \"toggle\" properties, " - "ignoring them.")); + ReportParamError + ( + "dropdown", + "drop-down tool can't have neither nor properties" + ); } kind = wxITEM_DROPDOWN; @@ -102,14 +105,20 @@ wxObject *wxToolBarXmlHandler::DoCreateResource() menu = wxDynamicCast(res, wxMenu); if ( !menu ) { - wxLogError(_("XRC syntax error: invalid drop-down tool " - "contents (expected a menu).")); + ReportError + ( + nodeMenu, + "drop-down tool contents can only be a wxMenu" + ); } if ( nodeMenu->GetNext() ) { - wxLogWarning(_("XRC syntax error: unexpected extra " - "contents under drop-down tool.")); + ReportError + ( + nodeMenu->GetNext(), + "unexpected extra contents under drop-down tool" + ); } } } @@ -139,8 +148,7 @@ wxObject *wxToolBarXmlHandler::DoCreateResource() { if ( !m_toolbar ) { - wxLogError(_("XRC syntax error: \"separator\" only allowed inside a " - "toolbar")); + ReportError("separator only allowed inside wxToolBar"); return NULL; } m_toolbar->AddSeparator(); diff --git a/src/xrc/xh_treebk.cpp b/src/xrc/xh_treebk.cpp index d3d427dfba..cd199b7bb6 100644 --- a/src/xrc/xh_treebk.cpp +++ b/src/xrc/xh_treebk.cpp @@ -95,7 +95,9 @@ wxObject *wxTreebookXmlHandler::DoCreateResource() wnd = wxDynamicCast(item, wxWindow); if (wnd == NULL && item != NULL) - wxLogError(wxT("Error in resource: control within treebook's tag is not a window.")); + { + ReportError(n, "treebookpage child must be a window"); + } } size_t depth = GetLong( wxT("depth") ); @@ -134,7 +136,10 @@ wxObject *wxTreebookXmlHandler::DoCreateResource() } else - wxLogError(wxT("Error in resource. wxTreebookPage has an invalid depth.")); + { + ReportParamError("depth", "invalid depth"); + } + return wnd; } diff --git a/src/xrc/xh_wizrd.cpp b/src/xrc/xh_wizrd.cpp index 7888b50e0c..97dc42b94d 100644 --- a/src/xrc/xh_wizrd.cpp +++ b/src/xrc/xh_wizrd.cpp @@ -75,7 +75,7 @@ wxObject *wxWizardXmlHandler::DoCreateResource() { if ( !m_instance ) { - wxLogError(wxT("wxWizardPage is abstract class, must be subclassed")); + ReportError("wxWizardPage is abstract class and must be subclassed"); return NULL; } diff --git a/src/xrc/xmladv.cpp b/src/xrc/xmladv.cpp index ad3c96aa93..5087147e2f 100644 --- a/src/xrc/xmladv.cpp +++ b/src/xrc/xmladv.cpp @@ -60,8 +60,11 @@ wxAnimation wxXmlResourceHandler::GetAnimation(const wxString& param) if ( !ani.IsOk() ) { - wxLogError(_("XRC resource: Cannot create animation from '%s'."), - name.c_str()); + ReportParamError + ( + param, + wxString::Format("cannot create animation from \"%s\"", name) + ); return wxNullAnimation; } diff --git a/src/xrc/xmlres.cpp b/src/xrc/xmlres.cpp index 6e7e3b9611..fc2fa3d3ce 100644 --- a/src/xrc/xmlres.cpp +++ b/src/xrc/xmlres.cpp @@ -403,7 +403,7 @@ bool wxXmlResource::AttachUnknownControl(const wxString& name, wxWindow *container = parent->FindWindow(name + wxT("_container")); if (!container) { - wxLogError(_("Cannot find container for unknown control '%s'."), name.c_str()); + wxLogError("Cannot find container for unknown control '%s'.", name); return false; } return control->Reparent(container); @@ -543,7 +543,11 @@ bool wxXmlResource::UpdateResources() } else if (rec->Doc->GetRoot()->GetName() != wxT("resource")) { - wxLogError(_("Invalid XRC resource '%s': doesn't have root node 'resource'."), rec->File); + ReportError + ( + rec->Doc->GetRoot(), + "invalid XRC resource, doesn't have root node " + ); wxDELETE(rec->Doc); rt = false; } @@ -562,7 +566,7 @@ bool wxXmlResource::UpdateResources() m_version = version; if (m_version != version) { - wxLogError(_("Resource files must have same version number!")); + wxLogError("Resource files must have same version number."); rt = false; } @@ -651,8 +655,15 @@ wxXmlNode *wxXmlResource::FindResource(const wxString& name, if ( !node ) { - wxLogError(_("XRC resource '%s' (class '%s') not found!"), - name, classname); + ReportError + ( + NULL, + wxString::Format + ( + "XRC resource \"%s\" (class \"%s\") not found", + name, classname + ) + ); } #if wxUSE_FILESYSTEM else // node was found @@ -770,8 +781,15 @@ wxObject *wxXmlResource::CreateResFromNode(wxXmlNode *node, wxObject *parent, if ( !refNode ) { - wxLogError(_("Referenced object node with ref=\"%s\" not found!"), - refName.c_str()); + ReportError + ( + node, + wxString::Format + ( + "referenced object node with ref=\"%s\" not found", + refName + ) + ); return NULL; } @@ -799,9 +817,16 @@ wxObject *wxXmlResource::CreateResFromNode(wxXmlNode *node, wxObject *parent, } } - wxLogError(_("No handler found for XML node '%s', class '%s'!"), - node->GetName().c_str(), - node->GetAttribute(wxT("class"), wxEmptyString).c_str()); + ReportError + ( + node, + wxString::Format + ( + "no handler found for XML node \"%s\" (class \"%s\")", + node->GetName(), + node->GetAttribute("class", wxEmptyString) + ) + ); return NULL; } @@ -873,8 +898,15 @@ wxObject *wxXmlResourceHandler::CreateResource(wxXmlNode *node, wxObject *parent if (!m_instance) { wxString name = node->GetAttribute(wxT("name"), wxEmptyString); - wxLogError(_("Subclass '%s' not found for resource '%s', not subclassing!"), - subclass.c_str(), name.c_str()); + ReportError + ( + node, + wxString::Format + ( + "subclass \"%s\" not found for resource \"%s\", not subclassing", + subclass, name + ) + ); } } } @@ -948,9 +980,17 @@ int wxXmlResourceHandler::GetStyle(const wxString& param, int defaults) fl = tkn.GetNextToken(); index = m_styleNames.Index(fl); if (index != wxNOT_FOUND) + { style |= m_styleValues[index]; + } else - wxLogError(_("Unknown style flag ") + fl); + { + ReportParamError + ( + param, + wxString::Format("unknown style flag \"%s\"", fl) + ); + } } return style; } @@ -1175,8 +1215,11 @@ wxColour wxXmlResourceHandler::GetColour(const wxString& param, const wxColour& if (clr.Ok()) return clr; - wxLogError(_("XRC resource: Incorrect colour specification '%s' for attribute '%s'."), - v.c_str(), param.c_str()); + ReportParamError + ( + param, + wxString::Format("incorrect colour specification \"%s\"", v) + ); return wxNullColour; } @@ -1217,8 +1260,11 @@ wxBitmap wxXmlResourceHandler::GetBitmap(const wxString& param, wxFSFile *fsfile = GetCurFileSystem().OpenFile(name, wxFS_READ | wxFS_SEEKABLE); if (fsfile == NULL) { - wxLogError(_("XRC resource: Cannot create bitmap from '%s'."), - name.c_str()); + ReportParamError + ( + param, + wxString::Format("cannot open bitmap resource \"%s\"", name) + ); return wxNullBitmap; } wxImage img(*(fsfile->GetStream())); @@ -1229,8 +1275,11 @@ wxBitmap wxXmlResourceHandler::GetBitmap(const wxString& param, if (!img.Ok()) { - wxLogError(_("XRC resource: Cannot create bitmap from '%s'."), - name.c_str()); + ReportParamError + ( + param, + wxString::Format("cannot create bitmap from \"%s\"", name) + ); return wxNullBitmap; } if (!(size == wxDefaultSize)) img.Rescale(size.x, size.y); @@ -1321,7 +1370,11 @@ wxSize wxXmlResourceHandler::GetSize(const wxString& param, if (!s.BeforeFirst(wxT(',')).ToLong(&sx) || !s.AfterLast(wxT(',')).ToLong(&sy)) { - wxLogError(_("Cannot parse coordinates from '%s'."), s.c_str()); + ReportParamError + ( + param, + wxString::Format("cannot parse coordinates value \"%s\"", s) + ); return wxDefaultSize; } @@ -1337,7 +1390,11 @@ wxSize wxXmlResourceHandler::GetSize(const wxString& param, } else { - wxLogError(_("Cannot convert dialog units: dialog unknown.")); + ReportParamError + ( + param, + "cannot convert dialog units: dialog unknown" + ); return wxDefaultSize; } } @@ -1369,7 +1426,11 @@ wxCoord wxXmlResourceHandler::GetDimension(const wxString& param, if (!s.ToLong(&sx)) { - wxLogError(_("Cannot parse dimension from '%s'."), s.c_str()); + ReportParamError + ( + param, + wxString::Format("cannot parse dimension value \"%s\"", s) + ); return defaultv; } @@ -1385,7 +1446,11 @@ wxCoord wxXmlResourceHandler::GetDimension(const wxString& param, } else { - wxLogError(_("Cannot convert dialog units: dialog unknown.")); + ReportParamError + ( + param, + "cannot convert dialog units: dialog unknown" + ); return defaultv; } } @@ -1419,7 +1484,8 @@ wxFont wxXmlResourceHandler::GetFont(const wxString& param) wxXmlNode *font_node = GetParamNode(param); if (font_node == NULL) { - wxLogError(_("Cannot find font node '%s'."), param.c_str()); + ReportError( + wxString::Format("cannot find font node \"%s\"", param)); return wxNullFont; } @@ -1610,12 +1676,87 @@ void wxXmlResourceHandler::CreateChildrenPrivately(wxObject *parent, wxXmlNode * } +//----------------------------------------------------------------------------- +// errors reporting +//----------------------------------------------------------------------------- + +void wxXmlResourceHandler::ReportError(const wxString& message) +{ + m_resource->ReportError(m_node, message); +} + +void wxXmlResourceHandler::ReportError(wxXmlNode *context, + const wxString& message) +{ + m_resource->ReportError(context ? context : m_node, message); +} + +void wxXmlResourceHandler::ReportParamError(const wxString& param, + const wxString& message) +{ + m_resource->ReportError(GetParamNode(param), message); +} + +namespace +{ + +wxString +GetFileNameFromNode(wxXmlNode *node, const wxXmlResourceDataRecords& files) +{ + wxXmlNode *root = node; + while ( root->GetParent() ) + root = root->GetParent(); + + for ( wxXmlResourceDataRecords::const_iterator i = files.begin(); + i != files.end(); ++i ) + { + if ( (*i)->Doc->GetRoot() == root ) + { + return (*i)->File; + } + } + + return wxEmptyString; // not found +} + +} // anonymous namespace + +void wxXmlResource::ReportError(wxXmlNode *context, const wxString& message) +{ + if ( !context ) + { + DoReportError("", NULL, message); + return; + } + // We need to find out the file that 'context' is part of. Performance of + // this code is not critical, so we simply find the root XML node and + // compare it with all loaded XRC files. + const wxString filename = GetFileNameFromNode(context, Data()); + DoReportError(filename, context, message); +} +void wxXmlResource::DoReportError(const wxString& xrcFile, wxXmlNode *position, + const wxString& message) +{ + const int line = position ? position->GetLineNumber() : -1; + + wxString loc; + if ( !xrcFile.empty() ) + loc = xrcFile + ':'; + if ( line != -1 ) + loc += wxString::Format("%d:", line); + if ( !loc.empty() ) + loc += ' '; + + wxLogError("XRC error: %s%s", loc, message); +} -// --------------- XRCID implementation ----------------------------- +//----------------------------------------------------------------------------- +// XRCID implementation +//----------------------------------------------------------------------------- #define XRCID_TABLE_SIZE 1024 @@ -1858,7 +1999,9 @@ static void AddStdXRCID_Records() -// --------------- module and globals ----------------------------- +//----------------------------------------------------------------------------- +// module and globals +//----------------------------------------------------------------------------- // normally we would do the cleanup from wxXmlResourceModule::OnExit() but it // can happen that some XRC records have been created because of the use of -- 2.45.2