]> git.saurik.com Git - wxWidgets.git/commitdiff
fixed XRC errors location reporting when using <object_ref>
authorVáclav Slavík <vslavik@fastmail.fm>
Sun, 3 May 2009 07:00:24 +0000 (07:00 +0000)
committerVáclav Slavík <vslavik@fastmail.fm>
Sun, 3 May 2009 07:00:24 +0000 (07:00 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@60493 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

src/xrc/xmlres.cpp

index d16bc62363f511dec33998b635977366b6f0f171..090d7da5f2c8cbbf54b7af9f3a2e839cd68e3c2f 100644 (file)
@@ -84,6 +84,48 @@ inline bool IsObjectNode(wxXmlNode *node)
                 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
 
 
@@ -714,10 +756,11 @@ wxXmlResource::GetResourceNodeAndLocation(const wxString& name,
     return NULL;
 }
 
-static void MergeNodes(wxXmlNode& dest, wxXmlNode& with)
+static void MergeNodesOver(wxXmlNode& dest, wxXmlNode& overwriteWith,
+                           const wxString& overwriteFilename)
 {
     // Merge attributes:
-    for ( wxXmlAttribute *attr = with.GetAttributes();
+    for ( wxXmlAttribute *attr = overwriteWith.GetAttributes();
           attr; attr = attr->GetNext() )
     {
         wxXmlAttribute *dattr;
@@ -736,7 +779,7 @@ static void MergeNodes(wxXmlNode& dest, wxXmlNode& with)
    }
 
     // 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);
         wxXmlNode *dnode;
@@ -747,28 +790,32 @@ static void MergeNodes(wxXmlNode& dest, wxXmlNode& with)
                  dnode->GetAttribute(wxT("name"), wxEmptyString) == name &&
                  dnode->GetType() == node->GetType() )
             {
-                MergeNodes(*dnode, *node);
+                MergeNodesOver(*dnode, *node, overwriteFilename);
                 break;
             }
         }
 
         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");
             wxString insert_pos = node->GetAttribute(wxT("insert_at"), AT_END);
             if ( insert_pos == AT_END )
             {
-                dest.AddChild(new wxXmlNode(*node));
+                dest.AddChild(copyOfNode);
             }
             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() )
-         dest.SetContent(with.GetContent());
+    if ( dest.GetType() == wxXML_TEXT_NODE && overwriteWith.GetContent().length() )
+         dest.SetContent(overwriteWith.GetContent());
 }
 
 wxObject *wxXmlResource::CreateResFromNode(wxXmlNode *node, wxObject *parent,
@@ -798,7 +845,11 @@ wxObject *wxXmlResource::CreateResFromNode(wxXmlNode *node, wxObject *parent,
         }
 
         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);
     }
@@ -1765,30 +1816,6 @@ void wxXmlResourceHandler::ReportParamError(const wxString& param,
     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 )