X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/aa78d22e2008726218d47da1f2ac5864c11b8ebb..48271822ef3d56c8f91af882b68fd1b674a8e8e6:/src/common/containr.cpp?ds=sidebyside diff --git a/src/common/containr.cpp b/src/common/containr.cpp index 185f8098d9..c62e2ebd42 100644 --- a/src/common/containr.cpp +++ b/src/common/containr.cpp @@ -24,21 +24,17 @@ #pragma hdrstop #endif +#ifndef WX_PRECOMP + #include "wx/containr.h" +#endif + #ifndef WX_PRECOMP #include "wx/log.h" #include "wx/event.h" #include "wx/window.h" -#endif //WX_PRECOMP - -#include "wx/containr.h" - -#ifdef __WXMAC__ #include "wx/scrolbar.h" -#endif - -#ifdef __WXMSW__ #include "wx/radiobut.h" -#endif +#endif //WX_PRECOMP // trace mask for focus messages #define TRACE_FOCUS _T("focus") @@ -47,58 +43,50 @@ // implementation // ============================================================================ -wxControlContainer::wxControlContainer(wxWindow *winParent) +// ---------------------------------------------------------------------------- +// wxControlContainerBase +// ---------------------------------------------------------------------------- + +void wxControlContainerBase::SetCanFocus(bool acceptsFocus) { - m_winParent = winParent; + if ( acceptsFocus == m_acceptsFocus ) + return; - m_winLastFocused = - m_winTmpDefault = - m_winDefault = NULL; - m_inSetFocus = false; + m_acceptsFocus = acceptsFocus; + + m_winParent->SetCanFocus(m_acceptsFocus); } -bool wxControlContainer::AcceptsFocus() const +bool wxControlContainerBase::HasAnyFocusableChildren() const { - // if we're not shown or disabled, we can't accept focus - if ( m_winParent->IsShown() && m_winParent->IsEnabled() ) + const wxWindowList& children = m_winParent->GetChildren(); + for ( wxWindowList::const_iterator i = children.begin(), + end = children.end(); + i != end; + ++i ) { - // otherwise we can accept focus either if we have no children at all - // (in this case we're probably not used as a container) or only when - // at least one child will accept focus - wxWindowList::compatibility_iterator node = m_winParent->GetChildren().GetFirst(); - if ( !node ) - return true; + const wxWindow * const child = *i; -#ifdef __WXMAC__ - // wxMac has eventually the two scrollbars as children, they don't count - // as real children in the algorithm mentioned above - bool hasRealChildren = false ; -#endif + if ( !m_winParent->IsClientAreaChild(child) ) + continue; - while ( node ) - { - wxWindow *child = node->GetData(); + if ( child->CanAcceptFocus() ) + return true; + } - if ( child->AcceptsFocus() ) - { - return true; - } + return false; +} -#ifdef __WXMAC__ - wxScrollBar *sb = wxDynamicCast( child , wxScrollBar ) ; - if ( sb == NULL || !m_winParent->MacIsWindowScrollbar( sb ) ) - hasRealChildren = true ; -#endif - node = node->GetNext(); - } +#ifndef wxHAS_NATIVE_TAB_TRAVERSAL -#ifdef __WXMAC__ - if ( !hasRealChildren ) - return true ; -#endif - } +// ---------------------------------------------------------------------------- +// generic wxControlContainer +// ---------------------------------------------------------------------------- - return false; +wxControlContainer::wxControlContainer() +{ + m_winLastFocused = NULL; + m_inSetFocus = false; } void wxControlContainer::SetLastFocus(wxWindow *win) @@ -143,12 +131,16 @@ void wxControlContainer::SetLastFocus(wxWindow *win) } // propagate the last focus upwards so that our parent can set focus back - // to us if it loses it now and regains later - wxWindow *parent = m_winParent->GetParent(); - if ( parent ) + // to us if it loses it now and regains later; do *not* do this if we are + // a toplevel window (e.g. wxDialog) that has another frame as its parent + if ( !m_winParent->IsTopLevel() ) { - wxChildFocusEvent eventFocus(m_winParent); - parent->GetEventHandler()->ProcessEvent(eventFocus); + wxWindow *parent = m_winParent->GetParent(); + if ( parent ) + { + wxChildFocusEvent eventFocus(m_winParent); + parent->GetEventHandler()->ProcessEvent(eventFocus); + } } } @@ -157,7 +149,7 @@ void wxControlContainer::SetLastFocus(wxWindow *win) // within the same group. Used by wxSetFocusToChild on wxMSW // -------------------------------------------------------------------- -#ifdef __WXMSW__ +#if defined(__WXMSW__) && wxUSE_RADIOBTN wxRadioButton* wxGetPreviousButtonInGroup(wxRadioButton *btn) { @@ -286,6 +278,49 @@ void wxControlContainer::HandleOnNavigationKey( wxNavigationKeyEvent& event ) const wxWindowList& children = m_winParent->GetChildren(); + // if we have exactly one notebook-like child window (actually it could be + // any window that returns true from its HasMultiplePages()), then + // [Shift-]Ctrl-Tab and Ctrl-PageUp/Down keys should iterate over its pages + // even if the focus is outside of the control because this is how the + // standard MSW properties dialogs behave and we do it under other platforms + // as well because it seems like a good idea -- but we can always put this + // block inside "#ifdef __WXMSW__" if it's not suitable there + if ( event.IsWindowChange() && !goingDown ) + { + // check if we have a unique notebook-like child + wxWindow *bookctrl = NULL; + for ( wxWindowList::const_iterator i = children.begin(), + end = children.end(); + i != end; + ++i ) + { + wxWindow * const window = *i; + if ( window->HasMultiplePages() ) + { + if ( bookctrl ) + { + // this is the second book-like control already so don't do + // anything as we don't know which one should have its page + // changed + bookctrl = NULL; + break; + } + + bookctrl = window; + } + } + + if ( bookctrl ) + { + // make sure that we don't bubble up the event again from the book + // control resulting in infinite recursion + wxNavigationKeyEvent eventCopy(event); + eventCopy.SetEventObject(m_winParent); + if ( bookctrl->GetEventHandler()->ProcessEvent(eventCopy) ) + return; + } + } + // there is not much to do if we don't have children and we're not // interested in "notebook page change" events here if ( !children.GetCount() || event.IsWindowChange() ) @@ -337,12 +372,12 @@ void wxControlContainer::HandleOnNavigationKey( wxNavigationKeyEvent& event ) if ( winFocus ) { -#ifdef __WXMSW__ +#if defined(__WXMSW__) && wxUSE_RADIOBTN // If we are in a radio button group, start from the first item in the // group if ( event.IsFromTab() && wxIsKindOf(winFocus, wxRadioButton ) ) winFocus = wxGetFirstButtonInGroup((wxRadioButton*)winFocus); -#endif +#endif // __WXMSW__ // ok, we found the focus - now is it our child? start_node = children.Find( winFocus ); } @@ -416,7 +451,7 @@ void wxControlContainer::HandleOnNavigationKey( wxNavigationKeyEvent& event ) wxWindow *child = node->GetData(); -#ifdef __WXMSW__ +#if defined(__WXMSW__) && wxUSE_RADIOBTN if ( event.IsFromTab() ) { if ( wxIsKindOf(child, wxRadioButton) ) @@ -472,7 +507,7 @@ void wxControlContainer::HandleOnNavigationKey( wxNavigationKeyEvent& event ) } #endif // __WXMSW__ - if ( child->AcceptsFocusFromKeyboard() ) + if ( child->CanAcceptFocusFromKeyboard() ) { // if we're setting the focus to a child panel we should prevent it // from giving it to the child which had the focus the last time @@ -511,12 +546,6 @@ void wxControlContainer::HandleOnWindowDestroy(wxWindowBase *child) { if ( child == m_winLastFocused ) m_winLastFocused = NULL; - - if ( child == m_winDefault ) - m_winDefault = NULL; - - if ( child == m_winTmpDefault ) - m_winTmpDefault = NULL; } // ---------------------------------------------------------------------------- @@ -617,10 +646,15 @@ bool wxSetFocusToChild(wxWindow *win, wxWindow **childLastFocused) while ( node ) { wxWindow *child = node->GetData(); + node = node->GetNext(); + + // skip special windows: + if ( !win->IsClientAreaChild(child) ) + continue; - if ( child->AcceptsFocusFromKeyboard() && !child->IsTopLevel() ) + if ( child->CanAcceptFocusFromKeyboard() && !child->IsTopLevel() ) { -#ifdef __WXMSW__ +#if defined(__WXMSW__) && wxUSE_RADIOBTN // If a radiobutton is the first focusable child, search for the // selected radiobutton in the same group wxRadioButton* btn = wxDynamicCast(child, wxRadioButton); @@ -630,7 +664,7 @@ bool wxSetFocusToChild(wxWindow *win, wxWindow **childLastFocused) if (selected) child = selected; } -#endif +#endif // __WXMSW__ wxLogTrace(TRACE_FOCUS, _T("SetFocusToChild() => first child (0x%p)."), @@ -640,10 +674,9 @@ bool wxSetFocusToChild(wxWindow *win, wxWindow **childLastFocused) child->SetFocusFromKbd(); return true; } - - node = node->GetNext(); } return false; } +#endif // !wxHAS_NATIVE_TAB_TRAVERSAL