home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / common / layout.cpp < prev    next >
C/C++ Source or Header  |  2002-01-22  |  39KB  |  1,147 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        layout.cpp
  3. // Purpose:     Constraint layout system classes
  4. // Author:      Julian Smart
  5. // Modified by:
  6. // Created:     04/01/98
  7. // RCS-ID:      $Id: layout.cpp,v 1.20 2002/01/22 18:30:54 RD Exp $
  8. // Copyright:   (c) Julian Smart and Markus Holzem
  9. // Licence:       wxWindows license
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. // =============================================================================
  13. // declarations
  14. // =============================================================================
  15.  
  16. // ----------------------------------------------------------------------------
  17. // headers
  18. // ----------------------------------------------------------------------------
  19.  
  20. #ifdef __GNUG__
  21.     #pragma implementation "layout.h"
  22. #endif
  23.  
  24. // For compilers that support precompilation, includes "wx.h".
  25. #include "wx/wxprec.h"
  26.  
  27. #ifdef __BORLANDC__
  28.   #pragma hdrstop
  29. #endif
  30.  
  31. #ifndef WX_PRECOMP
  32.   #include "wx/defs.h"
  33. #endif
  34.  
  35. #if wxUSE_CONSTRAINTS
  36.  
  37. #ifndef WX_PRECOMP
  38.   #include "wx/window.h"
  39.   #include "wx/utils.h"
  40.   #include "wx/dialog.h"
  41.   #include "wx/msgdlg.h"
  42.   #include "wx/intl.h"
  43. #endif
  44.  
  45. #include "wx/layout.h"
  46.  
  47.     IMPLEMENT_DYNAMIC_CLASS(wxIndividualLayoutConstraint, wxObject)
  48.     IMPLEMENT_DYNAMIC_CLASS(wxLayoutConstraints, wxObject)
  49.  
  50.  
  51. wxIndividualLayoutConstraint::wxIndividualLayoutConstraint()
  52. {
  53.     myEdge = wxTop;
  54.     relationship = wxUnconstrained;
  55.     margin = 0;
  56.     value = 0;
  57.     percent = 0;
  58.     otherEdge = wxTop;
  59.     done = FALSE;
  60.     otherWin = (wxWindowBase *) NULL;
  61. }
  62.  
  63. wxIndividualLayoutConstraint::~wxIndividualLayoutConstraint()
  64. {
  65. }
  66.  
  67. void wxIndividualLayoutConstraint::Set(wxRelationship rel, wxWindowBase *otherW, wxEdge otherE, int val, int marg)
  68. {
  69.     if (rel == wxSameAs)
  70.     {
  71.         // If Set is called by the user with wxSameAs then call SameAs to do
  72.         // it since it will actually use wxPercent instead.
  73.         SameAs(otherW, otherE, marg);
  74.         return;
  75.     }
  76.  
  77.     relationship = rel;
  78.     otherWin = otherW;
  79.     otherEdge = otherE;
  80.  
  81.     if ( rel == wxPercentOf )
  82.     {
  83.         percent = val;
  84.     }
  85.     else
  86.     {
  87.         value = val;
  88.     }
  89.  
  90.     margin = marg;
  91. }
  92.  
  93. void wxIndividualLayoutConstraint::LeftOf(wxWindowBase *sibling, int marg)
  94. {
  95.     Set(wxLeftOf, sibling, wxLeft, 0, marg);
  96. }
  97.  
  98. void wxIndividualLayoutConstraint::RightOf(wxWindowBase *sibling, int marg)
  99. {
  100.     Set(wxRightOf, sibling, wxRight, 0, marg);
  101. }
  102.  
  103. void wxIndividualLayoutConstraint::Above(wxWindowBase *sibling, int marg)
  104. {
  105.     Set(wxAbove, sibling, wxTop, 0, marg);
  106. }
  107.  
  108. void wxIndividualLayoutConstraint::Below(wxWindowBase *sibling, int marg)
  109. {
  110.     Set(wxBelow, sibling, wxBottom, 0, marg);
  111. }
  112.  
  113. //
  114. // 'Same edge' alignment
  115. //
  116. void wxIndividualLayoutConstraint::SameAs(wxWindowBase *otherW, wxEdge edge, int marg)
  117. {
  118.     Set(wxPercentOf, otherW, edge, 100, marg);
  119. }
  120.  
  121. // The edge is a percentage of the other window's edge
  122. void wxIndividualLayoutConstraint::PercentOf(wxWindowBase *otherW, wxEdge wh, int per)
  123. {
  124.     Set(wxPercentOf, otherW, wh, per);
  125. }
  126.  
  127. //
  128. // Edge has absolute value
  129. //
  130. void wxIndividualLayoutConstraint::Absolute(int val)
  131. {
  132.     value = val;
  133.     relationship = wxAbsolute;
  134. }
  135.  
  136. // Reset constraint if it mentions otherWin
  137. bool wxIndividualLayoutConstraint::ResetIfWin(wxWindowBase *otherW)
  138. {
  139.     if (otherW == otherWin)
  140.     {
  141.         myEdge = wxTop;
  142.         relationship = wxAsIs;
  143.         margin = 0;
  144.         value = 0;
  145.         percent = 0;
  146.         otherEdge = wxTop;
  147.         otherWin = (wxWindowBase *) NULL;
  148.         return TRUE;
  149.     }
  150.  
  151.     return FALSE;
  152. }
  153.  
  154. // Try to satisfy constraint
  155. bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constraints, wxWindowBase *win)
  156. {
  157.     if (relationship == wxAbsolute)
  158.     {
  159.         done = TRUE;
  160.         return TRUE;
  161.     }
  162.  
  163.     switch (myEdge)
  164.     {
  165.         case wxLeft:
  166.         {
  167.             switch (relationship)
  168.             {
  169.                 case wxLeftOf:
  170.                 {
  171.                     // We can know this edge if: otherWin is win's
  172.                     // parent, or otherWin has a satisfied constraint,
  173.                     // or otherWin has no constraint.
  174.                     int edgePos = GetEdge(otherEdge, win, otherWin);
  175.                     if (edgePos != -1)
  176.                     {
  177.                         value = edgePos - margin;
  178.                         done = TRUE;
  179.                         return TRUE;
  180.                     }
  181.                     else
  182.                         return FALSE;
  183.                 }
  184.                 case wxRightOf:
  185.                 {
  186.                     int edgePos = GetEdge(otherEdge, win, otherWin);
  187.                     if (edgePos != -1)
  188.                     {
  189.                         value = edgePos + margin;
  190.                         done = TRUE;
  191.                         return TRUE;
  192.                     }
  193.                     else
  194.                         return FALSE;
  195.                 }
  196.                 case wxPercentOf:
  197.                 {
  198.                     int edgePos = GetEdge(otherEdge, win, otherWin);
  199.                     if (edgePos != -1)
  200.                     {
  201.                         value = (int)(edgePos*(((float)percent)*0.01) + margin);
  202.                         done = TRUE;
  203.                         return TRUE;
  204.                     }
  205.                     else
  206.                         return FALSE;
  207.                 }
  208.                 case wxUnconstrained:
  209.                 {
  210.                     // We know the left-hand edge position if we know
  211.                     // the right-hand edge and we know the width; OR if
  212.                     // we know the centre and the width.
  213.                     if (constraints->right.GetDone() && constraints->width.GetDone())
  214.                     {
  215.                         value = (constraints->right.GetValue() - constraints->width.GetValue() + margin);
  216.                         done = TRUE;
  217.                         return TRUE;
  218.                     }
  219.                     else if (constraints->centreX.GetDone() && constraints->width.GetDone())
  220.                     {
  221.                         value = (int)(constraints->centreX.GetValue() - (constraints->width.GetValue()/2) + margin);
  222.                         done = TRUE;
  223.                         return TRUE;
  224.                     }
  225.                     else
  226.                         return FALSE;
  227.                 }
  228.                 case wxAsIs:
  229.                 {
  230.                     int y;
  231.                     win->GetPosition(&value, &y);
  232.                     done = TRUE;
  233.                     return TRUE;
  234.                 }
  235.                 default:
  236.                     break;
  237.             }
  238.             break;
  239.         }
  240.         case wxRight:
  241.         {
  242.             switch (relationship)
  243.             {
  244.                 case wxLeftOf:
  245.                 {
  246.                     // We can know this edge if: otherWin is win's
  247.                     // parent, or otherWin has a satisfied constraint,
  248.                     // or otherWin has no constraint.
  249.                     int edgePos = GetEdge(otherEdge, win, otherWin);
  250.                     if (edgePos != -1)
  251.                     {
  252.                         value = edgePos - margin;
  253.                         done = TRUE;
  254.                         return TRUE;
  255.                     }
  256.                     else
  257.                         return FALSE;
  258.                 }
  259.                 case wxRightOf:
  260.                 {
  261.                     int edgePos = GetEdge(otherEdge, win, otherWin);
  262.                     if (edgePos != -1)
  263.                     {
  264.                         value = edgePos + margin;
  265.                         done = TRUE;
  266.                         return TRUE;
  267.                     }
  268.                     else
  269.                         return FALSE;
  270.                 }
  271.                 case wxPercentOf:
  272.                 {
  273.                     int edgePos = GetEdge(otherEdge, win, otherWin);
  274.                     if (edgePos != -1)
  275.                     {
  276.                         value = (int)(edgePos*(((float)percent)*0.01) - margin);
  277.                         done = TRUE;
  278.                         return TRUE;
  279.                     }
  280.                     else
  281.                         return FALSE;
  282.                 }
  283.                 case wxUnconstrained:
  284.                 {
  285.                     // We know the right-hand edge position if we know the
  286.                     // left-hand edge and we know the width, OR if we know the
  287.                     // centre edge and the width.
  288.                     if (constraints->left.GetDone() && constraints->width.GetDone())
  289.                     {
  290.                         value = (constraints->left.GetValue() + constraints->width.GetValue() - margin);
  291.                         done = TRUE;
  292.                         return TRUE;
  293.                     }
  294.                     else if (constraints->centreX.GetDone() && constraints->width.GetDone())
  295.                     {
  296.                         value = (int)(constraints->centreX.GetValue() + (constraints->width.GetValue()/2) - margin);
  297.                         done = TRUE;
  298.                         return TRUE;
  299.                     }
  300.                     else
  301.                         return FALSE;
  302.                 }
  303.                 case wxAsIs:
  304.                 {
  305.                     int x, y;
  306.                     int w, h;
  307.                     win->GetSize(&w, &h);
  308.                     win->GetPosition(&x, &y);
  309.                     value = x + w;
  310.                     done = TRUE;
  311.                     return TRUE;
  312.                 }
  313.                 default:
  314.                     break;
  315.             }
  316.             break;
  317.         }
  318.         case wxTop:
  319.         {
  320.             switch (relationship)
  321.             {
  322.                 case wxAbove:
  323.                 {
  324.                     // We can know this edge if: otherWin is win's
  325.                     // parent, or otherWin has a satisfied constraint,
  326.                     // or otherWin has no constraint.
  327.                     int edgePos = GetEdge(otherEdge, win, otherWin);
  328.                     if (edgePos != -1)
  329.                     {
  330.                         value = edgePos - margin;
  331.                         done = TRUE;
  332.                         return TRUE;
  333.                     }
  334.                     else
  335.                         return FALSE;
  336.                 }
  337.                 case wxBelow:
  338.                 {
  339.                     int edgePos = GetEdge(otherEdge, win, otherWin);
  340.                     if (edgePos != -1)
  341.                     {
  342.                         value = edgePos + margin;
  343.                         done = TRUE;
  344.                         return TRUE;
  345.                     }
  346.                     else
  347.                         return FALSE;
  348.                 }
  349.                 case wxPercentOf:
  350.                 {
  351.                     int edgePos = GetEdge(otherEdge, win, otherWin);
  352.                     if (edgePos != -1)
  353.                     {
  354.                         value = (int)(edgePos*(((float)percent)*0.01) + margin);
  355.                         done = TRUE;
  356.                         return TRUE;
  357.                     }
  358.                     else
  359.                         return FALSE;
  360.                 }
  361.                 case wxUnconstrained:
  362.                 {
  363.                     // We know the top edge position if we know the bottom edge
  364.                     // and we know the height; OR if we know the centre edge and
  365.                     // the height.
  366.                     if (constraints->bottom.GetDone() && constraints->height.GetDone())
  367.                     {
  368.                         value = (constraints->bottom.GetValue() - constraints->height.GetValue() + margin);
  369.                         done = TRUE;
  370.                         return TRUE;
  371.                     }
  372.                     else if (constraints->centreY.GetDone() && constraints->height.GetDone())
  373.                     {
  374.                         value = (constraints->centreY.GetValue() - (constraints->height.GetValue()/2) + margin);
  375.                         done = TRUE;
  376.                         return TRUE;
  377.                     }
  378.                     else
  379.                         return FALSE;
  380.                 }
  381.                 case wxAsIs:
  382.                 {
  383.                     int x;
  384.                     win->GetPosition(&x, &value);
  385.                     done = TRUE;
  386.                     return TRUE;
  387.                 }
  388.                 default:
  389.                     break;
  390.             }
  391.             break;
  392.         }
  393.         case wxBottom:
  394.         {
  395.             switch (relationship)
  396.             {
  397.                 case wxAbove:
  398.                 {
  399.                     // We can know this edge if: otherWin is win's parent,
  400.                     // or otherWin has a satisfied constraint, or
  401.                     // otherWin has no constraint.
  402.                     int edgePos = GetEdge(otherEdge, win, otherWin);
  403.                     if (edgePos != -1)
  404.                     {
  405.                         value = edgePos + margin;
  406.                         done = TRUE;
  407.                         return TRUE;
  408.                     }
  409.                     else
  410.                         return FALSE;
  411.                 }
  412.                 case wxBelow:
  413.                 {
  414.                     int edgePos = GetEdge(otherEdge, win, otherWin);
  415.                     if (edgePos != -1)
  416.                     {
  417.                         value = edgePos - margin;
  418.                         done = TRUE;
  419.                         return TRUE;
  420.                     }
  421.                     else
  422.                         return FALSE;
  423.                 }
  424.                 case wxPercentOf:
  425.                 {
  426.                     int edgePos = GetEdge(otherEdge, win, otherWin);
  427.                     if (edgePos != -1)
  428.                     {
  429.                         value = (int)(edgePos*(((float)percent)*0.01) - margin);
  430.                         done = TRUE;
  431.                         return TRUE;
  432.                     }
  433.                     else
  434.                         return FALSE;
  435.                 }
  436.                 case wxUnconstrained:
  437.                 {
  438.                     // We know the bottom edge position if we know the top edge
  439.                     // and we know the height; OR if we know the centre edge and
  440.                     // the height.
  441.                     if (constraints->top.GetDone() && constraints->height.GetDone())
  442.                     {
  443.                         value = (constraints->top.GetValue() + constraints->height.GetValue() - margin);
  444.                         done = TRUE;
  445.                         return TRUE;
  446.                     }
  447.                     else if (constraints->centreY.GetDone() && constraints->height.GetDone())
  448.                     {
  449.                         value = (constraints->centreY.GetValue() + (constraints->height.GetValue()/2) - margin);
  450.                         done = TRUE;
  451.                         return TRUE;
  452.                     }
  453.                     else
  454.                         return FALSE;
  455.                 }
  456.                 case wxAsIs:
  457.                 {
  458.                     int x, y;
  459.                     int w, h;
  460.                     win->GetSize(&w, &h);
  461.                     win->GetPosition(&x, &y);
  462.                     value = h + y;
  463.                     done = TRUE;
  464.                     return TRUE;
  465.                 }
  466.                 default:
  467.                     break;
  468.             }
  469.             break;
  470.         }
  471.         case wxCentreX:
  472.         {
  473.             switch (relationship)
  474.             {
  475.                 case wxLeftOf:
  476.                 {
  477.                     // We can know this edge if: otherWin is win's parent, or
  478.                     // otherWin has a satisfied constraint, or otherWin has no
  479.                     // constraint.
  480.                     int edgePos = GetEdge(otherEdge, win, otherWin);
  481.                     if (edgePos != -1)
  482.                     {
  483.                         value = edgePos - margin;
  484.                         done = TRUE;
  485.                         return TRUE;
  486.                     }
  487.                     else
  488.                         return FALSE;
  489.                 }
  490.                 case wxRightOf:
  491.                 {
  492.                     int edgePos = GetEdge(otherEdge, win, otherWin);
  493.                     if (edgePos != -1)
  494.                     {
  495.                         value = edgePos + margin;
  496.                         done = TRUE;
  497.                         return TRUE;
  498.                     }
  499.                     else
  500.                         return FALSE;
  501.                 }
  502.                 case wxPercentOf:
  503.                 {
  504.                     int edgePos = GetEdge(otherEdge, win, otherWin);
  505.                     if (edgePos != -1)
  506.                     {
  507.                         value = (int)(edgePos*(((float)percent)*0.01) + margin);
  508.                         done = TRUE;
  509.                         return TRUE;
  510.                     }
  511.                     else
  512.                         return FALSE;
  513.                 }
  514.                 case wxUnconstrained:
  515.                 {
  516.                     // We know the centre position if we know
  517.                     // the left-hand edge and we know the width, OR
  518.                     // the right-hand edge and the width
  519.                     if (constraints->left.GetDone() && constraints->width.GetDone())
  520.                     {
  521.                         value = (int)(constraints->left.GetValue() + (constraints->width.GetValue()/2) + margin);
  522.                         done = TRUE;
  523.                         return TRUE;
  524.                     }
  525.                     else if (constraints->right.GetDone() && constraints->width.GetDone())
  526.                     {
  527.                         value = (int)(constraints->left.GetValue() - (constraints->width.GetValue()/2) + margin);
  528.                         done = TRUE;
  529.                         return TRUE;
  530.                     }
  531.                     else
  532.                         return FALSE;
  533.                 }
  534.                 default:
  535.                     break;
  536.             }
  537.             break;
  538.         }
  539.         case wxCentreY:
  540.         {
  541.             switch (relationship)
  542.             {
  543.                 case wxAbove:
  544.                 {
  545.                     // We can know this edge if: otherWin is win's parent,
  546.                     // or otherWin has a satisfied constraint, or otherWin
  547.                     // has no constraint.
  548.                     int edgePos = GetEdge(otherEdge, win, otherWin);
  549.                     if (edgePos != -1)
  550.                     {
  551.                         value = edgePos - margin;
  552.                         done = TRUE;
  553.                         return TRUE;
  554.                     }
  555.                     else
  556.                         return FALSE;
  557.                 }
  558.                 case wxBelow:
  559.                 {
  560.                     int edgePos = GetEdge(otherEdge, win, otherWin);
  561.                     if (edgePos != -1)
  562.                     {
  563.                         value = edgePos + margin;
  564.                         done = TRUE;
  565.                         return TRUE;
  566.                     }
  567.                     else
  568.                         return FALSE;
  569.                 }
  570.                 case wxPercentOf:
  571.                 {
  572.                     int edgePos = GetEdge(otherEdge, win, otherWin);
  573.                     if (edgePos != -1)
  574.                     {
  575.                         value = (int)(edgePos*(((float)percent)*0.01) + margin);
  576.                         done = TRUE;
  577.                         return TRUE;
  578.                     }
  579.                     else
  580.                         return FALSE;
  581.                 }
  582.                 case wxUnconstrained:
  583.                 {
  584.                     // We know the centre position if we know
  585.                     // the top edge and we know the height, OR
  586.                     // the bottom edge and the height.
  587.                     if (constraints->bottom.GetDone() && constraints->height.GetDone())
  588.                     {
  589.                         value = (int)(constraints->bottom.GetValue() - (constraints->height.GetValue()/2) + margin);
  590.                         done = TRUE;
  591.                         return TRUE;
  592.                     }
  593.                     else if (constraints->top.GetDone() && constraints->height.GetDone())
  594.                     {
  595.                         value = (int)(constraints->top.GetValue() + (constraints->height.GetValue()/2) + margin);
  596.                         done = TRUE;
  597.                         return TRUE;
  598.                     }
  599.                     else
  600.                         return FALSE;
  601.                 }
  602.                 default:
  603.                     break;
  604.             }
  605.             break;
  606.         }
  607.         case wxWidth:
  608.         {
  609.             switch (relationship)
  610.             {
  611.                 case wxPercentOf:
  612.                 {
  613.                     int edgePos = GetEdge(otherEdge, win, otherWin);
  614.                     if (edgePos != -1)
  615.                     {
  616.                         value = (int)(edgePos*(((float)percent)*0.01));
  617.                         done = TRUE;
  618.                         return TRUE;
  619.                     }
  620.                     else
  621.                         return FALSE;
  622.                 }
  623.                 case wxAsIs:
  624.                 {
  625.                     if (win)
  626.                     {
  627.                         int h;
  628.                         win->GetSize(&value, &h);
  629.                         done = TRUE;
  630.                         return TRUE;
  631.                     }
  632.                     else return FALSE;
  633.                 }
  634.                 case wxUnconstrained:
  635.                 {
  636.                     // We know the width if we know the left edge and the right edge, OR
  637.                     // if we know the left edge and the centre, OR
  638.                     // if we know the right edge and the centre
  639.                     if (constraints->left.GetDone() && constraints->right.GetDone())
  640.                     {
  641.                         value = constraints->right.GetValue() - constraints->left.GetValue();
  642.                         done = TRUE;
  643.                         return TRUE;
  644.                     }
  645.                     else if (constraints->centreX.GetDone() && constraints->left.GetDone())
  646.                     {
  647.                         value = (int)(2*(constraints->centreX.GetValue() - constraints->left.GetValue()));
  648.                         done = TRUE;
  649.                         return TRUE;
  650.                     }
  651.                     else if (constraints->centreX.GetDone() && constraints->right.GetDone())
  652.                     {
  653.                         value = (int)(2*(constraints->right.GetValue() - constraints->centreX.GetValue()));
  654.                         done = TRUE;
  655.                         return TRUE;
  656.                     }
  657.                     else
  658.                         return FALSE;
  659.                 }
  660.                 default:
  661.                     break;
  662.             }
  663.             break;
  664.         }
  665.         case wxHeight:
  666.         {
  667.             switch (relationship)
  668.             {
  669.                 case wxPercentOf:
  670.                 {
  671.                     int edgePos = GetEdge(otherEdge, win, otherWin);
  672.                     if (edgePos != -1)
  673.                     {
  674.                         value = (int)(edgePos*(((float)percent)*0.01));
  675.                         done = TRUE;
  676.                         return TRUE;
  677.                     }
  678.                     else
  679.                         return FALSE;
  680.                 }
  681.                 case wxAsIs:
  682.                 {
  683.                     if (win)
  684.                     {
  685.                         int w;
  686.                         win->GetSize(&w, &value);
  687.                         done = TRUE;
  688.                         return TRUE;
  689.                     }
  690.                     else return FALSE;
  691.                 }
  692.                 case wxUnconstrained:
  693.                 {
  694.                     // We know the height if we know the top edge and the bottom edge, OR
  695.                     // if we know the top edge and the centre, OR
  696.                     // if we know the bottom edge and the centre
  697.                     if (constraints->top.GetDone() && constraints->bottom.GetDone())
  698.                     {
  699.                         value = constraints->bottom.GetValue() - constraints->top.GetValue();
  700.                         done = TRUE;
  701.                         return TRUE;
  702.                     }
  703.                     else if (constraints->top.GetDone() && constraints->centreY.GetDone())
  704.                     {
  705.                         value = (int)(2*(constraints->centreY.GetValue() - constraints->top.GetValue()));
  706.                         done = TRUE;
  707.                         return TRUE;
  708.                     }
  709.                     else if (constraints->bottom.GetDone() && constraints->centreY.GetDone())
  710.                     {
  711.                         value = (int)(2*(constraints->bottom.GetValue() - constraints->centreY.GetValue()));
  712.                         done = TRUE;
  713.                         return TRUE;
  714.                     }
  715.                     else
  716.                         return FALSE;
  717.                 }
  718.                 default:
  719.                     break;
  720.             }
  721.             break;
  722.         }
  723.         default:
  724.             break;
  725.     }
  726.     return FALSE;
  727. }
  728.  
  729. // Get the value of this edge or dimension, or if this is not determinable, -1.
  730. int wxIndividualLayoutConstraint::GetEdge(wxEdge which,
  731.                                           wxWindowBase *thisWin,
  732.                                           wxWindowBase *other) const
  733. {
  734.     // If the edge or dimension belongs to the parent, then we know the
  735.     // dimension is obtainable immediately. E.g. a wxExpandSizer may contain a
  736.     // button (but the button's true parent is a panel, not the sizer)
  737.     if (other->GetChildren().Find(thisWin))
  738.     {
  739.         switch (which)
  740.         {
  741.             case wxLeft:
  742.                 {
  743.                     return 0;
  744.                 }
  745.             case wxTop:
  746.                 {
  747.                     return 0;
  748.                 }
  749.             case wxRight:
  750.                 {
  751.                     int w, h;
  752.                     other->GetClientSizeConstraint(&w, &h);
  753.                     return w;
  754.                 }
  755.             case wxBottom:
  756.                 {
  757.                     int w, h;
  758.                     other->GetClientSizeConstraint(&w, &h);
  759.                     return h;
  760.                 }
  761.             case wxWidth:
  762.                 {
  763.                     int w, h;
  764.                     other->GetClientSizeConstraint(&w, &h);
  765.                     return w;
  766.                 }
  767.             case wxHeight:
  768.                 {
  769.                     int w, h;
  770.                     other->GetClientSizeConstraint(&w, &h);
  771.                     return h;
  772.                 }
  773.             case wxCentreX:
  774.             case wxCentreY:
  775.                 {
  776.                     int w, h;
  777.                     other->GetClientSizeConstraint(&w, &h);
  778.                     if (which == wxCentreX)
  779.                         return (int)(w/2);
  780.                     else
  781.                         return (int)(h/2);
  782.                 }
  783.             default:
  784.                 return -1;
  785.         }
  786.     }
  787.     switch (which)
  788.     {
  789.         case wxLeft:
  790.             {
  791.                 wxLayoutConstraints *constr = other->GetConstraints();
  792.                 // If no constraints, it means the window is not dependent
  793.                 // on anything, and therefore we know its value immediately
  794.                 if (constr)
  795.                 {
  796.                     if (constr->left.GetDone())
  797.                         return constr->left.GetValue();
  798.                     else
  799.                         return -1;
  800.                 }
  801.                 else
  802.                 {
  803.                     int x, y;
  804.                     other->GetPosition(&x, &y);
  805.                     return x;
  806.                 }
  807.             }
  808.         case wxTop:
  809.             {
  810.                 wxLayoutConstraints *constr = other->GetConstraints();
  811.                 // If no constraints, it means the window is not dependent
  812.                 // on anything, and therefore we know its value immediately
  813.                 if (constr)
  814.                 {
  815.                     if (constr->top.GetDone())
  816.                         return constr->top.GetValue();
  817.                     else
  818.                         return -1;
  819.                 }
  820.                 else
  821.                 {
  822.                     int x, y;
  823.                     other->GetPosition(&x, &y);
  824.                     return y;
  825.                 }
  826.             }
  827.         case wxRight:
  828.             {
  829.                 wxLayoutConstraints *constr = other->GetConstraints();
  830.                 // If no constraints, it means the window is not dependent
  831.                 // on anything, and therefore we know its value immediately
  832.                 if (constr)
  833.                 {
  834.                     if (constr->right.GetDone())
  835.                         return constr->right.GetValue();
  836.                     else
  837.                         return -1;
  838.                 }
  839.                 else
  840.                 {
  841.                     int x, y, w, h;
  842.                     other->GetPosition(&x, &y);
  843.                     other->GetSize(&w, &h);
  844.                     return (int)(x + w);
  845.                 }
  846.             }
  847.         case wxBottom:
  848.             {
  849.                 wxLayoutConstraints *constr = other->GetConstraints();
  850.                 // If no constraints, it means the window is not dependent
  851.                 // on anything, and therefore we know its value immediately
  852.                 if (constr)
  853.                 {
  854.                     if (constr->bottom.GetDone())
  855.                         return constr->bottom.GetValue();
  856.                     else
  857.                         return -1;
  858.                 }
  859.                 else
  860.                 {
  861.                     int x, y, w, h;
  862.                     other->GetPosition(&x, &y);
  863.                     other->GetSize(&w, &h);
  864.                     return (int)(y + h);
  865.                 }
  866.             }
  867.         case wxWidth:
  868.             {
  869.                 wxLayoutConstraints *constr = other->GetConstraints();
  870.                 // If no constraints, it means the window is not dependent
  871.                 // on anything, and therefore we know its value immediately
  872.                 if (constr)
  873.                 {
  874.                     if (constr->width.GetDone())
  875.                         return constr->width.GetValue();
  876.                     else
  877.                         return -1;
  878.                 }
  879.                 else
  880.                 {
  881.                     int w, h;
  882.                     other->GetSize(&w, &h);
  883.                     return w;
  884.                 }
  885.             }
  886.         case wxHeight:
  887.             {
  888.                 wxLayoutConstraints *constr = other->GetConstraints();
  889.                 // If no constraints, it means the window is not dependent
  890.                 // on anything, and therefore we know its value immediately
  891.                 if (constr)
  892.                 {
  893.                     if (constr->height.GetDone())
  894.                         return constr->height.GetValue();
  895.                     else
  896.                         return -1;
  897.                 }
  898.                 else
  899.                 {
  900.                     int w, h;
  901.                     other->GetSize(&w, &h);
  902.                     return h;
  903.                 }
  904.             }
  905.         case wxCentreX:
  906.             {
  907.                 wxLayoutConstraints *constr = other->GetConstraints();
  908.                 // If no constraints, it means the window is not dependent
  909.                 // on anything, and therefore we know its value immediately
  910.                 if (constr)
  911.                 {
  912.                     if (constr->centreX.GetDone())
  913.                         return constr->centreX.GetValue();
  914.                     else
  915.                         return -1;
  916.                 }
  917.                 else
  918.                 {
  919.                     int x, y, w, h;
  920.                     other->GetPosition(&x, &y);
  921.                     other->GetSize(&w, &h);
  922.                     return (int)(x + (w/2));
  923.                 }
  924.             }
  925.         case wxCentreY:
  926.             {
  927.                 wxLayoutConstraints *constr = other->GetConstraints();
  928.                 // If no constraints, it means the window is not dependent
  929.                 // on anything, and therefore we know its value immediately
  930.                 if (constr)
  931.                 {
  932.                     if (constr->centreY.GetDone())
  933.                         return constr->centreY.GetValue();
  934.                     else
  935.                         return -1;
  936.                 }
  937.                 else
  938.                 {
  939.                     int x, y, w, h;
  940.                     other->GetPosition(&x, &y);
  941.                     other->GetSize(&w, &h);
  942.                     return (int)(y + (h/2));
  943.                 }
  944.             }
  945.         default:
  946.             break;
  947.     }
  948.     return -1;
  949. }
  950.  
  951. wxLayoutConstraints::wxLayoutConstraints()
  952. {
  953.     left.SetEdge(wxLeft);
  954.     top.SetEdge(wxTop);
  955.     right.SetEdge(wxRight);
  956.     bottom.SetEdge(wxBottom);
  957.     centreX.SetEdge(wxCentreX);
  958.     centreY.SetEdge(wxCentreY);
  959.     width.SetEdge(wxWidth);
  960.     height.SetEdge(wxHeight);
  961. }
  962.  
  963. wxLayoutConstraints::~wxLayoutConstraints()
  964. {
  965. }
  966.  
  967. bool wxLayoutConstraints::SatisfyConstraints(wxWindowBase *win, int *nChanges)
  968. {
  969.     int noChanges = 0;
  970.  
  971.     bool done = width.GetDone();
  972.     bool newDone = (done ? TRUE : width.SatisfyConstraint(this, win));
  973.     if (newDone != done)
  974.         noChanges ++;
  975.  
  976.     done = height.GetDone();
  977.     newDone = (done ? TRUE : height.SatisfyConstraint(this, win));
  978.     if (newDone != done)
  979.         noChanges ++;
  980.  
  981.     done = left.GetDone();
  982.     newDone = (done ? TRUE : left.SatisfyConstraint(this, win));
  983.     if (newDone != done)
  984.         noChanges ++;
  985.  
  986.     done = top.GetDone();
  987.     newDone = (done ? TRUE : top.SatisfyConstraint(this, win));
  988.     if (newDone != done)
  989.         noChanges ++;
  990.  
  991.     done = right.GetDone();
  992.     newDone = (done ? TRUE : right.SatisfyConstraint(this, win));
  993.     if (newDone != done)
  994.         noChanges ++;
  995.  
  996.     done = bottom.GetDone();
  997.     newDone = (done ? TRUE : bottom.SatisfyConstraint(this, win));
  998.     if (newDone != done)
  999.         noChanges ++;
  1000.  
  1001.     done = centreX.GetDone();
  1002.     newDone = (done ? TRUE : centreX.SatisfyConstraint(this, win));
  1003.     if (newDone != done)
  1004.         noChanges ++;
  1005.  
  1006.     done = centreY.GetDone();
  1007.     newDone = (done ? TRUE : centreY.SatisfyConstraint(this, win));
  1008.     if (newDone != done)
  1009.         noChanges ++;
  1010.  
  1011.     *nChanges = noChanges;
  1012.  
  1013.     return AreSatisfied();
  1014. }
  1015.  
  1016. /*
  1017.  * Main constrained layout algorithm. Look at all the child
  1018.  * windows, and their constraints (if any).
  1019.  * The idea is to keep iterating through the constraints
  1020.  * until all left, right, bottom and top edges, and widths and heights,
  1021.  * are known (or no change occurs and we've failed to resolve all
  1022.  * constraints).
  1023.  *
  1024.  * If the user has not specified a dimension or edge, it will be
  1025.  * be calculated from the other known values. E.g. If we know
  1026.  * the right hand edge and the left hand edge, we now know the width.
  1027.  * The snag here is that this means we must specify absolute dimensions
  1028.  * twice (in constructor and in constraint), if we wish to use the
  1029.  * constraint notation to just set the position, for example.
  1030.  * Otherwise, if we only set ONE edge and no dimension, it would never
  1031.  * find the other edge.
  1032.  *
  1033.  * Algorithm:
  1034.  
  1035.   Mark all constraints as not done.
  1036.  
  1037.   iterations = 0;
  1038.   until no change or iterations >= max iterations
  1039.     For each child:
  1040.     {
  1041.       Calculate all constraints
  1042.     }
  1043.     iterations ++;
  1044.  
  1045.   For each child
  1046.     Set each calculated position and size
  1047.  
  1048.  */
  1049.  
  1050. #if WXWIN_COMPATIBILITY
  1051. bool wxOldDoLayout(wxWindowBase *win)
  1052. {
  1053.   // Make sure this isn't called recursively from below
  1054.   static wxList doneSoFar;
  1055.  
  1056.   if (doneSoFar.Member(win))
  1057.     return TRUE;
  1058.  
  1059.   doneSoFar.Append(win);
  1060.  
  1061.   wxNode *node = win->GetChildren().First();
  1062.   while (node)
  1063.   {
  1064.     wxWindowBase *child = (wxWindowBase *)node->Data();
  1065.     wxLayoutConstraints *constr = child->GetConstraints();
  1066.     if (constr)
  1067.     {
  1068.       constr->left.SetDone(FALSE);
  1069.       constr->top.SetDone(FALSE);
  1070.       constr->right.SetDone(FALSE);
  1071.       constr->bottom.SetDone(FALSE);
  1072.       constr->width.SetDone(FALSE);
  1073.       constr->height.SetDone(FALSE);
  1074.       constr->centreX.SetDone(FALSE);
  1075.       constr->centreY.SetDone(FALSE);
  1076.     }
  1077.     node = node->Next();
  1078.   }
  1079.   int noIterations = 0;
  1080.   int maxIterations = 500;
  1081.   int noChanges = 1;
  1082.  
  1083.   while ((noChanges > 0) && (noIterations < maxIterations))
  1084.   {
  1085.     noChanges = 0;
  1086.     wxNode *node = win->GetChildren().First();
  1087.     while (node)
  1088.     {
  1089.       wxWindowBase *child = (wxWindowBase *)node->Data();
  1090.       wxLayoutConstraints *constr = child->GetConstraints();
  1091.       if (constr)
  1092.       {
  1093.         int tempNoChanges = 0;
  1094.         (void)constr->SatisfyConstraints(child, &tempNoChanges);
  1095.         noChanges += tempNoChanges;
  1096.       }
  1097.       node = node->Next();
  1098.     }
  1099.     noIterations ++;
  1100.   }
  1101. /*
  1102.   // Would be nice to have a test here to see _which_ constraint(s)
  1103.   // failed, so we can print a specific diagnostic message.
  1104.   if (noFailures > 0)
  1105.   {
  1106.     wxDebugMsg(_("wxWindowBase::Layout() failed.\n"));
  1107.   }
  1108. */
  1109.   // Now set the sizes and positions of the children, and
  1110.   // recursively call Layout().
  1111.   node = win->GetChildren().First();
  1112.   while (node)
  1113.   {
  1114.     wxWindowBase *child = (wxWindowBase *)node->Data();
  1115.     wxLayoutConstraints *constr = child->GetConstraints();
  1116.     if (constr && constr->left.GetDone() && constr->right.GetDone() &&
  1117.                   constr->width.GetDone() && constr->height.GetDone())
  1118.     {
  1119.       int x = constr->left.GetValue();
  1120.       int y = constr->top.GetValue();
  1121.       int w = constr->width.GetValue();
  1122.       int h = constr->height.GetValue();
  1123.  
  1124.       // If we don't want to resize this window, just move it...
  1125.       if ((constr->width.GetRelationship() != wxAsIs) ||
  1126.           (constr->height.GetRelationship() != wxAsIs))
  1127.       {
  1128.         // _Should_ call Layout() recursively.
  1129.         child->SetSize(x, y, w, h);
  1130.       }
  1131.       else
  1132.       {
  1133.         child->Move(x, y);
  1134.       }
  1135.     }
  1136.     else
  1137.       child->Layout();
  1138.     node = node->Next();
  1139.   }
  1140.   doneSoFar.DeleteObject(win);
  1141.  
  1142.   return TRUE;
  1143. }
  1144. #endif // WXWIN_COMPATIBILITY
  1145.  
  1146. #endif // wxUSE_CONSTRAINTS
  1147.