X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f0244295e3a35a37473e9ba83d6ceea0d17259da..80a779275ae04443c568dca919adb26cf6f5002c:/src/common/rendcmn.cpp diff --git a/src/common/rendcmn.cpp b/src/common/rendcmn.cpp index 202ec01517..86e02ce8b9 100644 --- a/src/common/rendcmn.cpp +++ b/src/common/rendcmn.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Name: common/rendcmn.cpp +// Name: src/common/rendcmn.cpp // Purpose: wxRendererNative common functions // Author: Vadim Zeitlin // Modified by: @@ -24,6 +24,9 @@ #endif #ifndef WX_PRECOMP + #include "wx/app.h" + #include "wx/log.h" + #include "wx/intl.h" #endif //WX_PRECOMP #include "wx/apptrait.h" @@ -31,18 +34,20 @@ #include "wx/ptr_scpd.h" +#if wxUSE_DYNLIB_CLASS + #include "wx/dynlib.h" +#endif // wxUSE_DYNLIB_CLASS + // ---------------------------------------------------------------------------- // wxRendererPtr: auto pointer holding the global renderer // ---------------------------------------------------------------------------- -wxDECLARE_SCOPED_PTR(wxRendererNative, wxRendererPtrBase); -wxDEFINE_SCOPED_PTR(wxRendererNative, wxRendererPtrBase); +wxDECLARE_SCOPED_PTR(wxRendererNative, wxRendererPtrBase) +wxDEFINE_SCOPED_PTR(wxRendererNative, wxRendererPtrBase) class wxRendererPtr : public wxRendererPtrBase { public: - wxRendererPtr() : wxRendererPtrBase(NULL) { m_initialized = false; } - // return true if we have a renderer, false otherwise bool IsOk() { @@ -57,7 +62,12 @@ public: return get() != NULL; } + // return the global and unique wxRendererPtr + static wxRendererPtr& Get(); + private: + wxRendererPtr() : wxRendererPtrBase(NULL) { m_initialized = false; } + void DoInit() { wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL; @@ -70,18 +80,129 @@ private: bool m_initialized; + // just to suppress a gcc warning + friend class wxRendererPtrDummyFriend; + DECLARE_NO_COPY_CLASS(wxRendererPtr) }; +// return the global and unique wxRendererPtr +/*static*/ wxRendererPtr& wxRendererPtr::Get() +{ + static wxRendererPtr s_renderer; + + return s_renderer; +} + +#if wxUSE_DYNLIB_CLASS + +// ---------------------------------------------------------------------------- +// wxRendererFromDynLib: represents a renderer dynamically loaded from a DLL +// ---------------------------------------------------------------------------- + +class wxRendererFromDynLib : public wxDelegateRendererNative +{ +public: + // create the object wrapping the given renderer created from this DLL + // + // we take ownership of the pointer and will delete it (and also unload the + // DLL) when we're deleted + wxRendererFromDynLib(wxDynamicLibrary& dll, wxRendererNative *renderer) + : wxDelegateRendererNative(*renderer), + m_renderer(renderer), + m_dllHandle(dll.Detach()) + { + } + + virtual ~wxRendererFromDynLib() + { + delete m_renderer; + wxDynamicLibrary::Unload(m_dllHandle); + } + +private: + wxRendererNative *m_renderer; + wxDllType m_dllHandle; +}; + +#endif // wxUSE_DYNLIB_CLASS + // ============================================================================ // wxRendererNative implementation // ============================================================================ +wxRendererNative::~wxRendererNative() +{ + // empty but necessary +} + +// ---------------------------------------------------------------------------- +// Managing the global renderer +// ---------------------------------------------------------------------------- + /* static */ wxRendererNative& wxRendererNative::Get() { - static wxRendererPtr s_renderer; + wxRendererPtr& renderer = wxRendererPtr::Get(); + + return renderer.IsOk() ? *renderer.get() : GetDefault(); +} + +/* static */ +wxRendererNative *wxRendererNative::Set(wxRendererNative *rendererNew) +{ + wxRendererPtr& renderer = wxRendererPtr::Get(); + + wxRendererNative *rendererOld = renderer.release(); + + renderer.reset(rendererNew); + + return rendererOld; +} + + +// ---------------------------------------------------------------------------- +// Dynamic renderers loading +// ---------------------------------------------------------------------------- + +#if wxUSE_DYNLIB_CLASS + +/* static */ +wxRendererNative *wxRendererNative::Load(const wxString& name) +{ + wxString fullname = wxDynamicLibrary::CanonicalizePluginName(name); + + wxDynamicLibrary dll(fullname); + if ( !dll.IsLoaded() ) + return NULL; + + // each theme DLL must export a wxCreateRenderer() function with this + // signature + typedef wxRendererNative *(*wxCreateRenderer_t)(); + + wxDYNLIB_FUNCTION(wxCreateRenderer_t, wxCreateRenderer, dll); + if ( !pfnwxCreateRenderer ) + return NULL; + + // create a renderer object + wxRendererNative *renderer = (*pfnwxCreateRenderer)(); + if ( !renderer ) + return NULL; + + // check that its version is compatible with ours + wxRendererVersion ver = renderer->GetVersion(); + if ( !wxRendererVersion::IsCompatible(ver) ) + { + wxLogError(_("Renderer \"%s\" has incompatible version %d.%d and couldn't be loaded."), + name.c_str(), ver.version, ver.age); + delete renderer; + + return NULL; + } - return s_renderer.IsOk() ? *s_renderer.get() : GetDefault(); + // finally wrap the renderer in an object which will delete it and unload + // the library when it is deleted and return it to the caller + return new wxRendererFromDynLib(dll, renderer); } +#endif // wxUSE_DYNLIB_CLASS