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