+ for (dnode = dest.GetChildren(); dnode; dnode = dnode->GetNext() )
+ {
+ if ( dnode->GetName() == node->GetName() &&
+ dnode->GetAttribute(wxT("name"), wxEmptyString) == name &&
+ dnode->GetType() == node->GetType() )
+ {
+ 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(copyOfNode);
+ }
+ else if ( insert_pos == wxT("begin") )
+ {
+ dest.InsertChild(copyOfNode, dest.GetChildren());
+ }
+ }
+ }
+
+ if ( dest.GetType() == wxXML_TEXT_NODE && overwriteWith.GetContent().length() )
+ dest.SetContent(overwriteWith.GetContent());
+}
+
+wxObject *
+wxXmlResource::DoCreateResFromNode(wxXmlNode& node,
+ wxObject *parent,
+ wxObject *instance,
+ wxXmlResourceHandler *handlerToUse)
+{
+ // handling of referenced resource
+ if ( node.GetName() == wxT("object_ref") )
+ {
+ wxString refName = node.GetAttribute(wxT("ref"), wxEmptyString);
+ wxXmlNode* refNode = FindResource(refName, wxEmptyString, true);
+
+ if ( !refNode )
+ {
+ ReportError
+ (
+ &node,
+ wxString::Format
+ (
+ "referenced object node with ref=\"%s\" not found",
+ refName
+ )
+ );
+ return NULL;
+ }
+
+ if ( !node.GetChildren() )
+ {
+ // In the typical, simple case, <object_ref> is used to link
+ // to another node and doesn't have any content of its own that
+ // would overwrite linked object's properties. In this case,
+ // we can simply create the resource from linked node.
+
+ return DoCreateResFromNode(*refNode, parent, instance);
+ }
+ else
+ {
+ // In the more complicated (but rare) case, <object_ref> has
+ // subnodes that partially overwrite content of the referenced
+ // object. In this case, we need to merge both XML trees and
+ // load the resource from result of the merge.
+
+ wxXmlNode copy(*refNode);
+ MergeNodesOver(copy, node, GetFileNameFromNode(&node, Data()));
+
+ // remember referenced object's file, see GetFileNameFromNode()
+ copy.AddAttribute(ATTR_INPUT_FILENAME,
+ GetFileNameFromNode(refNode, Data()));
+
+ return DoCreateResFromNode(copy, parent, instance);
+ }
+ }
+
+ if (handlerToUse)
+ {
+ if (handlerToUse->CanHandle(&node))
+ {
+ return handlerToUse->CreateResource(&node, parent, instance);
+ }
+ }
+ else if (node.GetName() == wxT("object"))
+ {
+ for ( wxVector<wxXmlResourceHandler*>::iterator h = m_handlers.begin();
+ h != m_handlers.end(); ++h )
+ {
+ wxXmlResourceHandler *handler = *h;
+ if (handler->CanHandle(&node))
+ return handler->CreateResource(&node, parent, instance);
+ }
+ }
+
+ ReportError
+ (
+ &node,
+ wxString::Format
+ (
+ "no handler found for XML node \"%s\" (class \"%s\")",
+ node.GetName(),
+ node.GetAttribute("class", wxEmptyString)
+ )
+ );
+ return NULL;
+}
+
+
+class wxXmlSubclassFactories : public wxVector<wxXmlSubclassFactory*>
+{
+ // this is a class so that it can be forward-declared
+};
+
+wxXmlSubclassFactories *wxXmlResource::ms_subclassFactories = NULL;
+
+/*static*/ void wxXmlResource::AddSubclassFactory(wxXmlSubclassFactory *factory)
+{
+ if (!ms_subclassFactories)
+ {
+ ms_subclassFactories = new wxXmlSubclassFactories;
+ }
+ ms_subclassFactories->push_back(factory);
+}
+
+class wxXmlSubclassFactoryCXX : public wxXmlSubclassFactory
+{
+public:
+ ~wxXmlSubclassFactoryCXX() {}
+
+ wxObject *Create(const wxString& className)
+ {
+ wxClassInfo* classInfo = wxClassInfo::FindClass(className);
+
+ if (classInfo)
+ return classInfo->CreateObject();
+ else
+ return NULL;
+ }
+};