]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/rendcmn.cpp
[ 1509599 ] 'Split pickers page in widgets sample' with more icons and rebaking.
[wxWidgets.git] / src / common / rendcmn.cpp
index 202ec01517b0e495556d808907fd0aa2e002d246..572600a9bdfea58890ffbdc5fab99426e4cf1225 100644 (file)
@@ -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"
 
 #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,130 @@ 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)();
 
-    return s_renderer.IsOk() ? *s_renderer.get() : GetDefault();
+    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;
+    }
+
+    // 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
+