text: /////////////////////////////////////////////////////////////////////////////
  // Name:        src/common/layout.cpp
  // Purpose:     Constraint layout system classes
  // Author:      Julian Smart
  // Modified by:
  // Created:     04/01/98
  // RCS-ID:      $Id$
  // Copyright:   (c) Julian Smart
  // Licence:     wxWindows licence
  /////////////////////////////////////////////////////////////////////////////
  
  // =============================================================================
  // declarations
  // =============================================================================
  
  // ----------------------------------------------------------------------------
  // headers
  // ----------------------------------------------------------------------------
  
  // For compilers that support precompilation, includes "wx.h".
  #include "wx/wxprec.h"
  
  #ifdef __BORLANDC__
      #pragma hdrstop
  #endif
  
  #if wxUSE_CONSTRAINTS
  
  #include "wx/layout.h"
  
  #ifndef WX_PRECOMP
      #include "wx/window.h"
      #include "wx/utils.h"
      #include "wx/dialog.h"
      #include "wx/msgdlg.h"
      #include "wx/intl.h"
  #endif
  
  
  IMPLEMENT_DYNAMIC_CLASS(wxIndividualLayoutConstraint, wxObject)
  IMPLEMENT_DYNAMIC_CLASS(wxLayoutConstraints, wxObject)
  
  
  inline void wxGetAsIs(wxWindowBase* win, int* w, int* h)
  {
  #if 1
      // The old way.  Works for me.
      win->GetSize(w, h);
  #endif
  
  #if 0
      // Vadim's change.  Breaks wxPython's LayoutAnchors
      win->GetBestSize(w, h);
  #endif
  
  #if 0
      // Proposed compromise.  Doesn't work.
      int sw, sh, bw, bh;
      win->GetSize(&sw, &sh);
      win->GetBestSize(&bw, &bh);
      if (w)
          *w = wxMax(sw, bw);
      if (h)
          *h = wxMax(sh, bh);
  #endif
  }
  
  
  wxIndividualLayoutConstraint::wxIndividualLayoutConstraint()
  {
      myEdge = wxTop;
      relationship = wxUnconstrained;
      margin = 0;
      value = 0;
      percent = 0;
      otherEdge = wxTop;
      done = false;
      otherWin = NULL;
  }
  
  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 = 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;
                      wxGetAsIs(win, &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;
                      wxGetAsIs(win, &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;
                          wxGetAsIs(win, &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;
                          wxGetAsIs(win, &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((wxWindow*)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);
  }
  
  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();
  }
  
  #endif // wxUSE_CONSTRAINTS
  