/////////////////////////////////////////////////////////////////////////////
// Name:        layout.cpp
// Purpose:     Constraint layout system classes
// Author:      Julian Smart
// Modified by:
// Created:     04/01/98
// RCS-ID:      $Id: layout.cpp,v 1.20 2002/01/22 18:30:54 RD Exp $
// Copyright:   (c) Julian Smart and Markus Holzem
// Licence:       wxWindows license
/////////////////////////////////////////////////////////////////////////////

// =============================================================================
// declarations
// =============================================================================

// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------

#ifdef __GNUG__
    #pragma implementation "layout.h"
#endif

// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
  #pragma hdrstop
#endif

#ifndef WX_PRECOMP
  #include "wx/defs.h"
#endif

#if wxUSE_CONSTRAINTS

#ifndef WX_PRECOMP
  #include "wx/window.h"
  #include "wx/utils.h"
  #include "wx/dialog.h"
  #include "wx/msgdlg.h"
  #include "wx/intl.h"
#endif

#include "wx/layout.h"

    IMPLEMENT_DYNAMIC_CLASS(wxIndividualLayoutConstraint, wxObject)
    IMPLEMENT_DYNAMIC_CLASS(wxLayoutConstraints, wxObject)


wxIndividualLayoutConstraint::wxIndividualLayoutConstraint()
{
    myEdge = wxTop;
    relationship = wxUnconstrained;
    margin = 0;
    value = 0;
    percent = 0;
    otherEdge = wxTop;
    done = FALSE;
    otherWin = (wxWindowBase *) NULL;
}

wxIndividualLayoutConstraint::~wxIndividualLayoutConstraint()
{
}

void wxIndividualLayoutConstraint::Set(wxRelationship rel, wxWindowBase *otherW, wxEdge otherE, int val, int marg)
{
    if (rel == wxSameAs)
    {
        // If Set is called by the user with wxSameAs then call SameAs to do
        // it since it will actually use wxPercent instead.
        SameAs(otherW, otherE, marg);
        return;
    }

    relationship = rel;
    otherWin = otherW;
    otherEdge = otherE;

    if ( rel == wxPercentOf )
    {
        percent = val;
    }
    else
    {
        value = val;
    }

    margin = marg;
}

void wxIndividualLayoutConstraint::LeftOf(wxWindowBase *sibling, int marg)
{
    Set(wxLeftOf, sibling, wxLeft, 0, marg);
}

void wxIndividualLayoutConstraint::RightOf(wxWindowBase *sibling, int marg)
{
    Set(wxRightOf, sibling, wxRight, 0, marg);
}

void wxIndividualLayoutConstraint::Above(wxWindowBase *sibling, int marg)
{
    Set(wxAbove, sibling, wxTop, 0, marg);
}

void wxIndividualLayoutConstraint::Below(wxWindowBase *sibling, int marg)
{
    Set(wxBelow, sibling, wxBottom, 0, marg);
}

//
// 'Same edge' alignment
//
void wxIndividualLayoutConstraint::SameAs(wxWindowBase *otherW, wxEdge edge, int marg)
{
    Set(wxPercentOf, otherW, edge, 100, marg);
}

// The edge is a percentage of the other window's edge
void wxIndividualLayoutConstraint::PercentOf(wxWindowBase *otherW, wxEdge wh, int per)
{
    Set(wxPercentOf, otherW, wh, per);
}

//
// Edge has absolute value
//
void wxIndividualLayoutConstraint::Absolute(int val)
{
    value = val;
    relationship = wxAbsolute;
}

// Reset constraint if it mentions otherWin
bool wxIndividualLayoutConstraint::ResetIfWin(wxWindowBase *otherW)
{
    if (otherW == otherWin)
    {
        myEdge = wxTop;
        relationship = wxAsIs;
        margin = 0;
        value = 0;
        percent = 0;
        otherEdge = wxTop;
        otherWin = (wxWindowBase *) NULL;
        return TRUE;
    }

    return FALSE;
}

