X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c6212a0cb7e6285f62198a9411d91bbe8dc06e60..c753eb9269d1e6c99b80a2d782ce49d9864ac1da:/src/common/wincmn.cpp diff --git a/src/common/wincmn.cpp b/src/common/wincmn.cpp index 5192410234..8a0ae4f54f 100644 --- a/src/common/wincmn.cpp +++ b/src/common/wincmn.cpp @@ -38,6 +38,7 @@ #include "wx/settings.h" #include "wx/dialog.h" #include "wx/msgdlg.h" + #include "wx/msgout.h" #include "wx/statusbr.h" #include "wx/toolbar.h" #include "wx/dcclient.h" @@ -71,16 +72,6 @@ #include "wx/sysopt.h" #endif -// For reporting compile- and runtime version of GTK+ in the ctrl+alt+mclick dialog. -// The gtk includes don't pull any other headers in, at least not on my system - MR -#ifdef __WXGTK__ - #ifdef __WXGTK20__ - #include - #else - #include - #endif -#endif - #include "wx/platinfo.h" // Windows List @@ -111,6 +102,7 @@ BEGIN_EVENT_TABLE(wxWindowBase, wxEvtHandler) EVT_HELP(wxID_ANY, wxWindowBase::OnHelp) #endif // wxUSE_HELP + EVT_SIZE(wxWindowBase::InternalOnSize) END_EVENT_TABLE() // ============================================================================ @@ -162,7 +154,7 @@ wxWindowBase::wxWindowBase() m_exStyle = m_windowStyle = 0; - m_backgroundStyle = wxBG_STYLE_SYSTEM; + m_backgroundStyle = wxBG_STYLE_ERASE; #if wxUSE_CONSTRAINTS // no constraints whatsoever @@ -226,17 +218,6 @@ bool wxWindowBase::CreateBase(wxWindowBase *parent, const wxValidator& wxVALIDATOR_PARAM(validator), const wxString& name) { -#if wxUSE_STATBOX - // wxGTK doesn't allow to create controls with static box as the parent so - // this will result in a crash when the program is ported to wxGTK so warn - // the user about it - - // if you get this assert, the correct solution is to create the controls - // as siblings of the static box - wxASSERT_MSG( !parent || !wxDynamicCast(parent, wxStaticBox), - _T("wxStaticBox can't be used as a window parent!") ); -#endif // wxUSE_STATBOX - // ids are limited to 16 bits under MSW so if you care about portability, // it's not a good idea to use ids out of this range (and negative ids are // reserved for wxWidgets own usage) @@ -407,6 +388,8 @@ void wxWindowBase::SendDestroyEvent() bool wxWindowBase::Destroy() { + SendDestroyEvent(); + delete this; return true; @@ -435,11 +418,11 @@ bool wxWindowBase::DestroyChildren() wxWindow *child = node->GetData(); - // note that we really want to call delete and not ->Destroy() here - // because we want to delete the child immediately, before we are - // deleted, and delayed deletion would result in problems as our (top - // level) child could outlive its parent - delete child; + // note that we really want to delete it immediately so don't call the + // possible overridden Destroy() version which might not delete the + // child immediately resulting in problems with our (top level) child + // outliving its parent + child->wxWindowBase::Destroy(); wxASSERT_MSG( !GetChildren().Find(child), wxT("child didn't remove itself using RemoveChild()") ); @@ -481,7 +464,7 @@ void wxWindowBase::FitInside() } // On Mac, scrollbars are explicitly children. -#ifdef __WXMAC__ +#if defined( __WXMAC__ ) && !defined(__WXUNIVERSAL__) static bool wxHasRealChildren(const wxWindowBase* win) { int realChildCount = 0; @@ -557,7 +540,7 @@ wxSize wxWindowBase::DoGetBestSize() const } #endif // wxUSE_CONSTRAINTS else if ( !GetChildren().empty() -#ifdef __WXMAC__ +#if defined( __WXMAC__ ) && !defined(__WXUNIVERSAL__) && wxHasRealChildren(this) #endif ) @@ -709,15 +692,36 @@ wxSize wxWindowBase::GetEffectiveMinSize() const { // merge the best size with the min size, giving priority to the min size wxSize min = GetMinSize(); + if (min.x == wxDefaultCoord || min.y == wxDefaultCoord) { wxSize best = GetBestSize(); if (min.x == wxDefaultCoord) min.x = best.x; if (min.y == wxDefaultCoord) min.y = best.y; } + return min; } +wxSize wxWindowBase::GetBestSize() const +{ + if ((!m_windowSizer) && (m_bestSizeCache.IsFullySpecified())) + return m_bestSizeCache; + + return DoGetBestSize(); +} + +void wxWindowBase::SetMinSize(const wxSize& minSize) +{ + m_minWidth = minSize.x; + m_minHeight = minSize.y; +} + +void wxWindowBase::SetMaxSize(const wxSize& maxSize) +{ + m_maxWidth = maxSize.x; + m_maxHeight = maxSize.y; +} void wxWindowBase::SetInitialSize(const wxSize& size) { @@ -1094,73 +1098,124 @@ bool wxWindowBase::Reparent(wxWindowBase *newParent) // event handler stuff // ---------------------------------------------------------------------------- -void wxWindowBase::PushEventHandler(wxEvtHandler *handler) +void wxWindowBase::SetEventHandler(wxEvtHandler *handler) +{ + wxCHECK_RET(handler != NULL, "SetEventHandler(NULL) called"); + + m_eventHandler = handler; +} + +void wxWindowBase::SetNextHandler(wxEvtHandler *WXUNUSED(handler)) +{ + // disable wxEvtHandler chain mechanism for wxWindows: + // wxWindow uses its own stack mechanism which doesn't mix well with wxEvtHandler's one + + wxFAIL_MSG("wxWindow cannot be part of a wxEvtHandler chain"); +} +void wxWindowBase::SetPreviousHandler(wxEvtHandler *WXUNUSED(handler)) { + // we can't simply wxFAIL here as in SetNextHandler: in fact the last + // handler of our stack when is destroyed will be Unlink()ed and thus + // will call this function to update the pointer of this window... + + //wxFAIL_MSG("wxWindow cannot be part of a wxEvtHandler chain"); +} + +void wxWindowBase::PushEventHandler(wxEvtHandler *handlerToPush) +{ + wxCHECK_RET( handlerToPush != NULL, "PushEventHandler(NULL) called" ); + + // the new handler is going to be part of the wxWindow stack of event handlers: + // it can't be part also of an event handler double-linked chain: + wxASSERT_MSG(handlerToPush->IsUnlinked(), + "The handler being pushed in the wxWindow stack shouldn't be part of " + "a wxEvtHandler chain; call Unlink() on it first"); + wxEvtHandler *handlerOld = GetEventHandler(); + wxCHECK_RET( handlerOld, "an old event handler is NULL?" ); + + // now use wxEvtHandler double-linked list to implement a stack: + handlerToPush->SetNextHandler(handlerOld); - handler->SetNextHandler(handlerOld); + if (handlerOld != this) + handlerOld->SetPreviousHandler(handlerToPush); - if ( handlerOld ) - GetEventHandler()->SetPreviousHandler(handler); + SetEventHandler(handlerToPush); - SetEventHandler(handler); +#if wxDEBUG_LEVEL + // final checks of the operations done above: + wxASSERT_MSG( handlerToPush->GetPreviousHandler() == NULL, + "the first handler of the wxWindow stack should " + "have no previous handlers set" ); + wxASSERT_MSG( handlerToPush->GetNextHandler() != NULL, + "the first handler of the wxWindow stack should " + "have non-NULL next handler" ); + + wxEvtHandler* pLast = handlerToPush; + while ( pLast && pLast != this ) + pLast = pLast->GetNextHandler(); + wxASSERT_MSG( pLast->GetNextHandler() == NULL, + "the last handler of the wxWindow stack should " + "have this window as next handler" ); +#endif // wxDEBUG_LEVEL } wxEvtHandler *wxWindowBase::PopEventHandler(bool deleteHandler) { - wxEvtHandler *handlerA = GetEventHandler(); - if ( handlerA ) - { - wxEvtHandler *handlerB = handlerA->GetNextHandler(); - handlerA->SetNextHandler(NULL); + // we need to pop the wxWindow stack, i.e. we need to remove the first handler - if ( handlerB ) - handlerB->SetPreviousHandler(NULL); - SetEventHandler(handlerB); + wxEvtHandler *firstHandler = GetEventHandler(); + wxCHECK_MSG( firstHandler != NULL, NULL, "wxWindow cannot have a NULL event handler" ); + wxCHECK_MSG( firstHandler != this, NULL, "cannot pop the wxWindow itself" ); + wxCHECK_MSG( firstHandler->GetPreviousHandler() == NULL, NULL, + "the first handler of the wxWindow stack should have no previous handlers set" ); - if ( deleteHandler ) - { - delete handlerA; - handlerA = NULL; - } + wxEvtHandler *secondHandler = firstHandler->GetNextHandler(); + wxCHECK_MSG( secondHandler != NULL, NULL, + "the first handler of the wxWindow stack should have non-NULL next handler" ); + + firstHandler->SetNextHandler(NULL); + secondHandler->SetPreviousHandler(NULL); + + // now firstHandler is completely unlinked; set secondHandler as the new window event handler + SetEventHandler(secondHandler); + + if ( deleteHandler ) + { + delete firstHandler; + firstHandler = NULL; } - return handlerA; + return firstHandler; } -bool wxWindowBase::RemoveEventHandler(wxEvtHandler *handler) +bool wxWindowBase::RemoveEventHandler(wxEvtHandler *handlerToRemove) { - wxCHECK_MSG( handler, false, _T("RemoveEventHandler(NULL) called") ); + wxCHECK_MSG( handlerToRemove != NULL, false, "RemoveEventHandler(NULL) called" ); + wxCHECK_MSG( handlerToRemove != this, false, "Cannot remove the window itself" ); - wxEvtHandler *handlerPrev = NULL, - *handlerCur = GetEventHandler(); - while ( handlerCur ) + if (handlerToRemove == GetEventHandler()) + { + // removing the first event handler is equivalent to "popping" the stack + PopEventHandler(false); + return true; + } + + // NOTE: the wxWindow event handler list is always terminated with "this" handler + wxEvtHandler *handlerCur = GetEventHandler()->GetNextHandler(); + while ( handlerCur != this ) { wxEvtHandler *handlerNext = handlerCur->GetNextHandler(); - if ( handlerCur == handler ) + if ( handlerCur == handlerToRemove ) { - if ( handlerPrev ) - { - handlerPrev->SetNextHandler(handlerNext); - } - else - { - SetEventHandler(handlerNext); - } - - if ( handlerNext ) - { - handlerNext->SetPreviousHandler ( handlerPrev ); - } - - handler->SetNextHandler(NULL); - handler->SetPreviousHandler(NULL); + handlerCur->Unlink(); + wxASSERT_MSG( handlerCur != GetEventHandler(), + "the case Remove == Pop should was already handled" ); return true; } - handlerPrev = handlerCur; handlerCur = handlerNext; } @@ -1171,6 +1226,7 @@ bool wxWindowBase::RemoveEventHandler(wxEvtHandler *handler) bool wxWindowBase::HandleWindowEvent(wxEvent& event) const { + // SafelyProcessEvent() will handle exceptions nicely return GetEventHandler()->SafelyProcessEvent(event); } @@ -1277,8 +1333,6 @@ bool wxWindowBase::SetBackgroundColour( const wxColour &colour ) return false; m_hasBgCol = colour.IsOk(); - if ( m_backgroundStyle != wxBG_STYLE_CUSTOM ) - m_backgroundStyle = m_hasBgCol ? wxBG_STYLE_COLOUR : wxBG_STYLE_SYSTEM; m_inheritBgCol = m_hasBgCol; m_backgroundColour = colour; @@ -2040,6 +2094,14 @@ bool wxWindowBase::Layout() return true; } +void wxWindowBase::InternalOnSize(wxSizeEvent& event) +{ + if ( GetAutoLayout() ) + Layout(); + + event.Skip(); +} + #if wxUSE_CONSTRAINTS // first phase of the constraints evaluation: set our own constraints @@ -2467,11 +2529,12 @@ wxWindowBase::DoGetPopupMenuSelectionFromUser(wxMenu& menu, int x, int y) static void DrawSizers(wxWindowBase *win); -static void DrawBorder(wxWindowBase *win, const wxRect& rect, bool fill = false) +static void DrawBorder(wxWindowBase *win, const wxRect& rect, bool fill, const wxPen* pen) { wxClientDC dc((wxWindow *)win); - dc.SetPen(*wxRED_PEN); - dc.SetBrush(fill ? wxBrush(*wxRED, wxBRUSHSTYLE_CROSSDIAG_HATCH) : *wxTRANSPARENT_BRUSH); + dc.SetPen(*pen); + dc.SetBrush(fill ? wxBrush(pen->GetColour(), wxBRUSHSTYLE_CROSSDIAG_HATCH) : + *wxTRANSPARENT_BRUSH); dc.DrawRectangle(rect.Deflate(1, 1)); } @@ -2486,26 +2549,29 @@ static void DrawSizer(wxWindowBase *win, wxSizer *sizer) wxSizerItem *item = *i; if ( item->IsSizer() ) { - DrawBorder(win, item->GetRect().Deflate(2)); + DrawBorder(win, item->GetRect().Deflate(2), false, wxRED_PEN); DrawSizer(win, item->GetSizer()); } else if ( item->IsSpacer() ) { - DrawBorder(win, item->GetRect().Deflate(2), true); + DrawBorder(win, item->GetRect().Deflate(2), true, wxBLUE_PEN); } else if ( item->IsWindow() ) { DrawSizers(item->GetWindow()); } + else + wxFAIL_MSG("inconsistent wxSizerItem status!"); } } static void DrawSizers(wxWindowBase *win) { + DrawBorder(win, win->GetClientSize(), false, wxGREEN_PEN); + wxSizer *sizer = win->GetSizer(); if ( sizer ) { - DrawBorder(win, win->GetClientSize()); DrawSizer(win, sizer); } else // no sizer, still recurse into the children @@ -2518,6 +2584,26 @@ static void DrawSizers(wxWindowBase *win) { DrawSizers(*i); } + + // show all kind of sizes of this window; see the "window sizing" topic + // overview for more info about the various differences: + wxSize fullSz = win->GetSize(); + wxSize clientSz = win->GetClientSize(); + wxSize bestSz = win->GetBestSize(); + wxSize minSz = win->GetMinSize(); + wxSize maxSz = win->GetMaxSize(); + wxSize virtualSz = win->GetVirtualSize(); + + wxMessageOutputDebug dbgout; + dbgout.Printf( + "%-10s => fullsz=%4d;%-4d clientsz=%4d;%-4d bestsz=%4d;%-4d minsz=%4d;%-4d maxsz=%4d;%-4d virtualsz=%4d;%-4d\n", + win->GetName(), + fullSz.x, fullSz.y, + clientSz.x, clientSz.y, + bestSz.x, bestSz.y, + minSz.x, minSz.y, + maxSz.x, maxSz.y, + virtualSz.x, virtualSz.y); } } @@ -2774,7 +2860,7 @@ bool wxWindowBase::UnregisterHotKey(int WXUNUSED(hotkeyId)) // event processing // ---------------------------------------------------------------------------- -bool wxWindowBase::TryValidator(wxEvent& wxVALIDATOR_PARAM(event)) +bool wxWindowBase::TryBefore(wxEvent& event) { #if wxUSE_VALIDATORS // Can only use the validator of the window which @@ -2789,10 +2875,10 @@ bool wxWindowBase::TryValidator(wxEvent& wxVALIDATOR_PARAM(event)) } #endif // wxUSE_VALIDATORS - return false; + return wxEvtHandler::TryBefore(event); } -bool wxWindowBase::TryParent(wxEvent& event) +bool wxWindowBase::TryAfter(wxEvent& event) { // carry on up the parent-child hierarchy if the propagation count hasn't // reached zero yet @@ -2814,7 +2900,7 @@ bool wxWindowBase::TryParent(wxEvent& event) } } - return wxEvtHandler::TryParent(event); + return wxEvtHandler::TryAfter(event); } // ---------------------------------------------------------------------------- @@ -2960,7 +3046,7 @@ public: private: wxWindowBase * const m_win; - DECLARE_NO_COPY_CLASS(DragAcceptFilesTarget) + wxDECLARE_NO_COPY_CLASS(DragAcceptFilesTarget); };