X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/301d7a0da67f917447e4f594a85a218eea4e003b..916eabe60eee4adb05387bbf1eaf1915ae5eac18:/src/common/wincmn.cpp?ds=sidebyside diff --git a/src/common/wincmn.cpp b/src/common/wincmn.cpp index 0c2f15dc96..03e49a2a0c 100644 --- a/src/common/wincmn.cpp +++ b/src/common/wincmn.cpp @@ -369,6 +369,20 @@ wxWindowBase::~wxWindowBase() #if wxUSE_ACCESSIBILITY delete m_accessible; #endif + +#if wxUSE_HELP + // NB: this has to be called unconditionally, because we don't know + // whether this window has associated help text or not + wxHelpProvider *helpProvider = wxHelpProvider::Get(); + if ( helpProvider ) + helpProvider->RemoveHelp(this); +#endif +} + +bool wxWindowBase::IsBeingDeleted() const +{ + return m_isBeingDeleted || + (!IsTopLevel() && m_parent && m_parent->IsBeingDeleted()); } void wxWindowBase::SendDestroyEvent() @@ -394,7 +408,7 @@ bool wxWindowBase::Close(bool force) // return false if window wasn't closed because the application vetoed the // close event - return GetEventHandler()->ProcessEvent(event) && !event.GetVeto(); + return HandleWindowEvent(event) && !event.GetVeto(); } bool wxWindowBase::DestroyChildren() @@ -833,6 +847,23 @@ void wxWindowBase::DoGetScreenPosition(int *x, int *y) const ClientToScreen(x, y); } +void wxWindowBase::SendSizeEvent(int flags) +{ + wxSizeEvent event(GetSize(), GetId()); + event.SetEventObject(this); + if ( flags & wxSEND_EVENT_POST ) + wxPostEvent(this, event); + else + HandleWindowEvent(event); +} + +void wxWindowBase::SendSizeEventToParent(int flags) +{ + wxWindow * const parent = GetParent(); + if ( parent && !parent->IsBeingDeleted() ) + parent->SendSizeEvent(flags); +} + // ---------------------------------------------------------------------------- // show/hide/enable/disable the window // ---------------------------------------------------------------------------- @@ -920,6 +951,52 @@ bool wxWindowBase::IsTopLevel() const return false; } +// ---------------------------------------------------------------------------- +// Freeze/Thaw +// ---------------------------------------------------------------------------- + +void wxWindowBase::Freeze() +{ + if ( !m_freezeCount++ ) + { + // physically freeze this window: + DoFreeze(); + + // and recursively freeze all children: + for ( wxWindowList::iterator i = GetChildren().begin(); + i != GetChildren().end(); ++i ) + { + wxWindow *child = *i; + if ( child->IsTopLevel() ) + continue; + + child->Freeze(); + } + } +} + +void wxWindowBase::Thaw() +{ + wxASSERT_MSG( m_freezeCount, "Thaw() without matching Freeze()" ); + + if ( !--m_freezeCount ) + { + // recursively thaw all children: + for ( wxWindowList::iterator i = GetChildren().begin(); + i != GetChildren().end(); ++i ) + { + wxWindow *child = *i; + if ( child->IsTopLevel() ) + continue; + + child->Thaw(); + } + + // physically thaw this window: + DoThaw(); + } +} + // ---------------------------------------------------------------------------- // reparenting the window // ---------------------------------------------------------------------------- @@ -935,12 +1012,25 @@ void wxWindowBase::AddChild(wxWindowBase *child) GetChildren().Append((wxWindow*)child); child->SetParent(this); + + // adding a child while frozen will assert when thawed, so freeze it as if + // it had been already present when we were frozen + if ( IsFrozen() && !child->IsTopLevel() ) + child->Freeze(); } void wxWindowBase::RemoveChild(wxWindowBase *child) { wxCHECK_RET( child, wxT("can't remove a NULL child") ); + // removing a child while frozen may result in permanently frozen window + // if used e.g. from Reparent(), so thaw it + // + // NB: IsTopLevel() doesn't return true any more when a TLW child is being + // removed from its ~wxWindowBase, so check for IsBeingDeleted() too + if ( IsFrozen() && !child->IsBeingDeleted() && !child->IsTopLevel() ) + child->Thaw(); + GetChildren().DeleteObject((wxWindow *)child); child->SetParent(NULL); } @@ -1335,7 +1425,7 @@ void wxWindowBase::ClearBackground() // wxGTK uses its own version, no need to add never used code #ifndef __WXGTK__ wxClientDC dc((wxWindow *)this); - wxBrush brush(GetBackgroundColour(), wxSOLID); + wxBrush brush(GetBackgroundColour(), wxBRUSHSTYLE_SOLID); dc.SetBackground(brush); dc.Clear(); #endif // __WXGTK__ @@ -1631,6 +1721,7 @@ void wxWindowBase::SetHelpText(const wxString& text) } } +#if WXWIN_COMPATIBILITY_2_8 // associate this help text with all windows with the same id as this // one void wxWindowBase::SetHelpTextForId(const wxString& text) @@ -1641,6 +1732,7 @@ void wxWindowBase::SetHelpTextForId(const wxString& text) helpProvider->AddHelp(GetId(), text); } } +#endif // WXWIN_COMPATIBILITY_2_8 // get the help string associated with this window (may be empty) // default implementation forwards calls to the help provider @@ -1664,7 +1756,29 @@ void wxWindowBase::OnHelp(wxHelpEvent& event) wxHelpProvider *helpProvider = wxHelpProvider::Get(); if ( helpProvider ) { - if ( helpProvider->ShowHelpAtPoint(this, event.GetPosition(), event.GetOrigin()) ) + wxPoint pos = event.GetPosition(); + const wxHelpEvent::Origin origin = event.GetOrigin(); + if ( origin == wxHelpEvent::Origin_Keyboard ) + { + // if the help event was generated from keyboard it shouldn't + // appear at the mouse position (which is still the only position + // associated with help event) if the mouse is far away, although + // we still do use the mouse position if it's over the window + // because we suppose the user looks approximately at the mouse + // already and so it would be more convenient than showing tooltip + // at some arbitrary position which can be quite far from it + const wxRect rectClient = GetClientRect(); + if ( !rectClient.Contains(ScreenToClient(pos)) ) + { + // position help slightly under and to the right of this window + pos = ClientToScreen(wxPoint( + 2*GetCharWidth(), + rectClient.height + GetCharHeight() + )); + } + } + + if ( helpProvider->ShowHelpAtPoint(this, pos, origin) ) { // skip the event.Skip() below return; @@ -2323,7 +2437,7 @@ static void DrawBorder(wxWindowBase *win, const wxRect& rect, bool fill = false) { wxClientDC dc((wxWindow *)win); dc.SetPen(*wxRED_PEN); - dc.SetBrush(fill ? wxBrush(*wxRED, wxCROSSDIAG_HATCH): *wxTRANSPARENT_BRUSH); + dc.SetBrush(fill ? wxBrush(*wxRED, wxBRUSHSTYLE_CROSSDIAG_HATCH) : *wxTRANSPARENT_BRUSH); dc.DrawRectangle(rect.Deflate(1, 1)); } @@ -2533,7 +2647,10 @@ void wxWindowBase::ReleaseMouse() wxASSERT_MSG( !ms_winCaptureChanging, _T("recursive ReleaseMouse call?") ); - wxASSERT_MSG( GetCapture() == this, wxT("attempt to release mouse, but this window hasn't captured it") ); + wxASSERT_MSG( GetCapture() == this, + "attempt to release mouse, but this window hasn't captured it" ); + wxASSERT_MSG( ms_winCaptureCurrent == this, + "attempt to release mouse, but this window hasn't captured it" ); ms_winCaptureChanging = true; @@ -2630,8 +2747,8 @@ bool wxWindowBase::TryValidator(wxEvent& wxVALIDATOR_PARAM(event)) // is receiving the event if ( event.GetEventObject() == this ) { - wxValidator *validator = GetValidator(); - if ( validator && validator->ProcessEvent(event) ) + wxValidator * const validator = GetValidator(); + if ( validator && validator->ProcessEventHere(event) ) { return true; } @@ -2700,12 +2817,33 @@ bool wxWindowBase::DoNavigateIn(int flags) return false; #else // !wxHAS_NATIVE_TAB_TRAVERSAL wxNavigationKeyEvent eventNav; + wxWindow *focused = FindFocus(); + eventNav.SetCurrentFocus(focused); + eventNav.SetEventObject(focused); eventNav.SetFlags(flags); - eventNav.SetEventObject(FindFocus()); return GetEventHandler()->ProcessEvent(eventNav); #endif // wxHAS_NATIVE_TAB_TRAVERSAL/!wxHAS_NATIVE_TAB_TRAVERSAL } +bool wxWindowBase::HandleAsNavigationKey(const wxKeyEvent& event) +{ + if ( event.GetKeyCode() != WXK_TAB ) + return false; + + int flags = wxNavigationKeyEvent::FromTab; + + if ( event.ShiftDown() ) + flags |= wxNavigationKeyEvent::IsBackward; + else + flags |= wxNavigationKeyEvent::IsForward; + + if ( event.ControlDown() ) + flags |= wxNavigationKeyEvent::WinChange; + + Navigate(flags); + return true; +} + void wxWindowBase::DoMoveInTabOrder(wxWindow *win, WindowOrder move) { // check that we're not a top level window