1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     Constraint layout system classes 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart and Markus Holzem 
   9 // Licence:       wxWindows license 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================= 
  14 // ============================================================================= 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  21     #pragma implementation "layout.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  36     #include "wx/window.h" 
  38     #include "wx/dialog.h" 
  39     #include "wx/msgdlg.h" 
  43 #include "wx/layout.h" 
  45 #if !USE_SHARED_LIBRARY 
  46     IMPLEMENT_DYNAMIC_CLASS(wxIndividualLayoutConstraint
, wxObject
) 
  47     IMPLEMENT_DYNAMIC_CLASS(wxLayoutConstraints
, wxObject
) 
  48     IMPLEMENT_DYNAMIC_CLASS(wxSizer
, wxObject
) 
  49     IMPLEMENT_DYNAMIC_CLASS(wxRowColSizer
, wxSizer
) 
  50     IMPLEMENT_DYNAMIC_CLASS(wxSpacingSizer
, wxSizer
) 
  55  - Non shrink-to-fit row-col behaviour. 
  56  - Give justification styles, so can e.g. centre 
  57  the rows & cols, distribute the available space... 
  58  - Shrink-to-fit: should resize outer window (e.g. dialog box) 
  59  if directly associated with this kind of window. 
  60  - How to deal with a rowcol that stretches in one direction 
  61  but shrinks-to-fit in other. E.g. a horizontal toolbar: the width 
  62  stretches to fit the frame, but the height is constant 
  63  or wraps around contents. The algorithm currently assumes 
  64  both dimensions have the same behaviour. Could assume a constant 
  65  height (absolute value). 
  66  - rowcol where each row or column is aligned (length of 
  67    largest element determines spacing) 
  69  - Analyze aesthetic dialog boxes and implement using sizers. 
  70  - What reuseable components can we provide? E.g. Ok/Cancel/Help 
  72  - use wxStaticItems for aesthetic dialogs. 
  76 // Find margin sizes if a sizer, or zero otherwise 
  77 int wxSizerMarginX(wxWindowBase 
*win
) 
  79     if ( win
->IsKindOf(CLASSINFO(wxSizer
)) ) 
  81         wxSizer 
*sizer 
= (wxSizer 
*)win
; 
  82         return sizer
->GetBorderX(); 
  88 int wxSizerMarginY(wxWindowBase 
*win
) 
  90     if ( win
->IsKindOf(CLASSINFO(wxSizer
)) ) 
  92         wxSizer 
*sizer 
= (wxSizer 
*)win
; 
  93         return sizer
->GetBorderY(); 
 100 wxIndividualLayoutConstraint::wxIndividualLayoutConstraint() 
 103     relationship 
= wxUnconstrained
; 
 109     otherWin 
= (wxWindowBase 
*) NULL
; 
 112 wxIndividualLayoutConstraint::~wxIndividualLayoutConstraint() 
 116 void wxIndividualLayoutConstraint::Set(wxRelationship rel
, wxWindowBase 
*otherW
, wxEdge otherE
, int val
, int marg
) 
 125 void wxIndividualLayoutConstraint::LeftOf(wxWindowBase 
*sibling
, int marg
) 
 127     Set(wxLeftOf
, sibling
, wxLeft
, 0, marg
); 
 130 void wxIndividualLayoutConstraint::RightOf(wxWindowBase 
*sibling
, int marg
) 
 132     Set(wxRightOf
, sibling
, wxRight
, 0, marg
); 
 135 void wxIndividualLayoutConstraint::Above(wxWindowBase 
*sibling
, int marg
) 
 137     Set(wxAbove
, sibling
, wxTop
, 0, marg
); 
 140 void wxIndividualLayoutConstraint::Below(wxWindowBase 
*sibling
, int marg
) 
 142     Set(wxBelow
, sibling
, wxBottom
, 0, marg
); 
 146 // 'Same edge' alignment 
 148 void wxIndividualLayoutConstraint::SameAs(wxWindowBase 
*otherW
, wxEdge edge
, int marg
) 
 150     Set(wxPercentOf
, otherW
, edge
, 0, marg
); 
 154 // The edge is a percentage of the other window's edge 
 155 void wxIndividualLayoutConstraint::PercentOf(wxWindowBase 
*otherW
, wxEdge wh
, int per
) 
 158     relationship 
= wxPercentOf
; 
 165 // Edge has absolute value 
 167 void wxIndividualLayoutConstraint::Absolute(int val
) 
 169     value 
= val
; relationship 
= wxAbsolute
; 
 172 // Reset constraint if it mentions otherWin 
 173 bool wxIndividualLayoutConstraint::ResetIfWin(wxWindowBase 
*otherW
) 
 175     if (otherW 
== otherWin
) 
 178         relationship 
= wxAsIs
; 
 183         otherWin 
= (wxWindowBase 
*) NULL
; 
 190 // Try to satisfy constraint 
 191 bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints 
