]> git.saurik.com Git - wxWidgets.git/commitdiff
Allow using windows that can't be focused with wxNavigationEnabled<>.
authorVadim Zeitlin <vadim@wxwidgets.org>
Sat, 13 Oct 2012 22:51:50 +0000 (22:51 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sat, 13 Oct 2012 22:51:50 +0000 (22:51 +0000)
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
include/wx/statbox.h
src/common/containr.cpp

index 004ac56f128fe4da2913224d0886b6b16c1592f2..69dc4a92c62c1bcd2c0a424bc317566ef2710950 100644 (file)
@@ -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 )            \
index 41aae1166a310b1b57f3698eaa8758e75d13de94..e1ea580b4be7aedcc3ea842050c8bfc93f2c497a 100644 (file)
@@ -28,7 +28,7 @@ extern WXDLLIMPEXP_DATA_CORE(const char) wxStaticBoxNameStr[];
 class WXDLLIMPEXP_CORE wxStaticBoxBase : public wxNavigationEnabled<wxControl>
 {
 public:
-    wxStaticBoxBase() { }
+    wxStaticBoxBase() { m_container.DisableSelfFocus(); }
 
     // overridden base class virtuals
     virtual bool HasTransparentBackground() { return true; }
index 53d4e01348777bfa658d3272249241c11ed84f5d..ecc7570e708ac2886a6183a6188ad59d2ec94c3a 100644 (file)
 // 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