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
80 { return m_acceptsFocusSelf
&& m_winParent
->CanBeFocused(); }
82 // Returns whether we or one of our children accepts focus.
83 bool AcceptsFocusRecursively() const
84 { return AcceptsFocus() ||
85 (m_acceptsFocusChildren
&& HasAnyChildrenAcceptingFocus()); }
87 // We accept focus from keyboard if we accept it at all.
88 bool AcceptsFocusFromKeyboard() const { return AcceptsFocusRecursively(); }
90 // Call this when the number of children of the window changes.
92 // Returns true if we have any focusable children, false otherwise.
93 bool UpdateCanFocusChildren();
96 // set the focus to the child which had it the last time
97 virtual bool SetFocusToChild();
99 // return true if we have any children accepting focus
100 bool HasAnyFocusableChildren() const;
102 // return true if we have any children that do accept focus right now
103 bool HasAnyChildrenAcceptingFocus() const;
106 // the parent window we manage the children for
107 wxWindow
*m_winParent
;
109 // the child which had the focus last time this panel was activated
110 wxWindow
*m_winLastFocused
;
113 // Update the window status to reflect whether it is getting focus or not.
114 void UpdateParentCanFocus();
116 // Indicates whether the associated window can ever have focus itself.
118 // Usually this is the case, e.g. a wxPanel can be used either as a
119 // container for its children or just as a normal window which can be
120 // focused. But sometimes, e.g. for wxStaticBox, we can never have focus
121 // ourselves and can only get it if we have any focusable children.
122 bool m_acceptsFocusSelf
;
124 // Cached value remembering whether we have any children accepting focus.
125 bool m_acceptsFocusChildren
;
127 // a guard against infinite recursion
131 #ifdef wxHAS_NATIVE_TAB_TRAVERSAL
133 // ----------------------------------------------------------------------------
134 // wxControlContainer for native TAB navigation
135 // ----------------------------------------------------------------------------
137 // this must be a real class as we forward-declare it elsewhere
138 class WXDLLIMPEXP_CORE wxControlContainer
: public wxControlContainerBase
141 // set the focus to the child which had it the last time
142 virtual bool SetFocusToChild();
145 #else // !wxHAS_NATIVE_TAB_TRAVERSAL
147 // ----------------------------------------------------------------------------
148 // wxControlContainer for TAB navigation implemented in wx itself
149 // ----------------------------------------------------------------------------
151 class WXDLLIMPEXP_CORE wxControlContainer
: public wxControlContainerBase
154 // default ctor, SetContainerWindow() must be called later
155 wxControlContainer();
157 // the methods to be called from the window event handlers
158 void HandleOnNavigationKey(wxNavigationKeyEvent
& event
);
159 void HandleOnFocus(wxFocusEvent
& event
);
160 void HandleOnWindowDestroy(wxWindowBase
*child
);
162 // called from OnChildFocus() handler, i.e. when one of our (grand)
163 // children gets the focus
164 void SetLastFocus(wxWindow
*win
);
168 wxDECLARE_NO_COPY_CLASS(wxControlContainer
);
171 #endif // wxHAS_NATIVE_TAB_TRAVERSAL/!wxHAS_NATIVE_TAB_TRAVERSAL
173 // this function is for wxWidgets internal use only
174 extern WXDLLIMPEXP_CORE
bool wxSetFocusToChild(wxWindow
*win
, wxWindow
**child
);
176 // ----------------------------------------------------------------------------
177 // wxNavigationEnabled: Derive from this class to support keyboard navigation
178 // among window children in a wxWindow-derived class. The details of this class
179 // don't matter, you just need to derive from it to make navigation work.
180 // ----------------------------------------------------------------------------
182 // The template parameter W must be a wxWindow-derived class.
184 class wxNavigationEnabled
: public W
187 typedef W BaseWindowClass
;
189 wxNavigationEnabled()
191 m_container
.SetContainerWindow(this);
193 #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
194 BaseWindowClass::Connect(wxEVT_NAVIGATION_KEY
,
195 wxNavigationKeyEventHandler(wxNavigationEnabled::OnNavigationKey
));
197 BaseWindowClass::Connect(wxEVT_SET_FOCUS
,
198 wxFocusEventHandler(wxNavigationEnabled::OnFocus
));
200 BaseWindowClass::Connect(wxEVT_CHILD_FOCUS
,
201 wxChildFocusEventHandler(wxNavigationEnabled::OnChildFocus
));
202 #endif // !wxHAS_NATIVE_TAB_TRAVERSAL
205 WXDLLIMPEXP_INLINE_CORE
virtual bool AcceptsFocus() const
207 return m_container
.AcceptsFocus();
210 WXDLLIMPEXP_INLINE_CORE
virtual bool AcceptsFocusRecursively() const
212 return m_container
.AcceptsFocusRecursively();
215 WXDLLIMPEXP_INLINE_CORE
virtual bool AcceptsFocusFromKeyboard() const
217 return m_container
.AcceptsFocusFromKeyboard();
220 WXDLLIMPEXP_INLINE_CORE
virtual void AddChild(wxWindowBase
*child
)
222 BaseWindowClass::AddChild(child
);
224 if ( m_container
.UpdateCanFocusChildren() )
226 // Under MSW we must have wxTAB_TRAVERSAL style for TAB navigation
228 if ( !BaseWindowClass::HasFlag(wxTAB_TRAVERSAL
) )
229 BaseWindowClass::ToggleWindowStyle(wxTAB_TRAVERSAL
);
233 WXDLLIMPEXP_INLINE_CORE
virtual void RemoveChild(wxWindowBase
*child
)
235 #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
236 m_container
.HandleOnWindowDestroy(child
);
237 #endif // !wxHAS_NATIVE_TAB_TRAVERSAL
239 BaseWindowClass::RemoveChild(child
);
241 // We could reset wxTAB_TRAVERSAL here but it doesn't seem to do any
243 m_container
.UpdateCanFocusChildren();
246 WXDLLIMPEXP_INLINE_CORE
virtual void SetFocus()
248 if ( !m_container
.DoSetFocus() )
249 BaseWindowClass::SetFocus();
252 void SetFocusIgnoringChildren()
254 BaseWindowClass::SetFocus();
258 #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
259 void OnNavigationKey(wxNavigationKeyEvent
& event
)
261 m_container
.HandleOnNavigationKey(event
);
264 void OnFocus(wxFocusEvent
& event
)
266 m_container
.HandleOnFocus(event
);
269 void OnChildFocus(wxChildFocusEvent
& event
)
271 m_container
.SetLastFocus(event
.GetWindow());
274 #endif // !wxHAS_NATIVE_TAB_TRAVERSAL
276 wxControlContainer m_container
;
279 wxDECLARE_NO_COPY_TEMPLATE_CLASS(wxNavigationEnabled
, W
);
282 // ----------------------------------------------------------------------------
283 // Compatibility macros from now on, do NOT use them and preferably do not even
285 // ----------------------------------------------------------------------------
287 #if WXWIN_COMPATIBILITY_2_8
289 // common part of WX_DECLARE_CONTROL_CONTAINER in the native and generic cases,
290 // it should be used in the wxWindow-derived class declaration
291 #define WX_DECLARE_CONTROL_CONTAINER_BASE() \
293 virtual bool AcceptsFocus() const; \
294 virtual bool AcceptsFocusRecursively() const; \
295 virtual bool AcceptsFocusFromKeyboard() const; \
296 virtual void AddChild(wxWindowBase *child); \
297 virtual void RemoveChild(wxWindowBase *child); \
298 virtual void SetFocus(); \
299 void SetFocusIgnoringChildren(); \
302 wxControlContainer m_container
304 // this macro must be used in the derived class ctor
305 #define WX_INIT_CONTROL_CONTAINER() \
306 m_container.SetContainerWindow(this)
308 // common part of WX_DELEGATE_TO_CONTROL_CONTAINER in the native and generic
309 // cases, must be used in the wxWindow-derived class implementation
310 #define WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \
311 void classname::AddChild(wxWindowBase *child) \
313 basename::AddChild(child); \
315 m_container.UpdateCanFocusChildren(); \
318 bool classname::AcceptsFocusRecursively() const \
320 return m_container.AcceptsFocusRecursively(); \
323 void classname::SetFocus() \
325 if ( !m_container.DoSetFocus() ) \
326 basename::SetFocus(); \
329 bool classname::AcceptsFocus() const \
331 return m_container.AcceptsFocus(); \
334 bool classname::AcceptsFocusFromKeyboard() const \
336 return m_container.AcceptsFocusFromKeyboard(); \
340 #ifdef wxHAS_NATIVE_TAB_TRAVERSAL
342 #define WX_EVENT_TABLE_CONTROL_CONTAINER(classname)
344 #define WX_DECLARE_CONTROL_CONTAINER WX_DECLARE_CONTROL_CONTAINER_BASE
346 #define WX_DELEGATE_TO_CONTROL_CONTAINER(classname, basename) \
347 WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \
349 void classname::RemoveChild(wxWindowBase *child) \
351 basename::RemoveChild(child); \
353 m_container.UpdateCanFocusChildren(); \
356 void classname::SetFocusIgnoringChildren() \
358 basename::SetFocus(); \
361 #else // !wxHAS_NATIVE_TAB_TRAVERSAL
363 // declare the methods to be forwarded
364 #define WX_DECLARE_CONTROL_CONTAINER() \
365 WX_DECLARE_CONTROL_CONTAINER_BASE(); \
368 void OnNavigationKey(wxNavigationKeyEvent& event); \
369 void OnFocus(wxFocusEvent& event); \
370 virtual void OnChildFocus(wxChildFocusEvent& event)
372 // implement the event table entries for wxControlContainer
373 #define WX_EVENT_TABLE_CONTROL_CONTAINER(classname) \
374 EVT_SET_FOCUS(classname::OnFocus) \
375 EVT_CHILD_FOCUS(classname::OnChildFocus) \
376 EVT_NAVIGATION_KEY(classname::OnNavigationKey)
378 // implement the methods forwarding to the wxControlContainer
379 #define WX_DELEGATE_TO_CONTROL_CONTAINER(classname, basename) \
380 WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \
382 void classname::RemoveChild(wxWindowBase *child) \
384 m_container.HandleOnWindowDestroy(child); \
386 basename::RemoveChild(child); \
388 m_container.UpdateCanFocusChildren(); \
391 void classname::OnNavigationKey( wxNavigationKeyEvent& event ) \
393 m_container.HandleOnNavigationKey(event); \
396 void classname::SetFocusIgnoringChildren() \
398 basename::SetFocus(); \
401 void classname::OnChildFocus(wxChildFocusEvent& event) \
403 m_container.SetLastFocus(event.GetWindow()); \
407 void classname::OnFocus(wxFocusEvent& event) \
409 m_container.HandleOnFocus(event); \
412 #endif // wxHAS_NATIVE_TAB_TRAVERSAL/!wxHAS_NATIVE_TAB_TRAVERSAL
414 #endif // WXWIN_COMPATIBILITY_2_8
416 #endif // _WX_CONTAINR_H_