// Purpose: XRC resources
// Author: Vaclav Slavik
// Created: 2000/03/05
-// RCS-ID: $Id$
// Copyright: (c) 2000 Vaclav Slavik
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#include "wx/dir.h"
#include "wx/xml/xml.h"
#include "wx/hashset.h"
+#include "wx/scopedptr.h"
+namespace
+{
+
+// Helper function to get modification time of either a wxFileSystem URI or
+// just a normal file name, depending on the build.
+#if wxUSE_DATETIME
+
+wxDateTime GetXRCFileModTime(const wxString& filename)
+{
+#if wxUSE_FILESYSTEM
+ wxFileSystem fsys;
+ wxScopedPtr<wxFSFile> file(fsys.OpenFile(filename));
+
+ return file ? file->GetModificationTime() : wxDateTime();
+#else // wxUSE_FILESYSTEM
+ return wxDateTime(wxFileModificationTime(filename));
+#endif // wxUSE_FILESYSTEM
+}
+
+#endif // wxUSE_DATETIME
+
+} // anonymous namespace
+
+// Assign the given value to the specified entry or add a new value with this
+// name.
+static void XRCID_Assign(const wxString& str_id, int value);
class wxXmlResourceDataRecord
{
public:
- wxXmlResourceDataRecord() : Doc(NULL) {
+ // Ctor takes ownership of the document pointer.
+ wxXmlResourceDataRecord(const wxString& File_,
+ wxXmlDocument *Doc_
+ )
+ : File(File_), Doc(Doc_)
+ {
#if wxUSE_DATETIME
- Time = wxDateTime::Now();
+ Time = GetXRCFileModTime(File);
#endif
}
+
~wxXmlResourceDataRecord() {delete Doc;}
wxString File;
#if wxUSE_DATETIME
wxDateTime Time;
#endif
+
+ wxDECLARE_NO_COPY_CLASS(wxXmlResourceDataRecord);
};
class wxXmlResourceDataRecords : public wxVector<wxXmlResourceDataRecord*>
// this is a class so that it can be forward-declared
};
-WX_DECLARE_HASH_SET(int, wxIntegerHash, wxIntegerEqual, wxHashSetInt);
+WX_DECLARE_HASH_SET_PTR(int, wxIntegerHash, wxIntegerEqual, wxHashSetInt);
class wxIdRange // Holds data for a particular rangename
{
void FinaliseRanges(const wxXmlNode* node) const;
// Searches for a known IdRange matching 'name', returning its index or -1
int Find(const wxString& rangename) const;
- // Removes, if it exists, an entry from the XRCID table. Used in id-ranges
- // to replace defunct or statically-initialised entries with current values
- static void RemoveXRCIDEntry(const char *str_id);
protected:
wxIdRange* FindRangeForItem(const wxXmlNode* node,
{
wxString filemask = ConvertFileNameToURL(filemask_);
+ bool allOK = true;
+
#if wxUSE_FILESYSTEM
wxFileSystem fsys;
# define wxXmlFindFirst fsys.FindFirst(filemask, wxFILE)
if ( IsArchive(fnd) )
{
if ( !Load(fnd + wxT("#zip:*.xrc")) )
- return false;
+ allOK = false;
}
else // a single resource URL
#endif // wxUSE_FILESYSTEM
{
- wxXmlResourceDataRecord *drec = new wxXmlResourceDataRecord;
- drec->File = fnd;
- Data().push_back(drec);
+ wxXmlDocument * const doc = DoLoadFile(fnd);
+ if ( !doc )
+ allOK = false;
+ else
+ Data().push_back(new wxXmlResourceDataRecord(fnd, doc));
}
fnd = wxXmlFindNext;
# undef wxXmlFindFirst
# undef wxXmlFindNext
- return UpdateResources();
+ return allOK;
}
bool wxXmlResource::Unload(const wxString& filename)
}
-IMPLEMENT_ABSTRACT_CLASS(wxXmlResourceHandler, wxObject)
-
void wxXmlResource::AddHandler(wxXmlResourceHandler *handler)
{
+ wxXmlResourceHandlerImpl *impl = new wxXmlResourceHandlerImpl(handler);
+ handler->SetImpl(impl);
m_handlers.push_back(handler);
handler->SetParentResource(this);
}
void wxXmlResource::InsertHandler(wxXmlResourceHandler *handler)
{
+ wxXmlResourceHandlerImpl *impl = new wxXmlResourceHandlerImpl(handler);
+ handler->SetImpl(impl);
m_handlers.insert(m_handlers.begin(), handler);
handler->SetParentResource(this);
}
bool wxXmlResource::UpdateResources()
{
bool rt = true;
- bool modif;
-# if wxUSE_FILESYSTEM
- wxFSFile *file = NULL;
- wxUnusedVar(file);
- wxFileSystem fsys;
-# endif
-
- wxString encoding(wxT("UTF-8"));
-#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.
- encoding = wxLocale::GetSystemEncodingName();
- }
-#endif
for ( wxXmlResourceDataRecords::iterator i = Data().begin();
i != Data().end(); ++i )
{
wxXmlResourceDataRecord* const rec = *i;
- modif = (rec->Doc == NULL);
+ // Check if we need to reload this one.
+
+ // We never do it if this flag is specified.
+ if ( m_flags & wxXRC_NO_RELOADING )
+ continue;
- if (!modif && !(m_flags & wxXRC_NO_RELOADING))
+ // Otherwise check its modification time if we can.
+#if wxUSE_DATETIME
+ const wxDateTime lastModTime = GetXRCFileModTime(rec->File);
+
+ if ( lastModTime.IsValid() && lastModTime <= rec->Time )
+#else // !wxUSE_DATETIME
+ // Never reload the file contents: we can't know whether it changed or
+ // not in this build configuration and it would be unexpected and
+ // counter-productive to get a performance hit (due to constant
+ // reloading of XRC files) in a minimal wx build which is presumably
+ // used because of resource constraints of the current platform.
+#endif // wxUSE_DATETIME/!wxUSE_DATETIME
{
-# if wxUSE_FILESYSTEM
- 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'."), rec->File);
- rt = false;
- }
- wxDELETE(file);
- 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
+ // No need to reload, the file wasn't modified since we did it
+ // last.
+ continue;
}
- if (modif)
+ wxXmlDocument * const doc = DoLoadFile(rec->File);
+ if ( !doc )
{
- wxLogTrace(wxT("xrc"), wxT("opening file '%s'"), rec->File);
+ // Notice that we keep the old XML document: it seems better to
+ // preserve it instead of throwing it away if we have nothing to
+ // replace it with.
+ rt = false;
+ continue;
+ }
- wxInputStream *stream = NULL;
+ // Replace the old resource contents with the new one.
+ delete rec->Doc;
+ rec->Doc = doc;
-# if wxUSE_FILESYSTEM
- file = fsys.OpenFile(rec->File);
- if (file)
- stream = file->GetStream();
-# else
- stream = new wxFileInputStream(rec->File);
-# endif
+ // And, now that we loaded it successfully, update the last load time.
+#if wxUSE_DATETIME
+ rec->Time = lastModTime.IsValid() ? lastModTime : wxDateTime::Now();
+#endif // wxUSE_DATETIME
+ }
- if (stream)
- {
- delete rec->Doc;
- rec->Doc = new wxXmlDocument;
- }
- if (!stream || !stream->IsOk() || !rec->Doc->Load(*stream, encoding))
- {
- wxLogError(_("Cannot load resources from file '%s'."),
- rec->File);
- wxDELETE(rec->Doc);
- rt = false;
- }
- else if (rec->Doc->GetRoot()->GetName() != wxT("resource"))
- {
- ReportError
- (
- rec->Doc->GetRoot(),
- "invalid XRC resource, doesn't have root node <resource>"
- );
- wxDELETE(rec->Doc);
- rt = false;
- }
- else
- {
- long version;
- int v1, v2, v3, v4;
- 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)
- version = v1*256*256*256+v2*256*256+v3*256+v4;
- else
- version = 0;
- if (m_version == -1)
- m_version = version;
- if (m_version != version)
- {
- wxLogError("Resource files must have same version number.");
- rt = false;
- }
+ return rt;
+}
+
+wxXmlDocument *wxXmlResource::DoLoadFile(const wxString& filename)
+{
+ wxLogTrace(wxT("xrc"), wxT("opening file '%s'"), filename);
+
+ wxInputStream *stream = NULL;
- ProcessPlatformProperty(rec->Doc->GetRoot());
- PreprocessForIdRanges(rec->Doc->GetRoot());
- wxIdRangeManager::Get()->FinaliseRanges(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
- }
+ wxFileSystem fsys;
+ wxScopedPtr<wxFSFile> file(fsys.OpenFile(filename));
+ if (file)
+ {
+ // Notice that we don't have ownership of the stream in this case, it
+ // remains owned by wxFSFile.
+ stream = file->GetStream();
+ }
+#else // !wxUSE_FILESYSTEM
+ wxFileInputStream fstream(filename);
+ stream = &fstream;
+#endif // wxUSE_FILESYSTEM/!wxUSE_FILESYSTEM
-# if wxUSE_FILESYSTEM
- wxDELETE(file);
- wxUnusedVar(file);
-# else
- wxDELETE(stream);
-# endif
- }
+ if ( !stream || !stream->IsOk() )
+ {
+ wxLogError(_("Cannot open resources file '%s'."), filename);
+ return NULL;
}
- return rt;
+ wxString encoding(wxT("UTF-8"));
+#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.
+ encoding = wxLocale::GetSystemEncodingName();
+ }
+#endif
+
+ wxScopedPtr<wxXmlDocument> doc(new wxXmlDocument);
+ if (!doc->Load(*stream, encoding))
+ {
+ wxLogError(_("Cannot load resources from file '%s'."), filename);
+ return NULL;
+ }
+
+ wxXmlNode * const root = doc->GetRoot();
+ if (root->GetName() != wxT("resource"))
+ {
+ ReportError
+ (
+ root,
+ "invalid XRC resource, doesn't have root node <resource>"
+ );
+ return NULL;
+ }
+
+ long version;
+ int v1, v2, v3, v4;
+ wxString verstr = root->GetAttribute(wxT("version"), wxT("0.0.0.0"));
+ if (wxSscanf(verstr, wxT("%i.%i.%i.%i"), &v1, &v2, &v3, &v4) == 4)
+ version = v1*256*256*256+v2*256*256+v3*256+v4;
+ else
+ version = 0;
+ if (m_version == -1)
+ m_version = version;
+ if (m_version != version)
+ {
+ wxLogWarning("Resource files must have same version number.");
+ }
+
+ ProcessPlatformProperty(root);
+ PreprocessForIdRanges(root);
+ wxIdRangeManager::Get()->FinaliseRanges(root);
+
+ return doc.release();
}
wxXmlNode *wxXmlResource::DoFindResource(wxXmlNode *parent,
return NULL;
}
- if ( !node.GetChildren() )
+ const bool hasOnlyRefAttr = node.GetAttributes() != NULL &&
+ node.GetAttributes()->GetNext() == NULL;
+
+ if ( hasOnlyRefAttr && !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
// Create the XRCIDs
for (int i=m_start; i <= m_end; ++i)
{
- // First clear any pre-existing XRCID
- // Necessary for wxXmlResource::Unload() followed by Load()
- wxIdRangeManager::RemoveXRCIDEntry(
- m_name + wxString::Format("[%i]", i-m_start));
+ // Ensure that we overwrite any existing value as otherwise
+ // wxXmlResource::Unload() followed by Load() wouldn't work correctly.
+ XRCID_Assign(m_name + wxString::Format("[%i]", i-m_start), i);
- // Use the second parameter of GetXRCID to force it to take the value i
- wxXmlResource::GetXRCID(m_name + wxString::Format("[%i]", i-m_start), i);
- wxLogTrace("xrcrange","integer = %i %s now returns %i", i,
- m_name + wxString::Format("[%i]", i-m_start).mb_str(),
- XRCID(m_name + wxString::Format("[%i]", i-m_start).mb_str()));
+ wxLogTrace("xrcrange",
+ "integer = %i %s now returns %i",
+ i,
+ m_name + wxString::Format("[%i]", i-m_start),
+ XRCID((m_name + wxString::Format("[%i]", i-m_start)).mb_str()));
}
// and these special ones
- wxIdRangeManager::RemoveXRCIDEntry(m_name + "[start]");
- wxXmlResource::GetXRCID(m_name + "[start]", m_start);
- wxIdRangeManager::RemoveXRCIDEntry(m_name + "[end]");
- wxXmlResource::GetXRCID(m_name + "[end]", m_end);
+ XRCID_Assign(m_name + "[start]", m_start);
+ XRCID_Assign(m_name + "[end]", m_end);
wxLogTrace("xrcrange","%s[start] = %i %s[end] = %i",
m_name.mb_str(),XRCID(wxString(m_name+"[start]").mb_str()),
m_name.mb_str(),XRCID(wxString(m_name+"[end]").mb_str()));
-wxXmlResourceHandler::wxXmlResourceHandler()
- : m_node(NULL), m_parent(NULL), m_instance(NULL),
- m_parentAsWindow(NULL)
-{}
+wxXmlResourceHandlerImpl::wxXmlResourceHandlerImpl(wxXmlResourceHandler *handler)
+ :wxXmlResourceHandlerImplBase(handler)
+{
+}
+wxObject *wxXmlResourceHandlerImpl::CreateResFromNode(wxXmlNode *node,
+ wxObject *parent, wxObject *instance)
+{
+ return m_handler->m_resource->CreateResFromNode(node, parent, instance);
+}
+#if wxUSE_FILESYSTEM
+wxFileSystem& wxXmlResourceHandlerImpl::GetCurFileSystem()
+{
+ return m_handler->m_resource->GetCurFileSystem();
+}
+#endif
-wxObject *wxXmlResourceHandler::CreateResource(wxXmlNode *node, wxObject *parent, wxObject *instance)
+
+wxObject *wxXmlResourceHandlerImpl::CreateResource(wxXmlNode *node, wxObject *parent, wxObject *instance)
{
- wxXmlNode *myNode = m_node;
- wxString myClass = m_class;
- wxObject *myParent = m_parent, *myInstance = m_instance;
- wxWindow *myParentAW = m_parentAsWindow;
+ wxXmlNode *myNode = m_handler->m_node;
+ wxString myClass = m_handler->m_class;
+ wxObject *myParent = m_handler->m_parent, *myInstance = m_handler->m_instance;
+ wxWindow *myParentAW = m_handler->m_parentAsWindow;
- m_instance = instance;
- if (!m_instance && node->HasAttribute(wxT("subclass")) &&
- !(m_resource->GetFlags() & wxXRC_NO_SUBCLASSING))
+ m_handler->m_instance = instance;
+ if (!m_handler->m_instance && node->HasAttribute(wxT("subclass")) &&
+ !(m_handler->m_resource->GetFlags() & wxXRC_NO_SUBCLASSING))
{
wxString subclass = node->GetAttribute(wxT("subclass"), wxEmptyString);
if (!subclass.empty())
for (wxXmlSubclassFactories::iterator i = wxXmlResource::ms_subclassFactories->begin();
i != wxXmlResource::ms_subclassFactories->end(); ++i)
{
- m_instance = (*i)->Create(subclass);
- if (m_instance)
+ m_handler->m_instance = (*i)->Create(subclass);
+ if (m_handler->m_instance)
break;
}
- if (!m_instance)
+ if (!m_handler->m_instance)
{
wxString name = node->GetAttribute(wxT("name"), wxEmptyString);
ReportError
}
}
- m_node = node;
- m_class = node->GetAttribute(wxT("class"), wxEmptyString);
- m_parent = parent;
- m_parentAsWindow = wxDynamicCast(m_parent, wxWindow);
+ m_handler->m_node = node;
+ m_handler->m_class = node->GetAttribute(wxT("class"), wxEmptyString);
+ m_handler->m_parent = parent;
+ m_handler->m_parentAsWindow = wxDynamicCast(m_handler->m_parent, wxWindow);
- wxObject *returned = DoCreateResource();
+ wxObject *returned = GetHandler()->DoCreateResource();
- m_node = myNode;
- m_class = myClass;
- m_parent = myParent; m_parentAsWindow = myParentAW;
- m_instance = myInstance;
+ m_handler->m_node = myNode;
+ m_handler->m_class = myClass;
+ m_handler->m_parent = myParent; m_handler->m_parentAsWindow = myParentAW;
+ m_handler->m_instance = myInstance;
return returned;
}
-
-void wxXmlResourceHandler::AddStyle(const wxString& name, int value)
-{
- m_styleNames.Add(name);
- m_styleValues.Add(value);
-}
-
-
-
-void wxXmlResourceHandler::AddWindowStyles()
-{
- 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); // 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(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);
-}
-
-
-
-bool wxXmlResourceHandler::HasParam(const wxString& param)
+bool wxXmlResourceHandlerImpl::HasParam(const wxString& param)
{
return (GetParamNode(param) != NULL);
}
-int wxXmlResourceHandler::GetStyle(const wxString& param, int defaults)
+int wxXmlResourceHandlerImpl::GetStyle(const wxString& param, int defaults)
{
wxString s = GetParamValue(param);
while (tkn.HasMoreTokens())
{
fl = tkn.GetNextToken();
- index = m_styleNames.Index(fl);
+ index = m_handler->m_styleNames.Index(fl);
if (index != wxNOT_FOUND)
{
- style |= m_styleValues[index];
+ style |= m_handler->m_styleValues[index];
}
else
{
-wxString wxXmlResourceHandler::GetText(const wxString& param, bool translate)
+wxString wxXmlResourceHandlerImpl::GetText(const wxString& param, bool translate)
{
wxXmlNode *parNode = GetParamNode(param);
wxString str1(GetNodeContent(parNode));
wxString str2;
// "\\" wasn't translated to "\" prior to 2.5.3.0:
- const bool escapeBackslash = (m_resource->CompareVersion(2,5,3,0) >= 0);
+ const bool escapeBackslash = (m_handler->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").
- const wxChar amp_char = (m_resource->CompareVersion(2,3,0,1) < 0)
+ const wxChar amp_char = (m_handler->m_resource->CompareVersion(2,3,0,1) < 0)
? '$' : '_';
for ( wxString::const_iterator dt = str1.begin(); dt != str1.end(); ++dt )
// like "&File..." -- this is illegal in XML, so we use "_File..."):
if ( *dt == amp_char )
{
- if ( *(++dt) == amp_char )
+ if ( dt+1 == str1.end() || *(++dt) == amp_char )
str2 << amp_char;
else
str2 << wxT('&') << *dt;
}
}
- if (m_resource->GetFlags() & wxXRC_USE_LOCALE)
+ if (m_handler->m_resource->GetFlags() & wxXRC_USE_LOCALE)
{
if (translate && parNode &&
parNode->GetAttribute(wxT("translate"), wxEmptyString) != wxT("0"))
{
- return wxGetTranslation(str2, m_resource->GetDomain());
+ return wxGetTranslation(str2, m_handler->m_resource->GetDomain());
}
else
{
-long wxXmlResourceHandler::GetLong(const wxString& param, long defaultv)
+long wxXmlResourceHandlerImpl::GetLong(const wxString& param, long defaultv)
{
- long value;
+ long value = defaultv;
wxString str1 = GetParamValue(param);
- if (!str1.ToLong(&value))
- value = defaultv;
+ if (!str1.empty())
+ {
+ if (!str1.ToLong(&value))
+ {
+ ReportParamError
+ (
+ param,
+ wxString::Format("invalid long specification \"%s\"", str1)
+ );
+ }
+ }
return value;
}
-float wxXmlResourceHandler::GetFloat(const wxString& param, float defaultv)
+float wxXmlResourceHandlerImpl::GetFloat(const wxString& param, float defaultv)
{
wxString str = GetParamValue(param);
// strings in XRC always use C locale so make sure to use the
// locale-independent wxString::ToCDouble() and not ToDouble() which uses
// the current locale with a potentially different decimal point character
- double value;
- if (!str.ToCDouble(&value))
- value = defaultv;
+ double value = defaultv;
+ if (!str.empty())
+ {
+ if (!str.ToCDouble(&value))
+ {
+ ReportParamError
+ (
+ param,
+ wxString::Format("invalid float specification \"%s\"", str)
+ );
+ }
+ }
return wx_truncate_cast(float, value);
}
-int wxXmlResourceHandler::GetID()
+int wxXmlResourceHandlerImpl::GetID()
{
return wxXmlResource::GetXRCID(GetName());
}
-wxString wxXmlResourceHandler::GetName()
+wxString wxXmlResourceHandlerImpl::GetName()
{
- return m_node->GetAttribute(wxT("name"), wxT("-1"));
+ return m_handler->m_node->GetAttribute(wxT("name"), wxT("-1"));
}
-bool wxXmlResourceHandler::GetBoolAttr(const wxString& attr, bool defaultv)
+bool wxXmlResourceHandlerImpl::GetBoolAttr(const wxString& attr, bool defaultv)
{
wxString v;
- return m_node->GetAttribute(attr, &v) ? v == '1' : defaultv;
+ return m_handler->m_node->GetAttribute(attr, &v) ? v == '1' : defaultv;
}
-bool wxXmlResourceHandler::GetBool(const wxString& param, bool defaultv)
+bool wxXmlResourceHandlerImpl::GetBool(const wxString& param, bool defaultv)
{
const wxString v = GetParamValue(param);
return wxNullColour;
}
-wxColour wxXmlResourceHandler::GetColour(const wxString& param, const wxColour& defaultv)
+wxColour wxXmlResourceHandlerImpl::GetColour(const wxString& param, const wxColour& defaultv)
{
wxString v = GetParamValue(param);
// the colour doesn't use #RRGGBB format, check if it is symbolic
// colour name:
clr = GetSystemColour(v);
- if (clr.Ok())
+ if (clr.IsOk())
return clr;
ReportParamError
} // anonymous namespace
-wxBitmap wxXmlResourceHandler::GetBitmap(const wxString& param,
+wxBitmap wxXmlResourceHandlerImpl::GetBitmap(const wxString& param,
const wxArtClient& defaultArtClient,
wxSize size)
{
return GetBitmap(node, defaultArtClient, size);
}
-wxBitmap wxXmlResourceHandler::GetBitmap(const wxXmlNode* node,
+wxBitmap wxXmlResourceHandlerImpl::GetBitmap(const wxXmlNode* node,
const wxArtClient& defaultArtClient,
wxSize size)
{
art_id, art_client) )
{
wxBitmap stockArt(wxArtProvider::GetBitmap(art_id, art_client, size));
- if ( stockArt.Ok() )
+ if ( stockArt.IsOk() )
return stockArt;
}
wxImage img(name);
#endif
- if (!img.Ok())
+ if (!img.IsOk())
{
ReportParamError
(
}
-wxIcon wxXmlResourceHandler::GetIcon(const wxString& param,
+wxIcon wxXmlResourceHandlerImpl::GetIcon(const wxString& param,
const wxArtClient& defaultArtClient,
wxSize size)
{
return GetIcon(node, defaultArtClient, size);
}
-wxIcon wxXmlResourceHandler::GetIcon(const wxXmlNode* node,
+wxIcon wxXmlResourceHandlerImpl::GetIcon(const wxXmlNode* node,
const wxArtClient& defaultArtClient,
wxSize size)
{
}
-wxIconBundle wxXmlResourceHandler::GetIconBundle(const wxString& param,
+wxIconBundle wxXmlResourceHandlerImpl::GetIconBundle(const wxString& param,
const wxArtClient& defaultArtClient)
{
wxString art_id, art_client;
}
-wxImageList *wxXmlResourceHandler::GetImageList(const wxString& param)
+wxImageList *wxXmlResourceHandlerImpl::GetImageList(const wxString& param)
{
wxXmlNode * const imagelist_node = GetParamNode(param);
if ( !imagelist_node )
return NULL;
- wxXmlNode * const oldnode = m_node;
- m_node = imagelist_node;
+ wxXmlNode * const oldnode = m_handler->m_node;
+ m_handler->m_node = imagelist_node;
// Get the size if we have it, otherwise we will use the size of the first
// list element.
wxString parambitmap = wxT("bitmap");
if ( HasParam(parambitmap) )
{
- wxXmlNode *n = m_node->GetChildren();
+ wxXmlNode *n = m_handler->m_node->GetChildren();
while (n)
{
if (n->GetType() == wxXML_ELEMENT_NODE && n->GetName() == parambitmap)
{
- wxIcon icon = GetIcon(n);
+ wxIcon icon = GetIcon(n, wxART_OTHER, size);
if ( !imagelist )
{
// We need the real image list size to create it.
}
}
- m_node = oldnode;
+ m_handler->m_node = oldnode;
return imagelist;
}
-wxXmlNode *wxXmlResourceHandler::GetParamNode(const wxString& param)
+wxXmlNode *wxXmlResourceHandlerImpl::GetParamNode(const wxString& param)
{
- wxCHECK_MSG(m_node, NULL, wxT("You can't access handler data before it was initialized!"));
+ wxCHECK_MSG(m_handler->m_node, NULL, wxT("You can't access handler data before it was initialized!"));
- wxXmlNode *n = m_node->GetChildren();
+ wxXmlNode *n = m_handler->m_node->GetChildren();
while (n)
{
return NULL;
}
-/* static */
-bool wxXmlResourceHandler::IsOfClass(wxXmlNode *node, const wxString& classname)
+bool wxXmlResourceHandlerImpl::IsOfClass(wxXmlNode *node, const wxString& classname) const
{
return node->GetAttribute(wxT("class")) == classname;
}
-wxString wxXmlResourceHandler::GetNodeContent(const wxXmlNode *node)
+wxString wxXmlResourceHandlerImpl::GetNodeContent(const wxXmlNode *node)
{
const wxXmlNode *n = node;
if (n == NULL) return wxEmptyString;
-wxString wxXmlResourceHandler::GetParamValue(const wxString& param)
+wxString wxXmlResourceHandlerImpl::GetParamValue(const wxString& param)
{
if (param.empty())
- return GetNodeContent(m_node);
+ return GetNodeContent(m_handler->m_node);
else
return GetNodeContent(GetParamNode(param));
}
-wxString wxXmlResourceHandler::GetParamValue(const wxXmlNode* node)
+wxString wxXmlResourceHandlerImpl::GetParamValue(const wxXmlNode* node)
{
return GetNodeContent(node);
}
-wxSize wxXmlResourceHandler::GetSize(const wxString& param,
+wxSize wxXmlResourceHandlerImpl::GetSize(const wxString& param,
wxWindow *windowToUse)
{
wxString s = GetParamValue(param);
{
return wxDLG_UNIT(windowToUse, wxSize(sx, sy));
}
- else if (m_parentAsWindow)
+ else if (m_handler->m_parentAsWindow)
{
- return wxDLG_UNIT(m_parentAsWindow, wxSize(sx, sy));
+ return wxDLG_UNIT(m_handler->m_parentAsWindow, wxSize(sx, sy));
}
else
{
-wxPoint wxXmlResourceHandler::GetPosition(const wxString& param)
+wxPoint wxXmlResourceHandlerImpl::GetPosition(const wxString& param)
{
wxSize sz = GetSize(param);
return wxPoint(sz.x, sz.y);
-wxCoord wxXmlResourceHandler::GetDimension(const wxString& param,
+wxCoord wxXmlResourceHandlerImpl::GetDimension(const wxString& param,
wxCoord defaultv,
wxWindow *windowToUse)
{
{
return wxDLG_UNIT(windowToUse, wxSize(sx, 0)).x;
}
- else if (m_parentAsWindow)
+ else if (m_handler->m_parentAsWindow)
{
- return wxDLG_UNIT(m_parentAsWindow, wxSize(sx, 0)).x;
+ return wxDLG_UNIT(m_handler->m_parentAsWindow, wxSize(sx, 0)).x;
}
else
{
return sx;
}
+wxDirection
+wxXmlResourceHandlerImpl::GetDirection(const wxString& param, wxDirection dirDefault)
+{
+ wxDirection dir;
+
+ const wxString dirstr = GetParamValue(param);
+ if ( dirstr.empty() )
+ dir = dirDefault;
+ else if ( dirstr == "wxLEFT" )
+ dir = wxLEFT;
+ else if ( dirstr == "wxRIGHT" )
+ dir = wxRIGHT;
+ else if ( dirstr == "wxTOP" )
+ dir = wxTOP;
+ else if ( dirstr == "wxBOTTOM" )
+ dir = wxBOTTOM;
+ else
+ {
+ ReportError
+ (
+ GetParamNode(param),
+ wxString::Format
+ (
+ "Invalid direction \"%s\": must be one of "
+ "wxLEFT|wxRIGHT|wxTOP|wxBOTTOM.",
+ dirstr
+ )
+ );
+
+ dir = dirDefault;
+ }
+
+ return dir;
+}
// Get system font index using indexname
static wxFont GetSystemFont(const wxString& name)
return wxNullFont;
}
-wxFont wxXmlResourceHandler::GetFont(const wxString& param)
+wxFont wxXmlResourceHandlerImpl::GetFont(const wxString& param, wxWindow* parent)
{
wxXmlNode *font_node = GetParamNode(param);
if (font_node == NULL)
return wxNullFont;
}
- wxXmlNode *oldnode = m_node;
- m_node = font_node;
+ wxXmlNode *oldnode = m_handler->m_node;
+ m_handler->m_node = font_node;
// font attributes:
istyle = wxITALIC;
else if (style == wxT("slant"))
istyle = wxSLANT;
+ else if (style != wxT("normal"))
+ {
+ ReportParamError
+ (
+ param,
+ wxString::Format("unknown font style \"%s\"", style)
+ );
+ }
}
// weight
iweight = wxBOLD;
else if (weight == wxT("light"))
iweight = wxLIGHT;
+ else if (weight != wxT("normal"))
+ {
+ ReportParamError
+ (
+ param,
+ wxString::Format("unknown font weight \"%s\"", weight)
+ );
+ }
}
// underline
else if (family == wxT("swiss")) ifamily = wxSWISS;
else if (family == wxT("modern")) ifamily = wxMODERN;
else if (family == wxT("teletype")) ifamily = wxTELETYPE;
+ else
+ {
+ ReportParamError
+ (
+ param,
+ wxString::Format("unknown font family \"%s\"", family)
+ );
+ }
}
}
#endif // wxUSE_FONTMAP
+ wxFont font;
+
// is this font based on a system font?
- wxFont font = GetSystemFont(GetParamValue(wxT("sysfont")));
+ if (HasParam(wxT("sysfont")))
+ {
+ font = GetSystemFont(GetParamValue(wxT("sysfont")));
+ if (HasParam(wxT("inherit")))
+ {
+ ReportParamError
+ (
+ param,
+ "double specification of \"sysfont\" and \"inherit\""
+ );
+ }
+ }
+ // or should the font of the widget be used?
+ else if (GetBool(wxT("inherit"), false))
+ {
+ if (parent)
+ font = parent->GetFont();
+ else
+ {
+ ReportParamError
+ (
+ param,
+ "no parent window specified to derive the font from"
+ );
+ }
+ }
- if (font.Ok())
+ if (font.IsOk())
{
if (hasSize && isize != -1)
+ {
font.SetPointSize(isize);
+ if (HasParam(wxT("relativesize")))
+ {
+ ReportParamError
+ (
+ param,
+ "double specification of \"size\" and \"relativesize\""
+ );
+ }
+ }
else if (HasParam(wxT("relativesize")))
font.SetPointSize(int(font.GetPointSize() *
GetFloat(wxT("relativesize"))));
underlined, facename, enc);
}
- m_node = oldnode;
+ m_handler->m_node = oldnode;
return font;
}
-void wxXmlResourceHandler::SetupWindow(wxWindow *wnd)
+void wxXmlResourceHandlerImpl::SetupWindow(wxWindow *wnd)
{
//FIXME : add cursor
wnd->SetToolTip(GetText(wxT("tooltip")));
#endif
if (HasParam(wxT("font")))
- wnd->SetFont(GetFont(wxT("font")));
+ wnd->SetFont(GetFont(wxT("font"), wnd));
if (HasParam(wxT("ownfont")))
- wnd->SetOwnFont(GetFont(wxT("ownfont")));
+ wnd->SetOwnFont(GetFont(wxT("ownfont"), wnd));
if (HasParam(wxT("help")))
wnd->SetHelpText(GetText(wxT("help")));
}
-void wxXmlResourceHandler::CreateChildren(wxObject *parent, bool this_hnd_only)
+void wxXmlResourceHandlerImpl::CreateChildren(wxObject *parent, bool this_hnd_only)
{
- for ( wxXmlNode *n = m_node->GetChildren(); n; n = n->GetNext() )
+ for ( wxXmlNode *n = m_handler->m_node->GetChildren(); n; n = n->GetNext() )
{
if ( IsObjectNode(n) )
{
- m_resource->DoCreateResFromNode(*n, parent, NULL,
- this_hnd_only ? this : NULL);
- }
+ m_handler->m_resource->DoCreateResFromNode(*n, parent, NULL,
+ this_hnd_only ? this->GetHandler() : NULL);
+ }
}
}
-void wxXmlResourceHandler::CreateChildrenPrivately(wxObject *parent, wxXmlNode *rootnode)
+void wxXmlResourceHandlerImpl::CreateChildrenPrivately(wxObject *parent, wxXmlNode *rootnode)
{
wxXmlNode *root;
- if (rootnode == NULL) root = m_node; else root = rootnode;
+ if (rootnode == NULL) root = m_handler->m_node; else root = rootnode;
wxXmlNode *n = root->GetChildren();
while (n)
{
- if (n->GetType() == wxXML_ELEMENT_NODE && CanHandle(n))
+ if (n->GetType() == wxXML_ELEMENT_NODE && GetHandler()->CanHandle(n))
{
CreateResource(n, parent, NULL);
}
// errors reporting
//-----------------------------------------------------------------------------
-void wxXmlResourceHandler::ReportError(const wxString& message)
+void wxXmlResourceHandlerImpl::ReportError(const wxString& message)
{
- m_resource->ReportError(m_node, message);
+ m_handler->m_resource->ReportError(m_handler->m_node, message);
}
-void wxXmlResourceHandler::ReportError(wxXmlNode *context,
+void wxXmlResourceHandlerImpl::ReportError(wxXmlNode *context,
const wxString& message)
{
- m_resource->ReportError(context ? context : m_node, message);
+ m_handler->m_resource->ReportError(context ? context : m_handler->m_node, message);
}
-void wxXmlResourceHandler::ReportParamError(const wxString& param,
+void wxXmlResourceHandlerImpl::ReportParamError(const wxString& param,
const wxString& message)
{
- m_resource->ReportError(GetParamNode(param), message);
+ m_handler->m_resource->ReportError(GetParamNode(param), message);
}
void wxXmlResource::ReportError(const wxXmlNode *context, const wxString& message)
static XRCID_record *XRCID_Records[XRCID_TABLE_SIZE] = {NULL};
-static int XRCID_Lookup(const char *str_id, int value_if_not_found = wxID_NONE)
+// Extremely simplistic hash function which probably ought to be replaced with
+// wxStringHash::stringHash().
+static inline unsigned XRCIdHash(const char *str_id)
{
- unsigned int index = 0;
+ unsigned index = 0;
for (const char *c = str_id; *c != '\0'; c++) index += (unsigned int)*c;
index %= XRCID_TABLE_SIZE;
+ return index;
+}
+
+static void XRCID_Assign(const wxString& str_id, int value)
+{
+ const wxCharBuffer buf_id(str_id.mb_str());
+ const unsigned index = XRCIdHash(buf_id);
+
+
+ XRCID_record *oldrec = NULL;
+ for (XRCID_record *rec = XRCID_Records[index]; rec; rec = rec->next)
+ {
+ if (wxStrcmp(rec->key, buf_id) == 0)
+ {
+ rec->id = value;
+ return;
+ }
+ oldrec = rec;
+ }
+
+ XRCID_record **rec_var = (oldrec == NULL) ?
+ &XRCID_Records[index] : &oldrec->next;
+ *rec_var = new XRCID_record;
+ (*rec_var)->key = wxStrdup(str_id);
+ (*rec_var)->id = value;
+ (*rec_var)->next = NULL;
+}
+
+static int XRCID_Lookup(const char *str_id, int value_if_not_found = wxID_NONE)
+{
+ const unsigned index = XRCIdHash(str_id);
+
+
XRCID_record *oldrec = NULL;
for (XRCID_record *rec = XRCID_Records[index]; rec; rec = rec->next)
{
stdID(wxID_PREVIEW);
stdID(wxID_ABOUT);
stdID(wxID_HELP_CONTENTS);
+ stdID(wxID_HELP_INDEX),
+ stdID(wxID_HELP_SEARCH),
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_REPLACE);
stdID(wxID_REPLACE_ALL);
stdID(wxID_PROPERTIES);
+
stdID(wxID_VIEW_DETAILS);
stdID(wxID_VIEW_LARGEICONS);
stdID(wxID_VIEW_SMALLICONS);
stdID(wxID_VIEW_SORTNAME);
stdID(wxID_VIEW_SORTSIZE);
stdID(wxID_VIEW_SORTTYPE);
+
+
stdID(wxID_FILE1);
stdID(wxID_FILE2);
stdID(wxID_FILE3);
stdID(wxID_FILE7);
stdID(wxID_FILE8);
stdID(wxID_FILE9);
+
+
stdID(wxID_OK);
stdID(wxID_CANCEL);
stdID(wxID_APPLY);
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_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);
stdID(wxID_CDROM);
stdID(wxID_CONVERT);
stdID(wxID_EXECUTE);
stdID(wxID_SPELL_CHECK);
stdID(wxID_STRIKETHROUGH);
+
+ 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);
+
+
+
+ stdID(wxID_MDI_WINDOW_CASCADE);
+ stdID(wxID_MDI_WINDOW_TILE_HORZ);
+ stdID(wxID_MDI_WINDOW_TILE_VERT);
+ stdID(wxID_MDI_WINDOW_ARRANGE_ICONS);
+ stdID(wxID_MDI_WINDOW_PREV);
+ stdID(wxID_MDI_WINDOW_NEXT);
#undef stdID
}
return wxString();
}
-/* static */
-void wxIdRangeManager::RemoveXRCIDEntry(const char *str_id)
-{
- int index = 0;
-
- for (const char *c = str_id; *c != '\0'; c++) index += (int)*c;
- index %= XRCID_TABLE_SIZE;
-
- XRCID_record **p_previousrec = &XRCID_Records[index];
- for (XRCID_record *rec = XRCID_Records[index]; rec; rec = rec->next)
- {
- if (wxStrcmp(rec->key, str_id) == 0)
- {
- // Found the item to be removed so delete its record; but first
- // replace it in the table with any rec->next (usually == NULL)
- (*p_previousrec) = rec->next;
- free(rec->key);
- delete rec;
- return;
- }
- else
- {
- (*p_previousrec) = rec;
- }
- }
-}
-
static void CleanXRCID_Record(XRCID_record *rec)
{
if (rec)
void wxXmlInitResourceModule()
{
wxModule* module = new wxXmlResourceModule;
- module->Init();
wxModule::RegisterModule(module);
+ wxModule::InitializeModules();
}
#endif // wxUSE_XRC