X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c7bfb76a2cf367dcdbff8f9a97e3250053a1adca..6f41c10973643552837c6bd38b23779e65a2eaa3:/include/wx/containr.h?ds=inline diff --git a/include/wx/containr.h b/include/wx/containr.h index 2d4cd3d099..d4eb907682 100644 --- a/include/wx/containr.h +++ b/include/wx/containr.h @@ -1,12 +1,11 @@ /////////////////////////////////////////////////////////////////////////////// // Name: wx/containr.h -// Purpose: wxControlContainer class declration: a "mix-in" class which -// implements the TAB navigation between the controls +// Purpose: wxControlContainer and wxNavigationEnabled declarations // Author: Vadim Zeitlin // Modified by: // Created: 06.08.01 // RCS-ID: $Id$ -// Copyright: (c) 2001 Vadim Zeitlin +// Copyright: (c) 2001, 2011 Vadim Zeitlin // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// @@ -15,23 +14,27 @@ #include "wx/defs.h" +#ifndef wxHAS_NATIVE_TAB_TRAVERSAL + // We need wxEVT_XXX declarations in this case. + #include "wx/event.h" +#endif + class WXDLLIMPEXP_FWD_CORE wxWindow; class WXDLLIMPEXP_FWD_CORE wxWindowBase; /* - Implementation note: wxControlContainer is not a real mix-in but rather - a class meant to be aggregated with (and not inherited from). Although - logically it should be a mix-in, doing it like this has no advantage from - the point of view of the existing code but does have some problems (we'd - need to play tricks with event handlers which may be difficult to do - safely). The price we pay for this simplicity is the ugly macros below. + This header declares wxControlContainer class however it's not a real + container of controls but rather just a helper used to implement TAB + navigation among the window children. You should rarely need to use it + directly, derive from the documented public wxNavigationEnabled<> class to + implement TAB navigation in a custom composite window. */ // ---------------------------------------------------------------------------- // wxControlContainerBase: common part used in both native and generic cases // ---------------------------------------------------------------------------- -class WXDLLEXPORT wxControlContainerBase +class WXDLLIMPEXP_CORE wxControlContainerBase { public: // default ctor, SetContainerWindow() must be called later @@ -49,7 +52,7 @@ public: void SetContainerWindow(wxWindow *winParent) { - wxASSERT_MSG( !m_winParent, _T("shouldn't be called twice") ); + wxASSERT_MSG( !m_winParent, wxT("shouldn't be called twice") ); m_winParent = winParent; } @@ -70,10 +73,14 @@ public: // wxListCtrl) and so should get focus for ourselves bool AcceptsFocusRecursively() const { return true; } - // call this when the number of children of the window changes - // - // note that we have any children, this panel (used just as container for - // them) shouldn't get focus for itself + // this is used to determine whether we can accept focus when Tab or + // another navigation key is pressed -- we alsways can, for the same reason + // as mentioned above for AcceptsFocusRecursively() + bool AcceptsFocusFromKeyboard() const { return true; } + + // Call this when the number of children of the window changes. + // If we have any children, this panel (used just as container for + // them) shouldn't get focus for itself. void UpdateCanFocus() { SetCanFocus(!HasAnyFocusableChildren()); } protected: @@ -86,6 +93,9 @@ protected: // the parent window we manage the children for wxWindow *m_winParent; + // the child which had the focus last time this panel was activated + wxWindow *m_winLastFocused; + private: // value returned by AcceptsFocus(), should be changed using SetCanFocus() // only @@ -93,18 +103,170 @@ private: // a guard against infinite recursion bool m_inSetFocus; +}; - // the child which had the focus last time this panel was activated - wxWindow *m_winLastFocused; +#ifdef wxHAS_NATIVE_TAB_TRAVERSAL + +// ---------------------------------------------------------------------------- +// wxControlContainer for native TAB navigation +// ---------------------------------------------------------------------------- + +// this must be a real class as we forward-declare it elsewhere +class WXDLLIMPEXP_CORE wxControlContainer : public wxControlContainerBase +{ +protected: + // set the focus to the child which had it the last time + virtual bool SetFocusToChild(); +}; + +#else // !wxHAS_NATIVE_TAB_TRAVERSAL + +// ---------------------------------------------------------------------------- +// wxControlContainer for TAB navigation implemented in wx itself +// ---------------------------------------------------------------------------- + +class WXDLLIMPEXP_CORE wxControlContainer : public wxControlContainerBase +{ +public: + // default ctor, SetContainerWindow() must be called later + wxControlContainer(); + + // the methods to be called from the window event handlers + void HandleOnNavigationKey(wxNavigationKeyEvent& event); + void HandleOnFocus(wxFocusEvent& event); + void HandleOnWindowDestroy(wxWindowBase *child); + + // called from OnChildFocus() handler, i.e. when one of our (grand) + // children gets the focus + void SetLastFocus(wxWindow *win); + +protected: + + wxDECLARE_NO_COPY_CLASS(wxControlContainer); +}; + +#endif // wxHAS_NATIVE_TAB_TRAVERSAL/!wxHAS_NATIVE_TAB_TRAVERSAL + +// this function is for wxWidgets internal use only +extern WXDLLIMPEXP_CORE bool wxSetFocusToChild(wxWindow *win, wxWindow **child); + +// ---------------------------------------------------------------------------- +// wxNavigationEnabled: Derive from this class to support keyboard navigation +// among window children in a wxWindow-derived class. The details of this class +// don't matter, you just need to derive from it to make navigation work. +// ---------------------------------------------------------------------------- + +// The template parameter W must be a wxWindow-derived class. +template +class wxNavigationEnabled : public W +{ +public: + typedef W BaseWindowClass; + + wxNavigationEnabled() + { + m_container.SetContainerWindow(this); + +#ifndef wxHAS_NATIVE_TAB_TRAVERSAL + BaseWindowClass::Connect(wxEVT_NAVIGATION_KEY, + wxNavigationKeyEventHandler(wxNavigationEnabled::OnNavigationKey)); + + BaseWindowClass::Connect(wxEVT_SET_FOCUS, + wxFocusEventHandler(wxNavigationEnabled::OnFocus)); + + BaseWindowClass::Connect(wxEVT_CHILD_FOCUS, + wxChildFocusEventHandler(wxNavigationEnabled::OnChildFocus)); +#endif // !wxHAS_NATIVE_TAB_TRAVERSAL + } + + WXDLLIMPEXP_INLINE_CORE virtual bool AcceptsFocus() const + { + return m_container.AcceptsFocus(); + } + + WXDLLIMPEXP_INLINE_CORE virtual bool AcceptsFocusRecursively() const + { + return m_container.AcceptsFocusRecursively(); + } + + WXDLLIMPEXP_INLINE_CORE virtual bool AcceptsFocusFromKeyboard() const + { + return m_container.AcceptsFocusFromKeyboard(); + } + + WXDLLIMPEXP_INLINE_CORE virtual void AddChild(wxWindowBase *child) + { + BaseWindowClass::AddChild(child); + + m_container.UpdateCanFocus(); + } + WXDLLIMPEXP_INLINE_CORE virtual void RemoveChild(wxWindowBase *child) + { +#ifndef wxHAS_NATIVE_TAB_TRAVERSAL + m_container.HandleOnWindowDestroy(child); +#endif // !wxHAS_NATIVE_TAB_TRAVERSAL + + BaseWindowClass::RemoveChild(child); + + m_container.UpdateCanFocus(); + } + + WXDLLIMPEXP_INLINE_CORE virtual void SetFocus() + { + if ( !m_container.DoSetFocus() ) + BaseWindowClass::SetFocus(); + } + + void SetFocusIgnoringChildren() + { + BaseWindowClass::SetFocus(); + } + + void AcceptFocus(bool acceptFocus) + { + m_container.SetCanFocus(acceptFocus); + } + +protected: +#ifndef wxHAS_NATIVE_TAB_TRAVERSAL + void OnNavigationKey(wxNavigationKeyEvent& event) + { + m_container.HandleOnNavigationKey(event); + } + + void OnFocus(wxFocusEvent& event) + { + m_container.HandleOnFocus(event); + } + + void OnChildFocus(wxChildFocusEvent& event) + { + m_container.SetLastFocus(event.GetWindow()); + event.Skip(); + } +#endif // !wxHAS_NATIVE_TAB_TRAVERSAL + + wxControlContainer m_container; + + + wxDECLARE_NO_COPY_TEMPLATE_CLASS(wxNavigationEnabled, W); }; +// ---------------------------------------------------------------------------- +// Compatibility macros from now on, do NOT use them and preferably do not even +// look at them. +// ---------------------------------------------------------------------------- + +#if WXWIN_COMPATIBILITY_2_8 + // common part of WX_DECLARE_CONTROL_CONTAINER in the native and generic cases, // it should be used in the wxWindow-derived class declaration #define WX_DECLARE_CONTROL_CONTAINER_BASE() \ public: \ virtual bool AcceptsFocus() const; \ virtual bool AcceptsFocusRecursively() const; \ + virtual bool AcceptsFocusFromKeyboard() const; \ virtual void AddChild(wxWindowBase *child); \ virtual void RemoveChild(wxWindowBase *child); \ virtual void SetFocus(); \ @@ -145,23 +307,16 @@ protected: \ bool classname::AcceptsFocus() const \ { \ return m_container.AcceptsFocus(); \ + } \ + \ + bool classname::AcceptsFocusFromKeyboard() const \ + { \ + return m_container.AcceptsFocusFromKeyboard(); \ } #ifdef wxHAS_NATIVE_TAB_TRAVERSAL -// ---------------------------------------------------------------------------- -// wxControlContainer for native TAB navigation -// ---------------------------------------------------------------------------- - -// this must be a real class as we forward-declare it elsewhere -class WXDLLEXPORT wxControlContainer : public wxControlContainerBase -{ -protected: - // set the focus to the child which had it the last time - virtual bool SetFocusToChild(); -}; - #define WX_EVENT_TABLE_CONTROL_CONTAINER(classname) #define WX_DECLARE_CONTROL_CONTAINER WX_DECLARE_CONTROL_CONTAINER_BASE @@ -178,43 +333,11 @@ protected: \ void classname::SetFocusIgnoringChildren() \ { \ - SetFocus(); \ + basename::SetFocus(); \ } #else // !wxHAS_NATIVE_TAB_TRAVERSAL -class WXDLLIMPEXP_FWD_CORE wxFocusEvent; -class WXDLLIMPEXP_FWD_CORE wxNavigationKeyEvent; - -// ---------------------------------------------------------------------------- -// wxControlContainer for TAB navigation implemented in wx itself -// ---------------------------------------------------------------------------- - -class WXDLLEXPORT wxControlContainer : public wxControlContainerBase -{ -public: - // default ctor, SetContainerWindow() must be called later - wxControlContainer(); - - // the methods to be called from the window event handlers - void HandleOnNavigationKey(wxNavigationKeyEvent& event); - void HandleOnFocus(wxFocusEvent& event); - void HandleOnWindowDestroy(wxWindowBase *child); - - // called from OnChildFocus() handler, i.e. when one of our (grand) - // children gets the focus - void SetLastFocus(wxWindow *win); - -protected: - - DECLARE_NO_COPY_CLASS(wxControlContainer) -}; - -// ---------------------------------------------------------------------------- -// macros which may be used by the classes wishing to implement TAB navigation -// among their children -// ---------------------------------------------------------------------------- - // declare the methods to be forwarded #define WX_DECLARE_CONTROL_CONTAINER() \ WX_DECLARE_CONTROL_CONTAINER_BASE(); \ @@ -256,16 +379,16 @@ public: \ void classname::OnChildFocus(wxChildFocusEvent& event) \ { \ m_container.SetLastFocus(event.GetWindow()); \ + event.Skip(); \ } \ \ void classname::OnFocus(wxFocusEvent& event) \ { \ m_container.HandleOnFocus(event); \ - } + } #endif // wxHAS_NATIVE_TAB_TRAVERSAL/!wxHAS_NATIVE_TAB_TRAVERSAL -// this function is for wxWidgets internal use only -extern bool wxSetFocusToChild(wxWindow *win, wxWindow **child); +#endif // WXWIN_COMPATIBILITY_2_8 #endif // _WX_CONTAINR_H_