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