]>
Commit | Line | Data |
---|---|---|
1 | /////////////////////////////////////////////////////////////////////////////// | |
2 | // Name: wx/persist.h | |
3 | // Purpose: common classes for persistence support | |
4 | // Author: Vadim Zeitlin | |
5 | // Created: 2009-01-18 | |
6 | // RCS-ID: $Id$ | |
7 | // Copyright: (c) 2009 Vadim Zeitlin <vadim@wxwidgets.org> | |
8 | // Licence: wxWindows licence | |
9 | /////////////////////////////////////////////////////////////////////////////// | |
10 | ||
11 | #ifndef _WX_PERSIST_H_ | |
12 | #define _WX_PERSIST_H_ | |
13 | ||
14 | #include "wx/string.h" | |
15 | #include "wx/hashmap.h" | |
16 | #include "wx/confbase.h" | |
17 | ||
18 | class wxPersistentObject; | |
19 | ||
20 | WX_DECLARE_VOIDPTR_HASH_MAP(wxPersistentObject *, wxPersistentObjectsMap); | |
21 | ||
22 | // ---------------------------------------------------------------------------- | |
23 | // global functions | |
24 | // ---------------------------------------------------------------------------- | |
25 | ||
26 | /* | |
27 | We do _not_ declare this function as doing this would force us to specialize | |
28 | it for the user classes deriving from the standard persistent classes. | |
29 | However we do define overloads of wxCreatePersistentObject() for all the wx | |
30 | classes which means that template wxPersistentObject::Restore() picks up the | |
31 | right overload to use provided that the header defining the correct overload | |
32 | is included before calling it. And a compilation error happens if this is | |
33 | not done. | |
34 | ||
35 | template <class T> | |
36 | wxPersistentObject *wxCreatePersistentObject(T *obj); | |
37 | ||
38 | */ | |
39 | ||
40 | // ---------------------------------------------------------------------------- | |
41 | // wxPersistenceManager: global aspects of persistent windows | |
42 | // ---------------------------------------------------------------------------- | |
43 | ||
44 | class WXDLLIMPEXP_CORE wxPersistenceManager | |
45 | { | |
46 | public: | |
47 | // accessor to the unique persistence manager object | |
48 | static wxPersistenceManager& Get(); | |
49 | ||
50 | // trivial but virtual dtor | |
51 | // | |
52 | // FIXME-VC6: this only needs to be public because of VC6 bug | |
53 | virtual ~wxPersistenceManager(); | |
54 | ||
55 | ||
56 | // globally disable restoring or saving the persistent properties (both are | |
57 | // enabled by default) | |
58 | void DisableSaving() { m_doSave = false; } | |
59 | void DisableRestoring() { m_doRestore = false; } | |
60 | ||
61 | ||
62 | // register an object with the manager: when using the first overload, | |
63 | // wxCreatePersistentObject() must be specialized for this object class; | |
64 | // with the second one the persistent adapter is created by the caller | |
65 | // | |
66 | // the object shouldn't be already registered with us | |
67 | template <class T> | |
68 | wxPersistentObject *Register(T *obj) | |
69 | { | |
70 | return Register(obj, wxCreatePersistentObject(obj)); | |
71 | } | |
72 | ||
73 | wxPersistentObject *Register(void *obj, wxPersistentObject *po); | |
74 | ||
75 | // check if the object is registered and return the associated | |
76 | // wxPersistentObject if it is or NULL otherwise | |
77 | wxPersistentObject *Find(void *obj) const; | |
78 | ||
79 | // unregister the object, this is called by wxPersistentObject itself so | |
80 | // there is usually no need to do it explicitly | |
81 | // | |
82 | // deletes the associated wxPersistentObject | |
83 | void Unregister(void *obj); | |
84 | ||
85 | ||
86 | // save/restore the state of an object | |
87 | // | |
88 | // these methods do nothing if DisableSaving/Restoring() was called | |
89 | // | |
90 | // Restore() returns true if the object state was really restored | |
91 | void Save(void *obj); | |
92 | bool Restore(void *obj); | |
93 | ||
94 | // combines both Save() and Unregister() calls | |
95 | void SaveAndUnregister(void *obj) | |
96 | { | |
97 | Save(obj); | |
98 | Unregister(obj); | |
99 | } | |
100 | ||
101 | // combines both Register() and Restore() calls | |
102 | template <class T> | |
103 | bool RegisterAndRestore(T *obj) | |
104 | { | |
105 | return Register(obj) && Restore(obj); | |
106 | } | |
107 | ||
108 | bool RegisterAndRestore(void *obj, wxPersistentObject *po) | |
109 | { | |
110 | return Register(obj, po) && Restore(obj); | |
111 | } | |
112 | ||
113 | ||
114 | // methods used by the persistent objects to save and restore the data | |
115 | // | |
116 | // currently these methods simply use wxConfig::Get() but they may be | |
117 | // overridden in the derived class (once we allow creating custom | |
118 | // persistent managers) | |
119 | #define wxPERSIST_DECLARE_SAVE_RESTORE_FOR(Type) \ | |
120 | virtual bool SaveValue(const wxPersistentObject& who, \ | |
121 | const wxString& name, \ | |
122 | Type value); \ | |
123 | \ | |
124 | virtual bool \ | |
125 | RestoreValue(const wxPersistentObject& who, \ | |
126 | const wxString& name, \ | |
127 | Type *value) | |
128 | ||
129 | wxPERSIST_DECLARE_SAVE_RESTORE_FOR(bool); | |
130 | wxPERSIST_DECLARE_SAVE_RESTORE_FOR(int); | |
131 | wxPERSIST_DECLARE_SAVE_RESTORE_FOR(long); | |
132 | wxPERSIST_DECLARE_SAVE_RESTORE_FOR(wxString); | |
133 | ||
134 | #undef wxPERSIST_DECLARE_SAVE_RESTORE_FOR | |
135 | ||
136 | private: | |
137 | // ctor is private, use Get() | |
138 | wxPersistenceManager() | |
139 | { | |
140 | m_doSave = | |
141 | m_doRestore = true; | |
142 | } | |
143 | ||
144 | ||
145 | // helpers of Save/Restore() | |
146 | // | |
147 | // TODO: make this customizable by allowing | |
148 | // (a) specifying custom wxConfig object to use | |
149 | // (b) allowing to use something else entirely | |
150 | wxConfigBase *GetConfig() const { return wxConfigBase::Get(); } | |
151 | wxString GetKey(const wxPersistentObject& who, const wxString& name) const; | |
152 | ||
153 | ||
154 | // map with the registered objects as keys and associated | |
155 | // wxPersistentObjects as values | |
156 | wxPersistentObjectsMap m_persistentObjects; | |
157 | ||
158 | // true if we should restore/save the settings (it doesn't make much sense | |
159 | // to use this class when both of them are false but setting one of them to | |
160 | // false may make sense in some situations) | |
161 | bool m_doSave, | |
162 | m_doRestore; | |
163 | ||
164 | wxDECLARE_NO_COPY_CLASS(wxPersistenceManager); | |
165 | }; | |
166 | ||
167 | // ---------------------------------------------------------------------------- | |
168 | // wxPersistentObject: ABC for anything persistent | |
169 | // ---------------------------------------------------------------------------- | |
170 | ||
171 | class wxPersistentObject | |
172 | { | |
173 | public: | |
174 | // ctor associates us with the object whose options we save/restore | |
175 | wxPersistentObject(void *obj) : m_obj(obj) { } | |
176 | ||
177 | // trivial but virtual dtor | |
178 | virtual ~wxPersistentObject() { } | |
179 | ||
180 | ||
181 | // methods used by wxPersistenceManager | |
182 | // ------------------------------------ | |
183 | ||
184 | // save/restore the corresponding objects settings | |
185 | // | |
186 | // these methods shouldn't be used directly as they don't respect the | |
187 | // global wxPersistenceManager::DisableSaving/Restoring() settings, use | |
188 | // wxPersistenceManager methods with the same name instead | |
189 | virtual void Save() const = 0; | |
190 | virtual bool Restore() = 0; | |
191 | ||
192 | ||
193 | // get the kind of the objects we correspond to, e.g. "Frame" | |
194 | virtual wxString GetKind() const = 0; | |
195 | ||
196 | // get the name of the object we correspond to, e.g. "Main" | |
197 | virtual wxString GetName() const = 0; | |
198 | ||
199 | ||
200 | // return the associated object | |
201 | void *GetObject() const { return m_obj; } | |
202 | ||
203 | protected: | |
204 | // wrappers for wxPersistenceManager methods which don't require passing | |
205 | // "this" as the first parameter all the time | |
206 | template <typename T> | |
207 | bool SaveValue(const wxString& name, T value) const | |
208 | { | |
209 | return wxPersistenceManager::Get().SaveValue(*this, name, value); | |
210 | } | |
211 | ||
212 | template <typename T> | |
213 | bool RestoreValue(const wxString& name, T *value) | |
214 | { | |
215 | return wxPersistenceManager::Get().RestoreValue(*this, name, value); | |
216 | } | |
217 | ||
218 | private: | |
219 | void * const m_obj; | |
220 | ||
221 | wxDECLARE_NO_COPY_CLASS(wxPersistentObject); | |
222 | }; | |
223 | ||
224 | // FIXME-VC6: VC6 has troubles with template methods of DLL-exported classes, | |
225 | // apparently it believes they should be defined in the DLL (which | |
226 | // is, of course, impossible as the DLL doesn't know for which types | |
227 | // will they be instantiated) instead of compiling them when | |
228 | // building the main application itself. Because of this problem | |
229 | // (which only arises in debug build!) we can't use the usual | |
230 | // RegisterAndRestore(obj) with it and need to explicitly create the | |
231 | // persistence adapter. To hide this ugliness we define a global | |
232 | // function which does it for us. | |
233 | template <typename T> | |
234 | inline bool wxPersistentRegisterAndRestore(T *obj) | |
235 | { | |
236 | wxPersistentObject * const pers = wxCreatePersistentObject(obj); | |
237 | ||
238 | return wxPersistenceManager::Get().RegisterAndRestore(obj, pers); | |
239 | ||
240 | } | |
241 | ||
242 | // A helper function which also sets the name for the (wxWindow-derived) object | |
243 | // before registering and restoring it. | |
244 | template <typename T> | |
245 | inline bool wxPersistentRegisterAndRestore(T *obj, const wxString& name) | |
246 | { | |
247 | obj->SetName(name); | |
248 | ||
249 | return wxPersistentRegisterAndRestore(obj); | |
250 | } | |
251 | ||
252 | #endif // _WX_PERSIST_H_ | |
253 |