*constraints
, wxWindowBase 
*win
) 
 193     if (relationship 
== wxAbsolute
) 
 203             switch (relationship
) 
 207                     // We can know this edge if: otherWin is win's 
 208                     // parent, or otherWin has a satisfied constraint, 
 209                     // or otherWin has no constraint. 
 210                     int edgePos 
= GetEdge(otherEdge
, win
, otherWin
); 
 213                         value 
= edgePos 
- margin
; 
 222                     int edgePos 
= GetEdge(otherEdge
, win
, otherWin
); 
 225                         value 
= edgePos 
+ margin
; 
 234                     int edgePos 
= GetEdge(otherEdge
, win
, otherWin
); 
 237                         value 
= (int)(edgePos
*(((float)percent
)*0.01) + margin
); 
 244                 case wxUnconstrained
: 
 246                     // We know the left-hand edge position if we know 
 247                     // the right-hand edge and we know the width; OR if 
 248                     // we know the centre and the width. 
 249                     if (constraints
->right
.GetDone() && constraints
->width
.GetDone()) 
 251                         value 
= (constraints
->right
.GetValue() - constraints
->width
.GetValue() + margin
); 
 255                     else if (constraints
->centreX
.GetDone() && constraints
->width
.GetDone()) 
 257                         value 
= (int)(constraints
->centreX
.GetValue() - (constraints
->width
.GetValue()/2) + margin
); 
 267                     win
->GetPosition(&value
, &y
); 
 278             switch (relationship
) 
 282                     // We can know this edge if: otherWin is win's 
 283                     // parent, or otherWin has a satisfied constraint, 
 284                     // or otherWin has no constraint. 
 285                     int edgePos 
= GetEdge(otherEdge
, win
, otherWin
); 
 288                         value 
= edgePos 
- margin
; 
 297                     int edgePos 
= GetEdge(otherEdge
, win
, otherWin
); 
 300                         value 
= edgePos 
+ margin
; 
 309                     int edgePos 
= GetEdge(otherEdge
, win
, otherWin
); 
 312                         value 
= (int)(edgePos
*(((float)percent
)*0.01) - margin
); 
 319                 case wxUnconstrained
: 
 321                     // We know the right-hand edge position if we know the 
 322                     // left-hand edge and we know the width, OR if we know the 
 323                     // centre edge and the width. 
 324                     if (constraints
->left
.GetDone() && constraints
->width
.GetDone()) 
 326                         value 
= (constraints
->left
.GetValue() + constraints
->width
.GetValue() - margin
); 
 330                     else if (constraints
->centreX
.GetDone() && constraints
->width
.GetDone()) 
 332                         value 
= (int)(constraints
->centreX
.GetValue() + (constraints
->width
.GetValue()/2) - margin
); 
 343                     win
->GetSize(&w
, &h
); 
 344                     win
->GetPosition(&x
, &y
); 
 356             switch (relationship
) 
 360                     // We can know this edge if: otherWin is win's 
 361                     // parent, or otherWin has a satisfied constraint, 
 362                     // or otherWin has no constraint. 
 363                     int edgePos 
= GetEdge(otherEdge
, win
, otherWin
); 
 366                         value 
= edgePos 
- margin
; 
 375                     int edgePos 
= GetEdge(otherEdge
, win
, otherWin
); 
 378                         value 
= edgePos 
+ margin
; 
 387                     int edgePos 
= GetEdge(otherEdge
, win
, otherWin
); 
 390                         value 
= (int)(edgePos
*(((float)percent
)*0.01) + margin
); 
 397                 case wxUnconstrained
: 
 399                     // We know the top edge position if we know the bottom edge 
 400                     // and we know the height; OR if we know the centre edge and 
 402                     if (constraints
->bottom
.GetDone() && constraints
->height
.GetDone()) 
 404                         value 
= (constraints
->bottom
.GetValue() - constraints
->height
.GetValue() + margin
); 
 408                     else if (constraints
->centreY
.GetDone() && constraints
->height
.GetDone()) 
 410                         value 
= (constraints
->centreY
.GetValue() - (constraints
->height
.GetValue()/2) + margin
); 
 420                     win
->GetPosition(&x
, &value
); 
 431             switch (relationship
) 
 435                     // We can know this edge if: otherWin is win's parent, 
 436                     // or otherWin has a satisfied constraint, or 
 437                     // otherWin has no constraint. 
 438                     int edgePos 
= GetEdge(otherEdge
, win
, otherWin
); 
 441                         value 
= edgePos 
+ margin
; 
 450                     int edgePos 
= GetEdge(otherEdge
, win
, otherWin
); 
 453                         value 
= edgePos 
- margin
; 
 462                     int edgePos 
= GetEdge(otherEdge
, win
, otherWin
); 
 465                         value 
= (int)(edgePos
*(((float)percent
)*0.01) - margin
); 
 472                 case wxUnconstrained
: 
 474                     // We know the bottom edge position if we know the top edge 
 475                     // and we know the height; OR if we know the centre edge and 
 477                     if (constraints
->top
.GetDone() && constraints
->height
.GetDone()) 
 479                         value 
