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