1 ///////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxControlContainer and wxNavigationEnabled declarations
4 // Author: Vadim Zeitlin
7 // Copyright: (c) 2001, 2011 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
11 #ifndef _WX_CONTAINR_H_
12 #define _WX_CONTAINR_H_
16 #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
17 // We need wxEVT_XXX declarations in this case.
21 class WXDLLIMPEXP_FWD_CORE wxWindow
;
22 class WXDLLIMPEXP_FWD_CORE wxWindowBase
;
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.
32 // ----------------------------------------------------------------------------
33 // wxControlContainerBase: common part used in both native and generic cases
34 // ----------------------------------------------------------------------------
36 class WXDLLIMPEXP_CORE wxControlContainerBase
39 // default ctor, SetContainerWindow() must be called later
40 wxControlContainerBase()
44 // By default, we accept focus ourselves.
45 m_acceptsFocusSelf
= true;
47 // But we don't have any children accepting it yet.
48 m_acceptsFocusChildren
= false;
51 m_winLastFocused
= NULL
;
53 virtual ~wxControlContainerBase() {}
55 void SetContainerWindow(wxWindow
*winParent
)
57 wxASSERT_MSG( !m_winParent
, wxT("shouldn't be called twice") );
59 m_winParent
= winParent
;
62 // This can be called by the window to indicate that it never wants to have
63 // the focus for itself.
64 void DisableSelfFocus()
65 { m_acceptsFocusSelf
= false; UpdateParentCanFocus(); }
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
70 void EnableSelfFocus()
71 { m_acceptsFocusSelf
= true; UpdateParentCanFocus(); }
73 // should be called from SetFocus(), returns false if we did nothing with
74 // the focus and the default processing should take place
77 // returns whether we should accept focus ourselves or not
78 bool AcceptsFocus() const;
80 // Returns whether we or one of our children accepts focus.
81 bool AcceptsFocusRecursively() const
82 { return AcceptsFocus() ||
83 (m_acceptsFocusChildren
&& HasAnyChildrenAcceptingFocus()); }
85 // We accept focus from keyboard if we accept it at all.
86 bool AcceptsFocusFromKeyboard() const { return AcceptsFocusRecursively(); }
88 // Call this when the number of children of the window changes.
90 // Returns true if we have any focusable children, false otherwise.
91 bool UpdateCanFocusChildren();
94 // set the focus to the child which had it the last time
95 virtual bool SetFocusToChild();
97 // return true if we have any children accepting focus
98 bool HasAnyFocusableChildren() const;
100 // return true if we have any children that do accept focus right now
101 bool HasAnyChildrenAcceptingFocus() const;
104 // the parent window we manage the children for
105 wxWindow
*m_winParent
;
107 // the child which had the focus last time this panel was activated
108 wxWindow
*m_winLastFocused
;
111 // Update the window status to reflect whether it is getting focus or not.
112 void UpdateParentCanFocus();
114 // Indicates whether the associated window can ever have focus itself.
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
;
122 // Cached value remembering whether we have any children accepting focus.
123 bool m_acceptsFocusChildren
;
125 // a guard against infinite recursion
129 #ifdef wxHAS_NATIVE_TAB_TRAVERSAL
131 // ----------------------------------------------------------------------------
132 // wxControlContainer for native TAB navigation
133 // ----------------------------------------------------------------------------
135 // this must be a real class as we forward-declare it elsewhere
136 class WXDLLIMPEXP_CORE wxControlContainer
: public wxControlContainerBase
139 // set the focus to the child which had it the last time
140 virtual bool SetFocusToChild();
143 #else // !wxHAS_NATIVE_TAB_TRAVERSAL
145 // ----------------------------------------------------------------------------
146 // wxControlContainer for TAB navigation implemented in wx itself
147 // ----------------------------------------------------------------------------
149 class WXDLLIMPEXP_CORE wxControlContainer
: public wxControlContainerBase
152 // default ctor, SetContainerWindow() must be called later
153 wxControlContainer();
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
);
160 // called from OnChildFocus() handler, i.e. when one of our (grand)
161 // children gets the focus
162 void SetLastFocus(wxWindow
*win
);
166 wxDECLARE_NO_COPY_CLASS(wxControlContainer
);
169 #endif // wxHAS_NATIVE_TAB_TRAVERSAL/!wxHAS_NATIVE_TAB_TRAVERSAL
171 // this function is for wxWidgets internal use only
172 extern WXDLLIMPEXP_CORE
bool wxSetFocusToChild(wxWindow
*win
, wxWindow
**child
);
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 // ----------------------------------------------------------------------------
180 // The template parameter W must be a wxWindow-derived class.
182 class wxNavigationEnabled
: public W
185 typedef W BaseWindowClass
;
187 wxNavigationEnabled()
189 m_container
.SetContainerWindow(this);
191 #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
192 BaseWindowClass::Connect(wxEVT_NAVIGATION_KEY
,
193 wxNavigationKeyEventHandler(wxNavigationEnabled::OnNavigationKey
));
195 BaseWindowClass::Connect(wxEVT_SET_FOCUS
,
196 wxFocusEventHandler(wxNavigationEnabled::OnFocus
));
198 BaseWindowClass::Connect(wxEVT_CHILD_FOCUS
,
199 wxChildFocusEventHandler(wxNavigationEnabled::OnChildFocus
));
200 #endif // !wxHAS_NATIVE_TAB_TRAVERSAL
203 WXDLLIMPEXP_INLINE_CORE
virtual bool AcceptsFocus() const
205 return m_container
.AcceptsFocus();
208 WXDLLIMPEXP_INLINE_CORE
virtual bool AcceptsFocusRecursively() const
210 return m_container
.AcceptsFocusRecursively();
213 WXDLLIMPEXP_INLINE_CORE
virtual bool AcceptsFocusFromKeyboard() const
215 return m_container
.AcceptsFocusFromKeyboard();
218 WXDLLIMPEXP_INLINE_CORE
virtual void AddChild(wxWindowBase
*child
)
220 BaseWindowClass::AddChild(child
);
222 if ( m_container
.UpdateCanFocusChildren() )
224 // Under MSW we must have wxTAB_TRAVERSAL style for TAB navigation
226 if ( !BaseWindowClass::HasFlag(wxTAB_TRAVERSAL
) )
227 BaseWindowClass::ToggleWindowStyle(wxTAB_TRAVERSAL
);
231 WXDLLIMPEXP_INLINE_CORE
virtual void RemoveChild(wxWindowBase
*child
)
233 #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
234 m_container
.HandleOnWindowDestroy(child
);
235 #endif // !wxHAS_NATIVE_TAB_TRAVERSAL
237 BaseWindowClass::RemoveChild(child
);
239 // We could reset wxTAB_TRAVERSAL here but it doesn't seem to do any
241 m_container
.UpdateCanFocusChildren();
244 WXDLLIMPEXP_INLINE_CORE
virtual void SetFocus()
246 if ( !m_container
.DoSetFocus() )
247 BaseWindowClass::SetFocus();
250 void SetFocusIgnoringChildren()
252 BaseWindowClass::SetFocus();
256 #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
257 void OnNavigationKey(wxNavigationKeyEvent
& event
)
259 m_container
.HandleOnNavigationKey(event
);
262 void OnFocus(wxFocusEvent
& event
)
264 m_container
.HandleOnFocus(event
);
267 void OnChildFocus(wxChildFocusEvent
& event
)
269 m_container
.SetLastFocus(event
.GetWindow());
272 #endif // !wxHAS_NATIVE_TAB_TRAVERSAL
274 wxControlContainer m_container
;
277 wxDECLARE_NO_COPY_TEMPLATE_CLASS(wxNavigationEnabled
, W
);
280 // ----------------------------------------------------------------------------
281 // Compatibility macros from now on, do NOT use them and preferably do not even
283 // ----------------------------------------------------------------------------
285 #if WXWIN_COMPATIBILITY_2_8
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() \
291 virtual bool AcceptsFocus() const; \
292 virtual bool AcceptsFocusRecursively() const; \
293 virtual bool AcceptsFocusFromKeyboard() const; \
294 virtual void AddChild(wxWindowBase *child); \
295 virtual void RemoveChild(wxWindowBase *child); \
296 virtual void SetFocus(); \
297 void SetFocusIgnoringChildren(); \
300 wxControlContainer m_container
302 // this macro must be used in the derived class ctor
303 #define WX_INIT_CONTROL_CONTAINER() \
304 m_container.SetContainerWindow(this)
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) \
311 basename::AddChild(child); \
313 m_container.UpdateCanFocusChildren(); \
316 bool classname::AcceptsFocusRecursively() const \
318 return m_container.AcceptsFocusRecursively(); \
321 void classname::SetFocus() \
323 if ( !m_container.DoSetFocus() ) \
324 basename::SetFocus(); \
327 bool classname::AcceptsFocus() const \
329 return m_container.AcceptsFocus(); \
332 bool classname::AcceptsFocusFromKeyboard() const \
334 return m_container.AcceptsFocusFromKeyboard(); \
338 #ifdef wxHAS_NATIVE_TAB_TRAVERSAL
340 #define WX_EVENT_TABLE_CONTROL_CONTAINER(classname)
342 #define WX_DECLARE_CONTROL_CONTAINER WX_DECLARE_CONTROL_CONTAINER_BASE
344 #define WX_DELEGATE_TO_CONTROL_CONTAINER(classname, basename) \
345 WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \
347 void classname::RemoveChild(wxWindowBase *child) \
349 basename::RemoveChild(child); \
351 m_container.UpdateCanFocusChildren(); \
354 void classname::SetFocusIgnoringChildren() \
356 basename::SetFocus(); \
359 #else // !wxHAS_NATIVE_TAB_TRAVERSAL
361 // declare the methods to be forwarded
362 #define WX_DECLARE_CONTROL_CONTAINER() \
363 WX_DECLARE_CONTROL_CONTAINER_BASE(); \
366 void OnNavigationKey(wxNavigationKeyEvent& event); \
367 void OnFocus(wxFocusEvent& event); \
368 virtual void OnChildFocus(wxChildFocusEvent& event)
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)
376 // implement the methods forwarding to the wxControlContainer
377 #define WX_DELEGATE_TO_CONTROL_CONTAINER(classname, basename) \
378 WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \
380 void classname::RemoveChild(wxWindowBase *child) \
382 m_container.HandleOnWindowDestroy(child); \
384 basename::RemoveChild(child); \
386 m_container.UpdateCanFocusChildren(); \
389 void classname::OnNavigationKey( wxNavigationKeyEvent& event ) \
391 m_container.HandleOnNavigationKey(event); \
394 void classname::SetFocusIgnoringChildren() \
396 basename::SetFocus(); \
399 void classname::OnChildFocus(wxChildFocusEvent& event) \
401 m_container.SetLastFocus(event.GetWindow()); \
405 void classname::OnFocus(wxFocusEvent& event) \
407 m_container.HandleOnFocus(event); \
410 #endif // wxHAS_NATIVE_TAB_TRAVERSAL/!wxHAS_NATIVE_TAB_TRAVERSAL
412 #endif // WXWIN_COMPATIBILITY_2_8
414 #endif // _WX_CONTAINR_H_