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() { m_acceptsFocusSelf
= false; }
67 // should be called from SetFocus(), returns false if we did nothing with
68 // the focus and the default processing should take place
71 // returns whether we should accept focus ourselves or not
72 bool AcceptsFocus() const { return m_acceptsFocusSelf
; }
74 // Returns whether we or one of our children accepts focus.
75 bool AcceptsFocusRecursively() const
76 { return m_acceptsFocusSelf
|| m_acceptsFocusChildren
; }
78 // We accept focus from keyboard if we accept it at all.
79 bool AcceptsFocusFromKeyboard() const { return AcceptsFocusRecursively(); }
81 // Call this when the number of children of the window changes.
83 // Returns true if we have any focusable children, false otherwise.
84 bool UpdateCanFocusChildren();
87 // set the focus to the child which had it the last time
88 virtual bool SetFocusToChild();
90 // return true if we have any children accepting focus
91 bool HasAnyFocusableChildren() const;
93 // the parent window we manage the children for
94 wxWindow
*m_winParent
;
96 // the child which had the focus last time this panel was activated
97 wxWindow
*m_winLastFocused
;
100 // Indicates whether the associated window can ever have focus itself.
102 // Usually this is the case, e.g. a wxPanel can be used either as a
103 // container for its children or just as a normal window which can be
104 // focused. But sometimes, e.g. for wxStaticBox, we can never have focus
105 // ourselves and can only get it if we have any focusable children.
106 bool m_acceptsFocusSelf
;
108 // Cached value remembering whether we have any children accepting focus.
109 bool m_acceptsFocusChildren
;
111 // a guard against infinite recursion
115 #ifdef wxHAS_NATIVE_TAB_TRAVERSAL
117 // ----------------------------------------------------------------------------
118 // wxControlContainer for native TAB navigation
119 // ----------------------------------------------------------------------------
121 // this must be a real class as we forward-declare it elsewhere
122 class WXDLLIMPEXP_CORE wxControlContainer
: public wxControlContainerBase
125 // set the focus to the child which had it the last time
126 virtual bool SetFocusToChild();
129 #else // !wxHAS_NATIVE_TAB_TRAVERSAL
131 // ----------------------------------------------------------------------------
132 // wxControlContainer for TAB navigation implemented in wx itself
133 // ----------------------------------------------------------------------------
135 class WXDLLIMPEXP_CORE wxControlContainer
: public wxControlContainerBase
138 // default ctor, SetContainerWindow() must be called later
139 wxControlContainer();
141 // the methods to be called from the window event handlers
142 void HandleOnNavigationKey(wxNavigationKeyEvent
& event
);
143 void HandleOnFocus(wxFocusEvent
& event
);
144 void HandleOnWindowDestroy(wxWindowBase
*child
);
146 // called from OnChildFocus() handler, i.e. when one of our (grand)
147 // children gets the focus
148 void SetLastFocus(wxWindow
*win
);
152 wxDECLARE_NO_COPY_CLASS(wxControlContainer
);
155 #endif // wxHAS_NATIVE_TAB_TRAVERSAL/!wxHAS_NATIVE_TAB_TRAVERSAL
157 // this function is for wxWidgets internal use only
158 extern WXDLLIMPEXP_CORE
bool wxSetFocusToChild(wxWindow
*win
, wxWindow
**child
);
160 // ----------------------------------------------------------------------------
161 // wxNavigationEnabled: Derive from this class to support keyboard navigation
162 // among window children in a wxWindow-derived class. The details of this class
163 // don't matter, you just need to derive from it to make navigation work.
164 // ----------------------------------------------------------------------------
166 // The template parameter W must be a wxWindow-derived class.
168 class wxNavigationEnabled
: public W
171 typedef W BaseWindowClass
;
173 wxNavigationEnabled()
175 m_container
.SetContainerWindow(this);
177 #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
178 BaseWindowClass::Connect(wxEVT_NAVIGATION_KEY
,
179 wxNavigationKeyEventHandler(wxNavigationEnabled::OnNavigationKey
));
181 BaseWindowClass::Connect(wxEVT_SET_FOCUS
,
182 wxFocusEventHandler(wxNavigationEnabled::OnFocus
));
184 BaseWindowClass::Connect(wxEVT_CHILD_FOCUS
,
185 wxChildFocusEventHandler(wxNavigationEnabled::OnChildFocus
));
186 #endif // !wxHAS_NATIVE_TAB_TRAVERSAL
189 WXDLLIMPEXP_INLINE_CORE
virtual bool AcceptsFocus() const
191 return m_container
.AcceptsFocus();
194 WXDLLIMPEXP_INLINE_CORE
virtual bool AcceptsFocusRecursively() const
196 return m_container
.AcceptsFocusRecursively();
199 WXDLLIMPEXP_INLINE_CORE
virtual bool AcceptsFocusFromKeyboard() const
201 return m_container
.AcceptsFocusFromKeyboard();
204 WXDLLIMPEXP_INLINE_CORE
virtual void AddChild(wxWindowBase
*child
)
206 BaseWindowClass::AddChild(child
);
208 if ( m_container
.UpdateCanFocusChildren() )
210 // Under MSW we must have wxTAB_TRAVERSAL style for TAB navigation
212 if ( !BaseWindowClass::HasFlag(wxTAB_TRAVERSAL
) )
213 BaseWindowClass::ToggleWindowStyle(wxTAB_TRAVERSAL
);
217 WXDLLIMPEXP_INLINE_CORE
virtual void RemoveChild(wxWindowBase
*child
)
219 #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
220 m_container
.HandleOnWindowDestroy(child
);
221 #endif // !wxHAS_NATIVE_TAB_TRAVERSAL
223 BaseWindowClass::RemoveChild(child
);
225 // We could reset wxTAB_TRAVERSAL here but it doesn't seem to do any
227 m_container
.UpdateCanFocusChildren();
230 WXDLLIMPEXP_INLINE_CORE
virtual void SetFocus()
232 if ( !m_container
.DoSetFocus() )
233 BaseWindowClass::SetFocus();
236 void SetFocusIgnoringChildren()
238 BaseWindowClass::SetFocus();
242 #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
243 void OnNavigationKey(wxNavigationKeyEvent
& event
)
245 m_container
.HandleOnNavigationKey(event
);
248 void OnFocus(wxFocusEvent
& event
)
250 m_container
.HandleOnFocus(event
);
253 void OnChildFocus(wxChildFocusEvent
& event
)
255 m_container
.SetLastFocus(event
.GetWindow());
258 #endif // !wxHAS_NATIVE_TAB_TRAVERSAL
260 wxControlContainer m_container
;
263 wxDECLARE_NO_COPY_TEMPLATE_CLASS(wxNavigationEnabled
, W
);
266 // ----------------------------------------------------------------------------
267 // Compatibility macros from now on, do NOT use them and preferably do not even
269 // ----------------------------------------------------------------------------
271 #if WXWIN_COMPATIBILITY_2_8
273 // common part of WX_DECLARE_CONTROL_CONTAINER in the native and generic cases,
274 // it should be used in the wxWindow-derived class declaration
275 #define WX_DECLARE_CONTROL_CONTAINER_BASE() \
277 virtual bool AcceptsFocus() const; \
278 virtual bool AcceptsFocusRecursively() const; \
279 virtual bool AcceptsFocusFromKeyboard() const; \
280 virtual void AddChild(wxWindowBase *child); \
281 virtual void RemoveChild(wxWindowBase *child); \
282 virtual void SetFocus(); \
283 void SetFocusIgnoringChildren(); \
286 wxControlContainer m_container
288 // this macro must be used in the derived class ctor
289 #define WX_INIT_CONTROL_CONTAINER() \
290 m_container.SetContainerWindow(this)
292 // common part of WX_DELEGATE_TO_CONTROL_CONTAINER in the native and generic
293 // cases, must be used in the wxWindow-derived class implementation
294 #define WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \
295 void classname::AddChild(wxWindowBase *child) \
297 basename::AddChild(child); \
299 m_container.UpdateCanFocusChildren(); \
302 bool classname::AcceptsFocusRecursively() const \
304 return m_container.AcceptsFocusRecursively(); \
307 void classname::SetFocus() \
309 if ( !m_container.DoSetFocus() ) \
310 basename::SetFocus(); \
313 bool classname::AcceptsFocus() const \
315 return m_container.AcceptsFocus(); \
318 bool classname::AcceptsFocusFromKeyboard() const \
320 return m_container.AcceptsFocusFromKeyboard(); \
324 #ifdef wxHAS_NATIVE_TAB_TRAVERSAL
326 #define WX_EVENT_TABLE_CONTROL_CONTAINER(classname)
328 #define WX_DECLARE_CONTROL_CONTAINER WX_DECLARE_CONTROL_CONTAINER_BASE
330 #define WX_DELEGATE_TO_CONTROL_CONTAINER(classname, basename) \
331 WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \
333 void classname::RemoveChild(wxWindowBase *child) \
335 basename::RemoveChild(child); \
337 m_container.UpdateCanFocusChildren(); \
340 void classname::SetFocusIgnoringChildren() \
342 basename::SetFocus(); \
345 #else // !wxHAS_NATIVE_TAB_TRAVERSAL
347 // declare the methods to be forwarded
348 #define WX_DECLARE_CONTROL_CONTAINER() \
349 WX_DECLARE_CONTROL_CONTAINER_BASE(); \
352 void OnNavigationKey(wxNavigationKeyEvent& event); \
353 void OnFocus(wxFocusEvent& event); \
354 virtual void OnChildFocus(wxChildFocusEvent& event)
356 // implement the event table entries for wxControlContainer
357 #define WX_EVENT_TABLE_CONTROL_CONTAINER(classname) \
358 EVT_SET_FOCUS(classname::OnFocus) \
359 EVT_CHILD_FOCUS(classname::OnChildFocus) \
360 EVT_NAVIGATION_KEY(classname::OnNavigationKey)
362 // implement the methods forwarding to the wxControlContainer
363 #define WX_DELEGATE_TO_CONTROL_CONTAINER(classname, basename) \
364 WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \
366 void classname::RemoveChild(wxWindowBase *child) \
368 m_container.HandleOnWindowDestroy(child); \
370 basename::RemoveChild(child); \
372 m_container.UpdateCanFocusChildren(); \
375 void classname::OnNavigationKey( wxNavigationKeyEvent& event ) \
377 m_container.HandleOnNavigationKey(event); \
380 void classname::SetFocusIgnoringChildren() \
382 basename::SetFocus(); \
385 void classname::OnChildFocus(wxChildFocusEvent& event) \
387 m_container.SetLastFocus(event.GetWindow()); \
391 void classname::OnFocus(wxFocusEvent& event) \
393 m_container.HandleOnFocus(event); \
396 #endif // wxHAS_NATIVE_TAB_TRAVERSAL/!wxHAS_NATIVE_TAB_TRAVERSAL
398 #endif // WXWIN_COMPATIBILITY_2_8
400 #endif // _WX_CONTAINR_H_