// 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;
#endif // wxUSE_FILESYSTEM
-bool wxXmlResource::Load(const wxString& filemask)
+bool wxXmlResource::LoadFile(const wxFileName& file)
{
- wxString fnd;
- bool iswild = wxIsWild(filemask);
- bool rt = true;
+ return Load(wxFileSystem::FileNameToURL(file));
+}
+
+bool wxXmlResource::Load(const wxString& filemask_)
+{
+ wxString filemask = ConvertFileNameToURL(filemask_);
#if wxUSE_FILESYSTEM
wxFileSystem fsys;
# define wxXmlFindFirst wxFindFirstFile(filemask, wxFILE)
# define wxXmlFindNext wxFindNextFile()
#endif
- if (iswild)
- fnd = wxXmlFindFirst;
- else
- fnd = filemask;
- while (!fnd.empty())
+ wxString fnd = wxXmlFindFirst;
+ if ( fnd.empty() )
{
- fnd = ConvertFileNameToURL(fnd);
+ wxLogError(_("Cannot load resources from '%s'."), filemask);
+ return false;
+ }
+ while (!fnd.empty())
+ {
#if wxUSE_FILESYSTEM
if ( IsArchive(fnd) )
{
- rt = rt && Load(fnd + wxT("#zip:*.xrc"));
+ if ( !Load(fnd + wxT("#zip:*.xrc")) )
+ return false;
}
else // a single resource URL
#endif // wxUSE_FILESYSTEM
Data().push_back(drec);
}
- if (iswild)
- fnd = wxXmlFindNext;
- else
- fnd = wxEmptyString;
+ fnd = wxXmlFindNext;
}
# undef wxXmlFindFirst
# undef wxXmlFindNext
- return rt && UpdateResources();
+
+ return UpdateResources();
}
bool wxXmlResource::Unload(const wxString& filename)
delete rec->Doc;
rec->Doc = new wxXmlDocument;
}
- if (!stream || !rec->Doc->Load(*stream, encoding))
+ if (!stream || !stream->IsOk() || !rec->Doc->Load(*stream, encoding))
{
wxLogError(_("Cannot load resources from file '%s'."),
rec->File);
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;
}
+bool wxXmlResourceHandler::GetBoolAttr(const wxString& attr, bool defaultv)
+{
+ wxString v;
+ return m_node->GetAttribute(attr, &v) ? v == '1' : defaultv;
+}
+
bool wxXmlResourceHandler::GetBool(const wxString& param, bool defaultv)
{
- wxString v = GetParamValue(param);
- v.MakeLower();
- if (!v) return defaultv;
+ const wxString v = GetParamValue(param);
- return (v == wxT("1"));
+ return v.empty() ? defaultv : (v == '1');
}
return wxBitmap(img);
}
-#if wxUSE_ANIMATIONCTRL
-wxAnimation wxXmlResourceHandler::GetAnimation(const wxString& param)
-{
- wxAnimation ani;
-
- /* load the animation from file: */
- wxString name = GetParamValue(param);
- if (name.empty()) return wxNullAnimation;
-#if wxUSE_FILESYSTEM
- wxFSFile *fsfile = GetCurFileSystem().OpenFile(name, wxFS_READ | wxFS_SEEKABLE);
- if (fsfile == NULL)
- {
- wxLogError(_("XRC resource: Cannot create animation from '%s'."),
- name.c_str());
- return wxNullAnimation;
- }
- ani.Load(*(fsfile->GetStream()));
- delete fsfile;
-#else
- ani.LoadFile(name);
-#endif
-
- if (!ani.IsOk())
- {
- wxLogError(_("XRC resource: Cannot create animation from '%s'."),
- name.c_str());
- return wxNullAnimation;
- }
-
- return ani;
-}
-#endif // wxUSE_ANIMATIONCTRL
-
-
wxIcon wxXmlResourceHandler::GetIcon(const wxString& param,
const wxArtClient& defaultArtClient,
while (n)
{
if (n->GetType() == wxXML_ELEMENT_NODE && n->GetName() == param)
+ {
+ // TODO: check that there are no other properties/parameters with
+ // the same name and log an error if there are (can't do this
+ // right now as I'm not sure if it's not going to break code
+ // using this function in unintentional way (i.e. for
+ // accessing other things than properties), for example
+ // wxBitmapComboBoxXmlHandler almost surely does
return n;
+ }
n = n->GetNext();
}
return NULL;
}
-
-
bool wxXmlResourceHandler::IsOfClass(wxXmlNode *node, const wxString& classname)
{
return node->GetAttribute(wxT("class"), wxEmptyString) == classname;
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();
}
}
return XRCID_Lookup(str_id, value_if_not_found);
}
+/* static */
+wxString wxXmlResource::FindXRCIDById(int numId)
+{
+ for ( int i = 0; i < XRCID_TABLE_SIZE; i++ )
+ {
+ for ( XRCID_record *rec = XRCID_Records[i]; rec; rec = rec->next )
+ {
+ if ( rec->id == numId )
+ return wxString(rec->key);
+ }
+ }
+
+ return wxString();
+}
static void CleanXRCID_Record(XRCID_record *rec)
{