]> git.saurik.com Git - wxWidgets.git/blob - include/wx/containr.h
0549e6be09a0ab2e0bd6e5bb6aceb0d3de83a6b9
[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 // By default, we accept focus ourselves.
46 m_acceptsFocusSelf = true;
47
48 // But we don't have any children accepting it yet.
49 m_acceptsFocusChildren = false;
50
51 m_inSetFocus = false;
52 m_winLastFocused = NULL;
53 }
54 virtual ~wxControlContainerBase() {}
55
56 void SetContainerWindow(wxWindow *winParent)
57 {
58 wxASSERT_MSG( !m_winParent, wxT("shouldn't be called twice") );
59
60 m_winParent = winParent;
61 }
62
63 // This can be called by the window to indicate that it never wants to have
64 // the focus for itself.
65 void DisableSelfFocus() { m_acceptsFocusSelf = false; }
66
67 // should be called from SetFocus(), returns false if we did nothing with
68 // the focus and the default processing should take place
69 bool DoSetFocus();
70
71 // returns whether we should accept focus ourselves or not
72 bool AcceptsFocus() const { return m_acceptsFocusSelf; }
73
74 // Returns whether we or one of our children accepts focus.
75 bool AcceptsFocusRecursively() const
76 { return m_acceptsFocusSelf || m_acceptsFocusChildren; }
77
78 // We accept focus from keyboard if we accept it at all.
79 bool AcceptsFocusFromKeyboard() const { return AcceptsFocusRecursively(); }
80
81 // Call this when the number of children of the window changes.
82 //
83 // Returns true if we have any focusable children, false otherwise.
84 bool UpdateCanFocusChildren();
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 // Update the window status to reflect whether it is getting focus or not.
101 void UpdateParentCanFocus();
102
103 // Indicates whether the associated window can ever have focus itself.
104 //
105 // Usually this is the case, e.g. a wxPanel can be used either as a
106 // container for its children or just as a normal window which can be
107 // focused. But sometimes, e.g. for wxStaticBox, we can never have focus
108 // ourselves and can only get it if we have any focusable children.
109 bool m_acceptsFocusSelf;
110
111 // Cached value remembering whether we have any children accepting focus.
112 bool m_acceptsFocusChildren;
113
114 // a guard against infinite recursion
115 bool m_inSetFocus;
116 };
117
118 #ifdef wxHAS_NATIVE_TAB_TRAVERSAL
119
120 // ----------------------------------------------------------------------------
121 // wxControlContainer for native TAB navigation
122 // ----------------------------------------------------------------------------
123
124 // this must be a real class as we forward-declare it elsewhere
125 class WXDLLIMPEXP_CORE wxControlContainer : public wxControlContainerBase
126 {
127 protected:
128 // set the focus to the child which had it the last time
129 virtual bool SetFocusToChild();
130 };
131
132 #else // !wxHAS_NATIVE_TAB_TRAVERSAL
133
134 // ----------------------------------------------------------------------------
135 // wxControlContainer for TAB navigation implemented in wx itself
136 // ----------------------------------------------------------------------------
137
138 class WXDLLIMPEXP_CORE wxControlContainer : public wxControlContainerBase
139 {
140 public:
141 // default ctor, SetContainerWindow() must be called later
142 wxControlContainer();
143
144 // the methods to be called from the window event handlers
145 void HandleOnNavigationKey(wxNavigationKeyEvent& event);
146 void HandleOnFocus(wxFocusEvent& event);
147 void HandleOnWindowDestroy(wxWindowBase *child);
148
149 // called from OnChildFocus() handler, i.e. when one of our (grand)
150 // children gets the focus
151 void SetLastFocus(wxWindow *win);
152
153 protected:
154
155 wxDECLARE_NO_COPY_CLASS(wxControlContainer);
156 };
157
158 #endif // wxHAS_NATIVE_TAB_TRAVERSAL/!wxHAS_NATIVE_TAB_TRAVERSAL
159
160 // this function is for wxWidgets internal use only
161 extern WXDLLIMPEXP_CORE bool wxSetFocusToChild(wxWindow *win, wxWindow **child);
162
163 // ----------------------------------------------------------------------------
164 // wxNavigationEnabled: Derive from this class to support keyboard navigation
165 // among window children in a wxWindow-derived class. The details of this class
166 // don't matter, you just need to derive from it to make navigation work.
167 // ----------------------------------------------------------------------------
168
169 // The template parameter W must be a wxWindow-derived class.
170 template <class W>
171 class wxNavigationEnabled : public W
172 {
173 public:
174 typedef W BaseWindowClass;
175
176 wxNavigationEnabled()
177 {
178 m_container.SetContainerWindow(this);
179
180 #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
181 BaseWindowClass::Connect(wxEVT_NAVIGATION_KEY,
182 wxNavigationKeyEventHandler(wxNavigationEnabled::OnNavigationKey));
183
184 BaseWindowClass::Connect(wxEVT_SET_FOCUS,
185 wxFocusEventHandler(wxNavigationEnabled::OnFocus));
186
187 BaseWindowClass::Connect(wxEVT_CHILD_FOCUS,
188 wxChildFocusEventHandler(wxNavigationEnabled::OnChildFocus));
189 #endif // !wxHAS_NATIVE_TAB_TRAVERSAL
190 }
191
192 WXDLLIMPEXP_INLINE_CORE virtual bool AcceptsFocus() const
193 {
194 return m_container.AcceptsFocus();
195 }
196
197 WXDLLIMPEXP_INLINE_CORE virtual bool AcceptsFocusRecursively() const
198 {
199 return m_container.AcceptsFocusRecursively();
200 }
201
202 WXDLLIMPEXP_INLINE_CORE virtual bool AcceptsFocusFromKeyboard() const
203 {
204 return m_container.AcceptsFocusFromKeyboard();
205 }
206
207 WXDLLIMPEXP_INLINE_CORE virtual void AddChild(wxWindowBase *child)
208 {
209 BaseWindowClass::AddChild(child);
210
211 if ( m_container.UpdateCanFocusChildren() )
212 {
213 // Under MSW we must have wxTAB_TRAVERSAL style for TAB navigation
214 // to work.
215 if ( !BaseWindowClass::HasFlag(wxTAB_TRAVERSAL) )
216 BaseWindowClass::ToggleWindowStyle(wxTAB_TRAVERSAL);
217 }
218 }
219
220 WXDLLIMPEXP_INLINE_CORE virtual void RemoveChild(wxWindowBase *child)
221 {
222 #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
223 m_container.HandleOnWindowDestroy(child);
224 #endif // !wxHAS_NATIVE_TAB_TRAVERSAL
225
226 BaseWindowClass::RemoveChild(child);
227
228 // We could reset wxTAB_TRAVERSAL here but it doesn't seem to do any
229 // harm to keep it.
230 m_container.UpdateCanFocusChildren();
231 }
232
233 WXDLLIMPEXP_INLINE_CORE virtual void SetFocus()
234 {
235 if ( !m_container.DoSetFocus() )
236 BaseWindowClass::SetFocus();
237 }
238
239 void SetFocusIgnoringChildren()
240 {
241 BaseWindowClass::SetFocus();
242 }
243
244 protected:
245 #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
246 void OnNavigationKey(wxNavigationKeyEvent& event)
247 {
248 m_container.HandleOnNavigationKey(event);
249 }
250
251 void OnFocus(wxFocusEvent& event)
252 {
253 m_container.HandleOnFocus(event);
254 }
255
256 void OnChildFocus(wxChildFocusEvent& event)
257 {
258 m_container.SetLastFocus(event.GetWindow());
259 event.Skip();
260 }
261 #endif // !wxHAS_NATIVE_TAB_TRAVERSAL
262
263 wxControlContainer m_container;
264
265
266 wxDECLARE_NO_COPY_TEMPLATE_CLASS(wxNavigationEnabled, W);
267 };
268
269 // ----------------------------------------------------------------------------
270 // Compatibility macros from now on, do NOT use them and preferably do not even
271 // look at them.
272 // ----------------------------------------------------------------------------
273
274 #if WXWIN_COMPATIBILITY_2_8
275
276 // common part of WX_DECLARE_CONTROL_CONTAINER in the native and generic cases,
277 // it should be used in the wxWindow-derived class declaration
278 #define WX_DECLARE_CONTROL_CONTAINER_BASE() \
279 public: \
280 virtual bool AcceptsFocus() const; \
281 virtual bool AcceptsFocusRecursively() const; \
282 virtual bool AcceptsFocusFromKeyboard() const; \
283 virtual void AddChild(wxWindowBase *child); \
284 virtual void RemoveChild(wxWindowBase *child); \
285 virtual void SetFocus(); \
286 void SetFocusIgnoringChildren(); \
287 \
288 protected: \
289 wxControlContainer m_container
290
291 // this macro must be used in the derived class ctor
292 #define WX_INIT_CONTROL_CONTAINER() \
293 m_container.SetContainerWindow(this)
294
295 // common part of WX_DELEGATE_TO_CONTROL_CONTAINER in the native and generic
296 // cases, must be used in the wxWindow-derived class implementation
297 #define WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \
298 void classname::AddChild(wxWindowBase *child) \
299 { \
300 basename::AddChild(child); \
301 \
302 m_container.UpdateCanFocusChildren(); \
303 } \
304 \
305 bool classname::AcceptsFocusRecursively() const \
306 { \
307 return m_container.AcceptsFocusRecursively(); \
308 } \
309 \
310 void classname::SetFocus() \
311 { \
312 if ( !m_container.DoSetFocus() ) \
313 basename::SetFocus(); \
314 } \
315 \
316 bool classname::AcceptsFocus() const \
317 { \
318 return m_container.AcceptsFocus(); \
319 } \
320 \
321 bool classname::AcceptsFocusFromKeyboard() const \
322 { \
323 return m_container.AcceptsFocusFromKeyboard(); \
324 }
325
326
327 #ifdef wxHAS_NATIVE_TAB_TRAVERSAL
328
329 #define WX_EVENT_TABLE_CONTROL_CONTAINER(classname)
330
331 #define WX_DECLARE_CONTROL_CONTAINER WX_DECLARE_CONTROL_CONTAINER_BASE
332
333 #define WX_DELEGATE_TO_CONTROL_CONTAINER(classname, basename) \
334 WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \
335 \
336 void classname::RemoveChild(wxWindowBase *child) \
337 { \
338 basename::RemoveChild(child); \
339 \
340 m_container.UpdateCanFocusChildren(); \
341 } \
342 \
343 void classname::SetFocusIgnoringChildren() \
344 { \
345 basename::SetFocus(); \
346 }
347
348 #else // !wxHAS_NATIVE_TAB_TRAVERSAL
349
350 // declare the methods to be forwarded
351 #define WX_DECLARE_CONTROL_CONTAINER() \
352 WX_DECLARE_CONTROL_CONTAINER_BASE(); \
353 \
354 public: \
355 void OnNavigationKey(wxNavigationKeyEvent& event); \
356 void OnFocus(wxFocusEvent& event); \
357 virtual void OnChildFocus(wxChildFocusEvent& event)
358
359 // implement the event table entries for wxControlContainer
360 #define WX_EVENT_TABLE_CONTROL_CONTAINER(classname) \
361 EVT_SET_FOCUS(classname::OnFocus) \
362 EVT_CHILD_FOCUS(classname::OnChildFocus) \
363 EVT_NAVIGATION_KEY(classname::OnNavigationKey)
364
365 // implement the methods forwarding to the wxControlContainer
366 #define WX_DELEGATE_TO_CONTROL_CONTAINER(classname, basename) \
367 WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \
368 \
369 void classname::RemoveChild(wxWindowBase *child) \
370 { \
371 m_container.HandleOnWindowDestroy(child); \
372 \
373 basename::RemoveChild(child); \
374 \
375 m_container.UpdateCanFocusChildren(); \
376 } \
377 \
378 void classname::OnNavigationKey( wxNavigationKeyEvent& event ) \
379 { \
380 m_container.HandleOnNavigationKey(event); \
381 } \
382 \
383 void classname::SetFocusIgnoringChildren() \
384 { \
385 basename::SetFocus(); \
386 } \
387 \
388 void classname::OnChildFocus(wxChildFocusEvent& event) \
389 { \
390 m_container.SetLastFocus(event.GetWindow()); \
391 event.Skip(); \
392 } \
393 \
394 void classname::OnFocus(wxFocusEvent& event) \
395 { \
396 m_container.HandleOnFocus(event); \
397 }
398
399 #endif // wxHAS_NATIVE_TAB_TRAVERSAL/!wxHAS_NATIVE_TAB_TRAVERSAL
400
401 #endif // WXWIN_COMPATIBILITY_2_8
402
403 #endif // _WX_CONTAINR_H_