]> git.saurik.com Git - wxWidgets.git/blob - src/common/layout.cpp
Applied patch #423927, (Min size for stretch parts of wxBoxSizer)
[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