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