1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        src/common/rendcmn.cpp
3 // Purpose:     wxRendererNative common functions
4 // Author:      Vadim Zeitlin
5 // Modified by:
6 // Created:     28.07.03
7 // Copyright:   (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
8 // Licence:     wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10 
11 // ============================================================================
12 // declarations
13 // ============================================================================
14 
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18 
19 #include "wx/wxprec.h"
20 
21 #ifdef __BORLANDC__
22     #pragma hdrstop
23 #endif
24 
25 #ifndef WX_PRECOMP
26     #include "wx/app.h"
27     #include "wx/log.h"
28     #include "wx/intl.h"
29 #endif //WX_PRECOMP
30 
31 #include "wx/apptrait.h"
32 #include "wx/renderer.h"
33 
34 #include "wx/scopedptr.h"
35 
36 #if wxUSE_DYNLIB_CLASS
37     #include "wx/dynlib.h"
38 #endif // wxUSE_DYNLIB_CLASS
39 
40 // ----------------------------------------------------------------------------
41 // wxRendererPtr: auto pointer holding the global renderer
42 // ----------------------------------------------------------------------------
43 
44 typedef wxScopedPtr<wxRendererNative> wxRendererPtrBase;
45 
46 class wxRendererPtr : public wxRendererPtrBase
47 {
48 public:
49     // return true if we have a renderer, false otherwise
IsOk()50     bool IsOk()
51     {
52         if ( !m_initialized )
53         {
54             // only try to create the renderer once
55             m_initialized = true;
56 
57             DoInit();
58         }
59 
60         return get() != NULL;
61     }
62 
63     // return the global and unique wxRendererPtr
64     static wxRendererPtr& Get();
65 
66 private:
wxRendererPtr()67     wxRendererPtr() : wxRendererPtrBase(NULL) { m_initialized = false; }
68 
DoInit()69     void DoInit()
70     {
71         wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL;
72         if ( traits )
73         {
74             // ask the traits object to create a renderer for us
75             reset(traits->CreateRenderer());
76         }
77     }
78 
79     bool m_initialized;
80 
81     // just to suppress a gcc warning
82     friend class wxRendererPtrDummyFriend;
83 
84     wxDECLARE_NO_COPY_CLASS(wxRendererPtr);
85 };
86 
87 // return the global and unique wxRendererPtr
Get()88 /*static*/ wxRendererPtr& wxRendererPtr::Get()
89 {
90     static wxRendererPtr s_renderer;
91 
92     return s_renderer;
93 }
94 
95 #if wxUSE_DYNLIB_CLASS
96 
97 // ----------------------------------------------------------------------------
98 // wxRendererFromDynLib: represents a renderer dynamically loaded from a DLL
99 // ----------------------------------------------------------------------------
100 
101 class wxRendererFromDynLib : public wxDelegateRendererNative
102 {
103 public:
104     // create the object wrapping the given renderer created from this DLL
105     //
106     // we take ownership of the pointer and will delete it (and also unload the
107     // DLL) when we're deleted
wxRendererFromDynLib(wxDynamicLibrary & dll,wxRendererNative * renderer)108     wxRendererFromDynLib(wxDynamicLibrary& dll, wxRendererNative *renderer)
109         : wxDelegateRendererNative(*renderer),
110           m_renderer(renderer),
111           m_dllHandle(dll.Detach())
112         {
113         }
114 
~wxRendererFromDynLib()115     virtual ~wxRendererFromDynLib()
116     {
117         delete m_renderer;
118         wxDynamicLibrary::Unload(m_dllHandle);
119     }
120 
121 private:
122     wxRendererNative *m_renderer;
123     wxDllType m_dllHandle;
124 };
125 
126 #endif // wxUSE_DYNLIB_CLASS
127 
128 // ============================================================================
129 // wxRendererNative implementation
130 // ============================================================================
131 
~wxRendererNative()132 wxRendererNative::~wxRendererNative()
133 {
134     // empty but necessary
135 }
136 
137 // ----------------------------------------------------------------------------
138 // Managing the global renderer
139 // ----------------------------------------------------------------------------
140 
141 /* static */
Get()142 wxRendererNative& wxRendererNative::Get()
143 {
144     wxRendererPtr& renderer = wxRendererPtr::Get();
145 
146     return renderer.IsOk() ? *renderer.get() : GetDefault();
147 }
148 
149 /* static */
Set(wxRendererNative * rendererNew)150 wxRendererNative *wxRendererNative::Set(wxRendererNative *rendererNew)
151 {
152     wxRendererPtr& renderer = wxRendererPtr::Get();
153 
154     wxRendererNative *rendererOld = renderer.release();
155 
156     renderer.reset(rendererNew);
157 
158     return rendererOld;
159 }
160 
161 
162 // ----------------------------------------------------------------------------
163 // Dynamic renderers loading
164 // ----------------------------------------------------------------------------
165 
166 #if wxUSE_DYNLIB_CLASS
167 
168 /* static */
Load(const wxString & name)169 wxRendererNative *wxRendererNative::Load(const wxString& name)
170 {
171     wxString fullname = wxDynamicLibrary::CanonicalizePluginName(name);
172 
173     wxDynamicLibrary dll(fullname);
174     if ( !dll.IsLoaded() )
175         return NULL;
176 
177     // each theme DLL must export a wxCreateRenderer() function with this
178     // signature
179     typedef wxRendererNative *(*wxCreateRenderer_t)();
180 
181     wxDYNLIB_FUNCTION(wxCreateRenderer_t, wxCreateRenderer, dll);
182     if ( !pfnwxCreateRenderer )
183         return NULL;
184 
185     // create a renderer object
186     wxRendererNative *renderer = (*pfnwxCreateRenderer)();
187     if ( !renderer )
188         return NULL;
189 
190     // check that its version is compatible with ours
191     wxRendererVersion ver = renderer->GetVersion();
192     if ( !wxRendererVersion::IsCompatible(ver) )
193     {
194         wxLogError(_("Renderer \"%s\" has incompatible version %d.%d and couldn't be loaded."),
195                    name.c_str(), ver.version, ver.age);
196         delete renderer;
197 
198         return NULL;
199     }
200 
201     // finally wrap the renderer in an object which will delete it and unload
202     // the library when it is deleted and return it to the caller
203     return new wxRendererFromDynLib(dll, renderer);
204 }
205 
206 #endif // wxUSE_DYNLIB_CLASS
207