using terminate: terminates prematurely, OnExit is not called anymore
[wxWidgets.git] / src / common / rendcmn.cpp
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
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:
67 wxRendererPtr() : wxRendererPtrBase(NULL) { m_initialized = false; }
68
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
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
108 wxRendererFromDynLib(wxDynamicLibrary& dll, wxRendererNative *renderer)
109 : wxDelegateRendererNative(*renderer),
110 m_renderer(renderer),
111 m_dllHandle(dll.Detach())
112 {
113 }
114
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
132 wxRendererNative::~wxRendererNative()
133 {
134 // empty but necessary
135 }
136
137 // ----------------------------------------------------------------------------
138 // Managing the global renderer
139 // ----------------------------------------------------------------------------
140
141 /* static */
142 wxRendererNative& wxRendererNative::Get()
143 {
144 wxRendererPtr& renderer = wxRendererPtr::Get();
145
146 return renderer.IsOk() ? *renderer.get() : GetDefault();
147 }
148
149 /* static */
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 */
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