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 { return m_acceptsFocusSelf
; }
81 // Returns whether we or one of our children accepts focus.
82 bool AcceptsFocusRecursively() const
83 { return m_acceptsFocusSelf
|| m_acceptsFocusChildren
; }
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 // the parent window we manage the children for
101 wxWindow
*m_winParent
;
103 // the child which had the focus last time this panel was activated
104 wxWindow
*m_winLastFocused
;
107 // Update the window status to reflect whether it is getting focus or not.
108 void UpdateParentCanFocus();
110 // Indicates whether the associated window can ever have focus itself.
112 // Usually this is the case, e.g. a wxPanel can be used either as a
113 // container for its children or just as a normal window which can be
114 // focused. But sometimes, e.g. for wxStaticBox, we can never have focus
115 // ourselves and can only get it if we have any focusable children.
116 bool m_acceptsFocusSelf
;
118 // Cached value remembering whether we have any children accepting focus.
119 bool m_acceptsFocusChildren
;
121 // a guard against infinite recursion
125 #ifdef wxHAS_NATIVE_TAB_TRAVERSAL
127 // ----------------------------------------------------------------------------
128 // wxControlContainer for native TAB navigation
129 // ----------------------------------------------------------------------------
131 // this must be a real class as we forward-declare it elsewhere
132 class WXDLLIMPEXP_CORE wxControlContainer
: public wxControlContainerBase
135 // set the focus to the child which had it the last time
136 virtual bool SetFocusToChild();
139 #else // !wxHAS_NATIVE_TAB_TRAVERSAL
141 // ----------------------------------------------------------------------------
142 // wxControlContainer for TAB navigation implemented in wx itself
143 // ----------------------------------------------------------------------------
145 class WXDLLIMPEXP_CORE wxControlContainer
: public wxControlContainerBase
148 // default ctor, SetContainerWindow() must be called later
149 wxControlContainer();
151 // the methods to be called from the window event handlers
152 void HandleOnNavigationKey(wxNavigationKeyEvent
& event
);
153 void HandleOnFocus(wxFocusEvent
& event
);
154 void HandleOnWindowDestroy(wxWindowBase
*child
);
156 // called from OnChildFocus() handler, i.e. when one of our (grand)
157 // children gets the focus
158 void SetLastFocus(wxWindow
*win
);
162 wxDECLARE_NO_COPY_CLASS(wxControlContainer
);
165 #endif // wxHAS_NATIVE_TAB_TRAVERSAL/!wxHAS_NATIVE_TAB_TRAVERSAL
167 // this function is for wxWidgets internal use only
168 extern WXDLLIMPEXP_CORE
bool wxSetFocusToChild(wxWindow
*win
, wxWindow
**child
);
170 // ----------------------------------------------------------------------------
171 // wxNavigationEnabled: Derive from this class to support keyboard navigation
172 // among window children in a wxWindow-derived class. The details of this class
173 // don't matter, you just need to derive from it to make navigation work.
174 // ----------------------------------------------------------------------------
176 // The template parameter W must be a wxWindow-derived class.
178 class wxNavigationEnabled
: public W
181 typedef W BaseWindowClass
;
183 wxNavigationEnabled()
185 m_container
.SetContainerWindow(this);
187 #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
188 BaseWindowClass::Connect(wxEVT_NAVIGATION_KEY
,
189 wxNavigationKeyEventHandler(wxNavigationEnabled::OnNavigationKey
));
191 BaseWindowClass::Connect(wxEVT_SET_FOCUS
,
192 wxFocusEventHandler(wxNavigationEnabled::OnFocus
));
194 BaseWindowClass::Connect(wxEVT_CHILD_FOCUS
,
195 wxChildFocusEventHandler(wxNavigationEnabled::OnChildFocus
));
196 #endif // !wxHAS_NATIVE_TAB_TRAVERSAL
199 WXDLLIMPEXP_INLINE_CORE
virtual bool AcceptsFocus() const
201 return m_container
.AcceptsFocus();
204 WXDLLIMPEXP_INLINE_CORE
virtual bool AcceptsFocusRecursively() const
206 return m_container
.AcceptsFocusRecursively();
209 WXDLLIMPEXP_INLINE_CORE
virtual bool AcceptsFocusFromKeyboard() const
211 return m_container
.AcceptsFocusFromKeyboard();
214 WXDLLIMPEXP_INLINE_CORE
virtual void AddChild(wxWindowBase
*child
)
216 BaseWindowClass::AddChild(child
);
218 if ( m_container
.UpdateCanFocusChildren() )
220 // Under MSW we must have wxTAB_TRAVERSAL style for TAB navigation
222 if ( !BaseWindowClass::HasFlag(wxTAB_TRAVERSAL
) )
223 BaseWindowClass::ToggleWindowStyle(wxTAB_TRAVERSAL
);
227 WXDLLIMPEXP_INLINE_CORE
virtual void RemoveChild(wxWindowBase
*child
)
229 #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
230 m_container
.HandleOnWindowDestroy(child
);
231 #endif // !wxHAS_NATIVE_TAB_TRAVERSAL
233 BaseWindowClass::RemoveChild(child
);
235 // We could reset wxTAB_TRAVERSAL here but it doesn't seem to do any
237 m_container
.UpdateCanFocusChildren();
240 WXDLLIMPEXP_INLINE_CORE
virtual void SetFocus()
242 if ( !m_container
.DoSetFocus() )
243 BaseWindowClass::SetFocus();
246 void SetFocusIgnoringChildren()
248 BaseWindowClass::SetFocus();
252 #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
253 void OnNavigationKey(wxNavigationKeyEvent
& event
)
255 m_container
.HandleOnNavigationKey(event
);
258 void OnFocus(wxFocusEvent
& event
)
260 m_container
.HandleOnFocus(event
);
263 void OnChildFocus(wxChildFocusEvent
& event
)
265 m_container
.SetLastFocus(event
.GetWindow());
268 #endif // !wxHAS_NATIVE_TAB_TRAVERSAL
270 wxControlContainer m_container
;
273 wxDECLARE_NO_COPY_TEMPLATE_CLASS(wxNavigationEnabled
, W
);
276 // ----------------------------------------------------------------------------
277 // Compatibility macros from now on, do NOT use them and preferably do not even
279 // ----------------------------------------------------------------------------
281 #if WXWIN_COMPATIBILITY_2_8
283 // common part of WX_DECLARE_CONTROL_CONTAINER in the native and generic cases,
284 // it should be used in the wxWindow-derived class declaration
285 #define WX_DECLARE_CONTROL_CONTAINER_BASE() \
287 virtual bool AcceptsFocus() const; \
288 virtual bool AcceptsFocusRecursively() const; \
289 virtual bool AcceptsFocusFromKeyboard() const; \
290 virtual void AddChild(wxWindowBase *child); \
291 virtual void RemoveChild(wxWindowBase *child); \
292 virtual void SetFocus(); \
293 void SetFocusIgnoringChildren(); \
296 wxControlContainer m_container
298 // this macro must be used in the derived class ctor
299 #define WX_INIT_CONTROL_CONTAINER() \
300 m_container.SetContainerWindow(this)
302 // common part of WX_DELEGATE_TO_CONTROL_CONTAINER in the native and generic
303 // cases, must be used in the wxWindow-derived class implementation
304 #define WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \
305 void classname::AddChild(wxWindowBase *child) \
307 basename::AddChild(child); \
309 m_container.UpdateCanFocusChildren(); \
312 bool classname::AcceptsFocusRecursively() const \
314 return m_container.AcceptsFocusRecursively(); \
317 void classname::SetFocus() \
319 if ( !m_container.DoSetFocus() ) \
320 basename::SetFocus(); \
323 bool classname::AcceptsFocus() const \
325 return m_container.AcceptsFocus(); \
328 bool classname::AcceptsFocusFromKeyboard() const \
330 return m_container.AcceptsFocusFromKeyboard(); \
334 #ifdef wxHAS_NATIVE_TAB_TRAVERSAL
336 #define WX_EVENT_TABLE_CONTROL_CONTAINER(classname)
338 #define WX_DECLARE_CONTROL_CONTAINER WX_DECLARE_CONTROL_CONTAINER_BASE
340 #define WX_DELEGATE_TO_CONTROL_CONTAINER(classname, basename) \
341 WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \
343 void classname::RemoveChild(wxWindowBase *child) \
345 basename::RemoveChild(child); \
347 m_container.UpdateCanFocusChildren(); \
350 void classname::SetFocusIgnoringChildren() \
352 basename::SetFocus(); \
355 #else // !wxHAS_NATIVE_TAB_TRAVERSAL
357 // declare the methods to be forwarded
358 #define WX_DECLARE_CONTROL_CONTAINER() \
359 WX_DECLARE_CONTROL_CONTAINER_BASE(); \
362 void OnNavigationKey(wxNavigationKeyEvent& event); \
363 void OnFocus(wxFocusEvent& event); \
364 virtual void OnChildFocus(wxChildFocusEvent& event)
366 // implement the event table entries for wxControlContainer
367 #define WX_EVENT_TABLE_CONTROL_CONTAINER(classname) \
368 EVT_SET_FOCUS(classname::OnFocus) \
369 EVT_CHILD_FOCUS(classname::OnChildFocus) \
370 EVT_NAVIGATION_KEY(classname::OnNavigationKey)
372 // implement the methods forwarding to the wxControlContainer
373 #define WX_DELEGATE_TO_CONTROL_CONTAINER(classname, basename) \
374 WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \
376 void classname::RemoveChild(wxWindowBase *child) \
378 m_container.HandleOnWindowDestroy(child); \
380 basename::RemoveChild(child); \
382 m_container.UpdateCanFocusChildren(); \
385 void classname::OnNavigationKey( wxNavigationKeyEvent& event ) \
387 m_container.HandleOnNavigationKey(event); \
390 void classname::SetFocusIgnoringChildren() \
392 basename::SetFocus(); \
395 void classname::OnChildFocus(wxChildFocusEvent& event) \
397 m_container.SetLastFocus(event.GetWindow()); \
401 void classname::OnFocus(wxFocusEvent& event) \
403 m_container.HandleOnFocus(event); \
406 #endif // wxHAS_NATIVE_TAB_TRAVERSAL/!wxHAS_NATIVE_TAB_TRAVERSAL
408 #endif // WXWIN_COMPATIBILITY_2_8
410 #endif // _WX_CONTAINR_H_