// Author: Vadim Zeitlin
// Modified by:
// Created: 06.08.01
-// RCS-ID: $Id$
// Copyright: (c) 2001, 2011 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
{
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;
}
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; UpdateParentCanFocus(); }
+
+ // This can be called to undo the effect of a previous DisableSelfFocus()
+ // (otherwise calling it is not necessary as the window does accept focus
+ // by default).
+ void EnableSelfFocus()
+ { m_acceptsFocusSelf = true; UpdateParentCanFocus(); }
+
// 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;
- // 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
+ { return AcceptsFocus() ||
+ (m_acceptsFocusChildren && HasAnyChildrenAcceptingFocus()); }
- // 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
// return true if we have any children accepting focus
bool HasAnyFocusableChildren() const;
+ // return true if we have any children that do accept focus right now
+ bool HasAnyChildrenAcceptingFocus() const;
+
+
// the parent window we manage the children for
wxWindow *m_winParent;
wxWindow *m_winLastFocused;
private:
- // value returned by AcceptsFocus(), should be changed using SetCanFocus()
- // only
- bool m_acceptsFocus;
+ // Update the window status to reflect whether it is getting focus or not.
+ void UpdateParentCanFocus();
+
+ // 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;
#endif // !wxHAS_NATIVE_TAB_TRAVERSAL
}
- WXDLLIMPEXP_CORE virtual bool AcceptsFocus() const
+ WXDLLIMPEXP_INLINE_CORE virtual bool AcceptsFocus() const
{
return m_container.AcceptsFocus();
}
- WXDLLIMPEXP_CORE virtual bool AcceptsFocusRecursively() const
+ WXDLLIMPEXP_INLINE_CORE virtual bool AcceptsFocusRecursively() const
{
return m_container.AcceptsFocusRecursively();
}
- WXDLLIMPEXP_CORE virtual bool AcceptsFocusFromKeyboard() const
+ WXDLLIMPEXP_INLINE_CORE virtual bool AcceptsFocusFromKeyboard() const
{
return m_container.AcceptsFocusFromKeyboard();
}
- WXDLLIMPEXP_CORE virtual void AddChild(wxWindowBase *child)
+ WXDLLIMPEXP_INLINE_CORE virtual void AddChild(wxWindowBase *child)
{
BaseWindowClass::AddChild(child);
- m_container.UpdateCanFocus();
+ if ( m_container.UpdateCanFocusChildren() )
+ {
+ // Under MSW we must have wxTAB_TRAVERSAL style for TAB navigation
+ // to work.
+ if ( !BaseWindowClass::HasFlag(wxTAB_TRAVERSAL) )
+ BaseWindowClass::ToggleWindowStyle(wxTAB_TRAVERSAL);
+ }
}
- WXDLLIMPEXP_CORE virtual void RemoveChild(wxWindowBase *child)
+ WXDLLIMPEXP_INLINE_CORE virtual void RemoveChild(wxWindowBase *child)
{
#ifndef wxHAS_NATIVE_TAB_TRAVERSAL
m_container.HandleOnWindowDestroy(child);
BaseWindowClass::RemoveChild(child);
- m_container.UpdateCanFocus();
+ // We could reset wxTAB_TRAVERSAL here but it doesn't seem to do any
+ // harm to keep it.
+ m_container.UpdateCanFocusChildren();
}
- WXDLLIMPEXP_CORE virtual void SetFocus()
+ WXDLLIMPEXP_INLINE_CORE virtual void SetFocus()
{
if ( !m_container.DoSetFocus() )
BaseWindowClass::SetFocus();
BaseWindowClass::SetFocus();
}
- void AcceptFocus(bool acceptFocus)
- {
- m_container.SetCanFocus(acceptFocus);
- }
-
protected:
#ifndef wxHAS_NATIVE_TAB_TRAVERSAL
void OnNavigationKey(wxNavigationKeyEvent& event)
virtual void RemoveChild(wxWindowBase *child); \
virtual void SetFocus(); \
void SetFocusIgnoringChildren(); \
- void AcceptFocus(bool acceptFocus) \
- { \
- m_container.SetCanFocus(acceptFocus); \
- } \
\
protected: \
wxControlContainer m_container
{ \
basename::AddChild(child); \
\
- m_container.UpdateCanFocus(); \
+ m_container.UpdateCanFocusChildren(); \
} \
\
bool classname::AcceptsFocusRecursively() const \
{ \
basename::RemoveChild(child); \
\
- m_container.UpdateCanFocus(); \
+ m_container.UpdateCanFocusChildren(); \
} \
\
void classname::SetFocusIgnoringChildren() \
\
basename::RemoveChild(child); \
\
- m_container.UpdateCanFocus(); \
+ m_container.UpdateCanFocusChildren(); \
} \
\
void classname::OnNavigationKey( wxNavigationKeyEvent& event ) \