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