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