= (constraints
->top
.GetValue() + constraints
->height
.GetValue() - margin
); 
 483                     else if (constraints
->centreY
.GetDone() && constraints
->height
.GetDone()) 
 485                         value 
= (constraints
->centreY
.GetValue() + (constraints
->height
.GetValue()/2) - margin
); 
 496                     win
->GetSize(&w
, &h
); 
 497                     win
->GetPosition(&x
, &y
); 
 509             switch (relationship
) 
 513                     // We can know this edge if: otherWin is win's parent, or 
 514                     // otherWin has a satisfied constraint, or otherWin has no 
 516                     int edgePos 
= GetEdge(otherEdge
, win
, otherWin
); 
 519                         value 
= edgePos 
- margin
; 
 528                     int edgePos 
= GetEdge(otherEdge
, win
, otherWin
); 
 531                         value 
= edgePos 
+ margin
; 
 540                     int edgePos 
= GetEdge(otherEdge
, win
, otherWin
); 
 543                         value 
= (int)(edgePos
*(((float)percent
)*0.01) + margin
); 
 550                 case wxUnconstrained
: 
 552                     // We know the centre position if we know 
 553                     // the left-hand edge and we know the width, OR 
 554                     // the right-hand edge and the width 
 555                     if (constraints
->left
.GetDone() && constraints
->width
.GetDone()) 
 557                         value 
= (int)(constraints
->left
.GetValue() + (constraints
->width
.GetValue()/2) + margin
); 
 561                     else if (constraints
->right
.GetDone() && constraints
->width
.GetDone()) 
 563                         value 
= (int)(constraints
->left
.GetValue() - (constraints
->width
.GetValue()/2) + margin
); 
 577             switch (relationship
) 
 581                     // We can know this edge if: otherWin is win's parent, 
 582                     // or otherWin has a satisfied constraint, or otherWin 
 583                     // has no constraint. 
 584                     int edgePos 
= GetEdge(otherEdge
, win
, otherWin
); 
 587                         value 
= edgePos 
- margin
; 
 596                     int edgePos 
= GetEdge(otherEdge
, win
, otherWin
); 
 599                         value 
= edgePos 
+ margin
; 
 608                     int edgePos 
= GetEdge(otherEdge
, win
, otherWin
); 
 611                         value 
= (int)(edgePos
*(((float)percent
)*0.01) + margin
); 
 618                 case wxUnconstrained
: 
 620                     // We know the centre position if we know 
 621                     // the top edge and we know the height, OR 
 622                     // the bottom edge and the height. 
 623                     if (constraints
->bottom
.GetDone() && constraints
->height
.GetDone()) 
 625                         value 
= (int)(constraints
->bottom
.GetValue() - (constraints
->height
.GetValue()/2) + margin
); 
 629                     else if (constraints
->top
.GetDone() && constraints
->height
.GetDone()) 
 631                         value 
= (int)(constraints
->top
.GetValue() + (constraints
->height
.GetValue()/2) + margin
); 
 645             switch (relationship
) 
 649                     int edgePos 
= GetEdge(otherEdge
, win
, otherWin
); 
 652                         value 
= (int)(edgePos
*(((float)percent
)*0.01)); 
 664                         win
->GetSize(&value
, &h
); 
 670                 case wxUnconstrained
: 
 672                     // We know the width if we know the left edge and the right edge, OR 
 673                     // if we know the left edge and the centre, OR 
 674                     // if we know the right edge and the centre 
 675                     if (constraints
->left
.GetDone() && constraints
->right
.GetDone()) 
 677                         value 
= constraints
->right
.GetValue() - constraints
->left
.GetValue(); 
 681                     else if (constraints
->centreX
.GetDone() && constraints
->left
.GetDone()) 
 683                         value 
= (int)(2*(constraints
->centreX
.GetValue() - constraints
->left
.GetValue())); 
 687                     else if (constraints
->centreX
.GetDone() && constraints
->right
.GetDone()) 
 689                         value 
= (int)(2*(constraints
->right
.GetValue() - constraints
->centreX
.GetValue())); 
 703             switch (relationship
) 
 707                     int edgePos 
= GetEdge(otherEdge
, win
, otherWin
); 
 710                         value 
= (int)(edgePos
*(((float)percent
)*0.01)); 
 722                         win
->GetSize(&w
, &value
); 
 728                 case wxUnconstrained
: 
 730                     // We know the height if we know the top edge and the bottom edge, OR 
 731                     // if we know the top edge and the centre, OR 
 732                     // if we know the bottom edge and the centre 
 733                     if (constraints
->top
.GetDone() && constraints
->bottom
.GetDone()) 
 735                         value 
= constraints
->bottom
.GetValue() - constraints
->top
.GetValue(); 
 739                     else if (constraints
->top
.GetDone() && constraints
->centreY
.GetDone()) 
 741                         value 
= (int)(2*(constraints
->centreY
.GetValue() - constraints
->top
.GetValue())); 
 745                     else if (constraints
->bottom
.GetDone() && constraints
->centreY
.GetDone()) 
 747                         value 
