1 ///////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxControlContainer and wxNavigationEnabled declarations
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 2001, 2011 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 #ifndef _WX_CONTAINR_H_
13 #define _WX_CONTAINR_H_
17 #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
18 // We need wxEVT_XXX declarations in this case.
22 class WXDLLIMPEXP_FWD_CORE wxWindow
;
23 class WXDLLIMPEXP_FWD_CORE wxWindowBase
;
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.
33 // ----------------------------------------------------------------------------
34 // wxControlContainerBase: common part used in both native and generic cases
35 // ----------------------------------------------------------------------------
37 class WXDLLIMPEXP_CORE wxControlContainerBase
40 // default ctor, SetContainerWindow() must be called later
41 wxControlContainerBase()
45 // By default, we accept focus ourselves.
46 m_acceptsFocusSelf
= true;
48 // But we don't have any children accepting it yet.
49 m_acceptsFocusChildren
= false;
52 m_winLastFocused
= NULL
;
54 virtual ~wxControlContainerBase() {}
56 void SetContainerWindow(wxWindow
*winParent
)
58 wxASSERT_MSG( !m_winParent
, wxT("shouldn't be called twice") );
60 m_winParent
= winParent
;
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(); }
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
71 void EnableSelfFocus()
72 { m_acceptsFocusSelf
= true; UpdateParentCanFocus(); }
74 // should be called from SetFocus(), returns false if we did nothing with
75 // the focus and the default processing should take place
78 // returns whether we should accept focus ourselves or not
79 bool AcceptsFocus() const;
81 // Returns whether we or one of our children accepts focus.
82 bool AcceptsFocusRecursively() const
83 { return AcceptsFocus() ||
84 (m_acceptsFocusChildren
&& HasAnyChildrenAcceptingFocus()); }
86 // We accept focus from keyboard if we accept it at all.
87 bool AcceptsFocusFromKeyboard() const { return AcceptsFocusRecursively(); }
89 // Call this when the number of children of the window changes.
91 // Returns true if we have any focusable children, false otherwise.
92 bool UpdateCanFocusChildren();
95 // set the focus to the child which had it the last time
96 virtual bool SetFocusToChild();
98 // return true if we have any children accepting focus
99 bool HasAnyFocusableChildren() const;
101 // return true if we have any children that do accept focus right now
102 bool HasAnyChildrenAcceptingFocus() const;
105 // the parent window we manage the children for
106 wxWindow
*m_winParent
;
108 // the child which had the focus last time this panel was activated
109 wxWindow
*m_winLastFocused
;
112 // Update the window status to reflect whether it is getting focus or not.
113 void UpdateParentCanFocus();
115 // Indicates whether the associated window can ever have focus itself.
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
;
123 // Cached value remembering whether we have any children accepting focus.
124 bool m_acceptsFocusChildren
;
126 // a guard against infinite recursion
130 #ifdef wxHAS_NATIVE_TAB_TRAVERSAL
132 // ----------------------------------------------------------------------------
133 // wxControlContainer for native TAB navigation
134 // ----------------------------------------------------------------------------
136 // this must be a real class as we forward-declare it elsewhere
137 class WXDLLIMPEXP_CORE wxControlContainer
: public wxControlContainerBase
140 // set the focus to the child which had it the last time
141 virtual bool SetFocusToChild();
144 #else // !wxHAS_NATIVE_TAB_TRAVERSAL
146 // ----------------------------------------------------------------------------
147 // wxControlContainer for TAB navigation implemented in wx itself
148 // ----------------------------------------------------------------------------
150 class WXDLLIMPEXP_CORE wxControlContainer
: public wxControlContainerBase
153 // default ctor, SetContainerWindow() must be called later
154 wxControlContainer();
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
);
161 // called from OnChildFocus() handler, i.e. when one of our (grand)
162 // children gets the focus
163 void SetLastFocus(wxWindow
*win
);
167 wxDECLARE_NO_COPY_CLASS(wxControlContainer
);
170 #endif // wxHAS_NATIVE_TAB_TRAVERSAL/!wxHAS_NATIVE_TAB_TRAVERSAL
172 // this function is for wxWidgets internal use only
173 extern WXDLLIMPEXP_CORE
bool wxSetFocusToChild(wxWindow
*win
, wxWindow
**child
);
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 // ----------------------------------------------------------------------------
181 // The template parameter W must be a wxWindow-derived class.
183 class wxNavigationEnabled
: public W
186 typedef W BaseWindowClass
;
188 wxNavigationEnabled()
190 m_container
.SetContainerWindow(this);
192 #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
193 BaseWindowClass::Connect(wxEVT_NAVIGATION_KEY
,
194 wxNavigationKeyEventHandler(wxNavigationEnabled::OnNavigationKey
));
196 BaseWindowClass::Connect(wxEVT_SET_FOCUS
,
197 wxFocusEventHandler(wxNavigationEnabled::OnFocus
));
199 BaseWindowClass::Connect(wxEVT_CHILD_FOCUS
,
200 wxChildFocusEventHandler(wxNavigationEnabled::OnChildFocus
));
201 #endif // !wxHAS_NATIVE_TAB_TRAVERSAL
204 WXDLLIMPEXP_INLINE_CORE
virtual bool AcceptsFocus() const
206 return m_container
.AcceptsFocus();
209 WXDLLIMPEXP_INLINE_CORE
virtual bool AcceptsFocusRecursively() const
211 return m_container
.AcceptsFocusRecursively();
214 WXDLLIMPEXP_INLINE_CORE
virtual bool AcceptsFocusFromKeyboard() const
216 return m_container
.AcceptsFocusFromKeyboard();
219 WXDLLIMPEXP_INLINE_CORE
virtual void AddChild(wxWindowBase
*child
)
221 BaseWindowClass::AddChild(child
);
223 if ( m_container
.UpdateCanFocusChildren() )
225 // Under MSW we must have wxTAB_TRAVERSAL style for TAB navigation
227 if ( !BaseWindowClass::HasFlag(wxTAB_TRAVERSAL
) )
228 BaseWindowClass::ToggleWindowStyle(wxTAB_TRAVERSAL
);
232 WXDLLIMPEXP_INLINE_CORE
virtual void RemoveChild(wxWindowBase
*child
)
234 #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
235 m_container
.HandleOnWindowDestroy(child
);
236 #endif // !wxHAS_NATIVE_TAB_TRAVERSAL
238 BaseWindowClass::RemoveChild(child
);
240 // We could reset wxTAB_TRAVERSAL here but it doesn't seem to do any
242 m_container
.UpdateCanFocusChildren();
245 WXDLLIMPEXP_INLINE_CORE
virtual void SetFocus()
247 if ( !m_container
.DoSetFocus() )
248 BaseWindowClass::SetFocus();
251 void SetFocusIgnoringChildren()
253 BaseWindowClass::SetFocus();
257 #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
258 void OnNavigationKey(wxNavigationKeyEvent
& event
)
260 m_container
.HandleOnNavigationKey(event
);
263 void OnFocus(wxFocusEvent
& event
)
265 m_container
.HandleOnFocus(event
);
268 void OnChildFocus(wxChildFocusEvent
& event
)
270 m_container
.SetLastFocus(event
.GetWindow());
273 #endif // !wxHAS_NATIVE_TAB_TRAVERSAL
275 wxControlContainer m_container
;
278 wxDECLARE_NO_COPY_TEMPLATE_CLASS(wxNavigationEnabled
, W
);
281 // ----------------------------------------------------------------------------
282 // Compatibility macros from now on, do NOT use them and preferably do not even
284 // ----------------------------------------------------------------------------
286 #if WXWIN_COMPATIBILITY_2_8
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() \
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(); \
301 wxControlContainer m_container
303 // this macro must be used in the derived class ctor
304 #define WX_INIT_CONTROL_CONTAINER() \
305 m_container.SetContainerWindow(this)
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) \
312 basename::AddChild(child); \
314 m_container.UpdateCanFocusChildren(); \
317 bool classname::AcceptsFocusRecursively() const \
319 return m_container.AcceptsFocusRecursively(); \
322 void classname::SetFocus() \
324 if ( !m_container.DoSetFocus() ) \
325 basename::SetFocus(); \
328 bool classname::AcceptsFocus() const \
330 return m_container.AcceptsFocus(); \
333 bool classname::AcceptsFocusFromKeyboard() const \
335 return m_container.AcceptsFocusFromKeyboard(); \
339 #ifdef wxHAS_NATIVE_TAB_TRAVERSAL
341 #define WX_EVENT_TABLE_CONTROL_CONTAINER(classname)
343 #define WX_DECLARE_CONTROL_CONTAINER WX_DECLARE_CONTROL_CONTAINER_BASE
345 #define WX_DELEGATE_TO_CONTROL_CONTAINER(classname, basename) \
346 WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \
348 void classname::RemoveChild(wxWindowBase *child) \
350 basename::RemoveChild(child); \
352 m_container.UpdateCanFocusChildren(); \
355 void classname::SetFocusIgnoringChildren() \
357 basename::SetFocus(); \
360 #else // !wxHAS_NATIVE_TAB_TRAVERSAL
362 // declare the methods to be forwarded
363 #define WX_DECLARE_CONTROL_CONTAINER() \
364 WX_DECLARE_CONTROL_CONTAINER_BASE(); \
367 void OnNavigationKey(wxNavigationKeyEvent& event); \
368 void OnFocus(wxFocusEvent& event); \
369 virtual void OnChildFocus(wxChildFocusEvent& event)
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)
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) \
381 void classname::RemoveChild(wxWindowBase *child) \
383 m_container.HandleOnWindowDestroy(child); \
385 basename::RemoveChild(child); \
387 m_container.UpdateCanFocusChildren(); \
390 void classname::OnNavigationKey( wxNavigationKeyEvent& event ) \
392 m_container.HandleOnNavigationKey(event); \
395 void classname::SetFocusIgnoringChildren() \
397 basename::SetFocus(); \
400 void classname::OnChildFocus(wxChildFocusEvent& event) \
402 m_container.SetLastFocus(event.GetWindow()); \
406 void classname::OnFocus(wxFocusEvent& event) \
408 m_container.HandleOnFocus(event); \
411 #endif // wxHAS_NATIVE_TAB_TRAVERSAL/!wxHAS_NATIVE_TAB_TRAVERSAL
413 #endif // WXWIN_COMPATIBILITY_2_8
415 #endif // _WX_CONTAINR_H_