X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/af1337b041be734b7e64bcf7a06086268ae6895e..fdf7ff738cb755be0e9e7e1378d8c3073f08f0e1:/src/xrc/xmlres.cpp diff --git a/src/xrc/xmlres.cpp b/src/xrc/xmlres.cpp index 2106d04ff7..466faa9870 100644 --- a/src/xrc/xmlres.cpp +++ b/src/xrc/xmlres.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: xmlres.cpp +// Name: src/xrc/xmlres.cpp // Purpose: XRC resources // Author: Vaclav Slavik // Created: 2000/03/05 @@ -8,10 +8,6 @@ // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "xmlres.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -19,26 +15,60 @@ #pragma hdrstop #endif -#include "wx/dialog.h" -#include "wx/panel.h" -#include "wx/frame.h" +#if wxUSE_XRC + +#include "wx/xrc/xmlres.h" + +#ifndef WX_PRECOMP + #include "wx/intl.h" + #include "wx/log.h" + #include "wx/panel.h" + #include "wx/frame.h" + #include "wx/dialog.h" + #include "wx/settings.h" + #include "wx/bitmap.h" + #include "wx/image.h" + #include "wx/module.h" + #include "wx/wxcrtvararg.h" +#endif + +#ifndef __WXWINCE__ + #include +#endif + +#include "wx/vector.h" #include "wx/wfstream.h" #include "wx/filesys.h" -#include "wx/log.h" -#include "wx/intl.h" +#include "wx/filename.h" #include "wx/tokenzr.h" #include "wx/fontenum.h" -#include "wx/module.h" -#include "wx/bitmap.h" -#include "wx/image.h" #include "wx/fontmap.h" #include "wx/artprov.h" -#include "wx/xrc/xml.h" -#include "wx/xrc/xmlres.h" +#include "wx/xml/xml.h" + + +class wxXmlResourceDataRecord +{ +public: + wxXmlResourceDataRecord() : Doc(NULL) { +#if wxUSE_DATETIME + Time = wxDateTime::Now(); +#endif + } + ~wxXmlResourceDataRecord() {delete Doc;} + + wxString File; + wxXmlDocument *Doc; +#if wxUSE_DATETIME + wxDateTime Time; +#endif +}; -#include "wx/arrimpl.cpp" -WX_DEFINE_OBJARRAY(wxXmlResourceDataRecords); +class wxXmlResourceDataRecords : public wxVector +{ + // this is a class so that it can be forward-declared +}; wxXmlResource *wxXmlResource::ms_instance = NULL; @@ -57,33 +87,86 @@ wxXmlResource *wxXmlResource::ms_instance = NULL; return old; } -wxXmlResource::wxXmlResource(int flags) +wxXmlResource::wxXmlResource(int flags, const wxString& domain) { - m_handlers.DeleteContents(TRUE); m_flags = flags; m_version = -1; + m_data = new wxXmlResourceDataRecords; + SetDomain(domain); } -wxXmlResource::wxXmlResource(const wxString& filemask, int flags) +wxXmlResource::wxXmlResource(const wxString& filemask, int flags, const wxString& domain) { m_flags = flags; m_version = -1; - m_handlers.DeleteContents(TRUE); + m_data = new wxXmlResourceDataRecords; + SetDomain(domain); Load(filemask); } wxXmlResource::~wxXmlResource() { ClearHandlers(); + + for ( wxXmlResourceDataRecords::iterator i = m_data->begin(); + i != m_data->end(); ++i ) + { + delete *i; + } + delete m_data; +} + +void wxXmlResource::SetDomain(const wxString& domain) +{ + m_domain = domain; } +/* static */ +wxString wxXmlResource::ConvertFileNameToURL(const wxString& filename) +{ + wxString fnd(filename); + + // NB: as Load() and Unload() accept both filenames and URLs (should + // probably be changed to filenames only, but embedded resources + // currently rely on its ability to handle URLs - FIXME) we need to + // determine whether found name is filename and not URL and this is the + // fastest/simplest way to do it + if (wxFileName::FileExists(fnd)) + { + // Make the name absolute filename, because the app may + // change working directory later: + wxFileName fn(fnd); + if (fn.IsRelative()) + { + fn.MakeAbsolute(); + fnd = fn.GetFullPath(); + } +#if wxUSE_FILESYSTEM + fnd = wxFileSystem::FileNameToURL(fnd); +#endif + } + + return fnd; +} + +#if wxUSE_FILESYSTEM + +/* static */ +bool wxXmlResource::IsArchive(const wxString& filename) +{ + const wxString fnd = filename.Lower(); + + return fnd.Matches(wxT("*.zip")) || fnd.Matches(wxT("*.xrs")); +} + +#endif // wxUSE_FILESYSTEM + bool wxXmlResource::Load(const wxString& filemask) { wxString fnd; - wxXmlResourceDataRecord *drec; bool iswild = wxIsWild(filemask); - bool rt = TRUE; + bool rt = true; #if wxUSE_FILESYSTEM wxFileSystem fsys; @@ -97,21 +180,21 @@ bool wxXmlResource::Load(const wxString& filemask) fnd = wxXmlFindFirst; else fnd = filemask; - while (!!fnd) + while (!fnd.empty()) { + fnd = ConvertFileNameToURL(fnd); + #if wxUSE_FILESYSTEM - if (filemask.Lower().Matches(wxT("*.zip")) || - filemask.Lower().Matches(wxT("*.xrs"))) + if ( IsArchive(fnd) ) { - rt = rt && Load(fnd + wxT("#zip:*.xmlbin")); rt = rt && Load(fnd + wxT("#zip:*.xrc")); } - else -#endif + else // a single resource URL +#endif // wxUSE_FILESYSTEM { - drec = new wxXmlResourceDataRecord; + wxXmlResourceDataRecord *drec = new wxXmlResourceDataRecord; drec->File = fnd; - m_data.Add(drec); + Data().push_back(drec); } if (iswild) @@ -121,14 +204,62 @@ bool wxXmlResource::Load(const wxString& filemask) } # undef wxXmlFindFirst # undef wxXmlFindNext - return rt; + return rt && UpdateResources(); } +bool wxXmlResource::Unload(const wxString& filename) +{ + wxASSERT_MSG( !wxIsWild(filename), + _T("wildcards not supported by wxXmlResource::Unload()") ); + wxString fnd = ConvertFileNameToURL(filename); +#if wxUSE_FILESYSTEM + const bool isArchive = IsArchive(fnd); + if ( isArchive ) + fnd += _T("#zip:"); +#endif // wxUSE_FILESYSTEM + + bool unloaded = false; + for ( wxXmlResourceDataRecords::iterator i = Data().begin(); + i != Data().end(); ++i ) + { +#if wxUSE_FILESYSTEM + if ( isArchive ) + { + if ( (*i)->File.StartsWith(fnd) ) + unloaded = true; + // don't break from the loop, we can have other matching files + } + else // a single resource URL +#endif // wxUSE_FILESYSTEM + { + if ( (*i)->File == fnd ) + { + delete *i; + Data().erase(i); + unloaded = true; + + // no sense in continuing, there is only one file with this URL + break; + } + } + } + + return unloaded; +} + + +IMPLEMENT_ABSTRACT_CLASS(wxXmlResourceHandler, wxObject) void wxXmlResource::AddHandler(wxXmlResourceHandler *handler) { - m_handlers.Append(handler); + m_handlers.push_back(handler); + handler->SetParentResource(this); +} + +void wxXmlResource::InsertHandler(wxXmlResourceHandler *handler) +{ + m_handlers.insert(m_handlers.begin(), handler); handler->SetParentResource(this); } @@ -136,11 +267,13 @@ void wxXmlResource::AddHandler(wxXmlResourceHandler *handler) void wxXmlResource::ClearHandlers() { - m_handlers.Clear(); + for ( wxVector::iterator i = m_handlers.begin(); + i != m_handlers.end(); ++i ) + delete *i; + m_handlers.clear(); } - wxMenu *wxXmlResource::LoadMenu(const wxString& name) { return (wxMenu*)CreateResFromNode(FindResource(name, wxT("wxMenu")), NULL, NULL); @@ -165,10 +298,7 @@ wxToolBar *wxXmlResource::LoadToolBar(wxWindow *parent, const wxString& name) wxDialog *wxXmlResource::LoadDialog(wxWindow *parent, const wxString& name) { - wxDialog *dialog = new wxDialog; - if (!LoadDialog(dialog, parent, name)) - { delete dialog; return NULL; } - else return dialog; + return (wxDialog*)CreateResFromNode(FindResource(name, wxT("wxDialog")), parent, NULL); } bool wxXmlResource::LoadDialog(wxDialog *dlg, wxWindow *parent, const wxString& name) @@ -188,6 +318,11 @@ bool wxXmlResource::LoadPanel(wxPanel *panel, wxWindow *parent, const wxString& return CreateResFromNode(FindResource(name, wxT("wxPanel")), parent, panel) != NULL; } +wxFrame *wxXmlResource::LoadFrame(wxWindow* parent, const wxString& name) +{ + return (wxFrame*)CreateResFromNode(FindResource(name, wxT("wxFrame")), parent, NULL); +} + bool wxXmlResource::LoadFrame(wxFrame* frame, wxWindow *parent, const wxString& name) { return CreateResFromNode(FindResource(name, wxT("wxFrame")), parent, frame) != NULL; @@ -213,6 +348,18 @@ wxIcon wxXmlResource::LoadIcon(const wxString& name) return rt; } + +wxObject *wxXmlResource::LoadObject(wxWindow *parent, const wxString& name, const wxString& classname) +{ + return CreateResFromNode(FindResource(name, classname), parent, NULL); +} + +bool wxXmlResource::LoadObject(wxObject *instance, wxWindow *parent, const wxString& name, const wxString& classname) +{ + return CreateResFromNode(FindResource(name, classname), parent, instance) != NULL; +} + + bool wxXmlResource::AttachUnknownControl(const wxString& name, wxWindow *control, wxWindow *parent) { @@ -222,7 +369,7 @@ bool wxXmlResource::AttachUnknownControl(const wxString& name, if (!container) { wxLogError(_("Cannot find container for unknown control '%s'."), name.c_str()); - return FALSE; + return false; } return control->Reparent(container); } @@ -236,29 +383,30 @@ static void ProcessPlatformProperty(wxXmlNode *node) wxXmlNode *c = node->GetChildren(); while (c) { - isok = FALSE; - if (!c->GetPropVal(wxT("platform"), &s)) - isok = TRUE; + isok = false; + if (!c->GetAttribute(wxT("platform"), &s)) + isok = true; else { - wxStringTokenizer tkn(s, " |"); + wxStringTokenizer tkn(s, wxT(" |")); while (tkn.HasMoreTokens()) { s = tkn.GetNextToken(); - if ( -#ifdef __WXMSW__ - s == wxString(wxT("win")) +#ifdef __WINDOWS__ + if (s == wxT("win")) isok = true; +#endif +#if defined(__MAC__) || defined(__APPLE__) + if (s == wxT("mac")) isok = true; #elif defined(__UNIX__) - s == wxString(wxT("unix")) -#elif defined(__MAC__) - s == wxString(wxT("mac")) -#elif defined(__OS2__) - s == wxString(wxT("os2")) -#else - FALSE + if (s == wxT("unix")) isok = true; #endif - ) isok = TRUE; +#ifdef __OS2__ + if (s == wxT("os2")) isok = true; +#endif + + if (isok) + break; } } @@ -269,8 +417,8 @@ static void ProcessPlatformProperty(wxXmlNode *node) } else { - node->RemoveChild(c); wxXmlNode *c2 = c->GetNext(); + node->RemoveChild(c); delete c; c = c2; } @@ -279,11 +427,13 @@ static void ProcessPlatformProperty(wxXmlNode *node) -void wxXmlResource::UpdateResources() +bool wxXmlResource::UpdateResources() { + bool rt = true; bool modif; # if wxUSE_FILESYSTEM wxFSFile *file = NULL; + wxUnusedVar(file); wxFileSystem fsys; # endif @@ -291,63 +441,82 @@ void wxXmlResource::UpdateResources() #if !wxUSE_UNICODE && wxUSE_INTL if ( (GetFlags() & wxXRC_USE_LOCALE) == 0 ) { - // In case we are not using wxLocale to translate strings, convert the strings - // GUI's charset. This must not be done when wxXRC_USE_LOCALE is on, because - // it could break wxGetTranslation lookup. + // In case we are not using wxLocale to translate strings, convert the + // strings GUI's charset. This must not be done when wxXRC_USE_LOCALE + // is on, because it could break wxGetTranslation lookup. encoding = wxLocale::GetSystemEncodingName(); } #endif - for (size_t i = 0; i < m_data.GetCount(); i++) + for ( wxXmlResourceDataRecords::iterator i = Data().begin(); + i != Data().end(); ++i ) { - modif = (m_data[i].Doc == NULL); + wxXmlResourceDataRecord* const rec = *i; - if (!modif) + modif = (rec->Doc == NULL); + + if (!modif && !(m_flags & wxXRC_NO_RELOADING)) { # if wxUSE_FILESYSTEM - file = fsys.OpenFile(m_data[i].File); - modif = file && file->GetModificationTime() > m_data[i].Time; + file = fsys.OpenFile(rec->File); +# if wxUSE_DATETIME + modif = file && file->GetModificationTime() > rec->Time; +# else // wxUSE_DATETIME + modif = true; +# endif // wxUSE_DATETIME if (!file) - wxLogError(_("Cannot open file '%s'."), m_data[i].File.c_str()); + { + wxLogError(_("Cannot open file '%s'."), rec->File); + rt = false; + } wxDELETE(file); -# else - modif = wxDateTime(wxFileModificationTime(m_data[i].File)) > m_data[i].Time; -# endif + wxUnusedVar(file); +# else // wxUSE_FILESYSTEM +# if wxUSE_DATETIME + modif = wxDateTime(wxFileModificationTime(rec->File)) > rec->Time; +# else // wxUSE_DATETIME + modif = true; +# endif // wxUSE_DATETIME +# endif // wxUSE_FILESYSTEM } if (modif) { + wxLogTrace(_T("xrc"), _T("opening file '%s'"), rec->File); + wxInputStream *stream = NULL; # if wxUSE_FILESYSTEM - file = fsys.OpenFile(m_data[i].File); - if (file) - stream = file->GetStream(); + file = fsys.OpenFile(rec->File); + if (file) + stream = file->GetStream(); # else - stream = new wxFileInputStream(m_data[i].File); + stream = new wxFileInputStream(rec->File); # endif if (stream) { - delete m_data[i].Doc; - m_data[i].Doc = new wxXmlDocument; + delete rec->Doc; + rec->Doc = new wxXmlDocument; } - if (!stream || !m_data[i].Doc->Load(*stream, encoding)) + if (!stream || !rec->Doc->Load(*stream, encoding)) { wxLogError(_("Cannot load resources from file '%s'."), - m_data[i].File.c_str()); - wxDELETE(m_data[i].Doc); + rec->File); + wxDELETE(rec->Doc); + rt = false; } - else if (m_data[i].Doc->GetRoot()->GetName() != wxT("resource")) + else if (rec->Doc->GetRoot()->GetName() != wxT("resource")) { - wxLogError(_("Invalid XRC resource '%s': doesn't have root node 'resource'."), m_data[i].File.c_str()); - wxDELETE(m_data[i].Doc); + wxLogError(_("Invalid XRC resource '%s': doesn't have root node 'resource'."), rec->File); + wxDELETE(rec->Doc); + rt = false; } else - { + { long version; int v1, v2, v3, v4; - wxString verstr = m_data[i].Doc->GetRoot()->GetPropVal( + wxString verstr = rec->Doc->GetRoot()->GetAttribute( wxT("version"), wxT("0.0.0.0")); if (wxSscanf(verstr.c_str(), wxT("%i.%i.%i.%i"), &v1, &v2, &v3, &v4) == 4) @@ -357,19 +526,31 @@ void wxXmlResource::UpdateResources() if (m_version == -1) m_version = version; if (m_version != version) + { wxLogError(_("Resource files must have same version number!")); + rt = false; + } - ProcessPlatformProperty(m_data[i].Doc->GetRoot()); - m_data[i].Time = file->GetModificationTime(); - } + ProcessPlatformProperty(rec->Doc->GetRoot()); +#if wxUSE_DATETIME +#if wxUSE_FILESYSTEM + rec->Time = file->GetModificationTime(); +#else // wxUSE_FILESYSTEM + rec->Time = wxDateTime(wxFileModificationTime(rec->File)); +#endif // wxUSE_FILESYSTEM +#endif // wxUSE_DATETIME + } # if wxUSE_FILESYSTEM - wxDELETE(file); + wxDELETE(file); + wxUnusedVar(file); # else - wxDELETE(stream); + wxDELETE(stream); # endif } } + + return rt; } @@ -388,10 +569,25 @@ wxXmlNode *wxXmlResource::DoFindResource(wxXmlNode *parent, if ( node->GetType() == wxXML_ELEMENT_NODE && (node->GetName() == wxT("object") || node->GetName() == wxT("object_ref")) && - (!classname || - node->GetPropVal(wxT("class"), wxEmptyString) == classname) && - node->GetPropVal(wxT("name"), &dummy) && dummy == name ) - return node; + node->GetAttribute(wxT("name"), &dummy) && dummy == name ) + { + wxString cls(node->GetAttribute(wxT("class"), wxEmptyString)); + if (!classname || cls == classname) + return node; + // object_ref may not have 'class' attribute: + if (cls.empty() && node->GetName() == wxT("object_ref")) + { + wxString refName = node->GetAttribute(wxT("ref"), wxEmptyString); + if (refName.empty()) + continue; + wxXmlNode* refNode = FindResource(refName, wxEmptyString, true); + if (refNode && + refNode->GetAttribute(wxT("class"), wxEmptyString) == classname) + { + return node; + } + } + } } if ( recursive ) @@ -401,7 +597,7 @@ wxXmlNode *wxXmlResource::DoFindResource(wxXmlNode *parent, (node->GetName() == wxT("object") || node->GetName() == wxT("object_ref")) ) { - wxXmlNode* found = DoFindResource(node, name, classname, TRUE); + wxXmlNode* found = DoFindResource(node, name, classname, true); if ( found ) return found; } @@ -417,17 +613,19 @@ wxXmlNode *wxXmlResource::FindResource(const wxString& name, UpdateResources(); //ensure everything is up-to-date wxString dummy; - for (size_t f = 0; f < m_data.GetCount(); f++) + for ( wxXmlResourceDataRecords::const_iterator f = Data().begin(); + f != Data().end(); ++f ) { - if ( m_data[f].Doc == NULL || m_data[f].Doc->GetRoot() == NULL ) + wxXmlResourceDataRecord* const rec = *f; + if ( rec->Doc == NULL || rec->Doc->GetRoot() == NULL ) continue; - wxXmlNode* found = DoFindResource(m_data[f].Doc->GetRoot(), + wxXmlNode* found = DoFindResource(rec->Doc->GetRoot(), name, classname, recursive); if ( found ) { #if wxUSE_FILESYSTEM - m_curFileSystem.ChangePathTo(m_data[f].File); + m_curFileSystem.ChangePathTo(rec->File); #endif return found; } @@ -440,34 +638,35 @@ wxXmlNode *wxXmlResource::FindResource(const wxString& name, static void MergeNodes(wxXmlNode& dest, wxXmlNode& with) { - // Merge properties: - for (wxXmlProperty *prop = with.GetProperties(); prop; prop = prop->GetNext()) + // Merge attributes: + for ( wxXmlAttribute *attr = with.GetAttributes(); + attr; attr = attr->GetNext() ) { - wxXmlProperty *dprop; - for (dprop = dest.GetProperties(); dprop; dprop = dprop->GetNext()) + wxXmlAttribute *dattr; + for (dattr = dest.GetAttributes(); dattr; dattr = dattr->GetNext()) { - if ( dprop->GetName() == prop->GetName() ) + if ( dattr->GetName() == attr->GetName() ) { - dprop->SetValue(prop->GetValue()); + dattr->SetValue(attr->GetValue()); break; } } - if ( !dprop ) - dest.AddProperty(prop->GetName(), prop->GetValue()); + if ( !dattr ) + dest.AddAttribute(attr->GetName(), attr->GetValue()); } // Merge child nodes: for (wxXmlNode* node = with.GetChildren(); node; node = node->GetNext()) { - wxString name = node->GetPropVal(wxT("name"), wxEmptyString); + wxString name = node->GetAttribute(wxT("name"), wxEmptyString); wxXmlNode *dnode; for (dnode = dest.GetChildren(); dnode; dnode = dnode->GetNext() ) { if ( dnode->GetName() == node->GetName() && - dnode->GetPropVal("name", wxEmptyString) == name && + dnode->GetAttribute(wxT("name"), wxEmptyString) == name && dnode->GetType() == node->GetType() ) { MergeNodes(*dnode, *node); @@ -476,22 +675,35 @@ static void MergeNodes(wxXmlNode& dest, wxXmlNode& with) } if ( !dnode ) - dest.AddChild(new wxXmlNode(*node)); + { + static const wxChar *AT_END = wxT("end"); + wxString insert_pos = node->GetAttribute(wxT("insert_at"), AT_END); + if ( insert_pos == AT_END ) + { + dest.AddChild(new wxXmlNode(*node)); + } + else if ( insert_pos == wxT("begin") ) + { + dest.InsertChild(new wxXmlNode(*node), dest.GetChildren()); + } + } } - if ( dest.GetType() == wxXML_TEXT_NODE && with.GetContent().Length() ) + if ( dest.GetType() == wxXML_TEXT_NODE && with.GetContent().length() ) dest.SetContent(with.GetContent()); } -wxObject *wxXmlResource::CreateResFromNode(wxXmlNode *node, wxObject *parent, wxObject *instance) +wxObject *wxXmlResource::CreateResFromNode(wxXmlNode *node, wxObject *parent, + wxObject *instance, + wxXmlResourceHandler *handlerToUse) { if (node == NULL) return NULL; // handling of referenced resource if ( node->GetName() == wxT("object_ref") ) { - wxString refName = node->GetPropVal(wxT("ref"), wxEmptyString); - wxXmlNode* refNode = FindResource(refName, wxEmptyString, TRUE); + wxString refName = node->GetAttribute(wxT("ref"), wxEmptyString); + wxXmlNode* refNode = FindResource(refName, wxEmptyString, true); if ( !refNode ) { @@ -506,32 +718,69 @@ wxObject *wxXmlResource::CreateResFromNode(wxXmlNode *node, wxObject *parent, wx return CreateResFromNode(©, parent, instance); } - wxXmlResourceHandler *handler; - wxObject *ret; - wxNode * ND = m_handlers.GetFirst(); - while (ND) + if (handlerToUse) + { + if (handlerToUse->CanHandle(node)) + { + return handlerToUse->CreateResource(node, parent, instance); + } + } + else if (node->GetName() == wxT("object")) { - handler = (wxXmlResourceHandler*)ND->GetData(); - if (node->GetName() == wxT("object") && handler->CanHandle(node)) + for ( wxVector::iterator h = m_handlers.begin(); + h != m_handlers.end(); ++h ) { - ret = handler->CreateResource(node, parent, instance); - if (ret) return ret; + wxXmlResourceHandler *handler = *h; + if (handler->CanHandle(node)) + return handler->CreateResource(node, parent, instance); } - ND = ND->GetNext(); } wxLogError(_("No handler found for XML node '%s', class '%s'!"), node->GetName().c_str(), - node->GetPropVal(wxT("class"), wxEmptyString).c_str()); + node->GetAttribute(wxT("class"), wxEmptyString).c_str()); return NULL; } +class wxXmlSubclassFactories : public wxVector +{ + // 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; + } +}; + + wxXmlResourceHandler::wxXmlResourceHandler() : m_node(NULL), m_parent(NULL), m_instance(NULL), - m_parentAsWindow(NULL), m_instanceAsWindow(NULL) + m_parentAsWindow(NULL) {} @@ -541,39 +790,43 @@ wxObject *wxXmlResourceHandler::CreateResource(wxXmlNode *node, wxObject *parent wxXmlNode *myNode = m_node; wxString myClass = m_class; wxObject *myParent = m_parent, *myInstance = m_instance; - wxWindow *myParentAW = m_parentAsWindow, *myInstanceAW = m_instanceAsWindow; + wxWindow *myParentAW = m_parentAsWindow; m_instance = instance; - if (!m_instance && node->HasProp(wxT("subclass")) && + if (!m_instance && node->HasAttribute(wxT("subclass")) && !(m_resource->GetFlags() & wxXRC_NO_SUBCLASSING)) { - wxString subclass = node->GetPropVal(wxT("subclass"), wxEmptyString); - wxClassInfo* classInfo = wxClassInfo::FindClass(subclass); - - if (classInfo) - m_instance = classInfo->CreateObject(); - - if (!m_instance) + wxString subclass = node->GetAttribute(wxT("subclass"), wxEmptyString); + if (!subclass.empty()) { - wxLogError(_("Subclass '%s' not found for resource '%s', not subclassing!"), - subclass.c_str(), node->GetPropVal(wxT("name"), wxEmptyString).c_str()); - } + for (wxXmlSubclassFactories::iterator i = wxXmlResource::ms_subclassFactories->begin(); + i != wxXmlResource::ms_subclassFactories->end(); ++i) + { + m_instance = (*i)->Create(subclass); + if (m_instance) + break; + } - m_instance = classInfo->CreateObject(); + if (!m_instance) + { + wxString name = node->GetAttribute(wxT("name"), wxEmptyString); + wxLogError(_("Subclass '%s' not found for resource '%s', not subclassing!"), + subclass.c_str(), name.c_str()); + } + } } m_node = node; - m_class = node->GetPropVal(wxT("class"), wxEmptyString); + m_class = node->GetAttribute(wxT("class"), wxEmptyString); m_parent = parent; m_parentAsWindow = wxDynamicCast(m_parent, wxWindow); - m_instanceAsWindow = wxDynamicCast(m_instance, wxWindow); wxObject *returned = DoCreateResource(); m_node = myNode; m_class = myClass; m_parent = myParent; m_parentAsWindow = myParentAW; - m_instance = myInstance; m_instanceAsWindow = myInstanceAW; + m_instance = myInstance; return returned; } @@ -589,15 +842,24 @@ void wxXmlResourceHandler::AddStyle(const wxString& name, int value) void wxXmlResourceHandler::AddWindowStyles() { - XRC_ADD_STYLE(wxSIMPLE_BORDER); - XRC_ADD_STYLE(wxSUNKEN_BORDER); - XRC_ADD_STYLE(wxDOUBLE_BORDER); - XRC_ADD_STYLE(wxRAISED_BORDER); - XRC_ADD_STYLE(wxSTATIC_BORDER); - XRC_ADD_STYLE(wxNO_BORDER); + XRC_ADD_STYLE(wxCLIP_CHILDREN); + + // 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(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(wxTRANSPARENT_WINDOW); XRC_ADD_STYLE(wxWANTS_CHARS); + XRC_ADD_STYLE(wxTAB_TRAVERSAL); XRC_ADD_STYLE(wxNO_FULL_REPAINT_ON_RESIZE); + XRC_ADD_STYLE(wxFULL_REPAINT_ON_RESIZE); + XRC_ADD_STYLE(wxALWAYS_SHOW_SB); + XRC_ADD_STYLE(wxWS_EX_BLOCK_EVENTS); + XRC_ADD_STYLE(wxWS_EX_VALIDATE_RECURSIVELY); } @@ -614,7 +876,7 @@ int wxXmlResourceHandler::GetStyle(const wxString& param, int defaults) if (!s) return defaults; - wxStringTokenizer tkn(s, wxT("| "), wxTOKEN_STRTOK); + wxStringTokenizer tkn(s, wxT("| \t\n"), wxTOKEN_STRTOK); int style = 0; int index; wxString fl; @@ -634,7 +896,8 @@ int wxXmlResourceHandler::GetStyle(const wxString& param, int defaults) wxString wxXmlResourceHandler::GetText(const wxString& param, bool translate) { - wxString str1(GetParamValue(param)); + wxXmlNode *parNode = GetParamNode(param); + wxString str1(GetNodeContent(parNode)); wxString str2; const wxChar *dt; wxChar amp_char; @@ -658,23 +921,61 @@ wxString wxXmlResourceHandler::GetText(const wxString& param, bool translate) else str2 << wxT('&') << *dt; } - // Remap \n to CR, \r to LF, \t to TAB: + // Remap \n to CR, \r to LF, \t to TAB, \\ to \: else if (*dt == wxT('\\')) switch (*(++dt)) { - case wxT('n') : str2 << wxT('\n'); break; - case wxT('t') : str2 << wxT('\t'); break; - case wxT('r') : str2 << wxT('\r'); break; - default : str2 << wxT('\\') << *dt; break; + case wxT('n'): + str2 << wxT('\n'); + break; + + case wxT('t'): + str2 << wxT('\t'); + break; + + case wxT('r'): + str2 << wxT('\r'); + break; + + case wxT('\\') : + // "\\" wasn't translated to "\" prior to 2.5.3.0: + if (m_resource->CompareVersion(2,5,3,0) >= 0) + { + str2 << wxT('\\'); + break; + } + // else fall-through to default: branch below + + default: + str2 << wxT('\\') << *dt; + break; } else str2 << *dt; } - if (translate && m_resource->GetFlags() & wxXRC_USE_LOCALE) - return wxGetTranslation(str2); - else - return str2; + if (m_resource->GetFlags() & wxXRC_USE_LOCALE) + { + if (translate && parNode && + parNode->GetAttribute(wxT("translate"), wxEmptyString) != wxT("0")) + { + return wxGetTranslation(str2, m_resource->GetDomain()); + } + else + { +#if wxUSE_UNICODE + return str2; +#else + // The string is internally stored as UTF-8, we have to convert + // it into system's default encoding so that it can be displayed: + return wxString(str2.wc_str(wxConvUTF8), wxConvLocal); +#endif + } + } + // If wxXRC_USE_LOCALE is not set, then the string is already in + // system's default encoding in ANSI build, so we don't have to + // do anything special here. + return str2; } @@ -690,99 +991,36 @@ long wxXmlResourceHandler::GetLong(const wxString& param, long defaultv) return value; } - - -int wxXmlResourceHandler::GetID() -{ - wxString sid = GetName(); - long num; - - if (sid == wxT("-1")) return -1; - else if (sid.IsNumber() && sid.ToLong(&num)) return num; -#define stdID(id) else if (sid == wxT(#id)) return id - stdID(wxID_OPEN); stdID(wxID_CLOSE); stdID(wxID_NEW); - stdID(wxID_SAVE); stdID(wxID_SAVEAS); stdID(wxID_REVERT); - stdID(wxID_EXIT); stdID(wxID_UNDO); stdID(wxID_REDO); - stdID(wxID_HELP); stdID(wxID_PRINT); stdID(wxID_PRINT_SETUP); - stdID(wxID_PREVIEW); stdID(wxID_ABOUT); stdID(wxID_HELP_CONTENTS); - stdID(wxID_HELP_COMMANDS); stdID(wxID_HELP_PROCEDURES); - stdID(wxID_CUT); stdID(wxID_COPY); stdID(wxID_PASTE); - stdID(wxID_CLEAR); stdID(wxID_FIND); stdID(wxID_DUPLICATE); - stdID(wxID_SELECTALL); stdID(wxID_OK); stdID(wxID_CANCEL); - stdID(wxID_APPLY); stdID(wxID_YES); stdID(wxID_NO); - stdID(wxID_STATIC); stdID(wxID_FORWARD); stdID(wxID_BACKWARD); - stdID(wxID_DEFAULT); stdID(wxID_MORE); stdID(wxID_SETUP); - stdID(wxID_RESET); stdID(wxID_HELP_CONTEXT); -#undef stdID - else return wxXmlResource::GetXRCID(sid); -} - - - -wxArtID wxXmlResourceHandler::GetStockID(const wxString& param) +float wxXmlResourceHandler::GetFloat(const wxString& param, float defaultv) { - wxXmlNode *stockIDNode = GetParamNode(param); - if (stockIDNode == NULL) - return wxEmptyString; - - wxXmlNode *oldnode = m_node; - m_node = stockIDNode; - - wxArtID sid = m_node->GetPropVal(wxT("stock_id"), wxT("")); - - m_node = oldnode; + wxString str = GetParamValue(param); + + // 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 + // + // TODO: use wxString::ToCDouble() when we have it + str.Replace(wxT("."), wxLocale::GetInfo(wxLOCALE_DECIMAL_POINT, + wxLOCALE_CAT_NUMBER)); + + double value; + if (!str.ToDouble(&value)) + value = defaultv; - if (sid.IsEmpty()) return wxEmptyString; -#define stdID(id) else if (sid == wxT(#id)) return id - stdID(wxART_ADD_BOOKMARK); stdID(wxART_DEL_BOOKMARK); - stdID(wxART_HELP_SIDE_PANEL); stdID(wxART_HELP_SETTINGS); - stdID(wxART_HELP_BOOK); stdID(wxART_HELP_FOLDER); - stdID(wxART_HELP_PAGE); stdID(wxART_GO_BACK); - stdID(wxART_GO_FORWARD); stdID(wxART_GO_UP); - stdID(wxART_GO_DOWN); stdID(wxART_GO_TO_PARENT); - stdID(wxART_GO_HOME); stdID(wxART_FILE_OPEN); - stdID(wxART_PRINT); stdID(wxART_HELP); stdID(wxART_TIP); - stdID(wxART_REPORT_VIEW); stdID(wxART_LIST_VIEW); - stdID(wxART_NEW_DIR); stdID(wxART_FOLDER); - stdID(wxART_GO_DIR_UP); stdID(wxART_EXECUTABLE_FILE); - stdID(wxART_NORMAL_FILE); stdID(wxART_TICK_MARK); - stdID(wxART_CROSS_MARK); stdID(wxART_ERROR); - stdID(wxART_QUESTION); stdID(wxART_WARNING); - stdID(wxART_INFORMATION); -#undef stdID - else return sid; + return wx_truncate_cast(float, value); } - -wxArtClient wxXmlResourceHandler::GetStockClient(const wxString& param) +int wxXmlResourceHandler::GetID() { - wxXmlNode *stockClientNode = GetParamNode(param); - if (stockClientNode == NULL) - return wxEmptyString; - - wxXmlNode *oldnode = m_node; - m_node = stockClientNode; - - wxArtClient sid = m_node->GetPropVal(wxT("stock_client"), wxT("wxART_OTHER")); - - m_node = oldnode; - - if (sid.IsEmpty()) return wxEmptyString; -#define stdID(id) else if (sid == wxT(#id)) return id - stdID(wxART_TOOLBAR); stdID(wxART_MENU); - stdID(wxART_FRAME_ICON); stdID(wxART_CMN_DIALOG); - stdID(wxART_HELP_BROWSER); stdID(wxART_MESSAGE_BOX); - stdID(wxART_OTHER); -#undef stdID - else return sid; + return wxXmlResource::GetXRCID(GetName()); } wxString wxXmlResourceHandler::GetName() { - return m_node->GetPropVal(wxT("name"), wxT("-1")); + return m_node->GetAttribute(wxT("name"), wxT("-1")); } @@ -792,80 +1030,181 @@ bool wxXmlResourceHandler::GetBool(const wxString& param, bool defaultv) wxString v = GetParamValue(param); v.MakeLower(); if (!v) return defaultv; - else return (v == wxT("1")); + + return (v == wxT("1")); } +static wxColour GetSystemColour(const wxString& name) +{ + if (!name.empty()) + { + #define SYSCLR(clr) \ + if (name == _T(#clr)) return wxSystemSettings::GetColour(clr); + SYSCLR(wxSYS_COLOUR_SCROLLBAR) + SYSCLR(wxSYS_COLOUR_BACKGROUND) + SYSCLR(wxSYS_COLOUR_DESKTOP) + SYSCLR(wxSYS_COLOUR_ACTIVECAPTION) + SYSCLR(wxSYS_COLOUR_INACTIVECAPTION) + SYSCLR(wxSYS_COLOUR_MENU) + SYSCLR(wxSYS_COLOUR_WINDOW) + SYSCLR(wxSYS_COLOUR_WINDOWFRAME) + SYSCLR(wxSYS_COLOUR_MENUTEXT) + SYSCLR(wxSYS_COLOUR_WINDOWTEXT) + SYSCLR(wxSYS_COLOUR_CAPTIONTEXT) + SYSCLR(wxSYS_COLOUR_ACTIVEBORDER) + SYSCLR(wxSYS_COLOUR_INACTIVEBORDER) + SYSCLR(wxSYS_COLOUR_APPWORKSPACE) + SYSCLR(wxSYS_COLOUR_HIGHLIGHT) + SYSCLR(wxSYS_COLOUR_HIGHLIGHTTEXT) + SYSCLR(wxSYS_COLOUR_BTNFACE) + SYSCLR(wxSYS_COLOUR_3DFACE) + SYSCLR(wxSYS_COLOUR_BTNSHADOW) + SYSCLR(wxSYS_COLOUR_3DSHADOW) + SYSCLR(wxSYS_COLOUR_GRAYTEXT) + SYSCLR(wxSYS_COLOUR_BTNTEXT) + SYSCLR(wxSYS_COLOUR_INACTIVECAPTIONTEXT) + SYSCLR(wxSYS_COLOUR_BTNHIGHLIGHT) + SYSCLR(wxSYS_COLOUR_BTNHILIGHT) + SYSCLR(wxSYS_COLOUR_3DHIGHLIGHT) + SYSCLR(wxSYS_COLOUR_3DHILIGHT) + SYSCLR(wxSYS_COLOUR_3DDKSHADOW) + SYSCLR(wxSYS_COLOUR_3DLIGHT) + SYSCLR(wxSYS_COLOUR_INFOTEXT) + SYSCLR(wxSYS_COLOUR_INFOBK) + SYSCLR(wxSYS_COLOUR_LISTBOX) + SYSCLR(wxSYS_COLOUR_HOTLIGHT) + SYSCLR(wxSYS_COLOUR_GRADIENTACTIVECAPTION) + SYSCLR(wxSYS_COLOUR_GRADIENTINACTIVECAPTION) + SYSCLR(wxSYS_COLOUR_MENUHILIGHT) + SYSCLR(wxSYS_COLOUR_MENUBAR) + #undef SYSCLR + } + + return wxNullColour; +} -wxColour wxXmlResourceHandler::GetColour(const wxString& param) +wxColour wxXmlResourceHandler::GetColour(const wxString& param, const wxColour& defaultv) { wxString v = GetParamValue(param); - unsigned long tmp = 0; - if (v.Length() != 7 || v[0u] != wxT('#') || - wxSscanf(v.c_str(), wxT("#%lX"), &tmp) != 1) + if ( v.empty() ) + return defaultv; + + wxColour clr; + + // wxString -> wxColour conversion + if (!clr.Set(v)) { - wxLogError(_("XRC resource: Incorrect colour specification '%s' for property '%s'."), + // the colour doesn't use #RRGGBB format, check if it is symbolic + // colour name: + clr = GetSystemColour(v); + if (clr.Ok()) + return clr; + + wxLogError(_("XRC resource: Incorrect colour specification '%s' for attribute '%s'."), v.c_str(), param.c_str()); return wxNullColour; } - return wxColour((unsigned char) ((tmp & 0xFF0000) >> 16) , - (unsigned char) ((tmp & 0x00FF00) >> 8), - (unsigned char) ((tmp & 0x0000FF))); + return clr; } -wxBitmap wxXmlResourceHandler::GetBitmap(const wxString& param, wxSize size) +wxBitmap wxXmlResourceHandler::GetBitmap(const wxString& param, + const wxArtClient& defaultArtClient, + wxSize size) { - wxString stk = param; - if (!GetStockID(stk).IsEmpty()) + /* If the bitmap is specified as stock item, query wxArtProvider for it: */ + wxXmlNode *bmpNode = GetParamNode(param); + if ( bmpNode ) { - wxBitmap stockArt = wxArtProvider::GetBitmap(GetStockID(stk), - GetStockClient(stk), size); - if (stockArt != wxNullBitmap) - return stockArt; + wxString sid = bmpNode->GetAttribute(wxT("stock_id"), wxEmptyString); + if ( !sid.empty() ) + { + wxString scl = bmpNode->GetAttribute(wxT("stock_client"), wxEmptyString); + if (scl.empty()) + scl = defaultArtClient; + else + scl = wxART_MAKE_CLIENT_ID_FROM_STR(scl); + + wxBitmap stockArt = + wxArtProvider::GetBitmap(wxART_MAKE_ART_ID_FROM_STR(sid), + scl, size); + if ( stockArt.Ok() ) + return stockArt; + } } + /* ...or load the bitmap from file: */ wxString name = GetParamValue(param); - if (name.IsEmpty()) return wxNullBitmap; + if (name.empty()) return wxNullBitmap; #if wxUSE_FILESYSTEM - wxFSFile *fsfile = GetCurFileSystem().OpenFile(name); + wxFSFile *fsfile = GetCurFileSystem().OpenFile(name, wxFS_READ | wxFS_SEEKABLE); if (fsfile == NULL) { - wxLogError(_("XRC resource: Cannot create bitmap from '%s'."), param.c_str()); + wxLogError(_("XRC resource: Cannot create bitmap from '%s'."), + name.c_str()); return wxNullBitmap; } wxImage img(*(fsfile->GetStream())); delete fsfile; #else - wxImage img(GetParamValue(wxT("bitmap"))); + wxImage img(name); #endif if (!img.Ok()) { - wxLogError(_("XRC resource: Cannot create bitmap from '%s'."), param.c_str()); + wxLogError(_("XRC resource: Cannot create bitmap from '%s'."), + name.c_str()); return wxNullBitmap; } if (!(size == wxDefaultSize)) img.Rescale(size.x, size.y); 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, wxSize size) +wxIcon wxXmlResourceHandler::GetIcon(const wxString& param, + const wxArtClient& defaultArtClient, + wxSize size) { -#if wxCHECK_VERSION(2,3,0) || defined(__WXMSW__) wxIcon icon; - icon.CopyFromBitmap(GetBitmap(param, size)); -#else - wxIcon *iconpt; - wxBitmap bmppt = GetBitmap(param, size); - iconpt = (wxIcon*)(&bmppt); - wxIcon icon(*iconpt); -#endif + icon.CopyFromBitmap(GetBitmap(param, defaultArtClient, size)); return icon; } @@ -873,6 +1212,8 @@ wxIcon wxXmlResourceHandler::GetIcon(const wxString& param, wxSize size) wxXmlNode *wxXmlResourceHandler::GetParamNode(const wxString& param) { + wxCHECK_MSG(m_node, NULL, wxT("You can't access handler data before it was initialized!")); + wxXmlNode *n = m_node->GetChildren(); while (n) @@ -885,6 +1226,14 @@ wxXmlNode *wxXmlResourceHandler::GetParamNode(const wxString& param) } + +bool wxXmlResourceHandler::IsOfClass(wxXmlNode *node, const wxString& classname) +{ + return node->GetAttribute(wxT("class"), wxEmptyString) == classname; +} + + + wxString wxXmlResourceHandler::GetNodeContent(wxXmlNode *node) { wxXmlNode *n = node; @@ -905,7 +1254,7 @@ wxString wxXmlResourceHandler::GetNodeContent(wxXmlNode *node) wxString wxXmlResourceHandler::GetParamValue(const wxString& param) { - if (param.IsEmpty()) + if (param.empty()) return GetNodeContent(m_node); else return GetNodeContent(GetParamNode(param)); @@ -913,14 +1262,15 @@ wxString wxXmlResourceHandler::GetParamValue(const wxString& param) -wxSize wxXmlResourceHandler::GetSize(const wxString& param) +wxSize wxXmlResourceHandler::GetSize(const wxString& param, + wxWindow *windowToUse) { wxString s = GetParamValue(param); - if (s.IsEmpty()) s = wxT("-1,-1"); + if (s.empty()) s = wxT("-1,-1"); bool is_dlg; - long sx, sy; + long sx, sy = 0; - is_dlg = s[s.Length()-1] == wxT('d'); + is_dlg = s[s.length()-1] == wxT('d'); if (is_dlg) s.RemoveLast(); if (!s.BeforeFirst(wxT(',')).ToLong(&sx) || @@ -932,17 +1282,22 @@ wxSize wxXmlResourceHandler::GetSize(const wxString& param) if (is_dlg) { - if (m_instanceAsWindow) - return wxDLG_UNIT(m_instanceAsWindow, wxSize(sx, sy)); + if (windowToUse) + { + return wxDLG_UNIT(windowToUse, wxSize(sx, sy)); + } else if (m_parentAsWindow) + { return wxDLG_UNIT(m_parentAsWindow, wxSize(sx, sy)); + } else { wxLogError(_("Cannot convert dialog units: dialog unknown.")); return wxDefaultSize; } } - else return wxSize(sx, sy); + + return wxSize(sx, sy); } @@ -955,14 +1310,16 @@ wxPoint wxXmlResourceHandler::GetPosition(const wxString& param) -wxCoord wxXmlResourceHandler::GetDimension(const wxString& param, wxCoord defaultv) +wxCoord wxXmlResourceHandler::GetDimension(const wxString& param, + wxCoord defaultv, + wxWindow *windowToUse) { wxString s = GetParamValue(param); - if (s.IsEmpty()) return defaultv; + if (s.empty()) return defaultv; bool is_dlg; long sx; - is_dlg = s[s.Length()-1] == wxT('d'); + is_dlg = s[s.length()-1] == wxT('d'); if (is_dlg) s.RemoveLast(); if (!s.ToLong(&sx)) @@ -973,20 +1330,45 @@ wxCoord wxXmlResourceHandler::GetDimension(const wxString& param, wxCoord defaul if (is_dlg) { - if (m_instanceAsWindow) - return wxDLG_UNIT(m_instanceAsWindow, wxSize(sx, 0)).x; + if (windowToUse) + { + return wxDLG_UNIT(windowToUse, wxSize(sx, 0)).x; + } else if (m_parentAsWindow) + { return wxDLG_UNIT(m_parentAsWindow, wxSize(sx, 0)).x; + } else { wxLogError(_("Cannot convert dialog units: dialog unknown.")); return defaultv; } } - else return sx; + + return sx; } +// Get system font index using indexname +static wxFont GetSystemFont(const wxString& name) +{ + if (!name.empty()) + { + #define SYSFNT(fnt) \ + if (name == _T(#fnt)) return wxSystemSettings::GetFont(fnt); + SYSFNT(wxSYS_OEM_FIXED_FONT) + SYSFNT(wxSYS_ANSI_FIXED_FONT) + SYSFNT(wxSYS_ANSI_VAR_FONT) + SYSFNT(wxSYS_SYSTEM_FONT) + SYSFNT(wxSYS_DEVICE_DEFAULT_FONT) + SYSFNT(wxSYS_DEFAULT_PALETTE) + SYSFNT(wxSYS_SYSTEM_FIXED_FONT) + SYSFNT(wxSYS_DEFAULT_GUI_FONT) + #undef SYSFNT + } + + return wxNullFont; +} wxFont wxXmlResourceHandler::GetFont(const wxString& param) { @@ -1000,52 +1382,120 @@ wxFont wxXmlResourceHandler::GetFont(const wxString& param) wxXmlNode *oldnode = m_node; m_node = font_node; - long size = GetLong(wxT("size"), 12); + // font attributes: + + // size + int isize = -1; + bool hasSize = HasParam(wxT("size")); + if (hasSize) + isize = GetLong(wxT("size"), -1); + + // style + int istyle = wxNORMAL; + bool hasStyle = HasParam(wxT("style")); + if (hasStyle) + { + wxString style = GetParamValue(wxT("style")); + if (style == wxT("italic")) + istyle = wxITALIC; + else if (style == wxT("slant")) + istyle = wxSLANT; + } + + // weight + int iweight = wxNORMAL; + bool hasWeight = HasParam(wxT("weight")); + if (hasWeight) + { + wxString weight = GetParamValue(wxT("weight")); + if (weight == wxT("bold")) + iweight = wxBOLD; + else if (weight == wxT("light")) + iweight = wxLIGHT; + } - wxString style = GetParamValue(wxT("style")); - wxString weight = GetParamValue(wxT("weight")); - int istyle = wxNORMAL, iweight = wxNORMAL; - if (style == wxT("italic")) istyle = wxITALIC; - else if (style == wxT("slant")) istyle = wxSLANT; - if (weight == wxT("bold")) iweight = wxBOLD; - else if (weight == wxT("light")) iweight = wxLIGHT; + // underline + bool hasUnderlined = HasParam(wxT("underlined")); + bool underlined = hasUnderlined ? GetBool(wxT("underlined"), false) : false; - wxString family = GetParamValue(wxT("family")); + // family and facename int ifamily = wxDEFAULT; - if (family == wxT("decorative")) ifamily = wxDECORATIVE; - else if (family == wxT("roman")) ifamily = wxROMAN; - else if (family == wxT("script")) ifamily = wxSCRIPT; - else if (family == wxT("swiss")) ifamily = wxSWISS; - else if (family == wxT("modern")) ifamily = wxMODERN; + bool hasFamily = HasParam(wxT("family")); + if (hasFamily) + { + wxString family = GetParamValue(wxT("family")); + if (family == wxT("decorative")) ifamily = wxDECORATIVE; + else if (family == wxT("roman")) ifamily = wxROMAN; + else if (family == wxT("script")) ifamily = wxSCRIPT; + else if (family == wxT("swiss")) ifamily = wxSWISS; + else if (family == wxT("modern")) ifamily = wxMODERN; + else if (family == wxT("teletype")) ifamily = wxTELETYPE; + } - bool underlined = GetBool(wxT("underlined"), FALSE); - wxString encoding = GetParamValue(wxT("encoding")); - wxFontMapper mapper; - wxFontEncoding enc = wxFONTENCODING_DEFAULT; - if (!encoding.IsEmpty()) - enc = mapper.CharsetToEncoding(encoding); - if (enc == wxFONTENCODING_SYSTEM) - enc = wxFONTENCODING_DEFAULT; - - wxString faces = GetParamValue(wxT("face")); - wxString facename = wxEmptyString; - wxFontEnumerator enu; - enu.EnumerateFacenames(); - wxStringTokenizer tk(faces, wxT(",")); - while (tk.HasMoreTokens()) + wxString facename; + bool hasFacename = HasParam(wxT("face")); + if (hasFacename) { - int index = enu.GetFacenames()->Index(tk.GetNextToken(), FALSE); - if (index != wxNOT_FOUND) + wxString faces = GetParamValue(wxT("face")); + wxArrayString facenames(wxFontEnumerator::GetFacenames()); + wxStringTokenizer tk(faces, wxT(",")); + while (tk.HasMoreTokens()) { - facename = (*enu.GetFacenames())[index]; - break; + int index = facenames.Index(tk.GetNextToken(), false); + if (index != wxNOT_FOUND) + { + facename = facenames[index]; + break; + } } } - m_node = oldnode; + // encoding + wxFontEncoding enc = wxFONTENCODING_DEFAULT; + bool hasEncoding = HasParam(wxT("encoding")); + if (hasEncoding) + { + wxString encoding = GetParamValue(wxT("encoding")); + wxFontMapper mapper; + if (!encoding.empty()) + enc = mapper.CharsetToEncoding(encoding); + if (enc == wxFONTENCODING_SYSTEM) + enc = wxFONTENCODING_DEFAULT; + } + + // is this font based on a system font? + wxFont font = GetSystemFont(GetParamValue(wxT("sysfont"))); - wxFont font(size, ifamily, istyle, iweight, underlined, facename, enc); + if (font.Ok()) + { + if (hasSize && isize != -1) + font.SetPointSize(isize); + else if (HasParam(wxT("relativesize"))) + font.SetPointSize(int(font.GetPointSize() * + GetFloat(wxT("relativesize")))); + + if (hasStyle) + font.SetStyle(istyle); + if (hasWeight) + font.SetWeight(iweight); + if (hasUnderlined) + font.SetUnderlined(underlined); + if (hasFamily) + font.SetFamily(ifamily); + if (hasFacename) + font.SetFaceName(facename); + if (hasEncoding) + font.SetDefaultEncoding(enc); + } + else // not based on system font + { + font = wxFont(isize == -1 ? wxNORMAL_FONT->GetPointSize() : isize, + ifamily, istyle, iweight, + underlined, facename, enc); + } + + m_node = oldnode; return font; } @@ -1055,23 +1505,28 @@ void wxXmlResourceHandler::SetupWindow(wxWindow *wnd) //FIXME : add cursor if (HasParam(wxT("exstyle"))) - wnd->SetExtraStyle(GetStyle(wxT("exstyle"))); + // Have to OR it with existing style, since + // some implementations (e.g. wxGTK) use the extra style + // during creation + wnd->SetExtraStyle(wnd->GetExtraStyle() | GetStyle(wxT("exstyle"))); if (HasParam(wxT("bg"))) wnd->SetBackgroundColour(GetColour(wxT("bg"))); if (HasParam(wxT("fg"))) wnd->SetForegroundColour(GetColour(wxT("fg"))); if (GetBool(wxT("enabled"), 1) == 0) - wnd->Enable(FALSE); + wnd->Enable(false); if (GetBool(wxT("focused"), 0) == 1) wnd->SetFocus(); if (GetBool(wxT("hidden"), 0) == 1) - wnd->Show(FALSE); + wnd->Show(false); #if wxUSE_TOOLTIPS if (HasParam(wxT("tooltip"))) wnd->SetToolTip(GetText(wxT("tooltip"))); #endif if (HasParam(wxT("font"))) wnd->SetFont(GetFont()); + if (HasParam(wxT("help"))) + wnd->SetHelpText(GetText(wxT("help"))); } @@ -1082,12 +1537,10 @@ void wxXmlResourceHandler::CreateChildren(wxObject *parent, bool this_hnd_only) while (n) { if (n->GetType() == wxXML_ELEMENT_NODE && - n->GetName() == wxT("object")) + (n->GetName() == wxT("object") || n->GetName() == wxT("object_ref"))) { - if (this_hnd_only && CanHandle(n)) - CreateResource(n, parent, NULL); - else - m_resource->CreateResFromNode(n, parent, NULL); + m_resource->CreateResFromNode(n, parent, NULL, + this_hnd_only ? this : NULL); } n = n->GetNext(); } @@ -1123,50 +1576,82 @@ void wxXmlResourceHandler::CreateChildrenPrivately(wxObject *parent, wxXmlNode * struct XRCID_record { - int id; - wxChar *key; + /* Hold the id so that once an id is allocated for a name, it + does not get created again by NewControlId at least + until we are done with it */ + wxWindowIDRef id; + char *key; XRCID_record *next; }; static XRCID_record *XRCID_Records[XRCID_TABLE_SIZE] = {NULL}; -/*static*/ int wxXmlResource::GetXRCID(const wxChar *str_id) +static int XRCID_Lookup(const char *str_id, int value_if_not_found = wxID_NONE) { - static int XRCID_LastID = wxID_HIGHEST; - int index = 0; - for (const wxChar *c = str_id; *c != wxT('\0'); c++) index += (int)*c; + for (const char *c = str_id; *c != '\0'; c++) index += (int)*c; index %= XRCID_TABLE_SIZE; XRCID_record *oldrec = NULL; - int matchcnt = 0; for (XRCID_record *rec = XRCID_Records[index]; rec; rec = rec->next) { if (wxStrcmp(rec->key, str_id) == 0) { return rec->id; } - matchcnt++; oldrec = rec; } XRCID_record **rec_var = (oldrec == NULL) ? &XRCID_Records[index] : &oldrec->next; *rec_var = new XRCID_record; - (*rec_var)->id = ++XRCID_LastID; (*rec_var)->key = wxStrdup(str_id); (*rec_var)->next = NULL; + char *end; + if (value_if_not_found != wxID_NONE) + (*rec_var)->id = value_if_not_found; + else + { + int asint = wxStrtol(str_id, &end, 10); + if (*str_id && *end == 0) + { + // if str_id was integer, keep it verbosely: + (*rec_var)->id = asint; + } + else + { + (*rec_var)->id = wxWindowBase::NewControlId(); + } + } + 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 void CleanXRCID_Record(XRCID_record *rec) { if (rec) { CleanXRCID_Record(rec->next); + free(rec->key); delete rec; } @@ -1175,11 +1660,121 @@ static void CleanXRCID_Record(XRCID_record *rec) static void CleanXRCID_Records() { for (int i = 0; i < XRCID_TABLE_SIZE; i++) + { CleanXRCID_Record(XRCID_Records[i]); + XRCID_Records[i] = NULL; + } } +static void AddStdXRCID_Records() +{ +#define stdID(id) XRCID_Lookup(#id, id) + stdID(-1); + + stdID(wxID_ANY); + stdID(wxID_SEPARATOR); + + stdID(wxID_OPEN); + stdID(wxID_CLOSE); + stdID(wxID_NEW); + stdID(wxID_SAVE); + stdID(wxID_SAVEAS); + stdID(wxID_REVERT); + stdID(wxID_EXIT); + stdID(wxID_UNDO); + stdID(wxID_REDO); + stdID(wxID_HELP); + stdID(wxID_PRINT); + stdID(wxID_PRINT_SETUP); + stdID(wxID_PAGE_SETUP); + stdID(wxID_PREVIEW); + stdID(wxID_ABOUT); + stdID(wxID_HELP_CONTENTS); + stdID(wxID_HELP_COMMANDS); + stdID(wxID_HELP_PROCEDURES); + stdID(wxID_HELP_CONTEXT); + stdID(wxID_CLOSE_ALL); + stdID(wxID_PREFERENCES); + stdID(wxID_EDIT); + stdID(wxID_CUT); + stdID(wxID_COPY); + stdID(wxID_PASTE); + stdID(wxID_CLEAR); + stdID(wxID_FIND); + stdID(wxID_DUPLICATE); + stdID(wxID_SELECTALL); + stdID(wxID_DELETE); + stdID(wxID_REPLACE); + stdID(wxID_REPLACE_ALL); + stdID(wxID_PROPERTIES); + stdID(wxID_VIEW_DETAILS); + stdID(wxID_VIEW_LARGEICONS); + stdID(wxID_VIEW_SMALLICONS); + stdID(wxID_VIEW_LIST); + stdID(wxID_VIEW_SORTDATE); + stdID(wxID_VIEW_SORTNAME); + stdID(wxID_VIEW_SORTSIZE); + stdID(wxID_VIEW_SORTTYPE); + stdID(wxID_FILE1); + stdID(wxID_FILE2); + stdID(wxID_FILE3); + stdID(wxID_FILE4); + stdID(wxID_FILE5); + stdID(wxID_FILE6); + stdID(wxID_FILE7); + stdID(wxID_FILE8); + stdID(wxID_FILE9); + stdID(wxID_OK); + stdID(wxID_CANCEL); + stdID(wxID_APPLY); + stdID(wxID_YES); + stdID(wxID_NO); + stdID(wxID_STATIC); + stdID(wxID_FORWARD); + stdID(wxID_BACKWARD); + stdID(wxID_DEFAULT); + stdID(wxID_MORE); + stdID(wxID_SETUP); + stdID(wxID_RESET); + stdID(wxID_CONTEXT_HELP); + stdID(wxID_YESTOALL); + stdID(wxID_NOTOALL); + stdID(wxID_ABORT); + stdID(wxID_RETRY); + stdID(wxID_IGNORE); + stdID(wxID_ADD); + stdID(wxID_REMOVE); + stdID(wxID_UP); + stdID(wxID_DOWN); + stdID(wxID_HOME); + stdID(wxID_REFRESH); + stdID(wxID_STOP); + stdID(wxID_INDEX); + stdID(wxID_BOLD); + stdID(wxID_ITALIC); + stdID(wxID_JUSTIFY_CENTER); + stdID(wxID_JUSTIFY_FILL); + stdID(wxID_JUSTIFY_RIGHT); + stdID(wxID_JUSTIFY_LEFT); + stdID(wxID_UNDERLINE); + stdID(wxID_INDENT); + stdID(wxID_UNINDENT); + stdID(wxID_ZOOM_100); + stdID(wxID_ZOOM_FIT); + stdID(wxID_ZOOM_IN); + stdID(wxID_ZOOM_OUT); + stdID(wxID_UNDELETE); + stdID(wxID_REVERT_TO_SAVED); + stdID(wxID_SYSTEM_MENU); + stdID(wxID_CLOSE_FRAME); + stdID(wxID_MOVE_FRAME); + stdID(wxID_RESIZE_FRAME); + stdID(wxID_MAXIMIZE_FRAME); + stdID(wxID_ICONIZE_FRAME); + stdID(wxID_RESTORE_FRAME); - +#undef stdID +} @@ -1194,11 +1789,21 @@ public: wxXmlResourceModule() {} bool OnInit() { - return TRUE; + wxXmlResource::AddSubclassFactory(new wxXmlSubclassFactoryCXX); + return true; } void OnExit() { delete wxXmlResource::Set(NULL); + if(wxXmlResource::ms_subclassFactories) + { + for ( wxXmlSubclassFactories::iterator i = wxXmlResource::ms_subclassFactories->begin(); + i != wxXmlResource::ms_subclassFactories->end(); ++i ) + { + delete *i; + } + wxDELETE(wxXmlResource::ms_subclassFactories); + } CleanXRCID_Records(); } }; @@ -1215,4 +1820,4 @@ void wxXmlInitResourceModule() wxModule::RegisterModule(module); } - +#endif // wxUSE_XRC