]> git.saurik.com Git - wxWidgets.git/blame - src/common/layout.cpp
* wxDataStreams use wxUint now.
[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
47#if !USE_SHARED_LIBRARY
f03fc89f
VZ
48 IMPLEMENT_DYNAMIC_CLASS(wxIndividualLayoutConstraint, wxObject)
49 IMPLEMENT_DYNAMIC_CLASS(wxLayoutConstraints, wxObject)
50 IMPLEMENT_DYNAMIC_CLASS(wxSizer, wxObject)
51 IMPLEMENT_DYNAMIC_CLASS(wxRowColSizer, wxSizer)
52 IMPLEMENT_DYNAMIC_CLASS(wxSpacingSizer, wxSizer)
c801d85f
KB
53#endif
54
55/*
56TODO:
57 - Non shrink-to-fit row-col behaviour.
58 - Give justification styles, so can e.g. centre
59 the rows & cols, distribute the available space...
60 - Shrink-to-fit: should resize outer window (e.g. dialog box)
61 if directly associated with this kind of window.
62 - How to deal with a rowcol that stretches in one direction
63 but shrinks-to-fit in other. E.g. a horizontal toolbar: the width
64 stretches to fit the frame, but the height is constant
65 or wraps around contents. The algorithm currently assumes
66 both dimensions have the same behaviour. Could assume a constant
67 height (absolute value).
68 - rowcol where each row or column is aligned (length of
69 largest element determines spacing)
70 - Groupbox sizer
71 - Analyze aesthetic dialog boxes and implement using sizers.
72 - What reuseable components can we provide? E.g. Ok/Cancel/Help
73 group of buttons.
74 - use wxStaticItems for aesthetic dialogs.
75
76*/
77
78// Find margin sizes if a sizer, or zero otherwise
f03fc89f 79int wxSizerMarginX(wxWindowBase *win)
c801d85f 80{
f03fc89f
VZ
81 if ( win->IsKindOf(CLASSINFO(wxSizer)) )
82 {
83 wxSizer *sizer = (wxSizer *)win;
84 return sizer->GetBorderX();
85 }
86 else
87 return 0;
c801d85f
KB
88}
89
f03fc89f 90int wxSizerMarginY(wxWindowBase *win)
c801d85f 91{
f03fc89f
VZ
92 if ( win->IsKindOf(CLASSINFO(wxSizer)) )
93 {
94 wxSizer *sizer = (wxSizer *)win;
95 return sizer->GetBorderY();
96 }
97 else
98 return 0;
c801d85f
KB
99}
100
101
a3622daa 102wxIndividualLayoutConstraint::wxIndividualLayoutConstraint()
c801d85f 103{
f03fc89f
VZ
104 myEdge = wxTop;
105 relationship = wxUnconstrained;
106 margin = 0;
107 value = 0;
108 percent = 0;
109 otherEdge = wxTop;
110 done = FALSE;
111 otherWin = (wxWindowBase *) NULL;
c801d85f
KB
112}
113
a3622daa 114wxIndividualLayoutConstraint::~wxIndividualLayoutConstraint()
c801d85f
KB
115{
116}
117
f03fc89f 118void wxIndividualLayoutConstraint::Set(wxRelationship rel, wxWindowBase *otherW, wxEdge otherE, int val, int marg)
c801d85f 119{
f03fc89f
VZ
120 relationship = rel;
121 otherWin = otherW;
122 otherEdge = otherE;
123 value = val;
124 margin = marg;
c801d85f
KB
125}
126
f03fc89f
VZ
127void wxIndividualLayoutConstraint::LeftOf(wxWindowBase *sibling, int marg)
128{
129 Set(wxLeftOf, sibling, wxLeft, 0, marg);
130}
c801d85f 131
f03fc89f
VZ
132void wxIndividualLayoutConstraint::RightOf(wxWindowBase *sibling, int marg)
133{
134 Set(wxRightOf, sibling, wxRight, 0, marg);
135}
c801d85f 136
f03fc89f
VZ
137void wxIndividualLayoutConstraint::Above(wxWindowBase *sibling, int marg)
138{
139 Set(wxAbove, sibling, wxTop, 0, marg);
140}
c801d85f 141
f03fc89f
VZ
142void wxIndividualLayoutConstraint::Below(wxWindowBase *sibling, int marg)
143{
144 Set(wxBelow, sibling, wxBottom, 0, marg);
145}
c801d85f
KB
146
147//
148// 'Same edge' alignment
149//
f03fc89f
VZ
150void wxIndividualLayoutConstraint::SameAs(wxWindowBase *otherW, wxEdge edge, int marg)
151{
152 Set(wxPercentOf, otherW, edge, 0, marg);
153 percent = 100;
154}
c801d85f
KB
155
156// The edge is a percentage of the other window's edge
f03fc89f
VZ
157void wxIndividualLayoutConstraint::PercentOf(wxWindowBase *otherW, wxEdge wh, int per)
158{
159 otherWin = otherW;
160 relationship = wxPercentOf;
161 percent = per;
162
163 otherEdge = wh;
c801d85f
KB
164}
165
166//
167// Edge has absolute value
168//
169void wxIndividualLayoutConstraint::Absolute(int val)
f03fc89f
VZ
170{
171 value = val; relationship = wxAbsolute;
172}
c801d85f
KB
173
174// Reset constraint if it mentions otherWin
f03fc89f 175bool wxIndividualLayoutConstraint::ResetIfWin(wxWindowBase *otherW)
c801d85f 176{
f03fc89f
VZ
177 if (otherW == otherWin)
178 {
179 myEdge = wxTop;
180 relationship = wxAsIs;
181 margin = 0;
182 value = 0;
183 percent = 0;
184 otherEdge = wxTop;
185 otherWin = (wxWindowBase *) NULL;
186 return TRUE;
187 }
188 else
189 return FALSE;
c801d85f
KB
190}
191
192// Try to satisfy constraint
f03fc89f 193bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constraints, wxWindowBase *win)
c801d85f 194{
f03fc89f 195 if (relationship == wxAbsolute)
c801d85f 196 {
f03fc89f
VZ
197 done = TRUE;
198 return TRUE;
c801d85f 199 }
f03fc89f
VZ
200
201 switch (myEdge)
c801d85f 202 {
f03fc89f 203 case wxLeft:
c801d85f 204 {
f03fc89f
VZ
205 switch (relationship)
206 {
207 case wxLeftOf:
208 {
209 // We can know this edge if: otherWin is win's
210 // parent, or otherWin has a satisfied constraint,
211 // or otherWin has no constraint.
212 int edgePos = GetEdge(otherEdge, win, otherWin);
213 if (edgePos != -1)
214 {
215 value = edgePos - margin;
216 done = TRUE;
217 return TRUE;
218 }
219 else
220 return FALSE;
221 }
222 case wxRightOf:
223 {
224 int edgePos = GetEdge(otherEdge, win, otherWin);
225 if (edgePos != -1)
226 {
227 value = edgePos + margin;
228 done = TRUE;
229 return TRUE;
230 }
231 else
232 return FALSE;
233 }
234 case wxPercentOf:
235 {
236 int edgePos = GetEdge(otherEdge, win, otherWin);
237 if (edgePos != -1)
238 {
239 value = (int)(edgePos*(((float)percent)*0.01) + margin);
240 done = TRUE;
241 return TRUE;
242 }
243 else
244 return FALSE;
245 }
246 case wxUnconstrained:
247 {
248 // We know the left-hand edge position if we know
249 // the right-hand edge and we know the width; OR if
250 // we know the centre and the width.
251 if (constraints->right.GetDone() && constraints->width.GetDone())
252 {
253 value = (constraints->right.GetValue() - constraints->width.GetValue() + margin);
254 done = TRUE;
255 return TRUE;
256 }
257 else if (constraints->centreX.GetDone() && constraints->width.GetDone())
258 {
259 value = (int)(constraints->centreX.GetValue() - (constraints->width.GetValue()/2) + margin);
260 done = TRUE;
261 return TRUE;
262 }
263 else
264 return FALSE;
265 }
266 case wxAsIs:
267 {
268 int y;
269 win->GetPosition(&value, &y);
270 done = TRUE;
271 return TRUE;
272 }
273 default:
274 break;
275 }
276 break;
c801d85f 277 }
f03fc89f 278 case wxRight:
c801d85f 279 {
f03fc89f
VZ
280 switch (relationship)
281 {
282 case wxLeftOf:
283 {
284 // We can know this edge if: otherWin is win's
285 // parent, or otherWin has a satisfied constraint,
286 // or otherWin has no constraint.
287 int edgePos = GetEdge(otherEdge, win, otherWin);
288 if (edgePos != -1)
289 {
290 value = edgePos - margin;
291 done = TRUE;
292 return TRUE;
293 }
294 else
295 return FALSE;
296 }
297 case wxRightOf:
298 {
299 int edgePos = GetEdge(otherEdge, win, otherWin);
300 if (edgePos != -1)
301 {
302 value = edgePos + margin;
303 done = TRUE;
304 return TRUE;
305 }
306 else
307 return FALSE;
308 }
309 case wxPercentOf:
310 {
311 int edgePos = GetEdge(otherEdge, win, otherWin);
312 if (edgePos != -1)
313 {
314 value = (int)(edgePos*(((float)percent)*0.01) - margin);
315 done = TRUE;
316 return TRUE;
317 }
318 else
319 return FALSE;
320 }
321 case wxUnconstrained:
322 {
323 // We know the right-hand edge position if we know the
324 // left-hand edge and we know the width, OR if we know the
325 // centre edge and the width.
326 if (constraints->left.GetDone() && constraints->width.GetDone())
327 {
328 value = (constraints->left.GetValue() + constraints->width.GetValue() - margin);
329 done = TRUE;
330 return TRUE;
331 }
332 else if (constraints->centreX.GetDone() && constraints->width.GetDone())
333 {
334 value = (int)(constraints->centreX.GetValue() + (constraints->width.GetValue()/2) - margin);
335 done = TRUE;
336 return TRUE;
337 }
338 else
339 return FALSE;
340 }
341 case wxAsIs:
342 {
343 int x, y;
344 int w, h;
345 win->GetSize(&w, &h);
346 win->GetPosition(&x, &y);
347 value = x + w;
348 done = TRUE;
349 return TRUE;
350 }
351 default:
352 break;
353 }
354 break;
c801d85f 355 }
f03fc89f 356 case wxTop:
c801d85f 357 {
f03fc89f
VZ
358 switch (relationship)
359 {
360 case wxAbove:
361 {
362 // We can know this edge if: otherWin is win's
363 // parent, or otherWin has a satisfied constraint,
364 // or otherWin has no constraint.
365 int edgePos = GetEdge(otherEdge, win, otherWin);
366 if (edgePos != -1)
367 {
368 value = edgePos - margin;
369 done = TRUE;
370 return TRUE;
371 }
372 else
373 return FALSE;
374 }
375 case wxBelow:
376 {
377 int edgePos = GetEdge(otherEdge, win, otherWin);
378 if (edgePos != -1)
379 {
380 value = edgePos + margin;
381 done = TRUE;
382 return TRUE;
383 }
384 else
385 return FALSE;
386 }
387 case wxPercentOf:
388 {
389 int edgePos = GetEdge(otherEdge, win, otherWin);
390 if (edgePos != -1)
391 {
392 value = (int)(edgePos*(((float)percent)*0.01) + margin);
393 done = TRUE;
394 return TRUE;
395 }
396 else
397 return FALSE;
398 }
399 case wxUnconstrained:
400 {
401 // We know the top edge position if we know the bottom edge
402 // and we know the height; OR if we know the centre edge and
403 // the height.
404 if (constraints->bottom.GetDone() && constraints->height.GetDone())
405 {
406 value = (constraints->bottom.GetValue() - constraints->height.GetValue() + margin);
407 done = TRUE;
408 return TRUE;
409 }
410 else if (constraints->centreY.GetDone() && constraints->height.GetDone())
411 {
412 value = (constraints->centreY.GetValue() - (constraints->height.GetValue()/2) + margin);
413 done = TRUE;
414 return TRUE;
415 }
416 else
417 return FALSE;
418 }
419 case wxAsIs:
420 {
421 int x;
422 win->GetPosition(&x, &value);
423 done = TRUE;
424 return TRUE;
425 }
426 default:
427 break;
428 }
429 break;
c801d85f 430 }
f03fc89f 431 case wxBottom:
c801d85f 432 {
f03fc89f
VZ
433 switch (relationship)
434 {
435 case wxAbove:
436 {
437 // We can know this edge if: otherWin is win's parent,
438 // or otherWin has a satisfied constraint, or
439 // otherWin has no constraint.
440 int edgePos = GetEdge(otherEdge, win, otherWin);
441 if (edgePos != -1)
442 {
443 value = edgePos + margin;
444 done = TRUE;
445 return TRUE;
446 }
447 else
448 return FALSE;
449 }
450 case wxBelow:
451 {
452 int edgePos = GetEdge(otherEdge, win, otherWin);
453 if (edgePos != -1)
454 {
455 value = edgePos - margin;
456 done = TRUE;
457 return TRUE;
458 }
459 else
460 return FALSE;
461 }
462 case wxPercentOf:
463 {
464 int edgePos = GetEdge(otherEdge, win, otherWin);
465 if (edgePos != -1)
466 {
467 value = (int)(edgePos*(((float)percent)*0.01) - margin);
468 done = TRUE;
469 return TRUE;
470 }
471 else
472 return FALSE;
473 }
474 case wxUnconstrained:
475 {
476 // We know the bottom edge position if we know the top edge
477 // and we know the height; OR if we know the centre edge and
478 // the height.
479 if (constraints->top.GetDone() && constraints->height.GetDone())
480 {
481 value = (constraints->top.GetValue() + constraints->height.GetValue() - margin);
482 done = TRUE;
483 return TRUE;
484 }
485 else if (constraints->centreY.GetDone() && constraints->height.GetDone())
486 {
487 value = (constraints->centreY.GetValue() + (constraints->height.GetValue()/2) - margin);
488 done = TRUE;
489 return TRUE;
490 }
491 else
492 return FALSE;
493 }
494 case wxAsIs:
495 {
496 int x, y;
497 int w, h;
498 win->GetSize(&w, &h);
499 win->GetPosition(&x, &y);
500 value = h + y;
501 done = TRUE;
502 return TRUE;
503 }
504 default:
505 break;
506 }
507 break;
c801d85f 508 }
f03fc89f 509 case wxCentreX:
c801d85f 510 {
f03fc89f
VZ
511 switch (relationship)
512 {
513 case wxLeftOf:
514 {
515 // We can know this edge if: otherWin is win's parent, or
516 // otherWin has a satisfied constraint, or otherWin has no
517 // constraint.
518 int edgePos = GetEdge(otherEdge, win, otherWin);
519 if (edgePos != -1)
520 {
521 value = edgePos - margin;
522 done = TRUE;
523 return TRUE;
524 }
525 else
526 return FALSE;
527 }
528 case wxRightOf:
529 {
530 int edgePos = GetEdge(otherEdge, win, otherWin);
531 if (edgePos != -1)
532 {
533 value = edgePos + margin;
534 done = TRUE;
535 return TRUE;
536 }
537 else
538 return FALSE;
539 }
540 case wxPercentOf:
541 {
542 int edgePos = GetEdge(otherEdge, win, otherWin);
543 if (edgePos != -1)
544 {
545 value = (int)(edgePos*(((float)percent)*0.01) + margin);
546 done = TRUE;
547 return TRUE;
548 }
549 else
550 return FALSE;
551 }
552 case wxUnconstrained:
553 {
554 // We know the centre position if we know
555 // the left-hand edge and we know the width, OR
556 // the right-hand edge and the width
557 if (constraints->left.GetDone() && constraints->width.GetDone())
558 {
559 value = (int)(constraints->left.GetValue() + (constraints->width.GetValue()/2) + margin);
560 done = TRUE;
561 return TRUE;
562 }
563 else if (constraints->right.GetDone() && constraints->width.GetDone())
564 {
565 value = (int)(constraints->left.GetValue() - (constraints->width.GetValue()/2) + margin);
566 done = TRUE;
567 return TRUE;
568 }
569 else
570 return FALSE;
571 }
572 default:
573 break;
574 }
575 break;
c801d85f 576 }
f03fc89f 577 case wxCentreY:
c801d85f 578 {
f03fc89f
VZ
579 switch (relationship)
580 {
581 case wxAbove:
582 {
583 // We can know this edge if: otherWin is win's parent,
584 // or otherWin has a satisfied constraint, or otherWin
585 // has no constraint.
586 int edgePos = GetEdge(otherEdge, win, otherWin);
587 if (edgePos != -1)
588 {
589 value = edgePos - margin;
590 done = TRUE;
591 return TRUE;
592 }
593 else
594 return FALSE;
595 }
596 case wxBelow:
597 {
598 int edgePos = GetEdge(otherEdge, win, otherWin);
599 if (edgePos != -1)
600 {
601 value = edgePos + margin;
602 done = TRUE;
603 return TRUE;
604 }
605 else
606 return FALSE;
607 }
608 case wxPercentOf:
609 {
610 int edgePos = GetEdge(otherEdge, win, otherWin);
611 if (edgePos != -1)
612 {
613 value = (int)(edgePos*(((float)percent)*0.01) + margin);
614 done = TRUE;
615 return TRUE;
616 }
617 else
618 return FALSE;
619 }
620 case wxUnconstrained:
621 {
622 // We know the centre position if we know
623 // the top edge and we know the height, OR
624 // the bottom edge and the height.
625 if (constraints->bottom.GetDone() && constraints->height.GetDone())
626 {
627 value = (int)(constraints->bottom.GetValue() - (constraints->height.GetValue()/2) + margin);
628 done = TRUE;
629 return TRUE;
630 }
631 else if (constraints->top.GetDone() && constraints->height.GetDone())
632 {
633 value = (int)(constraints->top.GetValue() + (constraints->height.GetValue()/2) + margin);
634 done = TRUE;
635 return TRUE;
636 }
637 else
638 return FALSE;
639 }
640 default:
641 break;
642 }
643 break;
c801d85f 644 }
f03fc89f 645 case wxWidth:
c801d85f 646 {
f03fc89f
VZ
647 switch (relationship)
648 {
649 case wxPercentOf:
650 {
651 int edgePos = GetEdge(otherEdge, win, otherWin);
652 if (edgePos != -1)
653 {
654 value = (int)(edgePos*(((float)percent)*0.01));
655 done = TRUE;
656 return TRUE;
657 }
658 else
659 return FALSE;
660 }
661 case wxAsIs:
662 {
663 if (win)
664 {
665 int h;
666 win->GetSize(&value, &h);
667 done = TRUE;
668 return TRUE;
669 }
670 else return FALSE;
671 }
672 case wxUnconstrained:
673 {
674 // We know the width if we know the left edge and the right edge, OR
675 // if we know the left edge and the centre, OR
676 // if we know the right edge and the centre
677 if (constraints->left.GetDone() && constraints->right.GetDone())
678 {
679 value = constraints->right.GetValue() - constraints->left.GetValue();
680 done = TRUE;
681 return TRUE;
682 }
683 else if (constraints->centreX.GetDone() && constraints->left.GetDone())
684 {
685 value = (int)(2*(constraints->centreX.GetValue() - constraints->left.GetValue()));
686 done = TRUE;
687 return TRUE;
688 }
689 else if (constraints->centreX.GetDone() && constraints->right.GetDone())
690 {
691 value = (int)(2*(constraints->right.GetValue() - constraints->centreX.GetValue()));
692 done = TRUE;
693 return TRUE;
694 }
695 else
696 return FALSE;
697 }
698 default:
699 break;
700 }
701 break;
c801d85f 702 }
f03fc89f 703 case wxHeight:
c801d85f 704 {
f03fc89f
VZ
705 switch (relationship)
706 {
707 case wxPercentOf:
708 {
709 int edgePos = GetEdge(otherEdge, win, otherWin);
710 if (edgePos != -1)
711 {
712 value = (int)(edgePos*(((float)percent)*0.01));
713 done = TRUE;
714 return TRUE;
715 }
716 else
717 return FALSE;
718 }
719 case wxAsIs:
720 {
721 if (win)
722 {
723 int w;
724 win->GetSize(&w, &value);
725 done = TRUE;
726 return TRUE;
727 }
728 else return FALSE;
729 }
730 case wxUnconstrained:
731 {
732 // We know the height if we know the top edge and the bottom edge, OR
733 // if we know the top edge and the centre, OR
734 // if we know the bottom edge and the centre
735 if (constraints->top.GetDone() && constraints->bottom.GetDone())
736 {
737 value = constraints->bottom.GetValue() - constraints->top.GetValue();
738 done = TRUE;
739 return TRUE;
740 }
741 else if (constraints->top.GetDone() && constraints->centreY.GetDone())
742 {
743 value = (int)(2*(constraints->centreY.GetValue() - constraints->top.GetValue()));
744 done = TRUE;
745 return TRUE;
746 }
747 else if (constraints->bottom.GetDone() && constraints->centreY.GetDone())
748 {
749 value = (int)(2*(constraints->bottom.GetValue() - constraints->centreY.GetValue()));
750 done = TRUE;
751 return TRUE;
752 }
753 else
754 return FALSE;
755 }
756 default:
757 break;
758 }
759 break;
c801d85f
KB
760 }
761 default:
f03fc89f 762 break;
c801d85f 763 }
f03fc89f 764 return FALSE;
c801d85f
KB
765}
766
f03fc89f 767// Get the value of this edge or dimension, or if this is not determinable, -1.
a3622daa 768int wxIndividualLayoutConstraint::GetEdge(wxEdge which,
f03fc89f
VZ
769 wxWindowBase *thisWin,
770 wxWindowBase *other) const
c801d85f 771{
f03fc89f
VZ
772 // If the edge or dimension belongs to the parent, then we know the
773 // dimension is obtainable immediately. E.g. a wxExpandSizer may contain a
774 // button (but the button's true parent is a panel, not the sizer)
775 if (other->GetChildren().Find(thisWin))
c801d85f 776 {
f03fc89f
VZ
777 switch (which)
778 {
779 case wxLeft:
780 {
781 return wxSizerMarginX(other);
782 }
783 case wxTop:
784 {
785 return wxSizerMarginY(other);
786 }
787 case wxRight:
788 {
789 int w, h;
790 other->GetClientSizeConstraint(&w, &h);
791 return w - wxSizerMarginX(other);
792 }
793 case wxBottom:
794 {
795 int w, h;
796 other->GetClientSizeConstraint(&w, &h);
797 return h - wxSizerMarginY(other);
798 }
799 case wxWidth:
800 {
801 int w, h;
802 other->GetClientSizeConstraint(&w, &h);
803 return w - 2*wxSizerMarginX(other);
804 }
805 case wxHeight:
806 {
807 int w, h;
808 other->GetClientSizeConstraint(&w, &h);
809 return h - 2*wxSizerMarginY(other);
810 }
811 case wxCentreX:
812 case wxCentreY:
813 {
814 int w, h;
815 other->GetClientSizeConstraint(&w, &h);
816 if (which == wxCentreX)
817 return (int)(w/2);
818 else
819 return (int)(h/2);
820 }
821 default:
822 return -1;
823 }
c801d85f 824 }
f03fc89f 825 switch (which)
c801d85f 826 {
f03fc89f
VZ
827 case wxLeft:
828 {
829 wxLayoutConstraints *constr = other->GetConstraints();
830 // If no constraints, it means the window is not dependent
831 // on anything, and therefore we know its value immediately
832 if (constr)
833 {
834 if (constr->left.GetDone())
835 return constr->left.GetValue();
836 else
837 return -1;
838 }
839 else
840 {
841 int x, y;
842 other->GetPosition(&x, &y);
843 return x;
844 }
845 }
846 case wxTop:
847 {
848 wxLayoutConstraints *constr = other->GetConstraints();
849 // If no constraints, it means the window is not dependent
850 // on anything, and therefore we know its value immediately
851 if (constr)
852 {
853 if (constr->top.GetDone())
854 return constr->top.GetValue();
855 else
856 return -1;
857 }
858 else
859 {
860 int x, y;
861 other->GetPosition(&x, &y);
862 return y;
863 }
864 }
865 case wxRight:
866 {
867 wxLayoutConstraints *constr = other->GetConstraints();
868 // If no constraints, it means the window is not dependent
869 // on anything, and therefore we know its value immediately
870 if (constr)
871 {
872 if (constr->right.GetDone())
873 return constr->right.GetValue();
874 else
875 return -1;
876 }
877 else
878 {
879 int x, y, w, h;
880 other->GetPosition(&x, &y);
881 other->GetSize(&w, &h);
882 return (int)(x + w);
883 }
884 }
885 case wxBottom:
886 {
887 wxLayoutConstraints *constr = other->GetConstraints();
888 // If no constraints, it means the window is not dependent
889 // on anything, and therefore we know its value immediately
890 if (constr)
891 {
892 if (constr->bottom.GetDone())
893 return constr->bottom.GetValue();
894 else
895 return -1;
896 }
897 else
898 {
899 int x, y, w, h;
900 other->GetPosition(&x, &y);
901 other->GetSize(&w, &h);
902 return (int)(y + h);
903 }
904 }
905 case wxWidth:
906 {
907 wxLayoutConstraints *constr = other->GetConstraints();
908 // If no constraints, it means the window is not dependent
909 // on anything, and therefore we know its value immediately
910 if (constr)
911 {
912 if (constr->width.GetDone())
913 return constr->width.GetValue();
914 else
915 return -1;
916 }
917 else
918 {
919 int w, h;
920 other->GetSize(&w, &h);
921 return w;
922 }
923 }
924 case wxHeight:
925 {
926 wxLayoutConstraints *constr = other->GetConstraints();
927 // If no constraints, it means the window is not dependent
928 // on anything, and therefore we know its value immediately
929 if (constr)
930 {
931 if (constr->height.GetDone())
932 return constr->height.GetValue();
933 else
934 return -1;
935 }
936 else
937 {
938 int w, h;
939 other->GetSize(&w, &h);
940 return h;
941 }
942 }
943 case wxCentreX:
944 {
945 wxLayoutConstraints *constr = other->GetConstraints();
946 // If no constraints, it means the window is not dependent
947 // on anything, and therefore we know its value immediately
948 if (constr)
949 {
950 if (constr->centreX.GetDone())
951 return constr->centreX.GetValue();
952 else
953 return -1;
954 }
955 else
956 {
957 int x, y, w, h;
958 other->GetPosition(&x, &y);
959 other->GetSize(&w, &h);
960 return (int)(x + (w/2));
961 }
962 }
963 case wxCentreY:
964 {
965 wxLayoutConstraints *constr = other->GetConstraints();
966 // If no constraints, it means the window is not dependent
967 // on anything, and therefore we know its value immediately
968 if (constr)
969 {
970 if (constr->centreY.GetDone())
971 return constr->centreY.GetValue();
972 else
973 return -1;
974 }
975 else
976 {
977 int x, y, w, h;
978 other->GetPosition(&x, &y);
979 other->GetSize(&w, &h);
980 return (int)(y + (h/2));
981 }
982 }
983 default:
984 break;
c801d85f 985 }
f03fc89f 986 return -1;
c801d85f
KB
987}
988
a3622daa 989wxLayoutConstraints::wxLayoutConstraints()
c801d85f 990{
f03fc89f
VZ
991 left.SetEdge(wxLeft);
992 top.SetEdge(wxTop);
993 right.SetEdge(wxRight);
994 bottom.SetEdge(wxBottom);
995 centreX.SetEdge(wxCentreX);
996 centreY.SetEdge(wxCentreY);
997 width.SetEdge(wxWidth);
998 height.SetEdge(wxHeight);
c801d85f
KB
999}
1000
a3622daa 1001wxLayoutConstraints::~wxLayoutConstraints()
c801d85f
KB
1002{
1003}
1004
f03fc89f 1005bool wxLayoutConstraints::SatisfyConstraints(wxWindowBase *win, int *nChanges)
c801d85f 1006{
f03fc89f
VZ
1007 int noChanges = 0;
1008
1009 bool done = width.GetDone();
1010 bool newDone = (done ? TRUE : width.SatisfyConstraint(this, win));
1011 if (newDone != done)
1012 noChanges ++;
1013
1014 done = height.GetDone();
1015 newDone = (done ? TRUE : height.SatisfyConstraint(this, win));
1016 if (newDone != done)
1017 noChanges ++;
1018
1019 done = left.GetDone();
1020 newDone = (done ? TRUE : left.SatisfyConstraint(this, win));
1021 if (newDone != done)
1022 noChanges ++;
1023
1024 done = top.GetDone();
1025 newDone = (done ? TRUE : top.SatisfyConstraint(this, win));
1026 if (newDone != done)
1027 noChanges ++;
1028
1029 done = right.GetDone();
1030 newDone = (done ? TRUE : right.SatisfyConstraint(this, win));
1031 if (newDone != done)
1032 noChanges ++;
1033
1034 done = bottom.GetDone();
1035 newDone = (done ? TRUE : bottom.SatisfyConstraint(this, win));
1036 if (newDone != done)
1037 noChanges ++;
1038
1039 done = centreX.GetDone();
1040 newDone = (done ? TRUE : centreX.SatisfyConstraint(this, win));
1041 if (newDone != done)
1042 noChanges ++;
1043
1044 done = centreY.GetDone();
1045 newDone = (done ? TRUE : centreY.SatisfyConstraint(this, win));
1046 if (newDone != done)
1047 noChanges ++;
1048
1049 *nChanges = noChanges;
1050
1051 return AreSatisfied();
c801d85f
KB
1052}
1053
1054/*
1055 * Main constrained layout algorithm. Look at all the child
1056 * windows, and their constraints (if any).
1057 * The idea is to keep iterating through the constraints
1058 * until all left, right, bottom and top edges, and widths and heights,
1059 * are known (or no change occurs and we've failed to resolve all
1060 * constraints).
1061 *
1062 * If the user has not specified a dimension or edge, it will be
1063 * be calculated from the other known values. E.g. If we know
1064 * the right hand edge and the left hand edge, we now know the width.
1065 * The snag here is that this means we must specify absolute dimensions
1066 * twice (in constructor and in constraint), if we wish to use the
1067 * constraint notation to just set the position, for example.
1068 * Otherwise, if we only set ONE edge and no dimension, it would never
1069 * find the other edge.
1070 *
1071 * Algorithm:
1072
1073 Mark all constraints as not done.
1074
1075 iterations = 0;
1076 until no change or iterations >= max iterations
1077 For each child:
1078 {
1079 Calculate all constraints
1080 }
1081 iterations ++;
1082
1083 For each child
1084 Set each calculated position and size
1085
1086 */
1087
f03fc89f
VZ
1088#if WXWIN_COMPATIBILITY
1089bool wxOldDoLayout(wxWindowBase *win)
c801d85f
KB
1090{
1091 // Make sure this isn't called recursively from below
1092 static wxList doneSoFar;
1093
1094 if (doneSoFar.Member(win))
1095 return TRUE;
1096
1097 doneSoFar.Append(win);
1098
c0ed460c 1099 wxNode *node = win->GetChildren().First();
c801d85f
KB
1100 while (node)
1101 {
f03fc89f 1102 wxWindowBase *child = (wxWindowBase *)node->Data();
c801d85f
KB
1103 wxLayoutConstraints *constr = child->GetConstraints();
1104 if (constr)
1105 {
1106 constr->left.SetDone(FALSE);
1107 constr->top.SetDone(FALSE);
1108 constr->right.SetDone(FALSE);
1109 constr->bottom.SetDone(FALSE);
1110 constr->width.SetDone(FALSE);
1111 constr->height.SetDone(FALSE);
1112 constr->centreX.SetDone(FALSE);
1113 constr->centreY.SetDone(FALSE);
1114 }
1115 node = node->Next();
1116 }
1117 int noIterations = 0;
1118 int maxIterations = 500;
1119 int noChanges = 1;
1120
1121 while ((noChanges > 0) && (noIterations < maxIterations))
1122 {
1123 noChanges = 0;
c0ed460c 1124 wxNode *node = win->GetChildren().First();
c801d85f
KB
1125 while (node)
1126 {
f03fc89f 1127 wxWindowBase *child = (wxWindowBase *)node->Data();
c801d85f
KB
1128 wxLayoutConstraints *constr = child->GetConstraints();
1129 if (constr)
1130 {
1131 int tempNoChanges = 0;
a3622daa 1132 (void)constr->SatisfyConstraints(child, &tempNoChanges);
c801d85f
KB
1133 noChanges += tempNoChanges;
1134 }
1135 node = node->Next();
1136 }
1137 noIterations ++;
1138 }
1139/*
1140 // Would be nice to have a test here to see _which_ constraint(s)
1141 // failed, so we can print a specific diagnostic message.
1142 if (noFailures > 0)
1143 {
f03fc89f 1144 wxDebugMsg(_("wxWindowBase::Layout() failed.\n"));
c801d85f
KB
1145 }
1146*/
1147 // Now set the sizes and positions of the children, and
1148 // recursively call Layout().
c0ed460c 1149 node = win->GetChildren().First();
c801d85f
KB
1150 while (node)
1151 {
f03fc89f 1152 wxWindowBase *child = (wxWindowBase *)node->Data();
c801d85f
KB
1153 wxLayoutConstraints *constr = child->GetConstraints();
1154 if (constr && constr->left.GetDone() && constr->right.GetDone() &&
1155 constr->width.GetDone() && constr->height.GetDone())
1156 {
1157 int x = constr->left.GetValue();
1158 int y = constr->top.GetValue();
1159 int w = constr->width.GetValue();
1160 int h = constr->height.GetValue();
1161
1162 // If we don't want to resize this window, just move it...
1163 if ((constr->width.GetRelationship() != wxAsIs) ||
1164 (constr->height.GetRelationship() != wxAsIs))
1165 {
1166 // _Should_ call Layout() recursively.
1167 child->SetSize(x, y, w, h);
1168 }
1169 else
1170 {
1171 child->Move(x, y);
1172 }
1173 }
1174 else
1175 child->Layout();
1176 node = node->Next();
1177 }
1178 doneSoFar.DeleteObject(win);
1179
1180 return TRUE;
1181}
f03fc89f 1182#endif // WXWIN_COMPATIBILITY
c801d85f 1183
a3622daa 1184wxSizer::wxSizer()
c801d85f 1185{
f03fc89f
VZ
1186 sizerBehaviour = wxSizerNone;
1187 borderX = 2;
1188 borderY = 2;
1189 sizerX = 0;
1190 sizerY = 0;
1191 sizerWidth = 0;
1192 sizerHeight = 0;
c801d85f
KB
1193}
1194
f03fc89f 1195wxSizer::wxSizer(wxWindowBase *parent, wxSizerBehaviour behav)
c801d85f 1196{
f03fc89f 1197 Create(parent, behav);
c801d85f
KB
1198}
1199
f03fc89f 1200bool wxSizer::Create(wxWindowBase *parent, wxSizerBehaviour behav)
c801d85f 1201{
f03fc89f
VZ
1202 sizerBehaviour = behav;
1203 borderX = 2;
1204 borderY = 2;
1205 m_sizerParent = parent;
1206 sizerX = 0;
1207 sizerY = 0;
1208 sizerWidth = 0;
1209 sizerHeight = 0;
1210
1211 // A normal window can have just one top-level sizer
1212 // associated with it.
1213 if (!parent->IsKindOf(CLASSINFO(wxSizer)))
c801d85f 1214 {
f03fc89f 1215 parent->SetSizer(this);
c801d85f 1216 }
f03fc89f
VZ
1217 else
1218 ((wxSizer *)parent)->AddSizerChild(this);
1219
1220 switch (sizerBehaviour)
c801d85f 1221 {
f03fc89f
VZ
1222 case wxSizerExpand:
1223 {
1224 // Defines a set of constraints
1225 // to expand the sizer to fit the parent window
1226 wxLayoutConstraints *c = new wxLayoutConstraints;
1227
1228 c->left.SameAs(parent, wxLeft, 0);
1229 c->top.SameAs(parent, wxTop, 0);
1230 c->right.SameAs(parent, wxRight, 0);
1231 c->bottom.SameAs(parent, wxBottom, 0);
1232
1233 SetConstraints(c);
1234 break;
1235 }
1236 case wxSizerShrink:
1237 case wxSizerNone:
1238 default:
1239 {
1240 }
c801d85f 1241 }
f03fc89f 1242 return TRUE;
c801d85f
KB
1243}
1244
a3622daa 1245wxSizer::~wxSizer()
c801d85f 1246{
f03fc89f
VZ
1247 // Remove all children without deleting them,
1248 // or ~wxbWindow will delete proper windows _twice_
1249 wxNode *node = GetChildren().First();
1250 while (node)
c801d85f 1251 {
f03fc89f
VZ
1252 wxNode *next = node->Next();
1253 wxWindowBase *win = (wxWindowBase *)node->Data();
1254 if (!win->IsKindOf(CLASSINFO(wxSizer)))
1255 {
1256 delete node;
1257 win->SetSizerParent((wxWindowBase *) NULL);
1258 }
1259 else
1260 {
1261 RemoveSizerChild(win);
1262 delete win;
1263 }
1264 node = next;
c801d85f 1265 }
c801d85f 1266
f03fc89f
VZ
1267 if (m_sizerParent) // && !m_sizerParent->IsKindOf(CLASSINFO(wxSizer)))
1268 {
1269 m_sizerParent->SetSizer((wxSizer *) NULL);
1270 m_sizerParent = (wxWindowBase *) NULL;
1271 }
c801d85f
KB
1272
1273}
1274
1275void wxSizer::SetBorder(int x, int y)
1276{
f03fc89f
VZ
1277 borderX = x;
1278 borderY = y;
1279 /* No: the margin is for inside, not outside (expansion)
1280
1281 if ( GetConstraints() )
1282 {
1283 GetConstraints()->left.SetMargin(x);
1284 GetConstraints()->right.SetMargin(x);
1285 GetConstraints()->top.SetMargin(y);
1286 GetConstraints()->bottom.SetMargin(y);
1287 }
1288 */
c801d85f
KB
1289
1290}
1291
f03fc89f 1292void wxSizer::AddSizerChild(wxWindowBase *child)
c801d85f 1293{
f03fc89f
VZ
1294 child->SetSizerParent(this);
1295 GetChildren().Append(child);
c801d85f 1296
f03fc89f
VZ
1297 // Add some constraints for the purpose of storing
1298 // the relative position of the window/sizer
1299 // during layout calculations.
1300 if (!child->GetConstraints())
1301 {
1302 wxLayoutConstraints *c = new wxLayoutConstraints;
1303 c->left.AsIs();
1304 c->top.AsIs();
1305 c->width.AsIs();
1306 c->height.AsIs();
1307 int w, h;
1308 child->GetSize(&w, &h);
1309 c->width.SetValue(w);
1310 c->height.SetValue(h);
1311
1312 child->SetConstraints(c);
1313 }
c801d85f
KB
1314}
1315
f03fc89f 1316void wxSizer::RemoveSizerChild(wxWindowBase *child)
c801d85f 1317{
f03fc89f 1318 GetChildren().DeleteObject(child);
c801d85f
KB
1319}
1320
bfc6fde4 1321void wxSizer::DoSetSize(int x, int y, int w, int h, int WXUNUSED(flags))
c801d85f 1322{
f03fc89f
VZ
1323 wxLayoutConstraints *constr = GetConstraints();
1324 if (x != -1)
1325 {
1326 sizerX = x;
1327 if (constr)
1328 constr->left.SetValue(x);
1329 }
1330 if (y != -1)
1331 {
1332 sizerY = y;
1333 if (constr)
1334 constr->top.SetValue(y);
1335 }
1336 if (w != -1)
1337 {
1338 sizerWidth = w;
1339 if (constr)
1340 constr->width.SetValue(w);
1341 }
1342 if (h != -1)
1343 {
1344 sizerHeight = h;
1345 if (constr)
1346 constr->height.SetValue(h);
1347 }
c801d85f
KB
1348}
1349
32ac755d 1350void wxSizer::DoGetSize(int *w, int *h) const
c801d85f 1351{
f03fc89f
VZ
1352 *w = sizerWidth;
1353 *h = sizerHeight;
c801d85f
KB
1354}
1355
32ac755d 1356void wxSizer::DoGetPosition(int *x, int *y) const
c801d85f 1357{
f03fc89f
VZ
1358 *x = sizerX;
1359 *y = sizerY;
c801d85f
KB
1360}
1361
1362bool wxSizer::LayoutPhase1(int *noChanges)
1363{
f03fc89f
VZ
1364 *noChanges = 0;
1365 switch (sizerBehaviour)
c801d85f 1366 {
f03fc89f
VZ
1367 case wxSizerExpand:
1368 {
1369 if (!m_sizerParent)
1370 {
1371 wxMessageBox(_("wxExpandSizer has no parent!"), _("Sizer error"), wxOK);
1372 return TRUE;
1373 }
1374
1375 // Set the size to fill the parent client area
1376 int pw, ph;
1377 m_sizerParent->GetClientSize(&pw, &ph);
1378 SetSize(GetBorderX(), GetBorderY(), pw - 2*GetBorderX(), ph - 2*GetBorderY());
1379 wxLayoutConstraints *constr = GetConstraints();
1380
1381 // Fill in the constraints
1382 if (constr)
1383 {
1384 constr->left.SetValue(0); constr->left.SetDone(TRUE);
1385 constr->top.SetValue(0); constr->right.SetDone(TRUE);
1386 constr->width.SetValue(pw); constr->width.SetDone(TRUE);
1387 constr->height.SetValue(ph); constr->height.SetDone(TRUE);
1388 }
1389
1390 return TRUE;
1391 break;
1392 }
1393 case wxSizerShrink:
1394 {
1395 wxLayoutConstraints *constr = GetConstraints();
1396
1397 if (constr)
1398 {
1399 // Force the constraint to have as-is width and height
1400 // if we're in shrink-to-fit mode, because if left unconstrained,
1401 // SatisfyConstraints will fail. The shrink-to-fit option
1402 // essentially specifies the width and height as 'whatever I calculate'.
1403 constr->width.AsIs();
1404 constr->height.AsIs();
1405 }
1406 DoPhase(1);
1407 DoPhase(2);
1408 // Find the bounding box and set own size
1409 int maxX = 0;
1410 int maxY = 0;
1411
1412 wxNode *node = GetChildren().First();
1413 while (node)
1414 {
1415 int x, y, width, height;
1416 wxWindowBase *win = (wxWindowBase *)node->Data();
1417 win->GetSizeConstraint(&width, &height);
1418 win->GetPositionConstraint(&x, &y);
1419 if ((x+width) > maxX)
1420 maxX = (x + width);
1421 if ((y+height) > maxY)
1422 maxY = (y + height);
1423
1424 node = node->Next();
1425 }
1426 SetSize(GetBorderX(), GetBorderY(), maxX, maxY);
1427
1428 // If this is the only sizer for the parent, size the parent to this sizer.
1429 if ( m_sizerParent && (m_sizerParent->GetSizer() == this) )
1430 m_sizerParent->SetClientSize(maxX + 2*GetBorderX(), maxY + 2*GetBorderY());
1431
1432 return TRUE;
1433 break;
1434 }
1435 case wxSizerNone:
1436 {
1437 wxLayoutConstraints *constr = GetConstraints();
1438 if (constr)
1439 {
1440 bool success = constr->SatisfyConstraints(this, noChanges);
1441 if (success)
1442 {
1443 int x = constr->left.GetValue();
1444 int y = constr->top.GetValue();
1445 int w = constr->width.GetValue();
1446 int h = constr->height.GetValue();
1447 SetSize(x, y, w, h);
1448 }
1449 return success;
1450 }
1451 else
1452 return TRUE;
1453 break;
1454 }
c801d85f 1455 }
f03fc89f 1456 return TRUE;
c801d85f
KB
1457
1458}
1459
1460bool wxSizer::LayoutPhase2(int *noChanges)
1461{
f03fc89f 1462 *noChanges = 0;
c801d85f 1463
f03fc89f 1464 switch (sizerBehaviour)
c801d85f 1465 {
f03fc89f
VZ
1466 case wxSizerExpand:
1467 {
1468 // Layout children
1469 DoPhase(1);
1470 DoPhase(2);
1471 return TRUE;
1472 }
1473 case wxSizerShrink:
1474 {
1475 wxLayoutConstraints *constr = GetConstraints();
1476 if (constr)
1477 {
1478 bool success = constr->SatisfyConstraints(this, noChanges);
1479 if (success)
1480 {
1481 int x = constr->left.GetValue();
1482 int y = constr->top.GetValue();
1483 Move(x, y);
1484 }
1485 return success;
1486 }
1487 break;
1488 }
1489 case wxSizerNone:
1490 {
1491 // Layout children
1492 DoPhase(1);
1493 DoPhase(2);
1494
1495 // Is this a dumb fix for lack of constraint evaluation?
1496 wxLayoutConstraints *constr = GetConstraints();
1497 if (constr)
1498 {
1499 bool success = constr->SatisfyConstraints(this, noChanges);
1500 if (success)
1501 {
1502 int x = constr->left.GetValue();
1503 int y = constr->top.GetValue();
1504 int w = constr->width.GetValue();
1505 int h = constr->height.GetValue();
1506 SetSize(x, y, w, h);
1507 }
1508 return success;
1509 }
1510 else
1511 return TRUE;
1512 }
c801d85f 1513 }
f03fc89f 1514 return TRUE;
c801d85f
KB
1515}
1516
1517/*
1518 * wxRowColSizer
1519 */
f03fc89f 1520
a3622daa 1521wxRowColSizer::wxRowColSizer()
c801d85f 1522{
f03fc89f
VZ
1523 rowOrCol = TRUE;
1524 rowOrColSize = 20;
1525 xSpacing = 2;
1526 ySpacing = 2;
c801d85f
KB
1527}
1528
f03fc89f 1529wxRowColSizer::wxRowColSizer(wxWindowBase *parent, bool rc, int n, wxSizerBehaviour behav)
c801d85f 1530{
f03fc89f 1531 Create(parent, rc, n, behav);
c801d85f
KB
1532}
1533
f03fc89f 1534bool wxRowColSizer::Create(wxWindowBase *parent, bool rc, int n, wxSizerBehaviour behav)
c801d85f 1535{
f03fc89f 1536 wxSizer::Create(parent, behav);
c801d85f 1537
f03fc89f
VZ
1538 rowOrCol = rc;
1539 rowOrColSize = n;
1540 xSpacing = 2;
1541 ySpacing = 2;
1542
1543 return TRUE;
c801d85f
KB
1544}
1545
a3622daa 1546wxRowColSizer::~wxRowColSizer()
c801d85f
KB
1547{
1548}
1549
c801d85f
KB
1550bool wxRowColSizer::LayoutPhase1(int *noChanges)
1551{
f03fc89f
VZ
1552 *noChanges = 0;
1553 wxLayoutConstraints *constr = GetConstraints();
c801d85f 1554
f03fc89f 1555 if (constr)
c801d85f 1556 {
f03fc89f
VZ
1557 // Force the constraint to have as-is width and height
1558 // if we're in shrink-to-fit mode, because if left unconstrained,
1559 // SatisfyConstraints will fail. The shrink-to-fit option
1560 // essentially specifies the width and height as 'whatever I calculate'.
1561 if (sizerBehaviour == wxSizerShrink)
1562 {
1563 constr->width.AsIs();
1564 constr->height.AsIs();
1565 }
c801d85f 1566
f03fc89f
VZ
1567 // Only evaluate the constraints FIRST if we're NOT
1568 // in shrink-to-fit mode, i.e. we want to size the rowcol
1569 // first, then lay the children out in the space we've calculated.
1570 if (sizerBehaviour != wxSizerShrink)
1571 {
1572 bool success = constr->SatisfyConstraints(this, noChanges);
1573 if (success)
1574 {
1575 int x = constr->left.GetValue();
1576 int y = constr->top.GetValue();
1577 int w = constr->width.GetValue();
1578 int h = constr->height.GetValue();
1579 SetSize(x, y, w, h);
1580 }
1581 else
1582 return FALSE;
1583
1584 // Continue to do the rest of the phase when the constraints have been
1585 // satisfied, i.e. we're on the last iteration of phase 1 and
1586 // can now do the actual rowcol laying out.
1587 }
c801d85f 1588 }
227e5e99 1589
f03fc89f
VZ
1590 // If we ARE in shrink-to-fit mode, we must now
1591 // calculate the child sizes BEFORE laying out in rows or columns.
1592 if (sizerBehaviour == wxSizerShrink)
c801d85f 1593 {
f03fc89f
VZ
1594 DoPhase(1);
1595 DoPhase(2);
1596
1597 // WILL THE WINDOW BE SIZED CORRECTLY AT THIS POINT?
1598 // CHECK CONSTRAINTS IF ANY...
1599 int noRows = 0;
1600 int noCols = 0;
1601 int currentX = borderX;
1602 int currentY = borderY;
1603 int maxX = currentX;
1604 int maxY = currentY;
1605
1606 wxNode *node = GetChildren().First();
1607 while (node)
c801d85f 1608 {
f03fc89f
VZ
1609 wxWindowBase *win = (wxWindowBase *)node->Data();
1610 int childWidth, childHeight;
1611 if (win->GetConstraints() &&
1612 win->GetConstraints()->width.GetDone() &&
1613 win->GetConstraints()->height.GetDone())
1614 {
1615 childWidth = win->GetConstraints()->width.GetValue();
1616 childHeight = win->GetConstraints()->height.GetValue();
1617 }
1618 else
1619 win->GetSize(&childWidth, &childHeight);
1620
1621 win->MoveConstraint(currentX, currentY);
1622
1623 if ((currentX + childWidth) > maxX)
1624 maxX = (currentX + childWidth);
1625 if ((currentY + childHeight) > maxY)
1626 maxY = (currentY + childHeight);
1627
1628 if (rowOrCol)
1629 {
1630 currentX += childWidth + xSpacing;
1631 noCols ++;
1632
1633 // Reset to start of row
1634 if (noCols == rowOrColSize)
1635 {
1636 currentX = borderX;
1637 currentY += childHeight + ySpacing;
1638 noCols = 0;
1639 }
1640 }
1641 else
1642 {
1643 currentY += childHeight + ySpacing;
1644 noRows ++;
1645
1646 // Reset to start of col
1647 if (noRows == rowOrColSize)
1648 {
1649 currentY = borderY;
1650 currentX += childWidth + xSpacing;
1651 noRows = 0;
1652 }
1653 }
1654
1655 node = node->Next();
c801d85f 1656 }
f03fc89f
VZ
1657 maxX += borderX;
1658 maxY += borderY;
c801d85f 1659
f03fc89f 1660 SetSize(-1, -1, maxX, maxY);
c801d85f 1661 }
f03fc89f 1662 return TRUE;
c801d85f
KB
1663}
1664
1665bool wxRowColSizer::LayoutPhase2(int *noChanges)
1666{
f03fc89f
VZ
1667 *noChanges = 0;
1668
1669 // If shrink-to-fit, it's only at Phase 2 that we know the size of
1670 // the wxRowColSizer, and now we can evaluate the
1671 // constraints and pass result back up to parent.
1672 // This implements a depth-first strategy
1673 if (sizerBehaviour == wxSizerShrink)
c801d85f 1674 {
f03fc89f
VZ
1675 wxLayoutConstraints *constr = GetConstraints();
1676 if (constr)
1677 {
1678 bool success = constr->SatisfyConstraints(this, noChanges);
1679 if (success)
1680 {
1681 int x = constr->left.GetValue();
1682 int y = constr->top.GetValue();
1683 Move(x, y);
1684 }
1685 return success;
1686 }
1687 else return TRUE;
c801d85f 1688 }
f03fc89f
VZ
1689 else
1690 {
1691 // Lay out the children: breadth-first strategy.
1692 DoPhase(1);
1693 DoPhase(2);
c801d85f 1694
f03fc89f
VZ
1695 // Space them
1696 }
1697 return TRUE;
c801d85f
KB
1698}
1699
1700
1701/*
1702 * wxSpacingSizer
1703 */
f03fc89f 1704
a3622daa 1705wxSpacingSizer::wxSpacingSizer()
c801d85f
KB
1706{
1707}
1708
f03fc89f 1709wxSpacingSizer::wxSpacingSizer(wxWindowBase *parent)
c801d85f 1710{
f03fc89f 1711 Create(parent);
c801d85f
KB
1712}
1713
f03fc89f 1714wxSpacingSizer::wxSpacingSizer(wxWindowBase *parent, wxRelationship rel, wxWindowBase *other, int spacing)
c801d85f 1715{
f03fc89f 1716 Create(parent, rel, other, spacing);
c801d85f
KB
1717}
1718
f03fc89f 1719bool wxSpacingSizer::Create(wxWindowBase *parent)
c801d85f 1720{
f03fc89f
VZ
1721 wxSizer::Create(parent);
1722 return TRUE;
c801d85f
KB
1723}
1724
f03fc89f 1725bool wxSpacingSizer::Create(wxWindowBase *parent, wxRelationship rel, wxWindowBase *other, int spacing)
c801d85f 1726{
f03fc89f 1727 wxLayoutConstraints *c = new wxLayoutConstraints;
c801d85f 1728
f03fc89f 1729 wxSizer::Create(parent);
c801d85f 1730
f03fc89f
VZ
1731 switch ( rel )
1732 {
1733 case wxLeftOf :
1734 c->width.Absolute (spacing);
1735 c->top.SameAs (other, wxTop);
1736 c->bottom.SameAs (other, wxBottom);
1737 c->right.LeftOf (other);
1738 break;
1739 case wxRightOf :
1740 c->width.Absolute (spacing);
1741 c->top.SameAs (other, wxTop);
1742 c->bottom.SameAs (other, wxBottom);
1743 c->left.RightOf (other);
1744 break;
1745 case wxBelow :
1746 c->height.Absolute (spacing);
1747 c->left.SameAs (other, wxLeft);
1748 c->right.SameAs (other, wxRight);
1749 c->top.Below (other);
1750 break;
1751 case wxAbove :
1752 c->height.Absolute (spacing);
1753 c->left.SameAs (other, wxLeft);
1754 c->right.SameAs (other, wxRight);
1755 c->bottom.Above (other);
1756 break;
1757
1758 default :
1759 break;
1760 }
1761 SetConstraints(c);
c801d85f 1762
f03fc89f 1763 return TRUE;
c801d85f
KB
1764}
1765
a3622daa 1766wxSpacingSizer::~wxSpacingSizer()
c801d85f
KB
1767{
1768}
1769
d427503c 1770#endif // wxUSE_CONSTRAINTS