= (int)(2*(constraints
->bottom
.GetValue() - constraints
->centreY
.GetValue())); 
 765 // Get the value of this edge or dimension, or if this is not determinable, -1. 
 766 int wxIndividualLayoutConstraint::GetEdge(wxEdge which
, 
 767                                           wxWindowBase 
*thisWin
, 
 768                                           wxWindowBase 
*other
) const 
 770     // If the edge or dimension belongs to the parent, then we know the 
 771     // dimension is obtainable immediately. E.g. a wxExpandSizer may contain a 
 772     // button (but the button's true parent is a panel, not the sizer) 
 773     if (other
->GetChildren().Find(thisWin
)) 
 779                     return wxSizerMarginX(other
); 
 783                     return wxSizerMarginY(other
); 
 788                     other
->GetClientSizeConstraint(&w
, &h
); 
 789                     return w 
- wxSizerMarginX(other
); 
 794                     other
->GetClientSizeConstraint(&w
, &h
); 
 795                     return h 
- wxSizerMarginY(other
); 
 800                     other
->GetClientSizeConstraint(&w
, &h
); 
 801                     return w 
- 2*wxSizerMarginX(other
); 
 806                     other
->GetClientSizeConstraint(&w
, &h
); 
 807                     return h 
- 2*wxSizerMarginY(other
); 
 813                     other
->GetClientSizeConstraint(&w
, &h
); 
 814                     if (which 
== wxCentreX
) 
 827                 wxLayoutConstraints 
*constr 
= other
->GetConstraints(); 
 828                 // If no constraints, it means the window is not dependent 
 829                 // on anything, and therefore we know its value immediately 
 832                     if (constr
->left
.GetDone()) 
 833                         return constr
->left
.GetValue(); 
 840                     other
->GetPosition(&x
, &y
); 
 846                 wxLayoutConstraints 
*constr 
= other
->GetConstraints(); 
 847                 // If no constraints, it means the window is not dependent 
 848                 // on anything, and therefore we know its value immediately 
 851                     if (constr
->top
.GetDone()) 
 852                         return constr
->top
.GetValue(); 
 859                     other
->GetPosition(&x
, &y
); 
 865                 wxLayoutConstraints 
*constr 
= other
->GetConstraints(); 
 866                 // If no constraints, it means the window is not dependent 
 867                 // on anything, and therefore we know its value immediately 
 870                     if (constr
->right
.GetDone()) 
 871                         return constr
->right
.GetValue(); 
 878                     other
->GetPosition(&x
, &y
); 
 879                     other
->GetSize(&w
, &h
); 
 885                 wxLayoutConstraints 
*constr 
= other
->GetConstraints(); 
 886                 // If no constraints, it means the window is not dependent 
 887                 // on anything, and therefore we know its value immediately 
 890                     if (constr
->bottom
.GetDone()) 
 891                         return constr
->bottom
.GetValue(); 
 898                     other
->GetPosition(&x
, &y
); 
 899                     other
->GetSize(&w
, &h
); 
 905                 wxLayoutConstraints 
*constr 
= other
->GetConstraints(); 
 906                 // If no constraints, it means the window is not dependent 
 907                 // on anything, and therefore we know its value immediately 
 910                     if (constr
->width
.GetDone()) 
 911                         return constr
->width
.GetValue(); 
 918                     other
->GetSize(&w
, &h
); 
 924                 wxLayoutConstraints 
*constr 
= other
->GetConstraints(); 
 925                 // If no constraints, it means the window is not dependent 
 926                 // on anything, and therefore we know its value immediately 
 929                     if (constr
->height
.GetDone()) 
 930                         return constr
->height
.GetValue(); 
 937                     other
->GetSize(&w
, &h
); 
 943                 wxLayoutConstraints 
*constr 
= other
->GetConstraints(); 
 944                 // If no constraints, it means the window is not dependent 
 945                 // on anything, and therefore we know its value immediately 
 948                     if (constr
->centreX
.GetDone()) 
 949                         return constr
->centreX
.GetValue(); 
 956                     other
->GetPosition(&x
, &y
); 
 957                     other
->GetSize(&w
, &h
); 
 958                     return (int)(x 
+ (w
/2)); 
 963                 wxLayoutConstraints 
*constr 
= other
->GetConstraints(); 
 964                 // If no constraints, it means the window is not dependent 
 965                 // on anything, and therefore we know its value immediately 
 968                     if (constr
->centreY
.GetDone()) 
 969                         return constr
->centreY
.GetValue(); 
 976                     other
->GetPosition(&x
, &y
); 
 977                     other
->GetSize(&w
, &h
); 
 978                     return (int)(y 
+ (h
/2)); 
 987 wxLayoutConstraints::wxLayoutConstraints() 
 989     left
.SetEdge(wxLeft
); 
 991     right
.SetEdge(wxRight
); 
 992     bottom
.SetEdge(wxBottom
); 
 993     centreX
.SetEdge(wxCentreX
); 
 994     centreY
.SetEdge(wxCentreY
); 
 995     width
.SetEdge(wxWidth
); 
 996     height
.SetEdge(wxHeight
); 
 999 wxLayoutConstraints::~wxLayoutConstraints() 
