add public wxXmlResource::GetResourceNode() which can be used directly instead of deriving from wxXmlResource and using FindResource()

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@59096 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2009-02-22 21:52:00 +00:00
parent c0b5b33b0d
commit 23239d944a
4 changed files with 136 additions and 43 deletions

View File

@@ -357,6 +357,7 @@ All:
- Added wxStrnlen() for safe computation of string length.
- Added wxImage::Clear() (troelsk).
- Added wxLog::Log().
- Added wxXmlResource::GetResourceNode().
All (Unix):

View File

@@ -227,7 +227,7 @@ public:
{ return GetVersion() -
(major*256*256*256 + minor*256*256 + release*256 + revision); }
//// Singleton accessors.
//// Singleton accessors.
// Gets the global resources object or creates one if none exists.
static wxXmlResource *Get();
@@ -245,16 +245,48 @@ public:
const wxString& GetDomain() const { return m_domain; }
void SetDomain(const wxString& domain);
// This function returns the wxXmlNode containing the definition of the
// object with the given name or NULL.
//
// It can be used to access additional information defined in the XRC file
// and not used by wxXmlResource itself.
const wxXmlNode *GetResourceNode(const wxString& name) const
{ return GetResourceNodeAndLocation(name, wxString(), true); }
protected:
// Scans the resources list for unloaded files and loads them. Also reloads
// files that have been modified since last loading.
bool UpdateResources();
// Finds a resource (calls UpdateResources) and returns a node containing it.
wxXmlNode *FindResource(const wxString& name, const wxString& classname, bool recursive = false);
// Helper function: finds a resource (calls UpdateResources) and returns a node containing it.
wxXmlNode *DoFindResource(wxXmlNode *parent, const wxString& name, const wxString& classname, bool recursive);
// Common implementation of GetResourceNode() and FindResource(): searches
// all top-level or all (if recursive == true) nodes if all loaded XRC
// files and returns the node, if found, as well as the path of the file it
// was found in if path is non-NULL
wxXmlNode *GetResourceNodeAndLocation(const wxString& name,
const wxString& classname,
bool recursive = false,
wxString *path = NULL) const;
// Note that these functions are used outside of wxWidgets itself, e.g.
// there are several known cases of inheriting from wxXmlResource just to
// be able to call FindResource() so we keep them for compatibility even if
// their names are not really consistent with GetResourceNode() public
// function and FindResource() is also non-const because it changes the
// current path of m_curFileSystem to ensure that relative paths work
// correctly when CreateResFromNode() is called immediately afterwards
// (something const public function intentionally does not do)
// Returns the node containing the resource with the given name and class
// name unless it's empty (then any class matches) or NULL if not found.
wxXmlNode *FindResource(const wxString& name, const wxString& classname,
bool recursive = false);
// Helper function used by FindResource() to look under the given node.
wxXmlNode *DoFindResource(wxXmlNode *parent, const wxString& name,
const wxString& classname, bool recursive) const;
// Creates a resource from information in the given node
// (Uses only 'handlerToUse' if != NULL)

View File

@@ -142,6 +142,26 @@ public:
*/
int GetFlags() const;
/**
Returns the wxXmlNode containing the definition of the object with the
given name or @NULL.
This function recursively searches all the loaded XRC files for an
object with the specified @a name. If the object is found, the
wxXmlNode corresponding to it is returned, so this function can be used
to access additional information defined in the XRC file and not used
by wxXmlResource itself, e.g. contents of application-specific XML
tags.
@param name
The name of the resource which must be unique for this function to
work correctly, if there is more than one resource with the given
name the choice of the one returned by this function is undefined.
@return
The node corresponding to the resource with the given name or @NULL.
*/
const wxXmlNode *GetResourceNode(const wxString& name) const;
/**
Returns version information (a.b.c.d = d + 256*c + 2562*b + 2563*a).
*/

View File

