]> git.saurik.com Git - wxWidgets.git/blob - include/wx/containr.h
avoid creating and immediately destroying a wxGraphicsContext when creating a wxDC...
[wxWidgets.git] / include / wx / containr.h
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: wx/containr.h
3 // Purpose: wxControlContainer and wxNavigationEnabled declarations
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 06.08.01
7 // RCS-ID: $Id$
8 // Copyright: (c) 2001, 2011 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 #ifndef _WX_CONTAINR_H_
13 #define _WX_CONTAINR_H_
14
15 #include "wx/defs.h"
16
17 #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
18 // We need wxEVT_XXX declarations in this case.
19 #include "wx/event.h"
20 #endif
21
22 class WXDLLIMPEXP_FWD_CORE wxWindow;
23 class WXDLLIMPEXP_FWD_CORE wxWindowBase;
24
25 /*
26 This header declares wxControlContainer class however it's not a real
27 container of controls but rather just a helper used to implement TAB
28 navigation among the window children. You should rarely need to use it
29 directly, derive from the documented public wxNavigationEnabled<> class to
30 implement TAB navigation in a custom composite window.
31 */
32
33 // ----------------------------------------------------------------------------
34 // wxControlContainerBase: common part used in both native and generic cases
35 // ----------------------------------------------------------------------------
36
37 class WXDLLIMPEXP_CORE wxControlContainerBase
38 {
39 public:
40 // default ctor, SetContainerWindow() must be called later
41 wxControlContainerBase()
42 {
43 m_winParent = NULL;
44
45 // do accept focus initially, we'll stop doing it if/when any children
46 // are added
47 m_acceptsFocus = true;
48 m_inSetFocus = false;
49 m_winLastFocused = NULL;
50 }
51 virtual ~wxControlContainerBase() {}
52
53 void SetContainerWindow(wxWindow *winParent)
54 {
55 wxASSERT_MSG( !m_winParent, wxT("shouldn't be called twice") );
56
57 m_winParent = winParent;
58 }
59
60 // should be called from SetFocus(), returns false if we did nothing with
61 // the focus and the default processing should take place
62 bool DoSetFocus();
63
64 // should be called when we decide that we should [stop] accepting focus
65 void SetCanFocus(bool acceptsFocus);
66
67 // returns whether we should accept focus ourselves or not
68 bool AcceptsFocus() const { return m_acceptsFocus; }
69
70 // returns whether we or one of our children accepts focus: we always do
71 // because if we don't have any focusable children it probably means that
72 // we're not being used as a container at all (think of wxGrid or generic
73 // wxListCtrl) and so should get focus for ourselves
74 bool AcceptsFocusRecursively() const { return true; }
75
76 // this is used to determine whether we can accept focus when Tab or
77 // another navigation key is pressed -- we alsways can, for the same reason
78 // as mentioned above for AcceptsFocusRecursively()
79 bool AcceptsFocusFromKeyboard() const { return true; }
80
81 // Call this when the number of children of the window changes.
82 // If we have any children, this panel (used just as container for
83 // them) shouldn't get focus for itself.
84 void UpdateCanFocus() { SetCanFocus(!HasAnyFocusableChildren()); }
85
86 protected:
87 // set the focus to the child which had it the last time
88 virtual bool SetFocusToChild();
89
90 // return true if we have any children accepting focus
91 bool HasAnyFocusableChildren() const;
92
93 // the parent window we manage the children for
94 wxWindow *m_winParent;
95
96 // the child which had the focus last time this panel was activated
97 wxWindow *m_winLastFocused;
98
99 private:
100 // value returned by AcceptsFocus(), should be changed using SetCanFocus()
101 // only
102 bool m_acceptsFocus;
103
104 // a guard against infinite recursion
105 bool m_inSetFocus;
106 };
107
108 #ifdef wxHAS_NATIVE_TAB_TRAVERSAL
109
110 // ----------------------------------------------------------------------------
111 // wxControlContainer for native TAB navigation
112 // ----------------------------------------------------------------------------
113
114 // this must be a real class as we forward-declare it elsewhere
115 class WXDLLIMPEXP_CORE wxControlContainer : public wxControlContainerBase
116 {
117 protected:
118 // set the focus to the child which had it the last time
119 virtual bool SetFocusToChild();
120 };
121
122 #else // !wxHAS_NATIVE_TAB_TRAVERSAL
123
124 // ----------------------------------------------------------------------------
125 // wxControlContainer for TAB navigation implemented in wx itself
126 // ----------------------------------------------------------------------------
127
128 class WXDLLIMPEXP_CORE wxControlContainer : public wxControlContainerBase
129 {
130 public:
131 // default ctor, SetContainerWindow() must be called later
132 wxControlContainer();
133
134 // the methods to be called from the window event handlers
135 void HandleOnNavigationKey(wxNavigationKeyEvent& event);
136 void HandleOnFocus(wxFocusEvent& event);
137 void HandleOnWindowDestroy(wxWindowBase *child);
138
139 // called from OnChildFocus() handler, i.e. when one of our (grand)
140 // children gets the focus
141 void SetLastFocus(wxWindow *win);
142
143 protected:
144
145 wxDECLARE_NO_COPY_CLASS(wxControlContainer);
146 };
147
148 #endif // wxHAS_NATIVE_TAB_TRAVERSAL/!wxHAS_NATIVE_TAB_TRAVERSAL
149
150 // this function is for wxWidgets internal use only
151 extern WXDLLIMPEXP_CORE bool wxSetFocusToChild(wxWindow *win, wxWindow **child);
152
153 // ----------------------------------------------------------------------------
154 // wxNavigationEnabled: Derive from this class to support keyboard navigation
155 // among window children in a wxWindow-derived class. The details of this class
156 // don't matter, you just need to derive from it to make navigation work.
157 // ----------------------------------------------------------------------------
158
159 // The template parameter W must be a wxWindow-derived class.
160 template <class W>
161 class wxNavigationEnabled : public W
162 {
163 public:
164 typedef W BaseWindowClass;
165
166 wxNavigationEnabled()
167 {
168 m_container.SetContainerWindow(this);
169
170 #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
171 BaseWindowClass::Connect(wxEVT_NAVIGATION_KEY,
172 wxNavigationKeyEventHandler(wxNavigationEnabled::OnNavigationKey));
173
174 BaseWindowClass::Connect(wxEVT_SET_FOCUS,
175 wxFocusEventHandler(wxNavigationEnabled::OnFocus));
176
177 BaseWindowClass::Connect(wxEVT_CHILD_FOCUS,
178 wxChildFocusEventHandler(wxNavigationEnabled::OnChildFocus));
179 #endif // !wxHAS_NATIVE_TAB_TRAVERSAL
180 }
181
182 WXDLLIMPEXP_INLINE_CORE virtual bool AcceptsFocus() const
183 {
184 return m_container.AcceptsFocus();
185 }
186
187 WXDLLIMPEXP_INLINE_CORE virtual bool AcceptsFocusRecursively() const
188 {
189 return m_container.AcceptsFocusRecursively();
190 }
191
192 WXDLLIMPEXP_INLINE_CORE virtual bool AcceptsFocusFromKeyboard() const
193 {
194 return m_container.AcceptsFocusFromKeyboard();
195 }
196
197 WXDLLIMPEXP_INLINE_CORE virtual void AddChild(wxWindowBase *child)
198 {
199 BaseWindowClass::AddChild(child);
200
201 m_container.UpdateCanFocus();
202 }
203
204 WXDLLIMPEXP_INLINE_CORE virtual void RemoveChild(wxWindowBase *child)
205 {
206 #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
207 m_container.HandleOnWindowDestroy(child);
208 #endif // !wxHAS_NATIVE_TAB_TRAVERSAL
209
210 BaseWindowClass::RemoveChild(child);
211
212 m_container.UpdateCanFocus();
213 }
214
215 WXDLLIMPEXP_INLINE_CORE virtual void SetFocus()
216 {
217 if ( !m_container.DoSetFocus() )
218 BaseWindowClass::SetFocus();
219 }
220
221 void SetFocusIgnoringChildren()
222 {
223 BaseWindowClass::SetFocus();
224 }
225
226 void AcceptFocus(bool acceptFocus)
227 {
228 m_container.SetCanFocus(acceptFocus);
229 }
230
231 protected:
232 #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
233 void OnNavigationKey(wxNavigationKeyEvent& event)
234 {
235 m_container.HandleOnNavigationKey(event);
236 }
237
238 void OnFocus(wxFocusEvent& event)
239 {
240 m_container.HandleOnFocus(event);
241 }
242
243 void OnChildFocus(wxChildFocusEvent& event)
244 {
245 m_container.SetLastFocus(event.GetWindow());
246 event.Skip();
247 }
248 #endif // !wxHAS_NATIVE_TAB_TRAVERSAL
249
250 wxControlContainer m_container;
251
252
253 wxDECLARE_NO_COPY_TEMPLATE_CLASS(wxNavigationEnabled, W);
254 };
255
256 // ----------------------------------------------------------------------------
257 // Compatibility macros from now on, do NOT use them and preferably do not even
258 // look at them.
259 // ----------------------------------------------------------------------------
260
261 #if WXWIN_COMPATIBILITY_2_8
262
263 // common part of WX_DECLARE_CONTROL_CONTAINER in the native and generic cases,
264 // it should be used in the wxWindow-derived class declaration
265 #define WX_DECLARE_CONTROL_CONTAINER_BASE() \
266 public: \
267 virtual bool AcceptsFocus() const; \
268 virtual bool AcceptsFocusRecursively() const; \
269 virtual bool AcceptsFocusFromKeyboard() const; \
270 virtual void AddChild(wxWindowBase *child); \
271 virtual void RemoveChild(wxWindowBase *child); \
272 virtual void SetFocus(); \
273 void SetFocusIgnoringChildren(); \
274 void AcceptFocus(bool acceptFocus) \
275 { \
276 m_container.SetCanFocus(acceptFocus); \
277 } \
278 \
279 protected: \
280 wxControlContainer m_container
281
282 // this macro must be used in the derived class ctor
283 #define WX_INIT_CONTROL_CONTAINER() \
284 m_container.SetContainerWindow(this)
285
286 // common part of WX_DELEGATE_TO_CONTROL_CONTAINER in the native and generic
287 // cases, must be used in the wxWindow-derived class implementation
288 #define WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \
289 void classname::AddChild(wxWindowBase *child) \
290 { \
291 basename::AddChild(child); \
292 \
293 m_container.UpdateCanFocus(); \
294 } \
295 \
296 bool classname::AcceptsFocusRecursively() const \
297 { \
298 return m_container.AcceptsFocusRecursively(); \
299 } \
300 \
301 void classname::SetFocus() \
302 { \
303 if ( !m_container.DoSetFocus() ) \
304 basename::SetFocus(); \
305 } \
306 \
307 bool classname::AcceptsFocus() const \
308 { \
309 return m_container.AcceptsFocus(); \
310 } \
311 \
312 bool classname::AcceptsFocusFromKeyboard() const \
313 { \
314 return m_container.AcceptsFocusFromKeyboard(); \
315 }
316
317
318 #ifdef wxHAS_NATIVE_TAB_TRAVERSAL
319
320 #define WX_EVENT_TABLE_CONTROL_CONTAINER(classname)
321
322 #define WX_DECLARE_CONTROL_CONTAINER WX_DECLARE_CONTROL_CONTAINER_BASE
323
324 #define WX_DELEGATE_TO_CONTROL_CONTAINER(classname, basename) \
325 WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \
326 \
327 void classname::RemoveChild(wxWindowBase *child) \
328 { \
329 basename::RemoveChild(child); \
330 \
331 m_container.UpdateCanFocus(); \
332 } \
333 \
334 void classname::SetFocusIgnoringChildren() \
335 { \
336 basename::SetFocus(); \
337 }
338
339 #else // !wxHAS_NATIVE_TAB_TRAVERSAL
340
341 // declare the methods to be forwarded
342 #define WX_DECLARE_CONTROL_CONTAINER() \
343 WX_DECLARE_CONTROL_CONTAINER_BASE(); \
344 \
345 public: \
346 void OnNavigationKey(wxNavigationKeyEvent& event); \
347 void OnFocus(wxFocusEvent& event); \
348 virtual void OnChildFocus(wxChildFocusEvent& event)
349
350 // implement the event table entries for wxControlContainer
351 #define WX_EVENT_TABLE_CONTROL_CONTAINER(classname) \
352 EVT_SET_FOCUS(classname::OnFocus) \
353 EVT_CHILD_FOCUS(classname::OnChildFocus) \
354 EVT_NAVIGATION_KEY(classname::OnNavigationKey)
355
356 // implement the methods forwarding to the wxControlContainer
357 #define WX_DELEGATE_TO_CONTROL_CONTAINER(classname, basename) \
358 WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \
359 \
360 void classname::RemoveChild(wxWindowBase *child) \
361 { \
362 m_container.HandleOnWindowDestroy(child); \
363 \
364 basename::RemoveChild(child); \
365 \
366 m_container.UpdateCanFocus(); \
367 } \
368 \
369 void classname::OnNavigationKey( wxNavigationKeyEvent& event ) \
370 { \
371 m_container.HandleOnNavigationKey(event); \
372 } \
373 \
374 void classname::SetFocusIgnoringChildren() \
375 { \
376 basename::SetFocus(); \
377 } \
378 \
379 void classname::OnChildFocus(wxChildFocusEvent& event) \
380 { \
381 m_container.SetLastFocus(event.GetWindow()); \
382 event.Skip(); \
383 } \
384 \
385 void classname::OnFocus(wxFocusEvent& event) \
386 { \
387 m_container.HandleOnFocus(event); \
388 }
389
390 #endif // wxHAS_NATIVE_TAB_TRAVERSAL/!wxHAS_NATIVE_TAB_TRAVERSAL
391
392 #endif // WXWIN_COMPATIBILITY_2_8
393
394 #endif // _WX_CONTAINR_H_