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