X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/146ba0feacf1222ec8a45dfd69dae77b063bf2cf..05159a2750ed2cc5945a85bc5fc6849ad1a30e75:/src/common/wincmn.cpp diff --git a/src/common/wincmn.cpp b/src/common/wincmn.cpp index 32185dcf68..7c40f7ce74 100644 --- a/src/common/wincmn.cpp +++ b/src/common/wincmn.cpp @@ -71,7 +71,11 @@ // static data // ---------------------------------------------------------------------------- +#if defined(__WXPM__) +int wxWindowBase::ms_lastControlId = 2000; +#else int wxWindowBase::ms_lastControlId = -200; +#endif IMPLEMENT_ABSTRACT_CLASS(wxWindowBase, wxEvtHandler) @@ -175,9 +179,10 @@ void wxWindowBase::InitBase() #endif // wxUSE_PALETTE m_virtualSize = wxDefaultSize; - m_minVirtualWidth = -1; - m_minVirtualHeight = -1; - m_maxVirtualWidth = -1; + + m_minVirtualWidth = + m_minVirtualHeight = + m_maxVirtualWidth = m_maxVirtualHeight = -1; // Whether we're using the current theme for this window (wxGTK only for now) @@ -363,6 +368,20 @@ void wxWindowBase::Centre(int direction) } } + // there is no wxTopLevelWindow under wxMotif yet +#ifndef __WXMOTIF__ + // we shouldn't center the dialog on the iconized window: under + // Windows, for example, this places it completely off the screen + if ( parent ) + { + wxTopLevelWindow *winTop = wxDynamicCast(parent, wxTopLevelWindow); + if ( winTop && winTop->IsIconized() ) + { + parent = NULL; + } + } +#endif // __WXMOTIF__ + // did we find the parent? if ( !parent ) { @@ -446,22 +465,65 @@ void wxWindowBase::Fit() { if ( GetChildren().GetCount() > 0 ) { - wxSize size = DoGetBestSize(); - - // for compatibility with the old versions and because it really looks - // slightly more pretty like this, add a pad - size.x += 7; - size.y += 14; - - SetClientSize(size); + SetClientSize(DoGetBestSize()); } //else: do nothing if we have no children } +// fits virtual size (ie. scrolled area etc.) around children +void wxWindowBase::FitInside() +{ + if ( GetChildren().GetCount() > 0 ) + { + SetVirtualSize( GetBestVirtualSize() ); + } +} + // return the size best suited for the current window wxSize wxWindowBase::DoGetBestSize() const { - if ( GetChildren().GetCount() > 0 ) + if ( m_windowSizer ) + { + return m_windowSizer->GetMinSize(); + } +#if wxUSE_CONSTRAINTS + else if ( m_constraints ) + { + wxConstCast(this, wxWindowBase)->SatisfyConstraints(); + + // our minimal acceptable size is such that all our windows fit inside + int maxX = 0, + maxY = 0; + + for ( wxWindowList::Node *node = GetChildren().GetFirst(); + node; + node = node->GetNext() ) + { + wxLayoutConstraints *c = node->GetData()->GetConstraints(); + if ( !c ) + { + // it's not normal that we have an unconstrained child, but + // what can we do about it? + continue; + } + + int x = c->right.GetValue(), + y = c->bottom.GetValue(); + + if ( x > maxX ) + maxX = x; + + if ( y > maxY ) + maxY = y; + + // TODO: we must calculate the overlaps somehow, otherwise we + // will never return a size bigger than the current one :-( + } + + return wxSize(maxX, maxY); + } +#endif // wxUSE_CONSTRAINTS + else if ( GetChildren().GetCount() > 0 ) { // our minimal acceptable size is such that all our windows fit inside int maxX = 0, @@ -501,6 +563,11 @@ wxSize wxWindowBase::DoGetBestSize() const maxY = wy + wh; } + // for compatibility with the old versions and because it really looks + // slightly more pretty like this, add a pad + maxX += 7; + maxY += 14; + return wxSize(maxX, maxY); } else @@ -535,19 +602,20 @@ void wxWindowBase::SetVirtualSizeHints( int minW, int minH, m_maxVirtualWidth = maxW; m_minVirtualHeight = minH; m_maxVirtualHeight = maxH; - - SetVirtualSize( GetClientSize() ); } void wxWindowBase::DoSetVirtualSize( int x, int y ) { - if( m_minVirtualWidth != -1 && m_minVirtualWidth > x ) x = m_minVirtualWidth; - if( m_maxVirtualWidth != -1 && m_maxVirtualWidth < x ) x = m_maxVirtualWidth; - if( m_minVirtualHeight != -1 && m_minVirtualHeight > y ) y = m_minVirtualHeight; - if( m_maxVirtualHeight != -1 && m_maxVirtualHeight < y ) y = m_maxVirtualHeight; + if ( m_minVirtualWidth != -1 && m_minVirtualWidth > x ) + x = m_minVirtualWidth; + if ( m_maxVirtualWidth != -1 && m_maxVirtualWidth < x ) + x = m_maxVirtualWidth; + if ( m_minVirtualHeight != -1 && m_minVirtualHeight > y ) + y = m_minVirtualHeight; + if ( m_maxVirtualHeight != -1 && m_maxVirtualHeight < y ) + y = m_maxVirtualHeight; - m_virtualSize.SetWidth( x ); - m_virtualSize.SetHeight( y ); + m_virtualSize = wxSize(x, y); } wxSize wxWindowBase::DoGetVirtualSize() const @@ -665,7 +733,13 @@ bool wxWindowBase::Reparent(wxWindowBase *newParent) void wxWindowBase::PushEventHandler(wxEvtHandler *handler) { - handler->SetNextHandler(GetEventHandler()); + wxEvtHandler *handlerOld = GetEventHandler(); + + handler->SetNextHandler(handlerOld); + + if ( handlerOld ) + GetEventHandler()->SetPreviousHandler(handler); + SetEventHandler(handler); } @@ -676,7 +750,11 @@ wxEvtHandler *wxWindowBase::PopEventHandler(bool deleteHandler) { wxEvtHandler *handlerB = handlerA->GetNextHandler(); handlerA->SetNextHandler((wxEvtHandler *)NULL); + + if ( handlerB ) + handlerB->SetPreviousHandler((wxEvtHandler *)NULL); SetEventHandler(handlerB); + if ( deleteHandler ) { delete handlerA; @@ -708,6 +786,10 @@ bool wxWindowBase::RemoveEventHandler(wxEvtHandler *handler) SetEventHandler(handlerNext); } + if ( handlerNext ) + { + handlerNext->SetPreviousHandler ( handlerPrev ); + } handler->SetNextHandler(NULL); return TRUE; @@ -1342,15 +1424,17 @@ void wxWindowBase::DeleteRelatedConstraints() m_constraintsInvolvedIn = (wxWindowList *) NULL; } } -#endif + +#endif // wxUSE_CONSTRAINTS void wxWindowBase::SetSizer(wxSizer *sizer, bool deleteOld) { - if (m_windowSizer && deleteOld) delete m_windowSizer; + if ( deleteOld ) + delete m_windowSizer; m_windowSizer = sizer; - SetAutoLayout( sizer != 0 ); + SetAutoLayout( sizer != NULL ); } void wxWindowBase::SetSizerAndFit(wxSizer *sizer, bool deleteOld) @@ -1359,6 +1443,33 @@ void wxWindowBase::SetSizerAndFit(wxSizer *sizer, bool deleteOld) sizer->SetSizeHints( (wxWindow*) this ); } +#if wxUSE_CONSTRAINTS + +void wxWindowBase::SatisfyConstraints() +{ + wxLayoutConstraints *constr = GetConstraints(); + bool wasOk = constr && constr->AreSatisfied(); + + ResetConstraints(); // Mark all constraints as unevaluated + + int noChanges = 1; + + // if we're a top level panel (i.e. our parent is frame/dialog), our + // own constraints will never be satisfied any more unless we do it + // here + if ( wasOk ) + { + while ( noChanges > 0 ) + { + LayoutPhase1(&noChanges); + } + } + + LayoutPhase2(&noChanges); +} + +#endif // wxUSE_CONSTRAINTS + bool wxWindowBase::Layout() { // If there is a sizer, use it instead of the constraints @@ -1371,25 +1482,7 @@ bool wxWindowBase::Layout() #if wxUSE_CONSTRAINTS else { - wxLayoutConstraints *constr = GetConstraints(); - bool wasOk = constr && constr->AreSatisfied(); - - ResetConstraints(); // Mark all constraints as unevaluated - - // if we're a top level panel (i.e. our parent is frame/dialog), our - // own constraints will never be satisfied any more unless we do it - // here - if ( wasOk ) - { - int noChanges = 1; - while ( noChanges > 0 ) - { - constr->SatisfyConstraints(this, &noChanges); - } - } - - DoPhase(1); // Layout children - DoPhase(2); // Layout grand children + SatisfyConstraints(); // Find the right constraints values SetConstraintSizes(); // Recursively set the real window sizes } #endif @@ -1398,67 +1491,78 @@ bool wxWindowBase::Layout() } #if wxUSE_CONSTRAINTS -// Do a phase of evaluating constraints: the default behaviour. wxSizers may -// do a similar thing, but also impose their own 'constraints' and order the -// evaluation differently. + +// first phase of the constraints evaluation: set our own constraints bool wxWindowBase::LayoutPhase1(int *noChanges) { wxLayoutConstraints *constr = GetConstraints(); - if ( constr ) - { - return constr->SatisfyConstraints(this, noChanges); - } - else - return TRUE; + + return !constr || constr->SatisfyConstraints(this, noChanges); } +// second phase: set the constraints for our children bool wxWindowBase::LayoutPhase2(int *noChanges) { *noChanges = 0; // Layout children DoPhase(1); + + // Layout grand children DoPhase(2); + return TRUE; } // Do a phase of evaluating child constraints bool wxWindowBase::DoPhase(int phase) { - int noIterations = 0; - int maxIterations = 500; - int noChanges = 1; - int noFailures = 0; + // the list containing the children for which the constraints are already + // set correctly wxWindowList succeeded; - while ((noChanges > 0) && (noIterations < maxIterations)) + + // the max number of iterations we loop before concluding that we can't set + // the constraints + static const int maxIterations = 500; + + for ( int noIterations = 0; noIterations < maxIterations; noIterations++ ) { - noChanges = 0; - noFailures = 0; - wxWindowList::Node *node = GetChildren().GetFirst(); - while (node) + int noChanges = 0; + + // loop over all children setting their constraints + for ( wxWindowList::Node *node = GetChildren().GetFirst(); + node; + node = node->GetNext() ) { wxWindow *child = node->GetData(); - if ( !child->IsTopLevel() ) + if ( child->IsTopLevel() ) { - wxLayoutConstraints *constr = child->GetConstraints(); - if ( constr ) - { - if ( !succeeded.Find(child) ) - { - int tempNoChanges = 0; - bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ; - noChanges += tempNoChanges; - if ( success ) - { - succeeded.Append(child); - } - } - } + // top level children are not inside our client area + continue; + } + + if ( !child->GetConstraints() || succeeded.Find(child) ) + { + // this one is either already ok or nothing we can do about it + continue; + } + + int tempNoChanges = 0; + bool success = phase == 1 ? child->LayoutPhase1(&tempNoChanges) + : child->LayoutPhase2(&tempNoChanges); + noChanges += tempNoChanges; + + if ( success ) + { + succeeded.Append(child); } - node = node->GetNext(); } - noIterations++; + if ( !noChanges ) + { + // constraints are set + break; + } } return TRUE; @@ -1660,10 +1764,16 @@ void wxWindowBase::UpdateWindowUI() #if wxUSE_TEXTCTRL wxTextCtrl *text = wxDynamicCast(control, wxTextCtrl); if ( text ) - text->SetValue(event.GetText()); + { + if ( event.GetText() != text->GetValue() ) + text->SetValue(event.GetText()); + } else #endif // wxUSE_TEXTCTRL - control->SetLabel(event.GetText()); + { + if ( event.GetText() != control->GetLabel() ) + control->SetLabel(event.GetText()); + } } } @@ -1873,13 +1983,13 @@ struct WXDLLEXPORT wxWindowNext void wxWindowBase::CaptureMouse() { - wxLogTrace(_T("mousecapture"), _T("CaptureMouse(0x%08x)"), this); + wxLogTrace(_T("mousecapture"), _T("CaptureMouse(%p)"), this); wxWindow *winOld = GetCapture(); if ( winOld ) { ((wxWindowBase*) winOld)->DoReleaseMouse(); - + // save it on stack wxWindowNext *item = new wxWindowNext; item->win = winOld; @@ -1893,16 +2003,16 @@ void wxWindowBase::CaptureMouse() void wxWindowBase::ReleaseMouse() { - wxLogTrace(_T("mousecapture"), _T("ReleaseMouse(0x%08x)"), this); + wxLogTrace(_T("mousecapture"), _T("ReleaseMouse(%p)"), this); - wxASSERT_MSG( GetCapture() == this, wxT("attempt to release mouse, but this window hasn't captured it") ) + wxASSERT_MSG( GetCapture() == this, wxT("attempt to release mouse, but this window hasn't captured it") ); DoReleaseMouse(); if ( ms_winCaptureNext ) { ((wxWindowBase*)ms_winCaptureNext->win)->DoCaptureMouse(); - + wxWindowNext *item = ms_winCaptureNext; ms_winCaptureNext = item->next; delete item; @@ -1910,7 +2020,7 @@ void wxWindowBase::ReleaseMouse() //else: stack is empty, no previous capture wxLogTrace(_T("mousecapture"), - _T("After ReleaseMouse() mouse is captured by 0x%08x"), + _T("After ReleaseMouse() mouse is captured by %p"), GetCapture()); } @@ -1926,3 +2036,4 @@ wxWindow* wxGetTopLevelParent(wxWindow *win) return win; } +// vi:sts=4:sw=4:et