attempts to make GetBestSize() work using constraints (failed)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@15678 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2002-05-26 22:37:42 +00:00
parent fb35f0c79c
commit ec5bb70d65
2 changed files with 135 additions and 67 deletions

View File

@@ -838,6 +838,10 @@ public:
#endif // wxUSE_PALETTE #endif // wxUSE_PALETTE
protected: protected:
#if wxUSE_CONSTRAINTS
// satisfy the constraints for the windows but don't set the window sizes
void SatisfyConstraints();
#endif // wxUSE_CONSTRAINTS
// the window id - a number which uniquely identifies a window among // the window id - a number which uniquely identifies a window among
// its siblings unless it is -1 // its siblings unless it is -1
@@ -850,7 +854,10 @@ protected:
// the minimal allowed size for the window (no minimal size if variable(s) // the minimal allowed size for the window (no minimal size if variable(s)
// contain(s) -1) // contain(s) -1)
int m_minWidth, m_minHeight, m_maxWidth, m_maxHeight; int m_minWidth,
m_minHeight,
m_maxWidth,
m_maxHeight;
// event handler for this window: usually is just 'this' but may be // event handler for this window: usually is just 'this' but may be
// changed with SetEventHandler() // changed with SetEventHandler()

View File

@@ -446,14 +446,7 @@ void wxWindowBase::Fit()
{ {
if ( GetChildren().GetCount() > 0 ) if ( GetChildren().GetCount() > 0 )
{ {
wxSize size = DoGetBestSize(); SetClientSize(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);
} }
//else: do nothing if we have no children //else: do nothing if we have no children
} }
@@ -461,7 +454,48 @@ void wxWindowBase::Fit()
// return the size best suited for the current window // return the size best suited for the current window
wxSize wxWindowBase::DoGetBestSize() const 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 // our minimal acceptable size is such that all our windows fit inside
int maxX = 0, int maxX = 0,
@@ -501,6 +535,11 @@ wxSize wxWindowBase::DoGetBestSize() const
maxY = wy + wh; 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); return wxSize(maxX, maxY);
} }
else else
@@ -1342,15 +1381,17 @@ void wxWindowBase::DeleteRelatedConstraints()
m_constraintsInvolvedIn = (wxWindowList *) NULL; m_constraintsInvolvedIn = (wxWindowList *) NULL;
} }
} }
#endif
#endif // wxUSE_CONSTRAINTS
void wxWindowBase::SetSizer(wxSizer *sizer, bool deleteOld) void wxWindowBase::SetSizer(wxSizer *sizer, bool deleteOld)
{ {
if (m_windowSizer && deleteOld) delete m_windowSizer; if ( deleteOld )
delete m_windowSizer;
m_windowSizer = sizer; m_windowSizer = sizer;
SetAutoLayout( sizer != 0 ); SetAutoLayout( sizer != NULL );
} }
void wxWindowBase::SetSizerAndFit(wxSizer *sizer, bool deleteOld) void wxWindowBase::SetSizerAndFit(wxSizer *sizer, bool deleteOld)
@@ -1359,6 +1400,33 @@ void wxWindowBase::SetSizerAndFit(wxSizer *sizer, bool deleteOld)
sizer->SetSizeHints( (wxWindow*) this ); 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() bool wxWindowBase::Layout()
{ {
// If there is a sizer, use it instead of the constraints // If there is a sizer, use it instead of the constraints
@@ -1371,25 +1439,7 @@ bool wxWindowBase::Layout()
#if wxUSE_CONSTRAINTS #if wxUSE_CONSTRAINTS
else else
{ {
wxLayoutConstraints *constr = GetConstraints(); SatisfyConstraints(); // Find the right constraints values
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
SetConstraintSizes(); // Recursively set the real window sizes SetConstraintSizes(); // Recursively set the real window sizes
} }
#endif #endif
@@ -1398,67 +1448,78 @@ bool wxWindowBase::Layout()
} }
#if wxUSE_CONSTRAINTS #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 // first phase of the constraints evaluation: set our own constraints
// evaluation differently.
bool wxWindowBase::LayoutPhase1(int *noChanges) bool wxWindowBase::LayoutPhase1(int *noChanges)
{ {
wxLayoutConstraints *constr = GetConstraints(); wxLayoutConstraints *constr = GetConstraints();
if ( constr )
{ return !constr || constr->SatisfyConstraints(this, noChanges);
return constr->SatisfyConstraints(this, noChanges);
}
else
return TRUE;
} }
// second phase: set the constraints for our children
bool wxWindowBase::LayoutPhase2(int *noChanges) bool wxWindowBase::LayoutPhase2(int *noChanges)
{ {
*noChanges = 0; *noChanges = 0;
// Layout children // Layout children
DoPhase(1); DoPhase(1);
// Layout grand children
DoPhase(2); DoPhase(2);
return TRUE; return TRUE;
} }
// Do a phase of evaluating child constraints // Do a phase of evaluating child constraints
bool wxWindowBase::DoPhase(int phase) bool wxWindowBase::DoPhase(int phase)
{ {
int noIterations = 0; // the list containing the children for which the constraints are already
int maxIterations = 500; // set correctly
int noChanges = 1;
int noFailures = 0;
wxWindowList succeeded; 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; int noChanges = 0;
noFailures = 0;
wxWindowList::Node *node = GetChildren().GetFirst(); // loop over all children setting their constraints
while (node) for ( wxWindowList::Node *node = GetChildren().GetFirst();
node;
node = node->GetNext() )
{ {
wxWindow *child = node->GetData(); wxWindow *child = node->GetData();
if ( !child->IsTopLevel() ) if ( child->IsTopLevel() )
{ {
wxLayoutConstraints *constr = child->GetConstraints(); // top level children are not inside our client area
if ( constr ) continue;
{ }
if ( !succeeded.Find(child) )
{ if ( !child->GetConstraints() || succeeded.Find(child) )
int tempNoChanges = 0; {
bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ; // this one is either already ok or nothing we can do about it
noChanges += tempNoChanges; continue;
if ( success ) }
{
succeeded.Append(child); 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; return TRUE;