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