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 // Update the window status to reflect whether it is getting focus or not.
101 void UpdateParentCanFocus();
103 // Indicates whether the associated window can ever have focus itself.
105 // Usually this is the case, e.g. a wxPanel can be used either as a
106 // container for its children or just as a normal window which can be
107 // focused. But sometimes, e.g. for wxStaticBox, we can never have focus
108 // ourselves and can only get it if we have any focusable children.
109 bool m_acceptsFocusSelf
;
111 // Cached value remembering whether we have any children accepting focus.
112 bool m_acceptsFocusChildren
;
114 // a guard against infinite recursion
118 #ifdef wxHAS_NATIVE_TAB_TRAVERSAL
120 // ----------------------------------------------------------------------------
121 // wxControlContainer for native TAB navigation
122 // ----------------------------------------------------------------------------
124 // this must be a real class as we forward-declare it elsewhere
125 class WXDLLIMPEXP_CORE wxControlContainer
: public wxControlContainerBase
128 // set the focus to the child which had it the last time
129 virtual bool SetFocusToChild();
132 #else // !wxHAS_NATIVE_TAB_TRAVERSAL
134 // ----------------------------------------------------------------------------
135 // wxControlContainer for TAB navigation implemented in wx itself
136 // ----------------------------------------------------------------------------
138 class WXDLLIMPEXP_CORE wxControlContainer
: public wxControlContainerBase
141 // default ctor, SetContainerWindow() must be called later
142 wxControlContainer();
144 // the methods to be called from the window event handlers
145 void HandleOnNavigationKey(wxNavigationKeyEvent
& event
);
146 void HandleOnFocus(wxFocusEvent
& event
);
147 void HandleOnWindowDestroy(wxWindowBase
*child
);
149 // called from OnChildFocus() handler, i.e. when one of our (grand)
150 // children gets the focus
151 void SetLastFocus(wxWindow
*win
);
155 wxDECLARE_NO_COPY_CLASS(wxControlContainer
);
158 #endif // wxHAS_NATIVE_TAB_TRAVERSAL/!wxHAS_NATIVE_TAB_TRAVERSAL
160 // this function is for wxWidgets internal use only
161 extern WXDLLIMPEXP_CORE
bool wxSetFocusToChild(wxWindow
*win
, wxWindow
**child
);
163 // ----------------------------------------------------------------------------
164 // wxNavigationEnabled: Derive from this class to support keyboard navigation
165 // among window children in a wxWindow-derived class. The details of this class
166 // don't matter, you just need to derive from it to make navigation work.
167 // ----------------------------------------------------------------------------
169 // The template parameter W must be a wxWindow-derived class.
171 class wxNavigationEnabled
: public W
174 typedef W BaseWindowClass
;
176 wxNavigationEnabled()
178 m_container
.SetContainerWindow(this);
180 #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
181 BaseWindowClass::Connect(wxEVT_NAVIGATION_KEY
,
182 wxNavigationKeyEventHandler(wxNavigationEnabled::OnNavigationKey
));
184 BaseWindowClass::Connect(wxEVT_SET_FOCUS
,
185 wxFocusEventHandler(wxNavigationEnabled::OnFocus
));
187 BaseWindowClass::Connect(wxEVT_CHILD_FOCUS
,
188 wxChildFocusEventHandler(wxNavigationEnabled::OnChildFocus
));
189 #endif // !wxHAS_NATIVE_TAB_TRAVERSAL
192 WXDLLIMPEXP_INLINE_CORE
virtual bool AcceptsFocus() const
194 return m_container
.AcceptsFocus();
197 WXDLLIMPEXP_INLINE_CORE
virtual bool AcceptsFocusRecursively() const
199 return m_container
.AcceptsFocusRecursively();
202 WXDLLIMPEXP_INLINE_CORE
virtual bool AcceptsFocusFromKeyboard() const
204 return m_container
.AcceptsFocusFromKeyboard();
207 WXDLLIMPEXP_INLINE_CORE
virtual void AddChild(wxWindowBase
*child
)
209 BaseWindowClass::AddChild(child
);
211 if ( m_container
.UpdateCanFocusChildren() )
213 // Under MSW we must have wxTAB_TRAVERSAL style for TAB navigation
215 if ( !BaseWindowClass::HasFlag(wxTAB_TRAVERSAL
) )
216 BaseWindowClass::ToggleWindowStyle(wxTAB_TRAVERSAL
);
220 WXDLLIMPEXP_INLINE_CORE
virtual void RemoveChild(wxWindowBase
*child
)
222 #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
223 m_container
.HandleOnWindowDestroy(child
);
224 #endif // !wxHAS_NATIVE_TAB_TRAVERSAL
226 BaseWindowClass::RemoveChild(child
);
228 // We could reset wxTAB_TRAVERSAL here but it doesn't seem to do any
230 m_container
.UpdateCanFocusChildren();
233 WXDLLIMPEXP_INLINE_CORE
virtual void SetFocus()
235 if ( !m_container
.DoSetFocus() )
236 BaseWindowClass::SetFocus();
239 void SetFocusIgnoringChildren()
241 BaseWindowClass::SetFocus();
245 #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
246 void OnNavigationKey(wxNavigationKeyEvent
& event
)
248 m_container
.HandleOnNavigationKey(event
);
251 void OnFocus(wxFocusEvent
& event
)
253 m_container
.HandleOnFocus(event
);
256 void OnChildFocus(wxChildFocusEvent
& event
)
258 m_container
.SetLastFocus(event
.GetWindow());
261 #endif // !wxHAS_NATIVE_TAB_TRAVERSAL
263 wxControlContainer m_container
;
266 wxDECLARE_NO_COPY_TEMPLATE_CLASS(wxNavigationEnabled
, W
);
269 // ----------------------------------------------------------------------------
270 // Compatibility macros from now on, do NOT use them and preferably do not even
272 // ----------------------------------------------------------------------------
274 #if WXWIN_COMPATIBILITY_2_8
276 // common part of WX_DECLARE_CONTROL_CONTAINER in the native and generic cases,
277 // it should be used in the wxWindow-derived class declaration
278 #define WX_DECLARE_CONTROL_CONTAINER_BASE() \
280 virtual bool AcceptsFocus() const; \
281 virtual bool AcceptsFocusRecursively() const; \
282 virtual bool AcceptsFocusFromKeyboard() const; \
283 virtual void AddChild(wxWindowBase *child); \
284 virtual void RemoveChild(wxWindowBase *child); \
285 virtual void SetFocus(); \
286 void SetFocusIgnoringChildren(); \
289 wxControlContainer m_container
291 // this macro must be used in the derived class ctor
292 #define WX_INIT_CONTROL_CONTAINER() \
293 m_container.SetContainerWindow(this)
295 // common part of WX_DELEGATE_TO_CONTROL_CONTAINER in the native and generic
296 // cases, must be used in the wxWindow-derived class implementation
297 #define WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \
298 void classname::AddChild(wxWindowBase *child) \
300 basename::AddChild(child); \
302 m_container.UpdateCanFocusChildren(); \
305 bool classname::AcceptsFocusRecursively() const \
307 return m_container.AcceptsFocusRecursively(); \
310 void classname::SetFocus() \
312 if ( !m_container.DoSetFocus() ) \
313 basename::SetFocus(); \
316 bool classname::AcceptsFocus() const \
318 return m_container.AcceptsFocus(); \
321 bool classname::AcceptsFocusFromKeyboard() const \
323 return m_container.AcceptsFocusFromKeyboard(); \
327 #ifdef wxHAS_NATIVE_TAB_TRAVERSAL
329 #define WX_EVENT_TABLE_CONTROL_CONTAINER(classname)
331 #define WX_DECLARE_CONTROL_CONTAINER WX_DECLARE_CONTROL_CONTAINER_BASE
333 #define WX_DELEGATE_TO_CONTROL_CONTAINER(classname, basename) \
334 WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \
336 void classname::RemoveChild(wxWindowBase *child) \
338 basename::RemoveChild(child); \
340 m_container.UpdateCanFocusChildren(); \
343 void classname::SetFocusIgnoringChildren() \
345 basename::SetFocus(); \
348 #else // !wxHAS_NATIVE_TAB_TRAVERSAL
350 // declare the methods to be forwarded
351 #define WX_DECLARE_CONTROL_CONTAINER() \
352 WX_DECLARE_CONTROL_CONTAINER_BASE(); \
355 void OnNavigationKey(wxNavigationKeyEvent& event); \
356 void OnFocus(wxFocusEvent& event); \
357 virtual void OnChildFocus(wxChildFocusEvent& event)
359 // implement the event table entries for wxControlContainer
360 #define WX_EVENT_TABLE_CONTROL_CONTAINER(classname) \
361 EVT_SET_FOCUS(classname::OnFocus) \
362 EVT_CHILD_FOCUS(classname::OnChildFocus) \
363 EVT_NAVIGATION_KEY(classname::OnNavigationKey)
365 // implement the methods forwarding to the wxControlContainer
366 #define WX_DELEGATE_TO_CONTROL_CONTAINER(classname, basename) \
367 WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \
369 void classname::RemoveChild(wxWindowBase *child) \
371 m_container.HandleOnWindowDestroy(child); \
373 basename::RemoveChild(child); \
375 m_container.UpdateCanFocusChildren(); \
378 void classname::OnNavigationKey( wxNavigationKeyEvent& event ) \
380 m_container.HandleOnNavigationKey(event); \
383 void classname::SetFocusIgnoringChildren() \
385 basename::SetFocus(); \
388 void classname::OnChildFocus(wxChildFocusEvent& event) \
390 m_container.SetLastFocus(event.GetWindow()); \
394 void classname::OnFocus(wxFocusEvent& event) \
396 m_container.HandleOnFocus(event); \
399 #endif // wxHAS_NATIVE_TAB_TRAVERSAL/!wxHAS_NATIVE_TAB_TRAVERSAL
401 #endif // WXWIN_COMPATIBILITY_2_8
403 #endif // _WX_CONTAINR_H_