]> git.saurik.com Git - wxWidgets.git/blob - src/common/layout.cpp
MIME classes with docs (not yet added to the makefiles)
[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::SetSize(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 void wxRowColSizer::SetSize(int x, int y, int w, int h, int flags)
1504 {
1505 wxSizer::SetSize(x, y, w, h, flags);
1506 }
1507
1508 bool wxRowColSizer::LayoutPhase1(int *noChanges)
1509 {
1510 *noChanges = 0;
1511 wxLayoutConstraints *constr = GetConstraints();
1512
1513 if (constr)
1514 {
1515 // Force the constraint to have as-is width and height
1516 // if we're in shrink-to-fit mode, because if left unconstrained,
1517 // SatisfyConstraints will fail. The shrink-to-fit option
1518 // essentially specifies the width and height as 'whatever I calculate'.
1519 if (sizerBehaviour == wxSizerShrink)
1520 {
1521 constr->width.AsIs();
1522 constr->height.AsIs();
1523 }
1524
1525 // Only evaluate the constraints FIRST if we're NOT
1526 // in shrink-to-fit mode, i.e. we want to size the rowcol
1527 // first, then lay the children out in the space we've calculated.
1528 if (sizerBehaviour != wxSizerShrink)
1529 {
1530 bool success = constr->SatisfyConstraints(this, noChanges);
1531 if (success)
1532 {
1533 int x = constr->left.GetValue();
1534 int y = constr->top.GetValue();
1535 int w = constr->width.GetValue();
1536 int h = constr->height.GetValue();
1537 SetSize(x, y, w, h);
1538 }
1539 else
1540 return FALSE;
1541
1542 // Continue to do the rest of the phase when the constraints have been
1543 // satisfied, i.e. we're on the last iteration of phase 1 and
1544 // can now do the actual rowcol laying out.
1545 }
1546 }
1547
1548 // If we ARE in shrink-to-fit mode, we must now
1549 // calculate the child sizes BEFORE laying out in rows or columns.
1550 if (sizerBehaviour == wxSizerShrink)
1551 {
1552 DoPhase(1);
1553 DoPhase(2);
1554
1555 // WILL THE WINDOW BE SIZED CORRECTLY AT THIS POINT?
1556 // CHECK CONSTRAINTS IF ANY...
1557 int noRows = 0;
1558 int noCols = 0;
1559 int currentX = borderX;
1560 int currentY = borderY;
1561 int maxX = currentX;
1562 int maxY = currentY;
1563
1564 wxNode *node = GetChildren().First();
1565 while (node)
1566 {
1567 wxWindow *win = (wxWindow *)node->Data();
1568 int childWidth, childHeight;
1569 if (win->GetConstraints() &&
1570 win->GetConstraints()->width.GetDone() &&
1571 win->GetConstraints()->height.GetDone())
1572 {
1573 childWidth = win->GetConstraints()->width.GetValue();
1574 childHeight = win->GetConstraints()->height.GetValue();
1575 }
1576 else
1577 win->GetSize(&childWidth, &childHeight);
1578
1579 win->MoveConstraint(currentX, currentY);
1580
1581 if ((currentX + childWidth) > maxX)
1582 maxX = (currentX + childWidth);
1583 if ((currentY + childHeight) > maxY)
1584 maxY = (currentY + childHeight);
1585
1586 if (rowOrCol)
1587 {
1588 currentX += childWidth + xSpacing;
1589 noCols ++;
1590
1591 // Reset to start of row
1592 if (noCols == rowOrColSize)
1593 {
1594 currentX = borderX;
1595 currentY += childHeight + ySpacing;
1596 noCols = 0;
1597 }
1598 }
1599 else
1600 {
1601 currentY += childHeight + ySpacing;
1602 noRows ++;
1603
1604 // Reset to start of col
1605 if (noRows == rowOrColSize)
1606 {
1607 currentY = borderY;
1608 currentX += childWidth + xSpacing;
1609 noRows = 0;
1610 }
1611 }
1612
1613 node = node->Next();
1614 }
1615 maxX += borderX;
1616 maxY += borderY;
1617
1618 SetSize(-1, -1, maxX, maxY);
1619 }
1620 return TRUE;
1621 }
1622
1623 bool wxRowColSizer::LayoutPhase2(int *noChanges)
1624 {
1625 *noChanges = 0;
1626
1627 // If shrink-to-fit, it's only at Phase 2 that we know the size of
1628 // the wxRowColSizer, and now we can evaluate the
1629 // constraints and pass result back up to parent.
1630 // This implements a depth-first strategy
1631 if (sizerBehaviour == wxSizerShrink)
1632 {
1633 wxLayoutConstraints *constr = GetConstraints();
1634 if (constr)
1635 {
1636 bool success = constr->SatisfyConstraints(this, noChanges);
1637 if (success)
1638 {
1639 int x = constr->left.GetValue();
1640 int y = constr->top.GetValue();
1641 Move(x, y);
1642 }
1643 return success;
1644 }
1645 else return TRUE;
1646 }
1647 else
1648 {
1649 // Lay out the children: breadth-first strategy.
1650 DoPhase(1);
1651 DoPhase(2);
1652
1653 // Space them
1654 }
1655 return TRUE;
1656 }
1657
1658
1659 /*
1660 * wxSpacingSizer
1661 */
1662
1663 wxSpacingSizer::wxSpacingSizer()
1664 {
1665 }
1666
1667 wxSpacingSizer::wxSpacingSizer(wxWindow *parent)
1668 {
1669 Create(parent);
1670 }
1671
1672 wxSpacingSizer::wxSpacingSizer(wxWindow *parent, wxRelationship rel, wxWindow *other, int spacing)
1673 {
1674 Create(parent, rel, other, spacing);
1675 }
1676
1677 bool wxSpacingSizer::Create(wxWindow *parent)
1678 {
1679 wxSizer::Create(parent);
1680 return TRUE;
1681 }
1682
1683 bool wxSpacingSizer::Create(wxWindow *parent, wxRelationship rel, wxWindow *other, int spacing)
1684 {
1685 wxLayoutConstraints *c = new wxLayoutConstraints;
1686
1687 wxSizer::Create(parent);
1688
1689 switch ( rel )
1690 {
1691 case wxLeftOf :
1692 c->width.Absolute (spacing);
1693 c->top.SameAs (other, wxTop);
1694 c->bottom.SameAs (other, wxBottom);
1695 c->right.LeftOf (other);
1696 break;
1697 case wxRightOf :
1698 c->width.Absolute (spacing);
1699 c->top.SameAs (other, wxTop);
1700 c->bottom.SameAs (other, wxBottom);
1701 c->left.RightOf (other);
1702 break;
1703 case wxBelow :
1704 c->height.Absolute (spacing);
1705 c->left.SameAs (other, wxLeft);
1706 c->right.SameAs (other, wxRight);
1707 c->top.Below (other);
1708 break;
1709 case wxAbove :
1710 c->height.Absolute (spacing);
1711 c->left.SameAs (other, wxLeft);
1712 c->right.SameAs (other, wxRight);
1713 c->bottom.Above (other);
1714 break;
1715
1716 default :
1717 break;
1718 }
1719 SetConstraints(c);
1720
1721 return TRUE;
1722 }
1723
1724 wxSpacingSizer::~wxSpacingSizer()
1725 {
1726 }
1727