]> git.saurik.com Git - wxWidgets.git/blobdiff - src/xrc/xmlres.cpp
fixing focus, fixes #11911
[wxWidgets.git] / src / xrc / xmlres.cpp
index 090d7da5f2c8cbbf54b7af9f3a2e839cd68e3c2f..88fa86ab4ac56e28626e4d72173eea07a6ec8609 100644 (file)
@@ -44,6 +44,7 @@
 #include "wx/fontenum.h"
 #include "wx/fontmap.h"
 #include "wx/artprov.h"
 #include "wx/fontenum.h"
 #include "wx/fontmap.h"
 #include "wx/artprov.h"
+#include "wx/imaglist.h"
 #include "wx/dir.h"
 #include "wx/xml/xml.h"
 
 #include "wx/dir.h"
 #include "wx/xml/xml.h"
 
@@ -291,13 +292,13 @@ bool wxXmlResource::Load(const wxString& filemask_)
 bool wxXmlResource::Unload(const wxString& filename)
 {
     wxASSERT_MSG( !wxIsWild(filename),
 bool wxXmlResource::Unload(const wxString& filename)
 {
     wxASSERT_MSG( !wxIsWild(filename),
-                    _T("wildcards not supported by wxXmlResource::Unload()") );
+                    wxT("wildcards not supported by wxXmlResource::Unload()") );
 
     wxString fnd = ConvertFileNameToURL(filename);
 #if wxUSE_FILESYSTEM
     const bool isArchive = IsArchive(fnd);
     if ( isArchive )
 
     wxString fnd = ConvertFileNameToURL(filename);
 #if wxUSE_FILESYSTEM
     const bool isArchive = IsArchive(fnd);
     if ( isArchive )
-        fnd += _T("#zip:");
+        fnd += wxT("#zip:");
 #endif // wxUSE_FILESYSTEM
 
     bool unloaded = false;
 #endif // wxUSE_FILESYSTEM
 
     bool unloaded = false;
@@ -430,14 +431,27 @@ wxIcon wxXmlResource::LoadIcon(const wxString& name)
 }
 
 
 }
 
 
-wxObject *wxXmlResource::LoadObject(wxWindow *parent, const wxString& name, const wxString& classname)
+wxObject *
+wxXmlResource::DoLoadObject(wxWindow *parent,
+                            const wxString& name,
+                            const wxString& classname,
+                            bool recursive)
 {
 {
-    return CreateResFromNode(FindResource(name, classname), parent, NULL);
+    wxXmlNode * const node = FindResource(name, classname, recursive);
+
+    return node ? DoCreateResFromNode(*node, parent, NULL) : NULL;
 }
 
 }
 
-bool wxXmlResource::LoadObject(wxObject *instance, wxWindow *parent, const wxString& name, const wxString& classname)
+bool
+wxXmlResource::DoLoadObject(wxObject *instance,
+                            wxWindow *parent,
+                            const wxString& name,
+                            const wxString& classname,
+                            bool recursive)
 {
 {
-    return CreateResFromNode(FindResource(name, classname), parent, instance) != NULL;
+    wxXmlNode * const node = FindResource(name, classname, recursive);
+
+    return node && DoCreateResFromNode(*node, parent, instance) != NULL;
 }
 
 
 }
 
 
