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