]> git.saurik.com Git - wxWidgets.git/blob - src/common/layout.cpp
Try to not include ctype functions for win32. Not really tested with
[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
1367 wxNode *node = GetChildren().First();
1368 while (node)
1369 {
1370 int x, y, width, height;
1371 wxWindow *win = (wxWindow *)node->Data();
1372 win->GetSizeConstraint(&width, &height);
1373 win->GetPositionConstraint(&x, &y);
1374 if ((x+width) > maxX)
1375 maxX = (x + width);
1376 if ((y+height) > maxY)
1377 maxY = (y + height);
1378
1379 node = node->Next();
1380 }
1381 SetSize(GetBorderX(), GetBorderY(), maxX, maxY);
1382
1383 // If this is the only sizer for the parent, size the parent to this sizer.
1384 if ( m_sizerParent && (m_sizerParent->GetSizer() == this) )
1385 m_sizerParent->SetClientSize(maxX + 2*GetBorderX(), maxY + 2*GetBorderY());
1386
1387 return TRUE;
1388 break;
1389 }
1390 case wxSizerNone:
1391 {
1392 wxLayoutConstraints *constr = GetConstraints();
1393 if (constr)
1394 {
1395 bool success = constr->SatisfyConstraints(this, noChanges);
1396 if (success)
1397 {
1398 int x = constr->left.GetValue();
1399 int y = constr->top.GetValue();
1400 int w = constr->width.GetValue();
1401 int h = constr->height.GetValue();
1402 SetSize(x, y, w, h);
1403 }
1404 return success;
1405 }
1406 else
1407 return TRUE;
1408 break;
1409 }
1410 }
1411 return TRUE;
1412
1413 }
1414
1415 bool wxSizer::LayoutPhase2(int *noChanges)
1416 {
1417 *noChanges = 0;
1418
1419 switch (sizerBehaviour)
1420 {
1421 case wxSizerExpand:
1422 {
1423 // Layout children
1424 DoPhase(1);
1425 DoPhase(2);
1426 return TRUE;
1427 }
1428 case wxSizerShrink:
1429 {
1430 wxLayoutConstraints *constr = GetConstraints();
1431 if (constr)
1432 {
1433 bool success = constr->SatisfyConstraints(this, noChanges);
1434 if (success)
1435 {
1436 int x = constr->left.GetValue();
1437 int y = constr->top.GetValue();
1438 Move(x, y);
1439 }
1440 return success;
1441 }
1442 break;
1443 }
1444 case wxSizerNone:
1445 {
1446 // Layout children
1447 DoPhase(1);
1448 DoPhase(2);
1449
1450 // Is this a dumb fix for lack of constraint evaluation?
1451 wxLayoutConstraints *constr = GetConstraints();
1452 if (constr)
1453 {
1454 bool success = constr->SatisfyConstraints(this, noChanges);
1455 if (success)
1456 {
1457 int x = constr->left.GetValue();
1458 int y = constr->top.GetValue();
1459 int w = constr->width.GetValue();
1460 int h = constr->height.GetValue();
1461 SetSize(x, y, w, h);
1462 }
1463 return success;
1464 }
1465 else
1466 return TRUE;
1467 }
1468 }
1469 return TRUE;
1470 }
1471
1472 /*
1473 * wxRowColSizer
1474 */
1475
1476 wxRowColSizer::wxRowColSizer()
1477 {
1478 rowOrCol = TRUE;
1479 rowOrColSize = 20;
1480 xSpacing = 2;
1481 ySpacing = 2;
1482 }
1483
1484 wxRowColSizer::wxRowColSizer(wxWindow *parent, bool rc, int n, wxSizerBehaviour behav)
1485 {
1486 Create(parent, rc, n, behav);
1487 }
1488
1489 bool wxRowColSizer::Create(wxWindow *parent, bool rc, int n, wxSizerBehaviour behav)
1490 {
1491 wxSizer::Create(parent, behav);
1492
1493 rowOrCol = rc;
1494 rowOrColSize = n;
1495 xSpacing = 2;
1496 ySpacing = 2;
1497
1498 return TRUE;
1499 }
1500
1501 wxRowColSizer::~wxRowColSizer()
1502 {
1503 }
1504
1505 bool wxRowColSizer::LayoutPhase1(int *noChanges)
1506 {
1507 *noChanges = 0;
1508 wxLayoutConstraints *constr = GetConstraints();
1509
1510 if (constr)
1511 {
1512 // Force the constraint to have as-is width and height
1513 // if we're in shrink-to-fit mode, because if left unconstrained,
1514 // SatisfyConstraints will fail. The shrink-to-fit option
1515 // essentially specifies the width and height as 'whatever I calculate'.
1516 if (sizerBehaviour == wxSizerShrink)
1517 {
1518 constr->width.AsIs();
1519 constr->height.AsIs();
1520 }
1521
1522 // Only evaluate the constraints FIRST if we're NOT
1523 // in shrink-to-fit mode, i.e. we want to size the rowcol
1524 // first, then lay the children out in the space we've calculated.
1525 if (sizerBehaviour != wxSizerShrink)
1526 {
1527 bool success = constr->SatisfyConstraints(this, noChanges);
1528 if (success)
1529 {
1530 int x = constr->left.GetValue();
1531 int y = constr->top.GetValue();
1532 int w = constr->width.GetValue();
1533 int h = constr->height.GetValue();
1534 SetSize(x, y, w, h);
1535 }
1536 else
1537 return FALSE;
1538
1539 // Continue to do the rest of the phase when the constraints have been
1540 // satisfied, i.e. we're on the last iteration of phase 1 and
1541 // can now do the actual rowcol laying out.
1542 }
1543 }
1544
1545 // If we ARE in shrink-to-fit mode, we must now
1546 // calculate the child sizes BEFORE laying out in rows or columns.
1547 if (sizerBehaviour == wxSizerShrink)
1548 {
1549 DoPhase(1);
1550 DoPhase(2);
1551
1552 // WILL THE WINDOW BE SIZED CORRECTLY AT THIS POINT?
1553 // CHECK CONSTRAINTS IF ANY...
1554 int noRows = 0;
1555 int noCols = 0;
1556 int currentX = borderX;
1557 int currentY = borderY;
1558 int maxX = currentX;
1559 int maxY = currentY;
1560
1561 wxNode *node = GetChildren().First();
1562 while (node)
1563 {
1564 wxWindow *win = (wxWindow *)node->Data();
1565 int childWidth, childHeight;
1566 if (win->GetConstraints() &&
1567 win->GetConstraints()->width.GetDone() &&
1568 win->GetConstraints()->height.GetDone())
1569 {
1570 childWidth = win->GetConstraints()->width.GetValue();
1571 childHeight = win->GetConstraints()->height.GetValue();
1572 }
1573 else
1574 win->GetSize(&childWidth, &childHeight);
1575
1576 win->MoveConstraint(currentX, currentY);
1577
1578 if ((currentX + childWidth) > maxX)
1579 maxX = (currentX + childWidth);
1580 if ((currentY + childHeight) > maxY)
1581 maxY = (currentY + childHeight);
1582
1583 if (rowOrCol)
1584 {
1585 currentX += childWidth + xSpacing;
1586 noCols ++;
1587
1588 // Reset to start of row
1589 if (noCols == rowOrColSize)
1590 {
1591 currentX = borderX;
1592 currentY += childHeight + ySpacing;
1593 noCols = 0;
1594 }
1595 }
1596 else
1597 {
1598 currentY += childHeight + ySpacing;
1599 noRows ++;
1600
1601 // Reset to start of col
1602 if (noRows == rowOrColSize)
1603 {
1604 currentY = borderY;
1605 currentX += childWidth + xSpacing;
1606 noRows = 0;
1607 }
1608 }
1609
1610 node = node->Next();
1611 }
1612 maxX += borderX;
1613 maxY += borderY;
1614
1615 SetSize(-1, -1, maxX, maxY);
1616 }
1617 return TRUE;
1618 }
1619
1620 bool wxRowColSizer::LayoutPhase2(int *noChanges)
1621 {
1622 *noChanges = 0;
1623
1624 // If shrink-to-fit, it's only at Phase 2 that we know the size of
1625 // the wxRowColSizer, and now we can evaluate the
1626 // constraints and pass result back up to parent.
1627 // This implements a depth-first strategy
1628 if (sizerBehaviour == wxSizerShrink)
1629 {
1630 wxLayoutConstraints *constr = GetConstraints();
1631 if (constr)
1632 {
1633 bool success = constr->SatisfyConstraints(this, noChanges);
1634 if (success)
1635 {
1636 int x = constr->left.GetValue();
1637 int y = constr->top.GetValue();
1638 Move(x, y);
1639 }
1640 return success;
1641 }
1642 else return TRUE;
1643 }
1644 else
1645 {
1646 // Lay out the children: breadth-first strategy.
1647 DoPhase(1);
1648 DoPhase(2);
1649
1650 // Space them
1651 }
1652 return TRUE;
1653 }
1654
1655
1656 /*
1657 * wxSpacingSizer
1658 */
1659
1660 wxSpacingSizer::wxSpacingSizer()
1661 {
1662 }
1663
1664 wxSpacingSizer::wxSpacingSizer(wxWindow *parent)
1665 {
1666 Create(parent);
1667 }
1668
1669 wxSpacingSizer::wxSpacingSizer(wxWindow *parent, wxRelationship rel, wxWindow *other, int spacing)
1670 {
1671 Create(parent, rel, other, spacing);
1672 }
1673
1674 bool wxSpacingSizer::Create(wxWindow *parent)
1675 {
1676 wxSizer::Create(parent);
1677 return TRUE;
1678 }
1679
1680 bool wxSpacingSizer::Create(wxWindow *parent, wxRelationship rel, wxWindow *other, int spacing)
1681 {
1682 wxLayoutConstraints *c = new wxLayoutConstraints;
1683
1684 wxSizer::Create(parent);
1685
1686 switch ( rel )
1687 {
1688 case wxLeftOf :
1689 c->width.Absolute (spacing);
1690 c->top.SameAs (other, wxTop);
1691 c->bottom.SameAs (other, wxBottom);
1692 c->right.LeftOf (other);
1693 break;
1694 case wxRightOf :
1695 c->width.Absolute (spacing);
1696 c->top.SameAs (other, wxTop);
1697 c->bottom.SameAs (other, wxBottom);
1698 c->left.RightOf (other);
1699 break;
1700 case wxBelow :
1701 c->height.Absolute (spacing);
1702 c->left.SameAs (other, wxLeft);
1703 c->right.SameAs (other, wxRight);
1704 c->top.Below (other);
1705 break;
1706 case wxAbove :
1707 c->height.Absolute (spacing);
1708 c->left.SameAs (other, wxLeft);
1709 c->right.SameAs (other, wxRight);
1710 c->bottom.Above (other);
1711 break;
1712
1713 default :
1714 break;
1715 }
1716 SetConstraints(c);
1717
1718 return TRUE;
1719 }
1720
1721 wxSpacingSizer::~wxSpacingSizer()
1722 {
1723 }
1724