]> git.saurik.com Git - wxWidgets.git/blobdiff - src/xrc/xmlres.cpp
Cast needed to fix compilation on 10.4 --This line, and those below,
[wxWidgets.git] / src / xrc / xmlres.cpp
index c69e3bb24ba2d4fc00a671d3a3202e9c87d42a1c..115f3461e51176295b8de89eec62c607b140f715 100644 (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;
 
@@ -162,11 +178,14 @@ bool wxXmlResource::IsArchive(const wxString& filename)
 
 #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;
@@ -176,18 +195,20 @@ bool wxXmlResource::Load(const wxString& filemask)
 #   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
@@ -197,14 +218,12 @@ bool wxXmlResource::Load(const wxString& filemask)
             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)
@@ -499,7 +518,7 @@ bool wxXmlResource::UpdateResources()
                 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);
@@ -553,86 +572,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;
 }
 
@@ -899,22 +946,21 @@ wxString wxXmlResourceHandler::GetText(const wxString& param, bool translate)
     wxXmlNode *parNode = GetParamNode(param);
     wxString str1(GetNodeContent(parNode));
     wxString str2;
-    const wxChar *dt;
-    wxChar amp_char;
+
+    // "\\" wasn't translated to "\" prior to 2.5.3.0:
+    const bool escapeBackslash = (m_resource->CompareVersion(2,5,3,0) >= 0);
 
     // VS: First version of XRC resources used $ instead of & (which is
     //     illegal in XML), but later I realized that '_' fits this purpose
     //     much better (because &File means "File with F underlined").
-    if (m_resource->CompareVersion(2,3,0,1) < 0)
-        amp_char = wxT('$');
-    else
-        amp_char = wxT('_');
+    const wxChar amp_char = (m_resource->CompareVersion(2,3,0,1) < 0)
+                            ? '$' : '_';
 
-    for (dt = str1.c_str(); *dt; dt++)
+    for ( wxString::const_iterator dt = str1.begin(); dt != str1.end(); ++dt )
     {
         // Remap amp_char to &, map double amp_char to amp_char (for things
         // like "&File..." -- this is illegal in XML, so we use "_File..."):
-        if (*dt == amp_char)
+        if ( *dt == amp_char )
         {
             if ( *(++dt) == amp_char )
                 str2 << amp_char;
@@ -922,8 +968,9 @@ wxString wxXmlResourceHandler::GetText(const wxString& param, bool translate)
                 str2 << wxT('&') << *dt;
         }
         // Remap \n to CR, \r to LF, \t to TAB, \\ to \:
-        else if (*dt == wxT('\\'))
-            switch (*(++dt))
+        else if ( *dt == wxT('\\') )
+        {
+            switch ( (*(++dt)).GetValue() )
             {
                 case wxT('n'):
                     str2 << wxT('\n');
@@ -939,7 +986,7 @@ wxString wxXmlResourceHandler::GetText(const wxString& param, bool translate)
 
                 case wxT('\\') :
                     // "\\" wasn't translated to "\" prior to 2.5.3.0:
-                    if (m_resource->CompareVersion(2,5,3,0) >= 0)
+                    if ( escapeBackslash )
                     {
                         str2 << wxT('\\');
                         break;
@@ -950,7 +997,11 @@ wxString wxXmlResourceHandler::GetText(const wxString& param, bool translate)
                     str2 << wxT('\\') << *dt;
                     break;
             }
-        else str2 << *dt;
+        }
+        else
+        {
+            str2 << *dt;
+        }
     }
 
     if (m_resource->GetFlags() & wxXRC_USE_LOCALE)
@@ -995,7 +1046,7 @@ float wxXmlResourceHandler::GetFloat(const wxString& param, float defaultv)
 {
     wxString str = GetParamValue(param);
 
-#if wxUSE_LOCALE
+#if wxUSE_INTL
     // strings in XRC always use C locale but wxString::ToDouble() uses the
     // current one, so transform the string to it supposing that the only
     // difference between them is the decimal separator
@@ -1003,7 +1054,7 @@ float wxXmlResourceHandler::GetFloat(const wxString& param, float defaultv)
     // TODO: use wxString::ToCDouble() when we have it
     str.Replace(wxT("."), wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT,
                                             wxLOCALE_CAT_NUMBER));
-#endif // wxUSE_LOCALE
+#endif // wxUSE_INTL
 
     double value;
     if (!str.ToDouble(&value))
@@ -1027,13 +1078,17 @@ wxString wxXmlResourceHandler::GetName()
 
 
 
+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');
 }
 
 
@@ -1166,40 +1221,6 @@ wxBitmap wxXmlResourceHandler::GetBitmap(const wxString& param,
     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,
@@ -1221,14 +1242,20 @@ wxXmlNode *wxXmlResourceHandler::GetParamNode(const wxString& param)
     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;
@@ -1440,8 +1467,9 @@ wxFont wxXmlResourceHandler::GetFont(const wxString& param)
     if (hasFacename)
     {
         wxString faces = GetParamValue(wxT("face"));
-        wxArrayString facenames(wxFontEnumerator::GetFacenames());
         wxStringTokenizer tk(faces, wxT(","));
+#if wxUSE_FONTENUM
+        wxArrayString facenames(wxFontEnumerator::GetFacenames());
         while (tk.HasMoreTokens())
         {
             int index = facenames.Index(tk.GetNextToken(), false);
@@ -1451,6 +1479,11 @@ wxFont wxXmlResourceHandler::GetFont(const wxString& param)
                 break;
             }
         }
+#else // !wxUSE_FONTENUM
+        // just use the first face name if we can't check its availability:
+        if (tk.HasMoreTokens())
+            facename = tk.GetNextToken();
+#endif // wxUSE_FONTENUM/!wxUSE_FONTENUM
     }
 
     // encoding
@@ -1534,17 +1567,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();
     }
 }
 
@@ -1647,6 +1676,20 @@ int wxXmlResource::DoGetXRCID(const char *str_id, int value_if_not_found)
     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)
 {
@@ -1774,6 +1817,24 @@ static void AddStdXRCID_Records()
     stdID(wxID_MAXIMIZE_FRAME);
     stdID(wxID_ICONIZE_FRAME);
     stdID(wxID_RESTORE_FRAME);
+    stdID(wxID_CDROM);
+    stdID(wxID_CONVERT);
+    stdID(wxID_EXECUTE);
+    stdID(wxID_FLOPPY);
+    stdID(wxID_HARDDISK);
+    stdID(wxID_BOTTOM);
+    stdID(wxID_FIRST);
+    stdID(wxID_LAST);
+    stdID(wxID_TOP);
+    stdID(wxID_INFO);
+    stdID(wxID_JUMP_TO);
+    stdID(wxID_NETWORK);
+    stdID(wxID_SELECT_COLOR);
+    stdID(wxID_SELECT_FONT);
+    stdID(wxID_SORT_ASCENDING);
+    stdID(wxID_SORT_DESCENDING);
+    stdID(wxID_SPELL_CHECK);
+    stdID(wxID_STRIKETHROUGH);
 
 #undef stdID
 }