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