fixed XRC errors location reporting when using <object_ref>

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@60493 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Václav Slavík 2009-05-03 07:00:24 +00:00
parent 0cbc1d0251
commit a1eeda0be2

View File

@ -84,6 +84,48 @@ inline bool IsObjectNode(wxXmlNode *node)
node->GetName() == wxS("object_ref")); node->GetName() == wxS("object_ref"));
} }
// special XML attribute with name of input file, see GetFileNameFromNode()
const char *ATTR_INPUT_FILENAME = "__wx:filename";
// helper to get filename corresponding to an XML node
wxString
GetFileNameFromNode(wxXmlNode *node, const wxXmlResourceDataRecords& files)
{
// this loop does two things: it looks for ATTR_INPUT_FILENAME among
// parents and if it isn't used, it finds the root of the XML tree 'node'
// is in
for ( ;; )
{
// in some rare cases (specifically, when an <object_ref> is used, see
// wxXmlResource::CreateResFromNode() and MergeNodesOver()), we work
// with XML nodes that are not rooted in any document from 'files'
// (because a new node was created by CreateResFromNode() to merge the
// content of <object_ref> and the referenced <object>); in that case,
// we hack around the problem by putting the information about input
// file into a custom attribute
if ( node->HasAttribute(ATTR_INPUT_FILENAME) )
return node->GetAttribute(ATTR_INPUT_FILENAME);
if ( !node->GetParent() )
break; // we found the root of this XML tree
node = node->GetParent();
}
// NB: 'node' now points to the root of XML document
for ( wxXmlResourceDataRecords::const_iterator i = files.begin();
i != files.end(); ++i )
{
if ( (*i)->Doc->GetRoot() == node )
{
return (*i)->File;
}
}
return wxEmptyString; // not found
}
} // anonymous namespace } // anonymous namespace
@ -714,10 +756,11 @@ wxXmlResource::GetResourceNodeAndLocation(const wxString& name,
return NULL; return NULL;
} }
static void MergeNodes(wxXmlNode& dest, wxXmlNode& with) static void MergeNodesOver(wxXmlNode& dest, wxXmlNode& overwriteWith,
const wxString& overwriteFilename)
{ {
// Merge attributes: // Merge attributes:
for ( wxXmlAttribute *attr = with.GetAttributes(); for ( wxXmlAttribute *attr = overwriteWith.GetAttributes();
attr; attr = attr->GetNext() ) attr; attr = attr->GetNext() )
{ {
wxXmlAttribute *dattr; wxXmlAttribute *dattr;
@ -736,7 +779,7 @@ static void MergeNodes(wxXmlNode& dest, wxXmlNode& with)
} }
// Merge child nodes: // Merge child nodes:
for (wxXmlNode* node = with.GetChildren(); node; node = node->GetNext()) for (wxXmlNode* node = overwriteWith.GetChildren(); node; node = node->GetNext())
{ {
wxString name = node->GetAttribute(wxT("name"), wxEmptyString); wxString name = node->GetAttribute(wxT("name"), wxEmptyString);
wxXmlNode *dnode; wxXmlNode *dnode;
@ -747,28 +790,32 @@ static void MergeNodes(wxXmlNode& dest, wxXmlNode& with)
dnode->GetAttribute(wxT("name"), wxEmptyString) == name && dnode->GetAttribute(wxT("name"), wxEmptyString) == name &&
dnode->GetType() == node->GetType() ) dnode->GetType() == node->GetType() )
{ {
MergeNodes(*dnode, *node); MergeNodesOver(*dnode, *node, overwriteFilename);
break; break;
} }
} }
if ( !dnode ) if ( !dnode )
{ {
wxXmlNode *copyOfNode = new wxXmlNode(*node);
// remember referenced object's file, see GetFileNameFromNode()
copyOfNode->AddAttribute(ATTR_INPUT_FILENAME, overwriteFilename);
static const wxChar *AT_END = wxT("end"); static const wxChar *AT_END = wxT("end");
wxString insert_pos = node->GetAttribute(wxT("insert_at"), AT_END); wxString insert_pos = node->GetAttribute(wxT("insert_at"), AT_END);
if ( insert_pos == AT_END ) if ( insert_pos == AT_END )
{ {
dest.AddChild(new wxXmlNode(*node)); dest.AddChild(copyOfNode);
} }
else if ( insert_pos == wxT("begin") ) else if ( insert_pos == wxT("begin") )
{ {
dest.InsertChild(new wxXmlNode(*node), dest.GetChildren()); dest.InsertChild(copyOfNode, dest.GetChildren());
} }
} }
} }
if ( dest.GetType() == wxXML_TEXT_NODE && with.GetContent().length() ) if ( dest.GetType() == wxXML_TEXT_NODE && overwriteWith.GetContent().length() )
dest.SetContent(with.GetContent()); dest.SetContent(overwriteWith.GetContent());
} }
wxObject *wxXmlResource::CreateResFromNode(wxXmlNode *node, wxObject *parent, wxObject *wxXmlResource::CreateResFromNode(wxXmlNode *node, wxObject *parent,
@ -798,7 +845,11 @@ wxObject *wxXmlResource::CreateResFromNode(wxXmlNode *node, wxObject *parent,
} }
wxXmlNode copy(*refNode); wxXmlNode copy(*refNode);
MergeNodes(copy, *node); MergeNodesOver(copy, *node, GetFileNameFromNode(node, Data()));
// remember referenced object's file, see GetFileNameFromNode()
copy.AddAttribute(ATTR_INPUT_FILENAME,
GetFileNameFromNode(refNode, Data()));
return CreateResFromNode(&copy, parent, instance); return CreateResFromNode(&copy, parent, instance);
} }
@ -1765,30 +1816,6 @@ void wxXmlResourceHandler::ReportParamError(const wxString& param,
m_resource->ReportError(GetParamNode(param), 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) void wxXmlResource::ReportError(wxXmlNode *context, const wxString& message)
{ {
if ( !context ) if ( !context )