@@ -70,6 +70,22 @@ class wxXmlResourceDataRecords : public wxVector<wxXmlResourceDataRecord*>
// this is a class so that it can be forward-declared
};
namespace
{
// helper used by DoFindResource() and elsewhere: returns true if this is an
// object or object_ref node
//
// node must be non-NULL
inline bool IsObjectNode(wxXmlNode *node)
{
return node->GetType() == wxXML_ELEMENT_NODE &&
(node->GetName() == wxS("object") ||
node->GetName() == wxS("object_ref"));
}
} // anonymous namespace
wxXmlResource *wxXmlResource::ms_instance = NULL;
@@ -551,86 +567,114 @@ bool wxXmlResource::UpdateResources()
return rt;
}
wxXmlNode *wxXmlResource::DoFindResource(wxXmlNode *parent,
const wxString& name,
const wxString& classname,
bool recursive)
bool recursive) const
{
wxString dummy;
wxXmlNode *node;
// first search for match at the top-level nodes (as this is
// where the resource is most commonly looked for):
for (node = parent->GetChildren(); node; node = node->GetNext())
{
if ( node->GetType() == wxXML_ELEMENT_NODE &&
(node->GetName() == wxT("object") ||
node->GetName() == wxT("object_ref")) &&
node->GetAttribute(wxT("name"), &dummy) && dummy == name )
if ( IsObjectNode(node) && node->GetAttribute(wxS("name")) == name )
{
wxString cls(node->GetAttribute(wxT("class"), wxEmptyString));
if (!classname || cls == classname)
// empty class name matches everything
if ( classname.empty() )
return node;
wxString cls(node->GetAttribute(wxS("class")));
// object_ref may not have 'class' attribute:
if (cls.empty() && node->GetName() == wxT("object_ref"))
if (cls.empty() && node->GetName() == wxS("object_ref"))
{
wxString refName = node->GetAttribute(wxT("ref"), wxEmptyString);
wxString refName = node->GetAttribute(wxS("ref"));
if (refName.empty())
continue;
wxXmlNode* refNode = FindResource(refName, wxEmptyString, true);
if (refNode &&
refNode->GetAttribute(wxT("class"), wxEmptyString) == classname)
{
return node;
}
const wxXmlNode * const refNode = GetResourceNode(refName);
if ( refNode )
cls = refNode->GetAttribute(wxS("class"));
}
if ( cls == classname )
return node;
}
}
// then recurse in child nodes
if ( recursive )
{
for (node = parent->GetChildren(); node; node = node->GetNext())
{
if ( node->GetType() == wxXML_ELEMENT_NODE &&
(node->GetName() == wxT("object") ||
node->GetName() == wxT("object_ref")) )
if ( IsObjectNode(node) )
{
wxXmlNode* found = DoFindResource(node, name, classname, true);
if ( found )
return found;
}
}
}
return NULL;
return NULL;
}
wxXmlNode *wxXmlResource::FindResource(const wxString& name,
const wxString& classname,
bool recursive)
{
UpdateResources(); //ensure everything is up-to-date
wxString path;
wxXmlNode * const
node = GetResourceNodeAndLocation(name, classname, recursive, &path);
if ( !node )
{
wxLogError(_("XRC resource '%s' (class '%s') not found!"),
name, classname);
}
#if wxUSE_FILESYSTEM
else // node was found
{
// ensure that relative paths work correctly when loading this node
// (which should happen as soon as we return as FindResource() result
// is always passed to CreateResFromNode())
m_curFileSystem.ChangePathTo(path);
}
#endif // wxUSE_FILESYSTEM
return node;
}
wxXmlNode *
wxXmlResource::GetResourceNodeAndLocation(const wxString& name,
const wxString& classname,
bool recursive,
wxString *path) const
{
// ensure everything is up-to-date: this is needed to support on-remand
// reloading of XRC files
const_cast<wxXmlResource *>(this)->UpdateResources();
wxString dummy;
for ( wxXmlResourceDataRecords::const_iterator f = Data().begin();
f != Data().end(); ++f )
{
wxXmlResourceDataRecord* const rec = *f;
if ( rec->Doc == NULL || rec->Doc->GetRoot() == NULL )
wxXmlResourceDataRecord *const rec = *f;
wxXmlDocument * const doc = rec->Doc;
if ( !doc || !doc->GetRoot() )
continue;
wxXmlNode* found = DoFindResource(rec->Doc->GetRoot(),
name, classname, recursive);
wxXmlNode * const
found = DoFindResource(doc->GetRoot(), name, classname, recursive);
if ( found )
{
#if wxUSE_FILESYSTEM
m_curFileSystem.ChangePathTo(rec->File);
#endif
if ( path )
*path = rec->File;
return found;
}
}
wxLogError(_("XRC resource '%s' (class '%s') not found!"),
name.c_str(), classname.c_str());
return NULL;
}
@@ -1518,17 +1562,13 @@ void wxXmlResourceHandler::SetupWindow(wxWindow *wnd)
void wxXmlResourceHandler::CreateChildren(wxObject *parent, bool this_hnd_only)
{
wxXmlNode *n = m_node->GetChildren();
while (n)
for ( wxXmlNode *n = m_node->GetChildren(); n; n = n->GetNext() )
{
if (n->GetType() == wxXML_ELEMENT_NODE &&
(n->GetName() == wxT("object") || n->GetName() == wxT("object_ref")))
if ( IsObjectNode(n) )
{
m_resource->CreateResFromNode(n, parent, NULL,
this_hnd_only ? this : NULL);
}
n = n->GetNext();
}
}