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