{ 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();
#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);
};
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);
};
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);
};
{
if ( !m_combobox )
{
- wxLogError(_("XRC syntex error: ownerdrawnitem only allowed within "
- " a bitmapcombobox!"));
+ ReportError("ownerdrawnitem only allowed within a wxBitmapComboBox");
return NULL;
}
}
}
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 <page> tag."));
+ ReportError("choicebookpage must have a window child");
return NULL;
}
}
}
else
{
- wxLogError(wxT("Error in resource: no control within collapsible pane's <panewindow> tag."));
+ ReportError("no control within panewindow");
return NULL;
}
}
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;
}
}
}
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 <page> tag."));
+ ReportError("listbookpage must have a window child");
return NULL;
}
}
if ( !mdiParent )
{
- wxLogError(wxT("Parent of wxMDIChildFrame must be wxMDIParentFrame."));
+ ReportError("parent of wxMDIChildFrame must be wxMDIParentFrame");
return NULL;
}
{
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 <radio> and <checkable> properties"
+ );
}
kind = wxITEM_CHECK;
}
}
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 <page> tag."));
+ ReportError("notebookpage must have a window child");
return NULL;
}
}
}
}
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 <page> tag."));
+ ReportError("propertysheetpage must have a window child");
return NULL;
}
}
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);
}
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;
}
}
{
if ( !m_parentSizer )
{
- wxLogError(_("XRC syntax error: \"spacer\" only allowed inside a "
- "sizer"));
+ ReportError("spacer only allowed inside a sizer");
return NULL;
}
(!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;
}
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;
}
{
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;
}
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;
}
}
}
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)
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);
{
if ( !m_toolbar )
{
- wxLogError(_("XRC syntax error: \"tool\" only allowed inside a "
- "toolbar"));
+ ReportError("tool only allowed inside a wxToolBar");
return NULL;
}
{
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 <radio> and <toggle> properties"
+ );
}
kind = wxITEM_CHECK;
{
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 <radio> nor <toggle> properties"
+ );
}
kind = wxITEM_DROPDOWN;
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"
+ );
}
}
}
{
if ( !m_toolbar )
{
- wxLogError(_("XRC syntax error: \"separator\" only allowed inside a "
- "toolbar"));
+ ReportError("separator only allowed inside wxToolBar");
return NULL;
}
m_toolbar->AddSeparator();
wnd = wxDynamicCast(item, wxWindow);
if (wnd == NULL && item != NULL)
- wxLogError(wxT("Error in resource: control within treebook's <page> tag is not a window."));
+ {
+ ReportError(n, "treebookpage child must be a window");
+ }
}
size_t depth = GetLong( wxT("depth") );
}
else
- wxLogError(wxT("Error in resource. wxTreebookPage has an invalid depth."));
+ {
+ ReportParamError("depth", "invalid depth");
+ }
+
return wnd;
}
{
if ( !m_instance )
{
- wxLogError(wxT("wxWizardPage is abstract class, must be subclassed"));
+ ReportError("wxWizardPage is abstract class and must be subclassed");
return NULL;
}
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;
}
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);
}
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 <resource>"
+ );
wxDELETE(rec->Doc);
rt = false;
}
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;
}
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
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;
}
}
}
- 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;
}
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
+ )
+ );
}
}
}
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;
}
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;
}
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()));
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);
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;
}
}
else
{
- wxLogError(_("Cannot convert dialog units: dialog unknown."));
+ ReportParamError
+ (
+ param,
+ "cannot convert dialog units: dialog unknown"
+ );
return wxDefaultSize;
}
}
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;
}
}
else
{
- wxLogError(_("Cannot convert dialog units: dialog unknown."));
+ ReportParamError
+ (
+ param,
+ "cannot convert dialog units: dialog unknown"
+ );
return defaultv;
}
}
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;
}
}
+//-----------------------------------------------------------------------------
+// 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
-// --------------- 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