From e68b7b364aff19665e2c6ee8c68266b6f3d56355 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 13 Oct 2012 22:51:50 +0000 Subject: [PATCH] Allow using windows that can't be focused with wxNavigationEnabled<>. The code in wxNavigationEnabled<> assumed that the window itself could be focused if it didn't have any focusable children because it was originally extracted from wxPanel that can, indeed, be focused. This is however not the case for all windows, notably not for wxStaticBox which now derives from wxNavigationEnabled as well but can never be focused itself. Add wxControlContainer::DisableSelfFocus() and call it from wxStaticBox to support this situation. This required splitting m_acceptsFocus flag into m_acceptsFocusSelf and m_acceptsFocusChildren and updating various methods using them. See #13271. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@72663 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/containr.h | 61 +++++++++++++++++++++++------------------ include/wx/statbox.h | 2 +- src/common/containr.cpp | 13 +++++---- 3 files changed, 43 insertions(+), 33 deletions(-) diff --git a/include/wx/containr.h b/include/wx/containr.h index 004ac56f12..69dc4a92c6 100644 --- a/include/wx/containr.h +++ b/include/wx/containr.h @@ -42,9 +42,12 @@ public: { m_winParent = NULL; - // do accept focus initially, we'll stop doing it if/when any children - // are added - m_acceptsFocus = true; + // By default, we accept focus ourselves. + m_acceptsFocusSelf = true; + + // But we don't have any children accepting it yet. + m_acceptsFocusChildren = false; + m_inSetFocus = false; m_winLastFocused = NULL; } @@ -57,31 +60,28 @@ public: m_winParent = winParent; } + // This can be called by the window to indicate that it never wants to have + // the focus for itself. + void DisableSelfFocus() { m_acceptsFocusSelf = false; } + // should be called from SetFocus(), returns false if we did nothing with // the focus and the default processing should take place bool DoSetFocus(); - // 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; } + bool AcceptsFocus() const { return m_acceptsFocusSelf; } - // 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; } + // Returns whether we or one of our children accepts focus. + bool AcceptsFocusRecursively() const + bool AcceptsFocus() const { return m_acceptsFocus; } - // 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; } + // We accept focus from keyboard if we accept it at all. + bool AcceptsFocusFromKeyboard() const { return AcceptsFocusRecursively(); } // 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()); } + // + // Returns true if we have any focusable children, false otherwise. + bool UpdateCanFocusChildren(); protected: // set the focus to the child which had it the last time @@ -97,9 +97,16 @@ protected: wxWindow *m_winLastFocused; private: - // value returned by AcceptsFocus(), should be changed using SetCanFocus() - // only - bool m_acceptsFocus; + // Indicates whether the associated window can ever have focus itself. + // + // Usually this is the case, e.g. a wxPanel can be used either as a + // container for its children or just as a normal window which can be + // focused. But sometimes, e.g. for wxStaticBox, we can never have focus + // ourselves and can only get it if we have any focusable children. + bool m_acceptsFocusSelf; + + // Cached value remembering whether we have any children accepting focus. + bool m_acceptsFocusChildren; // a guard against infinite recursion bool m_inSetFocus; @@ -198,7 +205,7 @@ public: { BaseWindowClass::AddChild(child); - m_container.UpdateCanFocus(); + m_container.UpdateCanFocusChildren(); } WXDLLIMPEXP_INLINE_CORE virtual void RemoveChild(wxWindowBase *child) @@ -209,7 +216,7 @@ public: BaseWindowClass::RemoveChild(child); - m_container.UpdateCanFocus(); + m_container.UpdateCanFocusChildren(); } WXDLLIMPEXP_INLINE_CORE virtual void SetFocus() @@ -281,7 +288,7 @@ protected: \ { \ basename::AddChild(child); \ \ - m_container.UpdateCanFocus(); \ + m_container.UpdateCanFocusChildren(); \ } \ \ bool classname::AcceptsFocusRecursively() const \ @@ -319,7 +326,7 @@ protected: \ { \ basename::RemoveChild(child); \ \ - m_container.UpdateCanFocus(); \ + m_container.UpdateCanFocusChildren(); \ } \ \ void classname::SetFocusIgnoringChildren() \ @@ -354,7 +361,7 @@ public: \ \ basename::RemoveChild(child); \ \ - m_container.UpdateCanFocus(); \ + m_container.UpdateCanFocusChildren(); \ } \ \ void classname::OnNavigationKey( wxNavigationKeyEvent& event ) \ diff --git a/include/wx/statbox.h b/include/wx/statbox.h index 41aae1166a..e1ea580b4b 100644 --- a/include/wx/statbox.h +++ b/include/wx/statbox.h @@ -28,7 +28,7 @@ extern WXDLLIMPEXP_DATA_CORE(const char) wxStaticBoxNameStr[]; class WXDLLIMPEXP_CORE wxStaticBoxBase : public wxNavigationEnabled { public: - wxStaticBoxBase() { } + wxStaticBoxBase() { m_container.DisableSelfFocus(); } // overridden base class virtuals virtual bool HasTransparentBackground() { return true; } diff --git a/src/common/containr.cpp b/src/common/containr.cpp index 53d4e01348..ecc7570e70 100644 --- a/src/common/containr.cpp +++ b/src/common/containr.cpp @@ -47,14 +47,17 @@ // wxControlContainerBase // ---------------------------------------------------------------------------- -void wxControlContainerBase::SetCanFocus(bool acceptsFocus) +bool wxControlContainerBase::UpdateCanFocusChildren() { - if ( acceptsFocus == m_acceptsFocus ) - return; + const bool acceptsFocusChildren = HasAnyFocusableChildren(); + if ( acceptsFocusChildren != m_acceptsFocusChildren ) + { + m_acceptsFocusChildren = acceptsFocusChildren; - m_acceptsFocus = acceptsFocus; + m_winParent->SetCanFocus(AcceptsFocusRecursively()); + } - m_winParent->SetCanFocus(m_acceptsFocus); + return m_acceptsFocusChildren; } bool wxControlContainerBase::HasAnyFocusableChildren() const -- 2.45.2