1003 bool wxLayoutConstraints::SatisfyConstraints(wxWindowBase 
*win
, int *nChanges
) 
1007     bool done 
= width
.GetDone(); 
1008     bool newDone 
= (done 
? TRUE 
: width
.SatisfyConstraint(this, win
)); 
1009     if (newDone 
!= done
) 
1012     done 
= height
.GetDone(); 
1013     newDone 
= (done 
? TRUE 
: height
.SatisfyConstraint(this, win
)); 
1014     if (newDone 
!= done
) 
1017     done 
= left
.GetDone(); 
1018     newDone 
= (done 
? TRUE 
: left
.SatisfyConstraint(this, win
)); 
1019     if (newDone 
!= done
) 
1022     done 
= top
.GetDone(); 
1023     newDone 
= (done 
? TRUE 
: top
.SatisfyConstraint(this, win
)); 
1024     if (newDone 
!= done
) 
1027     done 
= right
.GetDone(); 
1028     newDone 
= (done 
? TRUE 
: right
.SatisfyConstraint(this, win
)); 
1029     if (newDone 
!= done
) 
1032     done 
= bottom
.GetDone(); 
1033     newDone 
= (done 
? TRUE 
: bottom
.SatisfyConstraint(this, win
)); 
1034     if (newDone 
!= done
) 
1037     done 
= centreX
.GetDone(); 
1038     newDone 
= (done 
? TRUE 
: centreX
.SatisfyConstraint(this, win
)); 
1039     if (newDone 
!= done
) 
1042     done 
= centreY
.GetDone(); 
1043     newDone 
= (done 
? TRUE 
: centreY
.SatisfyConstraint(this, win
)); 
1044     if (newDone 
!= done
) 
1047     *nChanges 
= noChanges
; 
1049     return AreSatisfied(); 
1053  * Main constrained layout algorithm. Look at all the child 
1054  * windows, and their constraints (if any). 
1055  * The idea is to keep iterating through the constraints 
1056  * until all left, right, bottom and top edges, and widths and heights, 
1057  * are known (or no change occurs and we've failed to resolve all 
1060  * If the user has not specified a dimension or edge, it will be 
1061  * be calculated from the other known values. E.g. If we know 
1062  * the right hand edge and the left hand edge, we now know the width. 
1063  * The snag here is that this means we must specify absolute dimensions 
1064  * twice (in constructor and in constraint), if we wish to use the 
1065  * constraint notation to just set the position, for example. 
1066  * Otherwise, if we only set ONE edge and no dimension, it would never 
1067  * find the other edge. 
1071   Mark all constraints as not done. 
1074   until no change or iterations >= max iterations 
1077       Calculate all constraints 
1082     Set each calculated position and size 
1086 #if WXWIN_COMPATIBILITY 
1087 bool wxOldDoLayout(wxWindowBase 
*win
) 
1089   // Make sure this isn't called recursively from below 
1090   static wxList doneSoFar
; 
1092   if (doneSoFar
.Member(win
)) 
1095   doneSoFar
.Append(win
); 
1097   wxNode 
*node 
= win
->GetChildren().First(); 
1100     wxWindowBase 
*child 
= (wxWindowBase 
*)node
->Data(); 
1101     wxLayoutConstraints 
*constr 
= child
->GetConstraints(); 
1104       constr
->left
.SetDone(FALSE
); 
1105       constr
->top
.SetDone(FALSE
); 
1106       constr
->right
.SetDone(FALSE
); 
1107       constr
->bottom
.SetDone(FALSE
); 
1108       constr
->width
.SetDone(FALSE
); 
1109       constr
->height
.SetDone(FALSE
); 
1110       constr
->centreX
.SetDone(FALSE
); 
1111       constr
->centreY
.SetDone(FALSE
); 
1113     node 
= node
->Next(); 
1115   int noIterations 
= 0; 
1116   int maxIterations 
= 500; 
1119   while ((noChanges 
> 0) && (noIterations 
< maxIterations
)) 
1122     wxNode 
*node 
= win
->GetChildren().First(); 
1125       wxWindowBase 
*child 
= (wxWindowBase 
*)node
->Data(); 
1126       wxLayoutConstraints 
*constr 
= child
->GetConstraints(); 
1129         int tempNoChanges 
= 0; 
1130         (void)constr
->SatisfyConstraints(child
, &tempNoChanges
); 
1131         noChanges 
+= tempNoChanges
; 
1133       node 
= node
->Next(); 
1138   // Would be nice to have a test here to see _which_ constraint(s) 
1139   // failed, so we can print a specific diagnostic message. 
1142     wxDebugMsg(_("wxWindowBase::Layout() failed.\n")); 
1145   // Now set the sizes and positions of the children, and 
1146   // recursively call Layout(). 
1147   node 
= win
->GetChildren().First(); 
1150     wxWindowBase 
*child 
= (wxWindowBase 
*)node
->Data(); 
1151     wxLayoutConstraints 
*constr 
= child
->GetConstraints(); 
1152     if (constr 
&& constr
->left
.GetDone() && constr
->right
.GetDone() && 
1153                   constr
->width
.GetDone() && constr
->height
.GetDone()) 
1155       int x 
= constr
->left
.GetValue(); 
1156       int y 
= constr
->top
.GetValue(); 
1157       int w 
= constr
->width
.GetValue(); 
1158       int h 
= constr
->height
.GetValue(); 
1160       // If we don't want to resize this window, just move it... 
1161       if ((constr
->width
.GetRelationship() != wxAsIs
) || 
1162           (constr
->height
.GetRelationship() != wxAsIs
)) 
1164         // _Should_ call Layout() recursively. 
1165         child
->SetSize(x
, y
, w
, h
); 
1174     node 
= node
->Next(); 
1176   doneSoFar
.DeleteObject(win
); 
1180 #endif // WXWIN_COMPATIBILITY 
1184     sizerBehaviour 
= wxSizerNone
; 
1193 wxSizer::wxSizer(wxWindowBase 
*parent
, wxSizerBehaviour behav
) 
1195     Create(parent
, behav
); 
1198 bool wxSizer::Create(wxWindowBase 
*parent
, wxSizerBehaviour behav
) 
1200     sizerBehaviour 
= behav
; 
1203     m_sizerParent 
= parent
; 
1209     // A normal window can have just one top-level sizer 
1210     // associated with it. 
1211     if (!parent
->IsKindOf(CLASSINFO(wxSizer
))) 
1213         parent
->SetSizer(this); 
1216         ((wxSizer 
*)parent
)->AddSizerChild(this); 
1218     switch (sizerBehaviour
) 
1222                 // Defines a set of constraints 
1223                 // to expand the sizer to fit the parent window 
1224                 wxLayoutConstraints 
*c 
= new wxLayoutConstraints
; 
1226                 c
->left
.SameAs(parent
, wxLeft
, 0); 
1227                 c
->top
.SameAs(parent
, wxTop
, 0); 
1228                 c
->right
.SameAs(parent
, wxRight
, 0); 
1229                 c
->bottom
.SameAs(parent
, wxBottom
, 0); 
1245     // Remove all children without deleting them, 
1246     // or ~wxbWindow will delete proper windows _twice_ 
1247     wxNode 
*node 
= GetChildren().First(); 
1250         wxNode 
*next 
= node
->Next(); 
1251         wxWindowBase 
*win 
= (wxWindowBase 
*)node
->Data(); 
1252         if (!win
->IsKindOf(CLASSINFO(wxSizer
))) 
1255             win
->SetSizerParent((wxWindowBase 
*) NULL
); 
1259             RemoveSizerChild(win
); 
1265     if (m_sizerParent
) // && !m_sizerParent->IsKindOf(CLASSINFO(wxSizer))) 
1267         m_sizerParent
->SetSizer((wxSizer 
*) NULL
); 
1268         m_sizerParent 
= (wxWindowBase 
*) NULL
; 
1273 void wxSizer::SetBorder(int x
, int y
) 
1277     /* No: the margin is for inside, not outside (expansion) 
1279        if ( GetConstraints() ) 
1281        GetConstraints()->left.SetMargin(x); 
1282        GetConstraints()->right.SetMargin(x); 
1283        GetConstraints()->top.SetMargin(y); 
1284        GetConstraints()->bottom.SetMargin(y); 
1290 void wxSizer::AddSizerChild(wxWindowBase 
*child
) 
1292     child
->SetSizerParent(this); 
1293     GetChildren().Append(child
); 
1295     // Add some constraints for the purpose of storing 
1296     // the relative position of the window/sizer 
1297     // during layout calculations. 
1298     if (!child
->GetConstraints()) 
1300         wxLayoutConstraints 
*c 
= new wxLayoutConstraints
; 
1306         child
->GetSize(&w
, &h
); 
1307         c
->width
.SetValue(w
); 
1308         c
->height
.SetValue(h
); 
1310         child
->SetConstraints(c
); 
1314 void wxSizer::RemoveSizerChild(wxWindowBase 
*child
) 
1316     GetChildren().DeleteObject(child
); 
1319 void wxSizer::DoSetSize(int x
, int y
, int w
, int h
, int WXUNUSED(flags
)) 
1321     wxLayoutConstraints 
*constr 
= GetConstraints(); 
1326             constr
->left
.SetValue(x
); 
1332             constr
->top
.SetValue(y
); 
1338             constr
->width
.SetValue(w
); 
1344             constr
->height
.SetValue(h
); 
1348 void wxSizer::DoGetSize(int *w
, int *h
) const 
1354 void wxSizer::DoGetPosition(int *x
, int *y
) const 
1360 bool wxSizer::LayoutPhase1(int *noChanges
) 
1363     switch (sizerBehaviour
) 
1369                     wxMessageBox(_("wxExpandSizer has no parent!"), _("Sizer error"), wxOK
); 
1373                 // Set the size to fill the parent client area 
1375                 m_sizerParent
->GetClientSize(&pw
, &ph
); 
1376                 SetSize(GetBorderX(), GetBorderY(), pw 
- 2*GetBorderX(), ph 
- 2*GetBorderY()); 
1377                 wxLayoutConstraints 
*constr 
= GetConstraints(); 
1379                 // Fill in the constraints 
1382                     constr
->left
.SetValue(0); constr
->left
.SetDone(TRUE
); 
1383                     constr
->top
.SetValue(0); constr
->right
.SetDone(TRUE
); 
1384                     constr
->width
.SetValue(pw
); constr
->width
.SetDone(TRUE
); 
1385                     constr
->height
.SetValue(ph
); constr
->height
.SetDone(TRUE
); 
1393                 wxLayoutConstraints 
*constr 
= GetConstraints(); 
1397                     // Force the constraint to have as-is width and height 
1398                     // if we're in shrink-to-fit mode, because if left unconstrained, 
1399                     // SatisfyConstraints will fail. The shrink-to-fit option 
1400                     // essentially specifies the width and height as 'whatever I calculate'. 
1401                     constr
->width
.AsIs(); 
1402                     constr
->height
.AsIs(); 
1406                 // Find the bounding box and set own size 
1410                 wxNode 
*node 
= GetChildren().First(); 
1413                     int x
, y
, width
, height
; 
1414                     wxWindowBase 
*win 
= (wxWindowBase 
*)node
->Data(); 
1415                     win
->GetSizeConstraint(&width
, &height
); 
1416                     win
->GetPositionConstraint(&x
, &y
); 
1417                     if ((x
+width
) > maxX
) 
1419                     if ((y
+height
) > maxY
) 
1420                         maxY 
= (y 
+ height
); 
1422                     node 
= node
->Next(); 
1424                 SetSize(GetBorderX(), GetBorderY(), maxX
, maxY
); 
1426                 // If this is the only sizer for the parent, size the parent to this sizer. 
1427                 if ( m_sizerParent 
&& (m_sizerParent
->GetSizer() == this) ) 
1428                     m_sizerParent
->SetClientSize(maxX 
+ 2*GetBorderX(), maxY 
+ 2*GetBorderY()); 
1435                 wxLayoutConstraints 
*constr 
= GetConstraints(); 
1438                     bool success 
= constr
->SatisfyConstraints(this, noChanges
); 
1441                         int x 
= constr
->left
.GetValue(); 
1442                         int y 
= constr
->top
.GetValue(); 
1443                         int w 
= constr
->width
.GetValue(); 
1444                         int h 
= constr
->height
.GetValue(); 
1445                         SetSize(x
, y
, w
, h
); 
1458 bool wxSizer::LayoutPhase2(int *noChanges
) 
1462     switch (sizerBehaviour
) 
1473                 wxLayoutConstraints 
*constr 
= GetConstraints(); 
1476                     bool success 
= constr
->SatisfyConstraints(this, noChanges
); 
1479                         int x 
= constr
->left
.GetValue(); 
1480                         int y 
= constr
->top
.GetValue(); 
1493                 // Is this a dumb fix for lack of constraint evaluation? 
1494                 wxLayoutConstraints 
*constr 
= GetConstraints(); 
1497                     bool success 
= constr
->SatisfyConstraints(this, noChanges
); 
1500                         int x 
= constr
->left
.GetValue(); 
1501                         int y 
= constr
->top
.GetValue(); 
1502                         int w 
= constr
->width
.GetValue(); 
1503                         int h 
= constr
->height
.GetValue(); 
1504                         SetSize(x
, y
, w
, h
); 
1519 wxRowColSizer::wxRowColSizer() 
1527 wxRowColSizer::wxRowColSizer(wxWindowBase 
*parent
, bool rc
, int n
, wxSizerBehaviour behav
) 
1529     Create(parent
, rc
, n
, behav
); 
1532 bool wxRowColSizer::Create(wxWindowBase 
*parent
, bool rc
, int n
, wxSizerBehaviour behav
) 
1534     wxSizer::Create(parent
, behav
); 
1544 wxRowColSizer::~wxRowColSizer() 
1548 bool wxRowColSizer::LayoutPhase1(int *noChanges
) 
1551     wxLayoutConstraints 
*constr 
= GetConstraints(); 
1555         // Force the constraint to have as-is width and height 
1556         // if we're in shrink-to-fit mode, because if left unconstrained, 
1557         // SatisfyConstraints will fail. The shrink-to-fit option 
1558         // essentially specifies the width and height as 'whatever I calculate'. 
1559         if (sizerBehaviour 
== wxSizerShrink
) 
1561             constr
->width
.AsIs(); 
1562             constr
->height
.AsIs(); 
1565         // Only evaluate the constraints FIRST if we're NOT 
1566         // in shrink-to-fit mode, i.e. we want to size the rowcol 
1567         // first, then lay the children out in the space we've calculated. 
1568         if (sizerBehaviour 
!= wxSizerShrink
) 
1570             bool success 
= constr
->SatisfyConstraints(this, noChanges
); 
1573                 int x 
= constr
->left
.GetValue(); 
1574                 int y 
= constr
->top
.GetValue(); 
1575                 int w 
= constr
->width
.GetValue(); 
1576                 int h 
= constr
->height
.GetValue(); 
1577                 SetSize(x
, y
, w
, h
); 
1582             // Continue to do the rest of the phase when the constraints have been 
1583             // satisfied, i.e. we're on the last iteration of phase 1 and 
1584             // can now do the actual rowcol laying out. 
1588     // If we ARE in shrink-to-fit mode, we must now 
1589     // calculate the child sizes BEFORE laying out in rows or columns. 
1590     if (sizerBehaviour 
== wxSizerShrink
) 
1595         // WILL THE WINDOW BE SIZED CORRECTLY AT THIS POINT? 
1596         // CHECK CONSTRAINTS IF ANY... 
1599         int currentX 
= borderX
; 
1600         int currentY 
= borderY
; 
1601         int maxX 
= currentX
; 
1602         int maxY 
= currentY
; 
1604         wxNode 
*node 
= GetChildren().First(); 
1607             wxWindowBase 
*win 
= (wxWindowBase 
*)node
->Data(); 
1608             int childWidth
, childHeight
; 
1609             if (win
->GetConstraints() && 
1610                     win
->GetConstraints()->width
.GetDone() && 
1611                     win
->GetConstraints()->height
.GetDone()) 
1613                 childWidth 
= win
->GetConstraints()->width
.GetValue(); 
1614                 childHeight 
= win
->GetConstraints()->height
.GetValue(); 
1617                 win
->GetSize(&childWidth
, &childHeight
); 
1619             win
->MoveConstraint(currentX
, currentY
); 
1621             if ((currentX 
+ childWidth
) > maxX
) 
1622                 maxX 
= (currentX 
+ childWidth
); 
1623             if ((currentY 
+ childHeight
) > maxY
) 
1624                 maxY 
= (currentY 
+ childHeight
); 
1628                 currentX 
+= childWidth 
+ xSpacing
; 
1631                 // Reset to start of row 
1632                 if (noCols 
== rowOrColSize
) 
1635                     currentY 
+= childHeight 
+ ySpacing
; 
1641                 currentY 
+= childHeight 
+ ySpacing
; 
1644                 // Reset to start of col 
1645                 if (noRows 
== rowOrColSize
) 
1648                     currentX 
+= childWidth 
+ xSpacing
; 
1653             node 
= node
->Next(); 
1658         SetSize(-1, -1, maxX
, maxY
); 
1663 bool wxRowColSizer::LayoutPhase2(int *noChanges
) 
1667     // If shrink-to-fit, it's only at Phase 2 that we know the size of 
1668     // the wxRowColSizer, and now we can evaluate the 
1669     // constraints and pass result back up to parent. 
1670     // This implements a depth-first strategy 
1671     if (sizerBehaviour 
== wxSizerShrink
) 
1673         wxLayoutConstraints 
*constr 
= GetConstraints(); 
1676             bool success 
= constr
->SatisfyConstraints(this, noChanges
); 
1679                 int x 
= constr
->left
.GetValue(); 
1680                 int y 
= constr
->top
.GetValue(); 
1689         // Lay out the children: breadth-first strategy. 
1703 wxSpacingSizer::wxSpacingSizer() 
1707 wxSpacingSizer::wxSpacingSizer(wxWindowBase 
*parent
) 
1712 wxSpacingSizer::wxSpacingSizer(wxWindowBase 
*parent
, wxRelationship rel
, wxWindowBase 
*other
, int spacing
) 
1714     Create(parent
, rel
, other
, spacing
); 
1717 bool wxSpacingSizer::Create(wxWindowBase 
*parent
) 
1719     wxSizer::Create(parent
); 
1723 bool wxSpacingSizer::Create(wxWindowBase 
*parent
, wxRelationship rel
, wxWindowBase 
*other
, int spacing
) 
1725     wxLayoutConstraints 
*c 
= new wxLayoutConstraints
; 
1727     wxSizer::Create(parent
); 
1732             c
->width
.Absolute    (spacing
); 
1733             c
->top
.SameAs        (other
, wxTop
); 
1734             c
->bottom
.SameAs    (other
, wxBottom
); 
1735             c
->right
.LeftOf        (other
); 
1738             c
->width
.Absolute    (spacing
); 
1739             c
->top
.SameAs        (other
, wxTop
); 
1740             c
->bottom
.SameAs    (other
, wxBottom
); 
1741             c
->left
.RightOf        (other
); 
1744             c
->height
.Absolute    (spacing
); 
1745             c
->left
.SameAs        (other
, wxLeft
); 
1746             c
->right
.SameAs        (other
, wxRight
); 
1747             c
->top
.Below        (other
); 
1750             c
->height
.Absolute    (spacing
); 
1751             c
->left
.SameAs        (other
, wxLeft
); 
1752             c
->right
.SameAs        (other
, wxRight
); 
1753             c
->bottom
.Above        (other
); 
1764 wxSpacingSizer::~wxSpacingSizer() 
1768 #endif // wxUSE_CONSTRAINTS