make IsEnabled() return false even if the window parent, and not the window itself, is disabled and added IsThisEnabled() implementing the old IsEnabled() behaviour; also significantly simplify the window state management code in all ports by factoring out the common parts in wxWindowBase
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@45031 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -313,7 +313,6 @@ void wxWindowCocoa::Init()
|
||||
m_wxCocoaScrollView = NULL;
|
||||
m_isBeingDeleted = false;
|
||||
m_isInPaint = false;
|
||||
m_shouldBeEnabled = true;
|
||||
}
|
||||
|
||||
// Constructor
|
||||
@@ -601,32 +600,9 @@ void wxWindow::CocoaReplaceView(WX_NSView oldView, WX_NSView newView)
|
||||
[[oldView superview] replaceSubview:oldView with:newView];
|
||||
}
|
||||
|
||||
bool wxWindow::EnableSelfAndChildren(bool enable)
|
||||
void wxWindow::DoEnable(bool enable)
|
||||
{
|
||||
// If the state isn't changing, don't do anything
|
||||
if(!wxWindowBase::Enable(enable && m_shouldBeEnabled))
|
||||
return false;
|
||||
// Set the state of the Cocoa window
|
||||
CocoaSetEnabled(m_isEnabled);
|
||||
// Disable all children or (if enabling) return them to their proper state
|
||||
for(wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
|
||||
node; node = node->GetNext())
|
||||
{
|
||||
node->GetData()->EnableSelfAndChildren(enable);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxWindow::Enable(bool enable)
|
||||
{
|
||||
// Keep track of what the window SHOULD be doing
|
||||
m_shouldBeEnabled = enable;
|
||||
// If the parent is disabled for any reason, then this window will be too.
|
||||
if(!IsTopLevel() && GetParent())
|
||||
{
|
||||
enable = enable && GetParent()->IsEnabled();
|
||||
}
|
||||
return EnableSelfAndChildren(enable);
|
||||
CocoaSetEnabled(enable);
|
||||
}
|
||||
|
||||
bool wxWindow::Show(bool show)
|
||||
|
||||
@@ -858,18 +858,55 @@ bool wxWindowBase::Show(bool show)
|
||||
}
|
||||
}
|
||||
|
||||
bool wxWindowBase::IsEnabled() const
|
||||
{
|
||||
return IsThisEnabled() && (IsTopLevel() || !GetParent() || GetParent()->IsEnabled());
|
||||
}
|
||||
|
||||
void wxWindowBase::NotifyWindowOnEnableChange(bool enabled)
|
||||
{
|
||||
#ifndef wxHAS_NATIVE_ENABLED_MANAGEMENT
|
||||
DoEnable(enabled);
|
||||
#endif // !defined(wxHAS_NATIVE_ENABLED_MANAGEMENT)
|
||||
|
||||
OnEnabled(enabled);
|
||||
|
||||
// If we are top-level then the logic doesn't apply - otherwise
|
||||
// showing a modal dialog would result in total greying out (and ungreying
|
||||
// out later) of everything which would be really ugly
|
||||
if ( IsTopLevel() )
|
||||
return;
|
||||
|
||||
for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
|
||||
node;
|
||||
node = node->GetNext() )
|
||||
{
|
||||
wxWindowBase * const child = node->GetData();
|
||||
if ( !child->IsTopLevel() && child->IsThisEnabled() )
|
||||
child->NotifyWindowOnEnableChange(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
bool wxWindowBase::Enable(bool enable)
|
||||
{
|
||||
if ( enable != m_isEnabled )
|
||||
{
|
||||
m_isEnabled = enable;
|
||||
if ( enable == IsThisEnabled() )
|
||||
return false;
|
||||
|
||||
m_isEnabled = enable;
|
||||
|
||||
#ifdef wxHAS_NATIVE_ENABLED_MANAGEMENT
|
||||
DoEnable(enable);
|
||||
#else // !defined(wxHAS_NATIVE_ENABLED_MANAGEMENT)
|
||||
wxWindowBase * const parent = GetParent();
|
||||
if( !IsTopLevel() && parent && !parent->IsEnabled() )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif // !defined(wxHAS_NATIVE_ENABLED_MANAGEMENT)
|
||||
|
||||
NotifyWindowOnEnableChange(enable);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxWindowBase::IsShownOnScreen() const
|
||||
@@ -921,6 +958,8 @@ bool wxWindowBase::Reparent(wxWindowBase *newParent)
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool oldEnabledState = IsEnabled();
|
||||
|
||||
// unlink this window from the existing parent.
|
||||
if ( oldParent )
|
||||
{
|
||||
@@ -941,6 +980,14 @@ bool wxWindowBase::Reparent(wxWindowBase *newParent)
|
||||
wxTopLevelWindows.Append((wxWindow *)this);
|
||||
}
|
||||
|
||||
// We need to notify window (and its subwindows) if by changing the parent
|
||||
// we also change our enabled/disabled status.
|
||||
const bool newEnabledState = IsEnabled();
|
||||
if ( newEnabledState != oldEnabledState )
|
||||
{
|
||||
NotifyWindowOnEnableChange(newEnabledState);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -196,7 +196,7 @@ void wxBitmapButton::OnSetBitmap()
|
||||
InvalidateBestSize();
|
||||
|
||||
wxBitmap the_one;
|
||||
if (!m_isEnabled)
|
||||
if (!IsThisEnabled())
|
||||
the_one = m_bmpDisabled;
|
||||
else if (m_isSelected)
|
||||
the_one = m_bmpSelected;
|
||||
|
||||
@@ -1288,9 +1288,9 @@ bool wxTextCtrl::Enable( bool enable )
|
||||
}
|
||||
|
||||
// wxGTK-specific: called recursively by Enable,
|
||||
// to give widgets an oppprtunity to correct their colours after they
|
||||
// to give widgets an opportunity to correct their colours after they
|
||||
// have been changed by Enable
|
||||
void wxTextCtrl::OnParentEnable( bool enable )
|
||||
void wxTextCtrl::OnEnabled( bool enable )
|
||||
{
|
||||
// If we have a custom background colour, we use this colour in both
|
||||
// disabled and enabled mode, or we end up with a different colour under the
|
||||
|
||||
@@ -3021,40 +3021,13 @@ bool wxWindowGTK::Show( bool show )
|
||||
return true;
|
||||
}
|
||||
|
||||
static void wxWindowNotifyEnable(wxWindowGTK* win, bool enable)
|
||||
void wxWindowGTK::DoEnable( bool enable )
|
||||
{
|
||||
win->OnParentEnable(enable);
|
||||
|
||||
// Recurse, so that children have the opportunity to Do The Right Thing
|
||||
// and reset colours that have been messed up by a parent's (really ancestor's)
|
||||
// Enable call
|
||||
for ( wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
|
||||
node;
|
||||
node = node->GetNext() )
|
||||
{
|
||||
wxWindow *child = node->GetData();
|
||||
if (!child->IsKindOf(CLASSINFO(wxDialog)) && !child->IsKindOf(CLASSINFO(wxFrame)))
|
||||
wxWindowNotifyEnable(child, enable);
|
||||
}
|
||||
}
|
||||
|
||||
bool wxWindowGTK::Enable( bool enable )
|
||||
{
|
||||
wxCHECK_MSG( (m_widget != NULL), false, wxT("invalid window") );
|
||||
|
||||
if (!wxWindowBase::Enable(enable))
|
||||
{
|
||||
// nothing to do
|
||||
return false;
|
||||
}
|
||||
wxCHECK_RET( (m_widget != NULL), wxT("invalid window") );
|
||||
|
||||
gtk_widget_set_sensitive( m_widget, enable );
|
||||
if ( m_wxwindow )
|
||||
gtk_widget_set_sensitive( m_wxwindow, enable );
|
||||
|
||||
wxWindowNotifyEnable(this, enable);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int wxWindowGTK::GetCharHeight() const
|
||||
|
||||
@@ -202,7 +202,7 @@ void wxBitmapButton::OnSetBitmap()
|
||||
InvalidateBestSize();
|
||||
|
||||
wxBitmap the_one;
|
||||
if (!m_isEnabled)
|
||||
if (!IsThisEnabled())
|
||||
the_one = m_bmpDisabled;
|
||||
else if (m_isSelected)
|
||||
the_one = m_bmpSelected;
|
||||
|
||||
@@ -690,32 +690,26 @@ void wxTextCtrl::SetEditable( bool editable )
|
||||
}
|
||||
}
|
||||
|
||||
bool wxTextCtrl::Enable( bool enable )
|
||||
void wxTextCtrl::DoEnable( bool enable )
|
||||
{
|
||||
if (!wxWindowBase::Enable(enable))
|
||||
{
|
||||
// nothing to do
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_windowStyle & wxTE_MULTILINE)
|
||||
{
|
||||
gtk_text_set_editable( GTK_TEXT(m_text), enable );
|
||||
OnParentEnable(enable);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_set_sensitive( m_text, enable );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// wxGTK-specific: called recursively by Enable,
|
||||
// to give widgets an oppprtunity to correct their colours after they
|
||||
// have been changed by Enable
|
||||
void wxTextCtrl::OnParentEnable( bool enable )
|
||||
void wxTextCtrl::OnEnabled( bool enable )
|
||||
{
|
||||
if ( IsSingleLine() )
|
||||
return;
|
||||
|
||||
// If we have a custom background colour, we use this colour in both
|
||||
// disabled and enabled mode, or we end up with a different colour under the
|
||||
// text.
|
||||
|
||||
@@ -3203,40 +3203,13 @@ bool wxWindowGTK::Show( bool show )
|
||||
return true;
|
||||
}
|
||||
|
||||
static void wxWindowNotifyEnable(wxWindowGTK* win, bool enable)
|
||||
{
|
||||
win->OnParentEnable(enable);
|
||||
|
||||
// Recurse, so that children have the opportunity to Do The Right Thing
|
||||
// and reset colours that have been messed up by a parent's (really ancestor's)
|
||||
// Enable call
|
||||
for ( wxWindowList::compatibility_iterator node = win->GetChildren().GetFirst();
|
||||
node;
|
||||
node = node->GetNext() )
|
||||
{
|
||||
wxWindow *child = node->GetData();
|
||||
if (!child->IsKindOf(CLASSINFO(wxDialog)) && !child->IsKindOf(CLASSINFO(wxFrame)))
|
||||
wxWindowNotifyEnable(child, enable);
|
||||
}
|
||||
}
|
||||
|
||||
bool wxWindowGTK::Enable( bool enable )
|
||||
void wxWindowGTK::DoEnable( bool enable )
|
||||
{
|
||||
wxCHECK_MSG( (m_widget != NULL), false, wxT("invalid window") );
|
||||
|
||||
if (!wxWindowBase::Enable(enable))
|
||||
{
|
||||
// nothing to do
|
||||
return false;
|
||||
}
|
||||
|
||||
gtk_widget_set_sensitive( m_widget, enable );
|
||||
if ( m_wxwindow )
|
||||
gtk_widget_set_sensitive( m_wxwindow, enable );
|
||||
|
||||
wxWindowNotifyEnable(this, enable);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int wxWindowGTK::GetCharHeight() const
|
||||
|
||||
@@ -2139,19 +2139,9 @@ bool wxWindowMac::Show(bool show)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxWindowMac::Enable(bool enable)
|
||||
void wxWindowMac::DoEnable(bool enable)
|
||||
{
|
||||
wxASSERT( m_peer->Ok() ) ;
|
||||
bool former = MacIsReallyEnabled() ;
|
||||
if ( !wxWindowBase::Enable(enable) )
|
||||
return false;
|
||||
|
||||
m_peer->Enable( enable ) ;
|
||||
|
||||
if ( former != MacIsReallyEnabled() )
|
||||
MacPropagateEnabledStateChanged() ;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -2176,21 +2166,10 @@ void wxWindowMac::MacPropagateVisibilityChanged()
|
||||
#endif
|
||||
}
|
||||
|
||||
void wxWindowMac::MacPropagateEnabledStateChanged()
|
||||
void wxWindowMac::OnEnabled(bool enabled)
|
||||
{
|
||||
#if !TARGET_API_MAC_OSX
|
||||
MacEnabledStateChanged() ;
|
||||
|
||||
wxWindowMac *child;
|
||||
wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
|
||||
while ( node )
|
||||
{
|
||||
child = node->GetData();
|
||||
if ( child->IsEnabled() )
|
||||
child->MacPropagateEnabledStateChanged() ;
|
||||
|
||||
node = node->GetNext();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -484,7 +484,6 @@ void wxWindowMSW::Init()
|
||||
m_mouseInWindow = false;
|
||||
m_lastKeydownProcessed = false;
|
||||
|
||||
m_childrenDisabled = NULL;
|
||||
m_frozenness = 0;
|
||||
|
||||
m_hWnd = 0;
|
||||
@@ -545,8 +544,6 @@ wxWindowMSW::~wxWindowMSW()
|
||||
wxRemoveHandleAssociation(this);
|
||||
}
|
||||
|
||||
delete m_childrenDisabled;
|
||||
|
||||
}
|
||||
|
||||
// real construction (Init() must have been called before!)
|
||||
@@ -648,110 +645,11 @@ wxWindow *wxWindowBase::DoFindFocus()
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool wxWindowMSW::Enable(bool enable)
|
||||
void wxWindowMSW::DoEnable( bool enable )
|
||||
{
|
||||
// we shouldn't really enable the window if our parent is currently
|
||||
// disabled because under MSW this would indeed show the window in enabled
|
||||
// state but it still wouldn't respond to the input (as its parent is
|
||||
// disabled), so just update the internal m_childrenDisabled list in this
|
||||
// case and our state will be really changed when the parent is enabled
|
||||
|
||||
// the logic above doesn't apply to top level windows, of course
|
||||
wxWindowMSW * const parent = IsTopLevel() ? NULL : GetParent();
|
||||
if ( parent && !parent->IsEnabled() && !IsEnabled() )
|
||||
{
|
||||
// it's a reference as we can create it below
|
||||
wxWindowList *& disabledSiblings = parent->m_childrenDisabled;
|
||||
|
||||
bool rc = false;
|
||||
if ( enable )
|
||||
{
|
||||
// shouldn't be disabled when the parent is reenabled
|
||||
if ( disabledSiblings )
|
||||
{
|
||||
wxWindowList::compatibility_iterator
|
||||
i = disabledSiblings->Find(this);
|
||||
if ( i )
|
||||
{
|
||||
disabledSiblings->Erase(i);
|
||||
rc = true;
|
||||
}
|
||||
}
|
||||
//else: nothing to do
|
||||
}
|
||||
else // !enable
|
||||
{
|
||||
// should disable this window when the parent is enabled
|
||||
if ( !disabledSiblings )
|
||||
disabledSiblings = new wxWindowList;
|
||||
|
||||
disabledSiblings->Append(this);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
if ( !wxWindowBase::Enable(enable) )
|
||||
return false;
|
||||
|
||||
HWND hWnd = GetHwnd();
|
||||
if ( hWnd )
|
||||
::EnableWindow(hWnd, (BOOL)enable);
|
||||
|
||||
// the logic below doesn't apply to the top level windows -- otherwise
|
||||
// showing a modal dialog would result in total greying out (and ungreying
|
||||
// out later) of everything which would be really ugly
|
||||
if ( IsTopLevel() )
|
||||
return true;
|
||||
|
||||
// when the parent is disabled, all of its children should be disabled as
|
||||
// well but when it is enabled back, only those of the children which
|
||||
// hadn't been already disabled in the beginning should be enabled again,
|
||||
// so we have to keep the list of those children
|
||||
for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
|
||||
node;
|
||||
node = node->GetNext() )
|
||||
{
|
||||
wxWindow *child = node->GetData();
|
||||
if ( child->IsTopLevel() )
|
||||
{
|
||||
// the logic below doesn't apply to top level children
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( enable )
|
||||
{
|
||||
// re-enable the child unless it had been disabled before us
|
||||
if ( !m_childrenDisabled || !m_childrenDisabled->Find(child) )
|
||||
child->Enable();
|
||||
}
|
||||
else // we're being disabled
|
||||
{
|
||||
if ( child->IsEnabled() )
|
||||
{
|
||||
// disable it as children shouldn't stay enabled while the
|
||||
// parent is not
|
||||
child->Disable();
|
||||
}
|
||||
else // child already disabled, remember it
|
||||
{
|
||||
// have we created the list of disabled children already?
|
||||
if ( !m_childrenDisabled )
|
||||
m_childrenDisabled = new wxWindowList;
|
||||
|
||||
m_childrenDisabled->Append(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( enable && m_childrenDisabled )
|
||||
{
|
||||
// we don't need this list any more, don't keep unused memory
|
||||
delete m_childrenDisabled;
|
||||
m_childrenDisabled = NULL;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wxWindowMSW::Show(bool show)
|
||||
|
||||
@@ -295,7 +295,6 @@ void wxWindowOS2::Init()
|
||||
m_bUseCtl3D = false;
|
||||
m_bMouseInWindow = false;
|
||||
m_bLastKeydownProcessed = false;
|
||||
m_pChildrenDisabled = NULL;
|
||||
|
||||
//
|
||||
// wxWnd
|
||||
@@ -357,7 +356,6 @@ wxWindowOS2::~wxWindowOS2()
|
||||
//
|
||||
wxRemoveHandleAssociation(this);
|
||||
}
|
||||
delete m_pChildrenDisabled;
|
||||
} // end of wxWindowOS2::~wxWindowOS2
|
||||
|
||||
// real construction (Init() must have been called before!)
|
||||
@@ -479,70 +477,12 @@ wxWindow* wxWindowBase::DoFindFocus()
|
||||
return NULL;
|
||||
} // wxWindowBase::DoFindFocus
|
||||
|
||||
bool wxWindowOS2::Enable( bool bEnable )
|
||||
void wxWindowOS2::DoEnable( bool bEnable )
|
||||
{
|
||||
if (!wxWindowBase::Enable(bEnable))
|
||||
return false;
|
||||
|
||||
HWND hWnd = GetHwnd();
|
||||
|
||||
if ( hWnd )
|
||||
::WinEnableWindow(hWnd, (BOOL)bEnable);
|
||||
|
||||
//
|
||||
// The logic below doesn't apply to the top level windows -- otherwise
|
||||
// showing a modal dialog would result in total greying out (and ungreying
|
||||
// out later) of everything which would be really ugly
|
||||
//
|
||||
if (IsTopLevel())
|
||||
return true;
|
||||
|
||||
wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
|
||||
|
||||
while (node)
|
||||
{
|
||||
wxWindow* pChild = node->GetData();
|
||||
|
||||
if (bEnable)
|
||||
{
|
||||
//
|
||||
// Enable the child back unless it had been disabled before us
|
||||
//
|
||||
if (!m_pChildrenDisabled || !m_pChildrenDisabled->Find(pChild))
|
||||
pChild->Enable();
|
||||
}
|
||||
else // we're being disabled
|
||||
{
|
||||
if (pChild->IsEnabled())
|
||||
{
|
||||
//
|
||||
// Disable it as children shouldn't stay enabled while the
|
||||
// parent is not
|
||||
//
|
||||
pChild->Disable();
|
||||
}
|
||||
else // child already disabled, remember it
|
||||
{
|
||||
//
|
||||
// Have we created the list of disabled children already?
|
||||
//
|
||||
if (!m_pChildrenDisabled)
|
||||
m_pChildrenDisabled = new wxWindowList;
|
||||
m_pChildrenDisabled->Append(pChild);
|
||||
}
|
||||
}
|
||||
node = node->GetNext();
|
||||
}
|
||||
if (bEnable && m_pChildrenDisabled)
|
||||
{
|
||||
//
|
||||
// We don't need this list any more, don't keep unused memory
|
||||
//
|
||||
delete m_pChildrenDisabled;
|
||||
m_pChildrenDisabled = NULL;
|
||||
}
|
||||
return true;
|
||||
} // end of wxWindowOS2::Enable
|
||||
}
|
||||
|
||||
bool wxWindowOS2::Show( bool bShow )
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user