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