make wxControlContainer accept focus depending on whether it has any focusable children when using native TAB navigation too but also allow to manually override this automatic detection; added wxWindow::SetCanFocus() to notify GTK+ about changed focus state

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@45267 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2007-04-05 22:29:14 +00:00
parent 30d560f4cf
commit 80332672ab
5 changed files with 212 additions and 92 deletions

View File

@@ -15,23 +15,6 @@
#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;
/*
Implementation note: wxControlContainer is not a real mix-in but rather
a class meant to be aggregated with (and not inherited from). Although
@@ -42,15 +25,133 @@ 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; }
// call this when the number of children of the window changes
void UpdateCanFocus() { SetCanFocus(ShouldAcceptFocus()); }
protected:
// return true if we should be focusable
bool ShouldAcceptFocus() const;
private:
// the parent window we manage the children for
wxWindow *m_winParent;
// 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 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::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 WXDLLEXPORT wxFocusEvent;
class WXDLLEXPORT wxNavigationKeyEvent;
class WXDLLEXPORT wxWindow;
class WXDLLEXPORT wxWindowBase;
// ----------------------------------------------------------------------------
// 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);
@@ -72,9 +173,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;
@@ -97,19 +195,15 @@ extern bool wxSetFocusToChild(wxWindow *win, wxWindow **child);
public: \
void OnNavigationKey(wxNavigationKeyEvent& event); \
void OnFocus(wxFocusEvent& event); \
void SetFocusIgnoringChildren(); \
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)
// implement the event table entries for wxControlContainer
#define WX_EVENT_TABLE_CONTROL_CONTAINER(classname) \
EVT_SET_FOCUS(classname::OnFocus) \
@@ -117,43 +211,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