containr.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Name: wx/containr.h
  3. // Purpose: wxControlContainer and wxNavigationEnabled declarations
  4. // Author: Vadim Zeitlin
  5. // Modified by:
  6. // Created: 06.08.01
  7. // Copyright: (c) 2001, 2011 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
  8. // Licence: wxWindows licence
  9. ///////////////////////////////////////////////////////////////////////////////
  10. #ifndef _WX_CONTAINR_H_
  11. #define _WX_CONTAINR_H_
  12. #include "wx/defs.h"
  13. #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
  14. // We need wxEVT_XXX declarations in this case.
  15. #include "wx/event.h"
  16. #endif
  17. class WXDLLIMPEXP_FWD_CORE wxWindow;
  18. class WXDLLIMPEXP_FWD_CORE wxWindowBase;
  19. /*
  20. This header declares wxControlContainer class however it's not a real
  21. container of controls but rather just a helper used to implement TAB
  22. navigation among the window children. You should rarely need to use it
  23. directly, derive from the documented public wxNavigationEnabled<> class to
  24. implement TAB navigation in a custom composite window.
  25. */
  26. // ----------------------------------------------------------------------------
  27. // wxControlContainerBase: common part used in both native and generic cases
  28. // ----------------------------------------------------------------------------
  29. class WXDLLIMPEXP_CORE wxControlContainerBase
  30. {
  31. public:
  32. // default ctor, SetContainerWindow() must be called later
  33. wxControlContainerBase()
  34. {
  35. m_winParent = NULL;
  36. // By default, we accept focus ourselves.
  37. m_acceptsFocusSelf = true;
  38. // But we don't have any children accepting it yet.
  39. m_acceptsFocusChildren = false;
  40. m_inSetFocus = false;
  41. m_winLastFocused = NULL;
  42. }
  43. virtual ~wxControlContainerBase() {}
  44. void SetContainerWindow(wxWindow *winParent)
  45. {
  46. wxASSERT_MSG( !m_winParent, wxT("shouldn't be called twice") );
  47. m_winParent = winParent;
  48. }
  49. // This can be called by the window to indicate that it never wants to have
  50. // the focus for itself.
  51. void DisableSelfFocus()
  52. { m_acceptsFocusSelf = false; UpdateParentCanFocus(); }
  53. // This can be called to undo the effect of a previous DisableSelfFocus()
  54. // (otherwise calling it is not necessary as the window does accept focus
  55. // by default).
  56. void EnableSelfFocus()
  57. { m_acceptsFocusSelf = true; UpdateParentCanFocus(); }
  58. // should be called from SetFocus(), returns false if we did nothing with
  59. // the focus and the default processing should take place
  60. bool DoSetFocus();
  61. // returns whether we should accept focus ourselves or not
  62. bool AcceptsFocus() const;
  63. // Returns whether we or one of our children accepts focus.
  64. bool AcceptsFocusRecursively() const
  65. { return AcceptsFocus() ||
  66. (m_acceptsFocusChildren && HasAnyChildrenAcceptingFocus()); }
  67. // We accept focus from keyboard if we accept it at all.
  68. bool AcceptsFocusFromKeyboard() const { return AcceptsFocusRecursively(); }
  69. // Call this when the number of children of the window changes.
  70. //
  71. // Returns true if we have any focusable children, false otherwise.
  72. bool UpdateCanFocusChildren();
  73. protected:
  74. // set the focus to the child which had it the last time
  75. virtual bool SetFocusToChild();
  76. // return true if we have any children accepting focus
  77. bool HasAnyFocusableChildren() const;
  78. // return true if we have any children that do accept focus right now
  79. bool HasAnyChildrenAcceptingFocus() const;
  80. // the parent window we manage the children for
  81. wxWindow *m_winParent;
  82. // the child which had the focus last time this panel was activated
  83. wxWindow *m_winLastFocused;
  84. private:
  85. // Update the window status to reflect whether it is getting focus or not.
  86. void UpdateParentCanFocus();
  87. // Indicates whether the associated window can ever have focus itself.
  88. //
  89. // Usually this is the case, e.g. a wxPanel can be used either as a
  90. // container for its children or just as a normal window which can be
  91. // focused. But sometimes, e.g. for wxStaticBox, we can never have focus
  92. // ourselves and can only get it if we have any focusable children.
  93. bool m_acceptsFocusSelf;
  94. // Cached value remembering whether we have any children accepting focus.
  95. bool m_acceptsFocusChildren;
  96. // a guard against infinite recursion
  97. bool m_inSetFocus;
  98. };
  99. #ifdef wxHAS_NATIVE_TAB_TRAVERSAL
  100. // ----------------------------------------------------------------------------
  101. // wxControlContainer for native TAB navigation
  102. // ----------------------------------------------------------------------------
  103. // this must be a real class as we forward-declare it elsewhere
  104. class WXDLLIMPEXP_CORE wxControlContainer : public wxControlContainerBase
  105. {
  106. protected:
  107. // set the focus to the child which had it the last time
  108. virtual bool SetFocusToChild();
  109. };
  110. #else // !wxHAS_NATIVE_TAB_TRAVERSAL
  111. // ----------------------------------------------------------------------------
  112. // wxControlContainer for TAB navigation implemented in wx itself
  113. // ----------------------------------------------------------------------------
  114. class WXDLLIMPEXP_CORE wxControlContainer : public wxControlContainerBase
  115. {
  116. public:
  117. // default ctor, SetContainerWindow() must be called later
  118. wxControlContainer();
  119. // the methods to be called from the window event handlers
  120. void HandleOnNavigationKey(wxNavigationKeyEvent& event);
  121. void HandleOnFocus(wxFocusEvent& event);
  122. void HandleOnWindowDestroy(wxWindowBase *child);
  123. // called from OnChildFocus() handler, i.e. when one of our (grand)
  124. // children gets the focus
  125. void SetLastFocus(wxWindow *win);
  126. protected:
  127. wxDECLARE_NO_COPY_CLASS(wxControlContainer);
  128. };
  129. #endif // wxHAS_NATIVE_TAB_TRAVERSAL/!wxHAS_NATIVE_TAB_TRAVERSAL
  130. // this function is for wxWidgets internal use only
  131. extern WXDLLIMPEXP_CORE bool wxSetFocusToChild(wxWindow *win, wxWindow **child);
  132. // ----------------------------------------------------------------------------
  133. // wxNavigationEnabled: Derive from this class to support keyboard navigation
  134. // among window children in a wxWindow-derived class. The details of this class
  135. // don't matter, you just need to derive from it to make navigation work.
  136. // ----------------------------------------------------------------------------
  137. // The template parameter W must be a wxWindow-derived class.
  138. template <class W>
  139. class wxNavigationEnabled : public W
  140. {
  141. public:
  142. typedef W BaseWindowClass;
  143. wxNavigationEnabled()
  144. {
  145. m_container.SetContainerWindow(this);
  146. #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
  147. BaseWindowClass::Connect(wxEVT_NAVIGATION_KEY,
  148. wxNavigationKeyEventHandler(wxNavigationEnabled::OnNavigationKey));
  149. BaseWindowClass::Connect(wxEVT_SET_FOCUS,
  150. wxFocusEventHandler(wxNavigationEnabled::OnFocus));
  151. BaseWindowClass::Connect(wxEVT_CHILD_FOCUS,
  152. wxChildFocusEventHandler(wxNavigationEnabled::OnChildFocus));
  153. #endif // !wxHAS_NATIVE_TAB_TRAVERSAL
  154. }
  155. WXDLLIMPEXP_INLINE_CORE virtual bool AcceptsFocus() const
  156. {
  157. return m_container.AcceptsFocus();
  158. }
  159. WXDLLIMPEXP_INLINE_CORE virtual bool AcceptsFocusRecursively() const
  160. {
  161. return m_container.AcceptsFocusRecursively();
  162. }
  163. WXDLLIMPEXP_INLINE_CORE virtual bool AcceptsFocusFromKeyboard() const
  164. {
  165. return m_container.AcceptsFocusFromKeyboard();
  166. }
  167. WXDLLIMPEXP_INLINE_CORE virtual void AddChild(wxWindowBase *child)
  168. {
  169. BaseWindowClass::AddChild(child);
  170. if ( m_container.UpdateCanFocusChildren() )
  171. {
  172. // Under MSW we must have wxTAB_TRAVERSAL style for TAB navigation
  173. // to work.
  174. if ( !BaseWindowClass::HasFlag(wxTAB_TRAVERSAL) )
  175. BaseWindowClass::ToggleWindowStyle(wxTAB_TRAVERSAL);
  176. }
  177. }
  178. WXDLLIMPEXP_INLINE_CORE virtual void RemoveChild(wxWindowBase *child)
  179. {
  180. #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
  181. m_container.HandleOnWindowDestroy(child);
  182. #endif // !wxHAS_NATIVE_TAB_TRAVERSAL
  183. BaseWindowClass::RemoveChild(child);
  184. // We could reset wxTAB_TRAVERSAL here but it doesn't seem to do any
  185. // harm to keep it.
  186. m_container.UpdateCanFocusChildren();
  187. }
  188. WXDLLIMPEXP_INLINE_CORE virtual void SetFocus()
  189. {
  190. if ( !m_container.DoSetFocus() )
  191. BaseWindowClass::SetFocus();
  192. }
  193. void SetFocusIgnoringChildren()
  194. {
  195. BaseWindowClass::SetFocus();
  196. }
  197. protected:
  198. #ifndef wxHAS_NATIVE_TAB_TRAVERSAL
  199. void OnNavigationKey(wxNavigationKeyEvent& event)
  200. {
  201. m_container.HandleOnNavigationKey(event);
  202. }
  203. void OnFocus(wxFocusEvent& event)
  204. {
  205. m_container.HandleOnFocus(event);
  206. }
  207. void OnChildFocus(wxChildFocusEvent& event)
  208. {
  209. m_container.SetLastFocus(event.GetWindow());
  210. event.Skip();
  211. }
  212. #endif // !wxHAS_NATIVE_TAB_TRAVERSAL
  213. wxControlContainer m_container;
  214. wxDECLARE_NO_COPY_TEMPLATE_CLASS(wxNavigationEnabled, W);
  215. };
  216. // ----------------------------------------------------------------------------
  217. // Compatibility macros from now on, do NOT use them and preferably do not even
  218. // look at them.
  219. // ----------------------------------------------------------------------------
  220. #if WXWIN_COMPATIBILITY_2_8
  221. // common part of WX_DECLARE_CONTROL_CONTAINER in the native and generic cases,
  222. // it should be used in the wxWindow-derived class declaration
  223. #define WX_DECLARE_CONTROL_CONTAINER_BASE() \
  224. public: \
  225. virtual bool AcceptsFocus() const; \
  226. virtual bool AcceptsFocusRecursively() const; \
  227. virtual bool AcceptsFocusFromKeyboard() const; \
  228. virtual void AddChild(wxWindowBase *child); \
  229. virtual void RemoveChild(wxWindowBase *child); \
  230. virtual void SetFocus(); \
  231. void SetFocusIgnoringChildren(); \
  232. \
  233. protected: \
  234. wxControlContainer m_container
  235. // this macro must be used in the derived class ctor
  236. #define WX_INIT_CONTROL_CONTAINER() \
  237. m_container.SetContainerWindow(this)
  238. // common part of WX_DELEGATE_TO_CONTROL_CONTAINER in the native and generic
  239. // cases, must be used in the wxWindow-derived class implementation
  240. #define WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \
  241. void classname::AddChild(wxWindowBase *child) \
  242. { \
  243. basename::AddChild(child); \
  244. \
  245. m_container.UpdateCanFocusChildren(); \
  246. } \
  247. \
  248. bool classname::AcceptsFocusRecursively() const \
  249. { \
  250. return m_container.AcceptsFocusRecursively(); \
  251. } \
  252. \
  253. void classname::SetFocus() \
  254. { \
  255. if ( !m_container.DoSetFocus() ) \
  256. basename::SetFocus(); \
  257. } \
  258. \
  259. bool classname::AcceptsFocus() const \
  260. { \
  261. return m_container.AcceptsFocus(); \
  262. } \
  263. \
  264. bool classname::AcceptsFocusFromKeyboard() const \
  265. { \
  266. return m_container.AcceptsFocusFromKeyboard(); \
  267. }
  268. #ifdef wxHAS_NATIVE_TAB_TRAVERSAL
  269. #define WX_EVENT_TABLE_CONTROL_CONTAINER(classname)
  270. #define WX_DECLARE_CONTROL_CONTAINER WX_DECLARE_CONTROL_CONTAINER_BASE
  271. #define WX_DELEGATE_TO_CONTROL_CONTAINER(classname, basename) \
  272. WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \
  273. \
  274. void classname::RemoveChild(wxWindowBase *child) \
  275. { \
  276. basename::RemoveChild(child); \
  277. \
  278. m_container.UpdateCanFocusChildren(); \
  279. } \
  280. \
  281. void classname::SetFocusIgnoringChildren() \
  282. { \
  283. basename::SetFocus(); \
  284. }
  285. #else // !wxHAS_NATIVE_TAB_TRAVERSAL
  286. // declare the methods to be forwarded
  287. #define WX_DECLARE_CONTROL_CONTAINER() \
  288. WX_DECLARE_CONTROL_CONTAINER_BASE(); \
  289. \
  290. public: \
  291. void OnNavigationKey(wxNavigationKeyEvent& event); \
  292. void OnFocus(wxFocusEvent& event); \
  293. virtual void OnChildFocus(wxChildFocusEvent& event)
  294. // implement the event table entries for wxControlContainer
  295. #define WX_EVENT_TABLE_CONTROL_CONTAINER(classname) \
  296. EVT_SET_FOCUS(classname::OnFocus) \
  297. EVT_CHILD_FOCUS(classname::OnChildFocus) \
  298. EVT_NAVIGATION_KEY(classname::OnNavigationKey)
  299. // implement the methods forwarding to the wxControlContainer
  300. #define WX_DELEGATE_TO_CONTROL_CONTAINER(classname, basename) \
  301. WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \
  302. \
  303. void classname::RemoveChild(wxWindowBase *child) \
  304. { \
  305. m_container.HandleOnWindowDestroy(child); \
  306. \
  307. basename::RemoveChild(child); \
  308. \
  309. m_container.UpdateCanFocusChildren(); \
  310. } \
  311. \
  312. void classname::OnNavigationKey( wxNavigationKeyEvent& event ) \
  313. { \
  314. m_container.HandleOnNavigationKey(event); \
  315. } \
  316. \
  317. void classname::SetFocusIgnoringChildren() \
  318. { \
  319. basename::SetFocus(); \
  320. } \
  321. \
  322. void classname::OnChildFocus(wxChildFocusEvent& event) \
  323. { \
  324. m_container.SetLastFocus(event.GetWindow()); \
  325. event.Skip(); \
  326. } \
  327. \
  328. void classname::OnFocus(wxFocusEvent& event) \
  329. { \
  330. m_container.HandleOnFocus(event); \
  331. }
  332. #endif // wxHAS_NATIVE_TAB_TRAVERSAL/!wxHAS_NATIVE_TAB_TRAVERSAL
  333. #endif // WXWIN_COMPATIBILITY_2_8
  334. #endif // _WX_CONTAINR_H_