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