@@ -563,7 +577,7 @@ bool wxXmlResource::UpdateResources()
 
         if (modif)
         {
 
         if (modif)
         {
-            wxLogTrace(_T("xrc"), _T("opening file '%s'"), rec->File);
+            wxLogTrace(wxT("xrc"), wxT("opening file '%s'"), rec->File);
 
             wxInputStream *stream = NULL;
 
 
             wxInputStream *stream = NULL;
 
@@ -818,23 +832,23 @@ static void MergeNodesOver(wxXmlNode& dest, wxXmlNode& overwriteWith,
          dest.SetContent(overwriteWith.GetContent());
 }
 
          dest.SetContent(overwriteWith.GetContent());
 }
 
-wxObject *wxXmlResource::CreateResFromNode(wxXmlNode *node, wxObject *parent,
-                                           wxObject *instance,
-                                           wxXmlResourceHandler *handlerToUse)
+wxObject *
+wxXmlResource::DoCreateResFromNode(wxXmlNode& node,
+                                   wxObject *parent,
+                                   wxObject *instance,
+                                   wxXmlResourceHandler *handlerToUse)
 {
 {
-    if (node == NULL) return NULL;
-
     // handling of referenced resource
     // handling of referenced resource
-    if ( node->GetName() == wxT("object_ref") )
+    if ( node.GetName() == wxT("object_ref") )
     {
     {
-        wxString refName = node->GetAttribute(wxT("ref"), wxEmptyString);
+        wxString refName = node.GetAttribute(wxT("ref"), wxEmptyString);
         wxXmlNode* refNode = FindResource(refName, wxEmptyString, true);
 
         if ( !refNode )
         {
             ReportError
             (
         wxXmlNode* refNode = FindResource(refName, wxEmptyString, true);
 
         if ( !refNode )
         {
             ReportError
             (
-                node,
+                &node,
                 wxString::Format
                 (
                     "referenced object node with ref=\"%s\" not found",
                 wxString::Format
                 (
                     "referenced object node with ref=\"%s\" not found",
@@ -844,42 +858,59 @@ wxObject *wxXmlResource::CreateResFromNode(wxXmlNode *node, wxObject *parent,
             return NULL;
         }
 
             return NULL;
         }
 
-        wxXmlNode copy(*refNode);
-        MergeNodesOver(copy, *node, GetFileNameFromNode(node, Data()));
+        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()));
+            // remember referenced object's file, see GetFileNameFromNode()
+            copy.AddAttribute(ATTR_INPUT_FILENAME,
+                              GetFileNameFromNode(refNode, Data()));
 
 
-        return CreateResFromNode(&copy, parent, instance);
+            return DoCreateResFromNode(copy, parent, instance);
+        }
     }
 
     if (handlerToUse)
     {
     }
 
     if (handlerToUse)
     {
-        if (handlerToUse->CanHandle(node))
+        if (handlerToUse->CanHandle(&node))
         {
         {
-            return handlerToUse->CreateResource(node, parent, instance);
+            return handlerToUse->CreateResource(&node, parent, instance);
         }
     }
         }
     }
-    else if (node->GetName() == wxT("object"))
+    else if (node.GetName() == wxT("object"))
     {
         for ( wxVector<wxXmlResourceHandler*>::iterator h = m_handlers.begin();
               h != m_handlers.end(); ++h )
         {
             wxXmlResourceHandler *handler = *h;
     {
         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);
+            if (handler->CanHandle(&node))
+                return handler->CreateResource(&node, parent, instance);
         }
     }
 
     ReportError
     (
         }
     }
 
     ReportError
     (
-        node,
+        &node,
         wxString::Format
         (
             "no handler found for XML node \"%s\" (class \"%s\")",
         wxString::Format
         (
             "no handler found for XML node \"%s\" (class \"%s\")",
-            node->GetName(),
-            node->GetAttribute("class", wxEmptyString)
+            node.GetName(),
+            node.GetAttribute("class", wxEmptyString)
         )
     );
     return NULL;
         )
     );
     return NULL;
@@ -997,7 +1028,8 @@ void wxXmlResourceHandler::AddWindowStyles()
     // the border styles all have the old and new names, recognize both for now
     XRC_ADD_STYLE(wxSIMPLE_BORDER); XRC_ADD_STYLE(wxBORDER_SIMPLE);
     XRC_ADD_STYLE(wxSUNKEN_BORDER); XRC_ADD_STYLE(wxBORDER_SUNKEN);
     // the border styles all have the old and new names, recognize both for now
     XRC_ADD_STYLE(wxSIMPLE_BORDER); XRC_ADD_STYLE(wxBORDER_SIMPLE);
     XRC_ADD_STYLE(wxSUNKEN_BORDER); XRC_ADD_STYLE(wxBORDER_SUNKEN);
-    XRC_ADD_STYLE(wxDOUBLE_BORDER); XRC_ADD_STYLE(wxBORDER_DOUBLE);
+    XRC_ADD_STYLE(wxDOUBLE_BORDER); XRC_ADD_STYLE(wxBORDER_DOUBLE); // deprecated
+    XRC_ADD_STYLE(wxBORDER_THEME);
     XRC_ADD_STYLE(wxRAISED_BORDER); XRC_ADD_STYLE(wxBORDER_RAISED);
     XRC_ADD_STYLE(wxSTATIC_BORDER); XRC_ADD_STYLE(wxBORDER_STATIC);
     XRC_ADD_STYLE(wxNO_BORDER);     XRC_ADD_STYLE(wxBORDER_NONE);
     XRC_ADD_STYLE(wxRAISED_BORDER); XRC_ADD_STYLE(wxBORDER_RAISED);
     XRC_ADD_STYLE(wxSTATIC_BORDER); XRC_ADD_STYLE(wxBORDER_STATIC);
     XRC_ADD_STYLE(wxNO_BORDER);     XRC_ADD_STYLE(wxBORDER_NONE);
@@ -1208,7 +1240,7 @@ static wxColour GetSystemColour(const wxString& name)
     if (!name.empty())
     {
         #define SYSCLR(clr) \
     if (!name.empty())
     {
         #define SYSCLR(clr) \
-            if (name == _T(#clr)) return wxSystemSettings::GetColour(clr);
+            if (name == wxT(#clr)) return wxSystemSettings::GetColour(clr);
         SYSCLR(wxSYS_COLOUR_SCROLLBAR)
         SYSCLR(wxSYS_COLOUR_BACKGROUND)
         SYSCLR(wxSYS_COLOUR_DESKTOP)
         SYSCLR(wxSYS_COLOUR_SCROLLBAR)
         SYSCLR(wxSYS_COLOUR_BACKGROUND)
         SYSCLR(wxSYS_COLOUR_DESKTOP)
@@ -1316,9 +1348,32 @@ wxBitmap wxXmlResourceHandler::GetBitmap(const wxString& param,
                                          const wxArtClient& defaultArtClient,
                                          wxSize size)
 {
                                          const wxArtClient& defaultArtClient,
                                          wxSize size)
 {
+    // it used to be possible to pass an empty string here to indicate that the
+    // bitmap name should be read from this node itself but this is not
+    // supported any more because GetBitmap(m_node) can be used directly
+    // instead
+    wxASSERT_MSG( !param.empty(), "bitmap parameter name can't be empty" );
+
+    const wxXmlNode* const node = GetParamNode(param);
+
+    if ( !node )
+    {
+        // this is not an error as bitmap parameter could be optional
+        return wxNullBitmap;
+    }
+
+    return GetBitmap(node, defaultArtClient, size);
+}
+
+wxBitmap wxXmlResourceHandler::GetBitmap(const wxXmlNode* node,
+                                         const wxArtClient& defaultArtClient,
+                                         wxSize size)
+{
+    wxCHECK_MSG( node, wxNullBitmap, "bitmap node can't be NULL" );
+
     /* If the bitmap is specified as stock item, query wxArtProvider for it: */
     wxString art_id, art_client;
     /* If the bitmap is specified as stock item, query wxArtProvider for it: */
     wxString art_id, art_client;
-    if ( GetStockArtAttrs(GetParamNode(param), defaultArtClient,
+    if ( GetStockArtAttrs(node, defaultArtClient,
                           art_id, art_client) )
     {
         wxBitmap stockArt(wxArtProvider::GetBitmap(art_id, art_client, size));
                           art_id, art_client) )
     {
         wxBitmap stockArt(wxArtProvider::GetBitmap(art_id, art_client, size));
@@ -1327,7 +1382,7 @@ wxBitmap wxXmlResourceHandler::GetBitmap(const wxString& param,
     }
 
     /* ...or load the bitmap from file: */
     }
 
     /* ...or load the bitmap from file: */
-    wxString name = GetParamValue(param);
+    wxString name = GetParamValue(node);
     if (name.empty()) return wxNullBitmap;
 #if wxUSE_FILESYSTEM
     wxFSFile *fsfile = GetCurFileSystem().OpenFile(name, wxFS_READ | wxFS_SEEKABLE);
     if (name.empty()) return wxNullBitmap;
 #if wxUSE_FILESYSTEM
     wxFSFile *fsfile = GetCurFileSystem().OpenFile(name, wxFS_READ | wxFS_SEEKABLE);
@@ -1335,7 +1390,7 @@ wxBitmap wxXmlResourceHandler::GetBitmap(const wxString& param,
     {
         ReportParamError
         (
     {
         ReportParamError
         (
-            param,
+            node->GetName(),
             wxString::Format("cannot open bitmap resource \"%s\"", name)
         );
         return wxNullBitmap;
             wxString::Format("cannot open bitmap resource \"%s\"", name)
         );
         return wxNullBitmap;
@@ -1350,7 +1405,7 @@ wxBitmap wxXmlResourceHandler::GetBitmap(const wxString& param,
     {
         ReportParamError
         (
     {
         ReportParamError
         (
-            param,
+            node->GetName(),
             wxString::Format("cannot create bitmap from \"%s\"", name)
         );
         return wxNullBitmap;
             wxString::Format("cannot create bitmap from \"%s\"", name)
         );
         return wxNullBitmap;
@@ -1363,12 +1418,31 @@ wxBitmap wxXmlResourceHandler::GetBitmap(const wxString& param,
 wxIcon wxXmlResourceHandler::GetIcon(const wxString& param,
                                      const wxArtClient& defaultArtClient,
                                      wxSize size)
 wxIcon wxXmlResourceHandler::GetIcon(const wxString& param,
                                      const wxArtClient& defaultArtClient,
                                      wxSize size)
+{
+    // see comment in GetBitmap(wxString) overload
+    wxASSERT_MSG( !param.empty(), "icon parameter name can't be empty" );
+
+    const wxXmlNode* const node = GetParamNode(param);
+
+    if ( !node )
+    {
+        // this is not an error as icon parameter could be optional
+        return wxIcon();
+    }
+
+    return GetIcon(node, defaultArtClient, size);
+}
+
+wxIcon wxXmlResourceHandler::GetIcon(const wxXmlNode* node,
+                                     const wxArtClient& defaultArtClient,
+                                     wxSize size)
 {
     wxIcon icon;
 {
     wxIcon icon;
-    icon.CopyFromBitmap(GetBitmap(param, defaultArtClient, size));
+    icon.CopyFromBitmap(GetBitmap(node, defaultArtClient, size));
     return icon;
 }
 
     return icon;
 }
 
+
 wxIconBundle wxXmlResourceHandler::GetIconBundle(const wxString& param,
                                                  const wxArtClient& defaultArtClient)
 {
 wxIconBundle wxXmlResourceHandler::GetIconBundle(const wxString& param,
                                                  const wxArtClient& defaultArtClient)
 {
@@ -1417,6 +1491,46 @@ wxIconBundle wxXmlResourceHandler::GetIconBundle(const wxString& param,
 }
 
 
 }
 
 
+wxImageList *wxXmlResourceHandler::GetImageList(const wxString& param)
+{
+    wxXmlNode * const imagelist_node = GetParamNode(param);
+    if ( !imagelist_node )
+        return NULL;
+
+    wxXmlNode * const oldnode = m_node;
+    m_node = imagelist_node;
+
+    // size
+    wxSize size = GetSize();
+    size.SetDefaults(wxSize(wxSystemSettings::GetMetric(wxSYS_ICON_X),
+                            wxSystemSettings::GetMetric(wxSYS_ICON_Y)));
+
+    // mask: true by default
+    bool mask = HasParam(wxT("mask")) ? GetBool(wxT("mask"), true) : true;
+
+    // now we have everything we need to create the image list
+    wxImageList *imagelist = new wxImageList(size.x, size.y, mask);
+
+    // add images
+    wxString parambitmap = wxT("bitmap");
+    if ( HasParam(parambitmap) )
+    {
+        wxXmlNode *n = m_node->GetChildren();
+        while (n)
+        {
+            if (n->GetType() == wxXML_ELEMENT_NODE && n->GetName() == parambitmap)
+            {
+                // add icon instead of bitmap to keep the bitmap mask
+                imagelist->Add(GetIcon(n));
+            }
+            n = n->GetNext();
+        }
+    }
+
+    m_node = oldnode;
+    return imagelist;
+}
+
 wxXmlNode *wxXmlResourceHandler::GetParamNode(const wxString& param)
 {
     wxCHECK_MSG(m_node, NULL, wxT("You can't access handler data before it was initialized!"));
 wxXmlNode *wxXmlResourceHandler::GetParamNode(const wxString& param)
 {
     wxCHECK_MSG(m_node, NULL, wxT("You can't access handler data before it was initialized!"));
@@ -1447,9 +1561,9 @@ bool wxXmlResourceHandler::IsOfClass(wxXmlNode *node, const wxString& classname)
 
 
 
 
 
 
-wxString wxXmlResourceHandler::GetNodeContent(wxXmlNode *node)
+wxString wxXmlResourceHandler::GetNodeContent(const wxXmlNode *node)
 {
 {
-    wxXmlNode *n = node;
+    const wxXmlNode *n = node;
     if (n == NULL) return wxEmptyString;
     n = n->GetChildren();
 
     if (n == NULL) return wxEmptyString;
     n = n->GetChildren();
 
@@ -1473,6 +1587,10 @@ wxString wxXmlResourceHandler::GetParamValue(const wxString& param)
         return GetNodeContent(GetParamNode(param));
 }
 
         return GetNodeContent(GetParamNode(param));
 }
 
+wxString wxXmlResourceHandler::GetParamValue(const wxXmlNode* node)
+{
+    return GetNodeContent(node);
+}
 
 
 wxSize wxXmlResourceHandler::GetSize(const wxString& param,
 
 
 wxSize wxXmlResourceHandler::GetSize(const wxString& param,
@@ -1584,7 +1702,7 @@ static wxFont GetSystemFont(const wxString& name)
     if (!name.empty())
     {
         #define SYSFNT(fnt) \
     if (!name.empty())
     {
         #define SYSFNT(fnt) \
-            if (name == _T(#fnt)) return wxSystemSettings::GetFont(fnt);
+            if (name == wxT(#fnt)) return wxSystemSettings::GetFont(fnt);
         SYSFNT(wxSYS_OEM_FIXED_FONT)
         SYSFNT(wxSYS_ANSI_FIXED_FONT)
         SYSFNT(wxSYS_ANSI_VAR_FONT)
         SYSFNT(wxSYS_OEM_FIXED_FONT)
         SYSFNT(wxSYS_ANSI_FIXED_FONT)
         SYSFNT(wxSYS_ANSI_VAR_FONT)
@@ -1689,6 +1807,7 @@ wxFont wxXmlResourceHandler::GetFont(const wxString& param)
     // encoding
     wxFontEncoding enc = wxFONTENCODING_DEFAULT;
     bool hasEncoding = HasParam(wxT("encoding"));
     // encoding
     wxFontEncoding enc = wxFONTENCODING_DEFAULT;
     bool hasEncoding = HasParam(wxT("encoding"));
+#if wxUSE_FONTMAP
     if (hasEncoding)
     {
         wxString encoding = GetParamValue(wxT("encoding"));
     if (hasEncoding)
     {
         wxString encoding = GetParamValue(wxT("encoding"));
@@ -1698,6 +1817,7 @@ wxFont wxXmlResourceHandler::GetFont(const wxString& param)
         if (enc == wxFONTENCODING_SYSTEM)
             enc = wxFONTENCODING_DEFAULT;
     }
         if (enc == wxFONTENCODING_SYSTEM)
             enc = wxFONTENCODING_DEFAULT;
     }
+#endif // wxUSE_FONTMAP
 
     // is this font based on a system font?
     wxFont font = GetSystemFont(GetParamValue(wxT("sysfont")));
 
     // is this font based on a system font?
     wxFont font = GetSystemFont(GetParamValue(wxT("sysfont")));
@@ -1746,8 +1866,12 @@ void wxXmlResourceHandler::SetupWindow(wxWindow *wnd)
         wnd->SetExtraStyle(wnd->GetExtraStyle() | GetStyle(wxT("exstyle")));
     if (HasParam(wxT("bg")))
         wnd->SetBackgroundColour(GetColour(wxT("bg")));
         wnd->SetExtraStyle(wnd->GetExtraStyle() | GetStyle(wxT("exstyle")));
     if (HasParam(wxT("bg")))
         wnd->SetBackgroundColour(GetColour(wxT("bg")));
+    if (HasParam(wxT("ownbg")))
+        wnd->SetOwnBackgroundColour(GetColour(wxT("ownbg")));
     if (HasParam(wxT("fg")))
         wnd->SetForegroundColour(GetColour(wxT("fg")));
     if (HasParam(wxT("fg")))
         wnd->SetForegroundColour(GetColour(wxT("fg")));
+    if (HasParam(wxT("ownfg")))
+        wnd->SetOwnForegroundColour(GetColour(wxT("ownfg")));
     if (GetBool(wxT("enabled"), 1) == 0)
         wnd->Enable(false);
     if (GetBool(wxT("focused"), 0) == 1)
     if (GetBool(wxT("enabled"), 1) == 0)
         wnd->Enable(false);
     if (GetBool(wxT("focused"), 0) == 1)
@@ -1759,7 +1883,9 @@ void wxXmlResourceHandler::SetupWindow(wxWindow *wnd)
         wnd->SetToolTip(GetText(wxT("tooltip")));
 #endif
     if (HasParam(wxT("font")))
         wnd->SetToolTip(GetText(wxT("tooltip")));
 #endif
     if (HasParam(wxT("font")))
-        wnd->SetFont(GetFont());
+        wnd->SetFont(GetFont(wxT("font")));
+    if (HasParam(wxT("ownfont")))
+        wnd->SetOwnFont(GetFont(wxT("ownfont")));
     if (HasParam(wxT("help")))
         wnd->SetHelpText(GetText(wxT("help")));
 }
     if (HasParam(wxT("help")))
         wnd->SetHelpText(GetText(wxT("help")));
 }
@@ -1771,8 +1897,8 @@ void wxXmlResourceHandler::CreateChildren(wxObject *parent, bool this_hnd_only)
     {
         if ( IsObjectNode(n) )
         {
     {
         if ( IsObjectNode(n) )
         {
-            m_resource->CreateResFromNode(n, parent, NULL,
-                                          this_hnd_only ? this : NULL);
+            m_resource->DoCreateResFromNode(*n, parent, NULL,
+                                            this_hnd_only ? this : NULL);
         }
     }
 }
         }
     }
 }
@@ -1870,9 +1996,9 @@ static XRCID_record *XRCID_Records[XRCID_TABLE_SIZE] = {NULL};
 
 static int XRCID_Lookup(const char *str_id, int value_if_not_found = wxID_NONE)
 {
 
 static int XRCID_Lookup(const char *str_id, int value_if_not_found = wxID_NONE)
 {
-    int index = 0;
+    unsigned int index = 0;
 
 
-    for (const char *c = str_id; *c != '\0'; c++) index += (int)*c;
+    for (const char *c = str_id; *c != '\0'; c++) index += (unsigned int)*c;
     index %= XRCID_TABLE_SIZE;
 
     XRCID_record *oldrec = NULL;
     index %= XRCID_TABLE_SIZE;
 
     XRCID_record *oldrec = NULL;
@@ -1911,58 +2037,13 @@ static int XRCID_Lookup(const char *str_id, int value_if_not_found = wxID_NONE)
     return (*rec_var)->id;
 }
 
     return (*rec_var)->id;
 }
 
-static void AddStdXRCID_Records();
-
-/*static*/
-int wxXmlResource::DoGetXRCID(const char *str_id, int value_if_not_found)
-{
-    static bool s_stdIDsAdded = false;
-
-    if ( !s_stdIDsAdded )
-    {
-        s_stdIDsAdded = true;
-        AddStdXRCID_Records();
-    }
-
-    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)
+namespace
 {
 {
-    if (rec)
-    {
-        CleanXRCID_Record(rec->next);
-
-        free(rec->key);
-        delete rec;
-    }
-}
 
 
-static void CleanXRCID_Records()
-{
-    for (int i = 0; i < XRCID_TABLE_SIZE; i++)
-    {
-        CleanXRCID_Record(XRCID_Records[i]);
-        XRCID_Records[i] = NULL;
-    }
-}
+// flag indicating whether standard XRC ids were already initialized
+static bool gs_stdIDsAdded = false;
 
 
-static void AddStdXRCID_Records()
+void AddStdXRCID_Records()
 {
 #define stdID(id) XRCID_Lookup(#id, id)
     stdID(-1);
 {
 #define stdID(id) XRCID_Lookup(#id, id)
     stdID(-1);
@@ -2090,8 +2171,57 @@ static void AddStdXRCID_Records()
 #undef stdID
 }
 
 #undef stdID
 }
 
+} // anonymous namespace
+
+
+/*static*/
+int wxXmlResource::DoGetXRCID(const char *str_id, int value_if_not_found)
+{
+    if ( !gs_stdIDsAdded )
+    {
+        gs_stdIDsAdded = true;
+        AddStdXRCID_Records();
+    }
+
+    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)
+{
+    if (rec)
+    {
+        CleanXRCID_Record(rec->next);
 
 
+        free(rec->key);
+        delete rec;
+    }
+}
 
 
+static void CleanXRCID_Records()
+{
+    for (int i = 0; i < XRCID_TABLE_SIZE; i++)
+    {
+        CleanXRCID_Record(XRCID_Records[i]);
+        XRCID_Records[i] = NULL;
+    }
+
+    gs_stdIDsAdded = false;
+}
 
 
 //-----------------------------------------------------------------------------
 
 
 //-----------------------------------------------------------------------------