X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/28e88942bc2c9db6ae9a8ef59545d446eefea5fb..333e57d578e9e0fb6555452b5a53698ffd85ee69:/include/wx/containr.h diff --git a/include/wx/containr.h b/include/wx/containr.h index af248caf73..6ac64a4616 100644 --- a/include/wx/containr.h +++ b/include/wx/containr.h @@ -13,27 +13,10 @@ #ifndef _WX_CONTAINR_H_ #define _WX_CONTAINR_H_ -// use native tab traversal logic under GTK+ 2 (doesn't work yet) -#ifdef __WXGTK20__ - #define wxHAS_NATIVE_TAB_TRAVERSAL -#endif +#include "wx/defs.h" -#ifdef wxHAS_NATIVE_TAB_TRAVERSAL - -#define WX_DECLARE_CONTROL_CONTAINER() \ - virtual bool AcceptsFocus() const { return false; } \ - void SetFocusIgnoringChildren() { SetFocus(); } - -#define WX_INIT_CONTROL_CONTAINER() -#define WX_EVENT_TABLE_CONTROL_CONTAINER(classname) -#define WX_DELEGATE_TO_CONTROL_CONTAINER(classname, basename) - -#else // !wxHAS_NATIVE_TAB_TRAVERSAL - -class WXDLLEXPORT wxFocusEvent; -class WXDLLEXPORT wxNavigationKeyEvent; -class WXDLLEXPORT wxWindow; -class WXDLLEXPORT wxWindowBase; +class WXDLLIMPEXP_FWD_CORE wxWindow; +class WXDLLIMPEXP_FWD_CORE wxWindowBase; /* Implementation note: wxControlContainer is not a real mix-in but rather @@ -45,15 +28,146 @@ class WXDLLEXPORT wxWindowBase; */ // ---------------------------------------------------------------------------- -// wxControlContainer +// wxControlContainerBase: common part used in both native and generic cases // ---------------------------------------------------------------------------- -class WXDLLEXPORT wxControlContainer +class WXDLLEXPORT wxControlContainerBase { public: - // ctors and such - wxControlContainer(wxWindow *winParent = NULL); - void SetContainerWindow(wxWindow *winParent) { m_winParent = winParent; } + // default ctor, SetContainerWindow() must be called later + wxControlContainerBase() + { + m_winParent = NULL; + + // do accept focus initially, we'll stop doing it if/when any children + // are added + m_acceptsFocus = true; + } + + void SetContainerWindow(wxWindow *winParent) + { + wxASSERT_MSG( !m_winParent, _T("shouldn't be called twice") ); + + m_winParent = winParent; + } + + // should be called when we decide that we should [stop] accepting focus + void SetCanFocus(bool acceptsFocus); + + // returns whether we should accept focus ourselves or not + bool AcceptsFocus() const { return m_acceptsFocus; } + + // returns whether we or one of our children accepts focus: we always do + // because if we don't have any focusable children it probably means that + // we're not being used as a container at all (think of wxGrid or generic + // 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 + void UpdateCanFocus() { SetCanFocus(!HasAnyFocusableChildren()); } + +protected: + // return true if we have any children accepting focus + bool HasAnyFocusableChildren() const; + + // the parent window we manage the children for + wxWindow *m_winParent; + +private: + // value returned by AcceptsFocus(), should be changed using SetCanFocus() + // only + bool m_acceptsFocus; +}; + +// 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 void AddChild(wxWindowBase *child); \ + virtual void RemoveChild(wxWindowBase *child); \ + void SetFocusIgnoringChildren(); \ + void AcceptFocus(bool acceptFocus) \ + { \ + m_container.SetCanFocus(acceptFocus); \ + } \ + \ +protected: \ + wxControlContainer m_container + +// this macro must be used in the derived class ctor +#define WX_INIT_CONTROL_CONTAINER() \ + m_container.SetContainerWindow(this) + +// common part of WX_DELEGATE_TO_CONTROL_CONTAINER in the native and generic +// cases, must be used in the wxWindow-derived class implementation +#define WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \ + void classname::AddChild(wxWindowBase *child) \ + { \ + basename::AddChild(child); \ + \ + m_container.UpdateCanFocus(); \ + } \ + \ + bool classname::AcceptsFocusRecursively() const \ + { \ + return m_container.AcceptsFocusRecursively(); \ + } \ + \ + bool classname::AcceptsFocus() const \ + { \ + return m_container.AcceptsFocus(); \ + } + + +#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 +{ +}; + +#define WX_EVENT_TABLE_CONTROL_CONTAINER(classname) + +#define WX_DECLARE_CONTROL_CONTAINER WX_DECLARE_CONTROL_CONTAINER_BASE + +#define WX_DELEGATE_TO_CONTROL_CONTAINER(classname, basename) \ + WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \ + \ + void classname::RemoveChild(wxWindowBase *child) \ + { \ + basename::RemoveChild(child); \ + \ + m_container.UpdateCanFocus(); \ + } \ + \ + void classname::SetFocusIgnoringChildren() \ + { \ + 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); @@ -64,9 +178,6 @@ public: // the focus and the default processing should take place bool DoSetFocus(); - // can our child get the focus? - bool AcceptsFocus() const; - // called from OnChildFocus() handler, i.e. when one of our (grand) // children gets the focus void SetLastFocus(wxWindow *win); @@ -75,9 +186,6 @@ protected: // set the focus to the child which had it the last time bool SetFocusToChild(); - // 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; @@ -96,22 +204,14 @@ extern bool wxSetFocusToChild(wxWindow *win, wxWindow **child); // ---------------------------------------------------------------------------- // declare the methods to be forwarded -#define WX_DECLARE_CONTROL_CONTAINER() \ -public: \ - void OnNavigationKey(wxNavigationKeyEvent& event); \ - void OnFocus(wxFocusEvent& event); \ - virtual void OnChildFocus(wxChildFocusEvent& event); \ - virtual void SetFocus(); \ - virtual void SetFocusIgnoringChildren(); \ - virtual void RemoveChild(wxWindowBase *child); \ - virtual bool AcceptsFocus() const; \ -\ -protected: \ - wxControlContainer m_container - -// this macro must be used in the derived class ctor -#define WX_INIT_CONTROL_CONTAINER() \ - m_container.SetContainerWindow(this) +#define WX_DECLARE_CONTROL_CONTAINER() \ + WX_DECLARE_CONTROL_CONTAINER_BASE(); \ + \ +public: \ + void OnNavigationKey(wxNavigationKeyEvent& event); \ + void OnFocus(wxFocusEvent& event); \ + virtual void OnChildFocus(wxChildFocusEvent& event); \ + virtual void SetFocus() // implement the event table entries for wxControlContainer #define WX_EVENT_TABLE_CONTROL_CONTAINER(classname) \ @@ -120,43 +220,43 @@ protected: \ EVT_NAVIGATION_KEY(classname::OnNavigationKey) // implement the methods forwarding to the wxControlContainer -#define WX_DELEGATE_TO_CONTROL_CONTAINER(classname, basename) \ -void classname::OnNavigationKey( wxNavigationKeyEvent& event ) \ -{ \ - m_container.HandleOnNavigationKey(event); \ -} \ - \ -void classname::RemoveChild(wxWindowBase *child) \ -{ \ - m_container.HandleOnWindowDestroy(child); \ - \ - basename::RemoveChild(child); \ -} \ - \ -void classname::SetFocus() \ -{ \ - if ( !m_container.DoSetFocus() ) \ - basename::SetFocus(); \ -} \ - \ -void classname::SetFocusIgnoringChildren() \ -{ \ - basename::SetFocus(); \ -} \ - \ -void classname::OnChildFocus(wxChildFocusEvent& event) \ -{ \ - m_container.SetLastFocus(event.GetWindow()); \ -} \ - \ -void classname::OnFocus(wxFocusEvent& event) \ -{ \ - m_container.HandleOnFocus(event); \ -} \ -bool classname::AcceptsFocus() const \ -{ \ - return m_container.AcceptsFocus(); \ -} +#define WX_DELEGATE_TO_CONTROL_CONTAINER(classname, basename) \ + WX_DELEGATE_TO_CONTROL_CONTAINER_BASE(classname, basename) \ + \ + void classname::RemoveChild(wxWindowBase *child) \ + { \ + m_container.HandleOnWindowDestroy(child); \ + \ + basename::RemoveChild(child); \ + \ + m_container.UpdateCanFocus(); \ + } \ + \ + void classname::OnNavigationKey( wxNavigationKeyEvent& event ) \ + { \ + m_container.HandleOnNavigationKey(event); \ + } \ + \ + void classname::SetFocus() \ + { \ + if ( !m_container.DoSetFocus() ) \ + basename::SetFocus(); \ + } \ + \ + void classname::SetFocusIgnoringChildren() \ + { \ + basename::SetFocus(); \ + } \ + \ + void classname::OnChildFocus(wxChildFocusEvent& event) \ + { \ + m_container.SetLastFocus(event.GetWindow()); \ + } \ + \ + void classname::OnFocus(wxFocusEvent& event) \ + { \ + m_container.HandleOnFocus(event); \ + } #endif // wxHAS_NATIVE_TAB_TRAVERSAL/!wxHAS_NATIVE_TAB_TRAVERSAL