// Try to satisfy constraint
bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constraints, wxWindowBase *win)
{
    if (relationship == wxAbsolute)
    {
        done = TRUE;
        return TRUE;
    }

    switch (myEdge)
    {
        case wxLeft:
        {
            switch (relationship)
            {
                case wxLeftOf:
                {
                    // We can know this edge if: otherWin is win's
                    // parent, or otherWin has a satisfied constraint,
                    // or otherWin has no constraint.
                    int edgePos = GetEdge(otherEdge, win, otherWin);
                    if (edgePos != -1)
                    {
                        value = edgePos - margin;
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                case wxRightOf:
                {
                    int edgePos = GetEdge(otherEdge, win, otherWin);
                    if (edgePos != -1)
                    {
                        value = edgePos + margin;
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                case wxPercentOf:
                {
                    int edgePos = GetEdge(otherEdge, win, otherWin);
                    if (edgePos != -1)
                    {
                        value = (int)(edgePos*(((float)percent)*0.01) + margin);
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                case wxUnconstrained:
                {
                    // We know the left-hand edge position if we know
                    // the right-hand edge and we know the width; OR if
                    // we know the centre and the width.
                    if (constraints->right.GetDone() && constraints->width.GetDone())
                    {
                        value = (constraints->right.GetValue() - constraints->width.GetValue() + margin);
                        done = TRUE;
                        return TRUE;
                    }
                    else if (constraints->centreX.GetDone() && constraints->width.GetDone())
                    {
                        value = (int)(constraints->centreX.GetValue() - (constraints->width.GetValue()/2) + margin);
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                case wxAsIs:
                {
                    int y;
                    win->GetPosition(&value, &y);
                    done = TRUE;
                    return TRUE;
                }
                default:
                    break;
            }
            break;
        }
        case wxRight:
        {
            switch (relationship)
            {
                case wxLeftOf:
                {
                    // We can know this edge if: otherWin is win's
                    // parent, or otherWin has a satisfied constraint,
                    // or otherWin has no constraint.
                    int edgePos = GetEdge(otherEdge, win, otherWin);
                    if (edgePos != -1)
                    {
                        value = edgePos - margin;
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                case wxRightOf:
                {
                    int edgePos = GetEdge(otherEdge, win, otherWin);
                    if (edgePos != -1)
                    {
                        value = edgePos + margin;
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                case wxPercentOf:
                {
                    int edgePos = GetEdge(otherEdge, win, otherWin);
                    if (edgePos != -1)
                    {
                        value = (int)(edgePos*(((float)percent)*0.01) - margin);
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                case wxUnconstrained:
                {
                    // We know the right-hand edge position if we know the
                    // left-hand edge and we know the width, OR if we know the
                    // centre edge and the width.
                    if (constraints->left.GetDone() && constraints->width.GetDone())
                    {
                        value = (constraints->left.GetValue() + constraints->width.GetValue() - margin);
                        done = TRUE;
                        return TRUE;
                    }
                    else if (constraints->centreX.GetDone() && constraints->width.GetDone())
                    {
                        value = (int)(constraints->centreX.GetValue() + (constraints->width.GetValue()/2) - margin);
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                case wxAsIs:
                {
                    int x, y;
                    int w, h;
                    win->GetSize(&w, &h);
                    win->GetPosition(&x, &y);
                    value = x + w;
                    done = TRUE;
                    return TRUE;
                }
                default:
                    break;
            }
            break;
        }
        case wxTop:
        {
            switch (relationship)
            {
                case wxAbove:
                {
                    // We can know this edge if: otherWin is win's
                    // parent, or otherWin has a satisfied constraint,
                    // or otherWin has no constraint.
                    int edgePos = GetEdge(otherEdge, win, otherWin);
                    if (edgePos != -1)
                    {
                        value = edgePos - margin;
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                case wxBelow:
                {
                    int edgePos = GetEdge(otherEdge, win, otherWin);
                    if (edgePos != -1)
                    {
                        value = edgePos + margin;
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                case wxPercentOf:
                {
                    int edgePos = GetEdge(otherEdge, win, otherWin);
                    if (edgePos != -1)
                    {
                        value = (int)(edgePos*(((float)percent)*0.01) + margin);
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                case wxUnconstrained:
                {
                    // We know the top edge position if we know the bottom edge
                    // and we know the height; OR if we know the centre edge and
                    // the height.
                    if (constraints->bottom.GetDone() && constraints->height.GetDone())
                    {
                        value = (constraints->bottom.GetValue() - constraints->height.GetValue() + margin);
                        done = TRUE;
                        return TRUE;
                    }
                    else if (constraints->centreY.GetDone() && constraints->height.GetDone())
                    {
                        value = (constraints->centreY.GetValue() - (constraints->height.GetValue()/2) + margin);
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                case wxAsIs:
                {
                    int x;
                    win->GetPosition(&x, &value);
                    done = TRUE;
                    return TRUE;
                }
                default:
                    break;
            }
            break;
        }
        case wxBottom:
        {
            switch (relationship)
            {
                case wxAbove:
                {
                    // We can know this edge if: otherWin is win's parent,
                    // or otherWin has a satisfied constraint, or
                    // otherWin has no constraint.
                    int edgePos = GetEdge(otherEdge, win, otherWin);
                    if (edgePos != -1)
                    {
                        value = edgePos + margin;
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                case wxBelow:
                {
                    int edgePos = GetEdge(otherEdge, win, otherWin);
                    if (edgePos != -1)
                    {
                        value = edgePos - margin;
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                case wxPercentOf:
                {
                    int edgePos = GetEdge(otherEdge, win, otherWin);
                    if (edgePos != -1)
                    {
                        value = (int)(edgePos*(((float)percent)*0.01) - margin);
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                case wxUnconstrained:
                {
                    // We know the bottom edge position if we know the top edge
                    // and we know the height; OR if we know the centre edge and
                    // the height.
                    if (constraints->top.GetDone() && constraints->height.GetDone())
                    {
                        value = (constraints->top.GetValue() + constraints->height.GetValue() - margin);
                        done = TRUE;
                        return TRUE;
                    }
                    else if (constraints->centreY.GetDone() && constraints->height.GetDone())
                    {
                        value = (constraints->centreY.GetValue() + (constraints->height.GetValue()/2) - margin);
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                case wxAsIs:
                {
                    int x, y;
                    int w, h;
                    win->GetSize(&w, &h);
                    win->GetPosition(&x, &y);
                    value = h + y;
                    done = TRUE;
                    return TRUE;
                }
                default:
                    break;
            }
            break;
        }
        case wxCentreX:
        {
            switch (relationship)
            {
                case wxLeftOf:
                {
                    // We can know this edge if: otherWin is win's parent, or
                    // otherWin has a satisfied constraint, or otherWin has no
                    // constraint.
                    int edgePos = GetEdge(otherEdge, win, otherWin);
                    if (edgePos != -1)
                    {
                        value = edgePos - margin;
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                case wxRightOf:
                {
                    int edgePos = GetEdge(otherEdge, win, otherWin);
                    if (edgePos != -1)
                    {
                        value = edgePos + margin;
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                case wxPercentOf:
                {
                    int edgePos = GetEdge(otherEdge, win, otherWin);
                    if (edgePos != -1)
                    {
                        value = (int)(edgePos*(((float)percent)*0.01) + margin);
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                case wxUnconstrained:
                {
                    // We know the centre position if we know
                    // the left-hand edge and we know the width, OR
                    // the right-hand edge and the width
                    if (constraints->left.GetDone() && constraints->width.GetDone())
                    {
                        value = (int)(constraints->left.GetValue() + (constraints->width.GetValue()/2) + margin);
                        done = TRUE;
                        return TRUE;
                    }
                    else if (constraints->right.GetDone() && constraints->width.GetDone())
                    {
                        value = (int)(constraints->left.GetValue() - (constraints->width.GetValue()/2) + margin);
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                default:
                    break;
            }
            break;
        }
        case wxCentreY:
        {
            switch (relationship)
            {
                case wxAbove:
                {
                    // We can know this edge if: otherWin is win's parent,
                    // or otherWin has a satisfied constraint, or otherWin
                    // has no constraint.
                    int edgePos = GetEdge(otherEdge, win, otherWin);
                    if (edgePos != -1)
                    {
                        value = edgePos - margin;
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                case wxBelow:
                {
                    int edgePos = GetEdge(otherEdge, win, otherWin);
                    if (edgePos != -1)
                    {
                        value = edgePos + margin;
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                case wxPercentOf:
                {
                    int edgePos = GetEdge(otherEdge, win, otherWin);
                    if (edgePos != -1)
                    {
                        value = (int)(edgePos*(((float)percent)*0.01) + margin);
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                case wxUnconstrained:
                {
                    // We know the centre position if we know
                    // the top edge and we know the height, OR
                    // the bottom edge and the height.
                    if (constraints->bottom.GetDone() && constraints->height.GetDone())
                    {
                        value = (int)(constraints->bottom.GetValue() - (constraints->height.GetValue()/2) + margin);
                        done = TRUE;
                        return TRUE;
                    }
                    else if (constraints->top.GetDone() && constraints->height.GetDone())
                    {
                        value = (int)(constraints->top.GetValue() + (constraints->height.GetValue()/2) + margin);
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                default:
                    break;
            }
            break;
        }
        case wxWidth:
        {
            switch (relationship)
            {
                case wxPercentOf:
                {
                    int edgePos = GetEdge(otherEdge, win, otherWin);
                    if (edgePos != -1)
                    {
                        value = (int)(edgePos*(((float)percent)*0.01));
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                case wxAsIs:
                {
                    if (win)
                    {
                        int h;
                        win->GetSize(&value, &h);
                        done = TRUE;
                        return TRUE;
                    }
                    else return FALSE;
                }
                case wxUnconstrained:
                {
                    // We know the width if we know the left edge and the right edge, OR
                    // if we know the left edge and the centre, OR
                    // if we know the right edge and the centre
                    if (constraints->left.GetDone() && constraints->right.GetDone())
                    {
                        value = constraints->right.GetValue() - constraints->left.GetValue();
                        done = TRUE;
                        return TRUE;
                    }
                    else if (constraints->centreX.GetDone() && constraints->left.GetDone())
                    {
                        value = (int)(2*(constraints->centreX.GetValue() - constraints->left.GetValue()));
                        done = TRUE;
                        return TRUE;
                    }
                    else if (constraints->centreX.GetDone() && constraints->right.GetDone())
                    {
                        value = (int)(2*(constraints->right.GetValue() - constraints->centreX.GetValue()));
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                default:
                    break;
            }
            break;
        }
        case wxHeight:
        {
            switch (relationship)
            {
                case wxPercentOf:
                {
                    int edgePos = GetEdge(otherEdge, win, otherWin);
                    if (edgePos != -1)
                    {
                        value = (int)(edgePos*(((float)percent)*0.01));
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                case wxAsIs:
                {
                    if (win)
                    {
                        int w;
                        win->GetSize(&w, &value);
                        done = TRUE;
                        return TRUE;
                    }
                    else return FALSE;
                }
                case wxUnconstrained:
                {
                    // We know the height if we know the top edge and the bottom edge, OR
                    // if we know the top edge and the centre, OR
                    // if we know the bottom edge and the centre
                    if (constraints->top.GetDone() && constraints->bottom.GetDone())
                    {
                        value = constraints->bottom.GetValue() - constraints->top.GetValue();
                        done = TRUE;
                        return TRUE;
                    }
                    else if (constraints->top.GetDone() && constraints->centreY.GetDone())
                    {
                        value = (int)(2*(constraints->centreY.GetValue() - constraints->top.GetValue()));
                        done = TRUE;
                        return TRUE;
                    }
                    else if (constraints->bottom.GetDone() && constraints->centreY.GetDone())
                    {
                        value = (int)(2*(constraints->bottom.GetValue() - constraints->centreY.GetValue()));
                        done = TRUE;
                        return TRUE;
                    }
                    else
                        return FALSE;
                }
                default:
                    break;
            }
            break;
        }
        default:
            break;
    }
    return FALSE;
}

// Get the value of this edge or dimension, or if this is not determinable, -1.
int wxIndividualLayoutConstraint::GetEdge(wxEdge which,
                                          wxWindowBase *thisWin,
                                          wxWindowBase *other) const
{
    // If the edge or dimension belongs to the parent, then we know the
    // dimension is obtainable immediately. E.g. a wxExpandSizer may contain a
    // button (but the button's true parent is a panel, not the sizer)
    if (other->GetChildren().Find(thisWin))
    {
        switch (which)
        {
            case wxLeft:
                {
                    return 0;
                }
            case wxTop:
                {
                    return 0;
                }
            case wxRight:
                {
                    int w, h;
                    other->GetClientSizeConstraint(&w, &h);
                    return w;
                }
            case wxBottom:
                {
                    int w, h;
                    other->GetClientSizeConstraint(&w, &h);
                    return h;
                }
            case wxWidth:
                {
                    int w, h;
                    other->GetClientSizeConstraint(&w, &h);
                    return w;
                }
            case wxHeight:
                {
                    int w, h;
                    other->GetClientSizeConstraint(&w, &h);
                    return h;
                }
            case wxCentreX:
            case wxCentreY:
                {
                    int w, h;
                    other->GetClientSizeConstraint(&w, &h);
                    if (which == wxCentreX)
                        return (int)(w/2);
                    else
                        return (int)(h/2);
                }
            default:
                return -1;
        }
    }
    switch (which)
    {
        case wxLeft:
            {
                wxLayoutConstraints *constr = other->GetConstraints();
                // If no constraints, it means the window is not dependent
                // on anything, and therefore we know its value immediately
                if (constr)
                {
                    if (constr->left.GetDone())
                        return constr->left.GetValue();
                    else
                        return -1;
                }
                else
                {
                    int x, y;
                    other->GetPosition(&x, &y);
                    return x;
                }
            }
        case wxTop:
            {
                wxLayoutConstraints *constr = other->GetConstraints();
                // If no constraints, it means the window is not dependent
                // on anything, and therefore we know its value immediately
                if (constr)
                {
                    if (constr->top.GetDone())
                        return constr->top.GetValue();
                    else
                        return -1;
                }
                else
                {
                    int x, y;
                    other->GetPosition(&x, &y);
                    return y;
                }
            }
        case wxRight:
            {
                wxLayoutConstraints *constr = other->GetConstraints();
                // If no constraints, it means the window is not dependent
                // on anything, and therefore we know its value immediately
                if (constr)
                {
                    if (constr->right.GetDone())
                        return constr->right.GetValue();
                    else
                        return -1;
                }
                else
                {
                    int x, y, w, h;
                    other->GetPosition(&x, &y);
                    other->GetSize(&w, &h);
                    return (int)(x + w);
                }
            }
        case wxBottom:
            {
                wxLayoutConstraints *constr = other->GetConstraints();
                // If no constraints, it means the window is not dependent
                // on anything, and therefore we know its value immediately
                if (constr)
                {
                    if (constr->bottom.GetDone())
                        return constr->bottom.GetValue();
                    else
                        return -1;
                }
                else
                {
                    int x, y, w, h;
                    other->GetPosition(&x, &y);
                    other->GetSize(&w, &h);
                    return (int)(y + h);
                }
            }
        case wxWidth:
            {
                wxLayoutConstraints *constr = other->GetConstraints();
                // If no constraints, it means the window is not dependent
                // on anything, and therefore we know its value immediately
                if (constr)
                {
                    if (constr->width.GetDone())
                        return constr->width.GetValue();
                    else
                        return -1;
                }
                else
                {
                    int w, h;
                    other->GetSize(&w, &h);
                    return w;
                }
            }
        case wxHeight:
            {
                wxLayoutConstraints *constr = other->GetConstraints();
                // If no constraints, it means the window is not dependent
                // on anything, and therefore we know its value immediately
                if (constr)
                {
                    if (constr->height.GetDone())
                        return constr->height.GetValue();
                    else
                        return -1;
                }
                else
                {
                    int w, h;
                    other->GetSize(&w, &h);
                    return h;
                }
            }
        case wxCentreX:
            {
                wxLayoutConstraints *constr = other->GetConstraints();
                // If no constraints, it means the window is not dependent
                // on anything, and therefore we know its value immediately
                if (constr)
                {
                    if (constr->centreX.GetDone())
                        return constr->centreX.GetValue();
                    else
                        return -1;
                }
                else
                {
                    int x, y, w, h;
                    other->GetPosition(&x, &y);
                    other->GetSize(&w, &h);
                    return (int)(x + (w/2));
                }
            }
        case wxCentreY:
            {
                wxLayoutConstraints *constr = other->GetConstraints();
                // If no constraints, it means the window is not dependent
                // on anything, and therefore we know its value immediately
                if (constr)
                {
                    if (constr->centreY.GetDone())
                        return constr->centreY.GetValue();
                    else
                        return -1;
                }
                else
                {
                    int x, y, w, h;
                    other->GetPosition(&x, &y);
                    other->GetSize(&w, &h);
                    return (int)(y + (h/2));
                }
            }
        default:
            break;
    }
    return -1;
}

wxLayoutConstraints::wxLayoutConstraints()
{
    left.SetEdge(wxLeft);
    top.SetEdge(wxTop);
    right.SetEdge(wxRight);
    bottom.SetEdge(wxBottom);
    centreX.SetEdge(wxCentreX);
    centreY.SetEdge(wxCentreY);
    width.SetEdge(wxWidth);
    height.SetEdge(wxHeight);
}

wxLayoutConstraints::~wxLayoutConstraints()
{
}

bool wxLayoutConstraints::SatisfyConstraints(wxWindowBase *win, int *nChanges)
{
    int noChanges = 0;

    bool done = width.GetDone();
    bool newDone = (done ? TRUE : width.SatisfyConstraint(this, win));
    if (newDone != done)
        noChanges ++;

    done = height.GetDone();
    newDone = (done ? TRUE : height.SatisfyConstraint(this, win));
    if (newDone != done)
        noChanges ++;

    done = left.GetDone();
    newDone = (done ? TRUE : left.SatisfyConstraint(this, win));
    if (newDone != done)
        noChanges ++;

    done = top.GetDone();
    newDone = (done ? TRUE : top.SatisfyConstraint(this, win));
    if (newDone != done)
        noChanges ++;

    done = right.GetDone();
    newDone = (done ? TRUE : right.SatisfyConstraint(this, win));
    if (newDone != done)
        noChanges ++;

    done = bottom.GetDone();
    newDone = (done ? TRUE : bottom.SatisfyConstraint(this, win));
    if (newDone != done)
        noChanges ++;

    done = centreX.GetDone();
    newDone = (done ? TRUE : centreX.SatisfyConstraint(this, win));
    if (newDone != done)
        noChanges ++;

    done = centreY.GetDone();
    newDone = (done ? TRUE : centreY.SatisfyConstraint(this, win));
    if (newDone != done)
        noChanges ++;

    *nChanges = noChanges;

    return AreSatisfied();
}

/*
 * Main constrained layout algorithm. Look at all the child
 * windows, and their constraints (if any).
 * The idea is to keep iterating through the constraints
 * until all left, right, bottom and top edges, and widths and heights,
 * are known (or no change occurs and we've failed to resolve all
 * constraints).
 *
 * If the user has not specified a dimension or edge, it will be
 * be calculated from the other known values. E.g. If we know
 * the right hand edge and the left hand edge, we now know the width.
 * The snag here is that this means we must specify absolute dimensions
 * twice (in constructor and in constraint), if we wish to use the
 * constraint notation to just set the position, for example.
 * Otherwise, if we only set ONE edge and no dimension, it would never
 * find the other edge.
 *
 * Algorithm:

  Mark all constraints as not done.

  iterations = 0;
  until no change or iterations >= max iterations
    For each child:
    {
      Calculate all constraints
    }
    iterations ++;

  For each child
    Set each calculated position and size

 */

#if WXWIN_COMPATIBILITY
bool wxOldDoLayout(wxWindowBase *win)
{
  // Make sure this isn't called recursively from below
  static wxList doneSoFar;

  if (doneSoFar.Member(win))
    return TRUE;

  doneSoFar.Append(win);

  wxNode *node = win->GetChildren().First();
  while (node)
  {
    wxWindowBase *child = (wxWindowBase *)node->Data();
    wxLayoutConstraints *constr = child->GetConstraints();
    if (constr)
    {
      constr->left.SetDone(FALSE);
      constr->top.SetDone(FALSE);
      constr->right.SetDone(FALSE);
      constr->bottom.SetDone(FALSE);
      constr->width.SetDone(FALSE);
      constr->height.SetDone(FALSE);
      constr->centreX.SetDone(FALSE);
      constr->centreY.SetDone(FALSE);
    }
    node = node->Next();
  }
  int noIterations = 0;
  int maxIterations = 500;
  int noChanges = 1;

  while ((noChanges > 0) && (noIterations < maxIterations))
  {
    noChanges = 0;
    wxNode *node = win->GetChildren().First();
    while (node)
    {
      wxWindowBase *child = (wxWindowBase *)node->Data();
      wxLayoutConstraints *constr = child->GetConstraints();
      if (constr)
      {
        int tempNoChanges = 0;
        (void)constr->SatisfyConstraints(child, &tempNoChanges);
        noChanges += tempNoChanges;
      }
      node = node->Next();
    }
    noIterations ++;
  }
/*
  // Would be nice to have a test here to see _which_ constraint(s)
  // failed, so we can print a specific diagnostic message.
  if (noFailures > 0)
  {
    wxDebugMsg(_("wxWindowBase::Layout() failed.\n"));
  }
*/
  // Now set the sizes and positions of the children, and
  // recursively call Layout().
  node = win->GetChildren().First();
  while (node)
  {
    wxWindowBase *child = (wxWindowBase *)node->Data();
    wxLayoutConstraints *constr = child->GetConstraints();
    if (constr && constr->left.GetDone() && constr->right.GetDone() &&
                  constr->width.GetDone() && constr->height.GetDone())
    {
      int x = constr->left.GetValue();
      int y = constr->top.GetValue();
      int w = constr->width.GetValue();
      int h = constr->height.GetValue();

      // If we don't want to resize this window, just move it...
      if ((constr->width.GetRelationship() != wxAsIs) ||
          (constr->height.GetRelationship() != wxAsIs))
      {
        // _Should_ call Layout() recursively.
        child->SetSize(x, y, w, h);
      }
      else
      {
        child->Move(x, y);
      }
    }
    else
      child->Layout();
    node = node->Next();
  }
  doneSoFar.DeleteObject(win);

  return TRUE;
}
#endif // WXWIN_COMPATIBILITY

#endif // wxUSE_CONSTRAINTS
