]> git.saurik.com Git - wxWidgets.git/blob - src/common/layout.cpp
now compiles with USE_XPM_IN_MSW on
[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(void)
92 {
93 myEdge = wxTop; relationship = wxUnconstrained; margin = 0; value = 0; percent = 0; otherEdge = wxTop;
94 done = FALSE; otherWin = NULL;
95 }
96
97 wxIndividualLayoutConstraint::~wxIndividualLayoutConstraint(void)
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, wxWindow *thisWin, wxWindow *other)
726 {
727 // If the edge or dimension belongs to the parent, then we
728 // know the dimension is obtainable immediately.
729 // E.g. a wxExpandSizer may contain a button (but the button's
730 // true parent is a panel, not the sizer)
731 if (other->GetChildren()->Member(thisWin))
732 {
733 switch (which)
734 {
735 case wxLeft:
736 {
737 return wxSizerMarginX(other);
738 }
739 case wxTop:
740 {
741 return wxSizerMarginY(other);
742 }
743 case wxRight:
744 {
745 int w, h;
746 other->GetClientSizeConstraint(&w, &h);
747 return w - wxSizerMarginX(other);
748 }
749 case wxBottom:
750 {
751 int w, h;
752 other->GetClientSizeConstraint(&w, &h);
753 return h - wxSizerMarginY(other);
754 }
755 case wxWidth:
756 {
757 int w, h;
758 other->GetClientSizeConstraint(&w, &h);
759 return w - 2*wxSizerMarginX(other);
760 }
761 case wxHeight:
762 {
763 int w, h;
764 other->GetClientSizeConstraint(&w, &h);
765 return h - 2*wxSizerMarginY(other);
766 }
767 case wxCentreX:
768 case wxCentreY:
769 {
770 int w, h;
771 other->GetClientSizeConstraint(&w, &h);
772 if (which == wxCentreX)
773 return (int)(w/2);
774 else
775 return (int)(h/2);
776 }
777 default:
778 return -1;
779 }
780 }
781 switch (which)
782 {
783 case wxLeft:
784 {
785 wxLayoutConstraints *constr = other->GetConstraints();
786 // If no constraints, it means the window is not dependent
787 // on anything, and therefore we know its value immediately
788 if (constr)
789 {
790 if (constr->left.GetDone())
791 return constr->left.GetValue();
792 else
793 return -1;
794 }
795 else
796 {
797 int x, y;
798 other->GetPosition(&x, &y);
799 return x;
800 }
801 }
802 case wxTop:
803 {
804 wxLayoutConstraints *constr = other->GetConstraints();
805 // If no constraints, it means the window is not dependent
806 // on anything, and therefore we know its value immediately
807 if (constr)
808 {
809 if (constr->top.GetDone())
810 return constr->top.GetValue();
811 else
812 return -1;
813 }
814 else
815 {
816 int x, y;
817 other->GetPosition(&x, &y);
818 return y;
819 }
820 }
821 case wxRight:
822 {
823 wxLayoutConstraints *constr = other->GetConstraints();
824 // If no constraints, it means the window is not dependent
825 // on anything, and therefore we know its value immediately
826 if (constr)
827 {
828 if (constr->right.GetDone())
829 return constr->right.GetValue();
830 else
831 return -1;
832 }
833 else
834 {
835 int x, y, w, h;
836 other->GetPosition(&x, &y);
837 other->GetSize(&w, &h);
838 return (int)(x + w);
839 }
840 }
841 case wxBottom:
842 {
843 wxLayoutConstraints *constr = other->GetConstraints();
844 // If no constraints, it means the window is not dependent
845 // on anything, and therefore we know its value immediately
846 if (constr)
847 {
848 if (constr->bottom.GetDone())
849 return constr->bottom.GetValue();
850 else
851 return -1;
852 }
853 else
854 {
855 int x, y, w, h;
856 other->GetPosition(&x, &y);
857 other->GetSize(&w, &h);
858 return (int)(y + h);
859 }
860 }
861 case wxWidth:
862 {
863 wxLayoutConstraints *constr = other->GetConstraints();
864 // If no constraints, it means the window is not dependent
865 // on anything, and therefore we know its value immediately
866 if (constr)
867 {
868 if (constr->width.GetDone())
869 return constr->width.GetValue();
870 else
871 return -1;
872 }
873 else
874 {
875 int w, h;
876 other->GetSize(&w, &h);
877 return w;
878 }
879 }
880 case wxHeight:
881 {
882 wxLayoutConstraints *constr = other->GetConstraints();
883 // If no constraints, it means the window is not dependent
884 // on anything, and therefore we know its value immediately
885 if (constr)
886 {
887 if (constr->height.GetDone())
888 return constr->height.GetValue();
889 else
890 return -1;
891 }
892 else
893 {
894 int w, h;
895 other->GetSize(&w, &h);
896 return h;
897 }
898 }
899 case wxCentreX:
900 {
901 wxLayoutConstraints *constr = other->GetConstraints();
902 // If no constraints, it means the window is not dependent
903 // on anything, and therefore we know its value immediately
904 if (constr)
905 {
906 if (constr->centreX.GetDone())
907 return constr->centreX.GetValue();
908 else
909 return -1;
910 }
911 else
912 {
913 int x, y, w, h;
914 other->GetPosition(&x, &y);
915 other->GetSize(&w, &h);
916 return (int)(x + (w/2));
917 }
918 }
919 case wxCentreY:
920 {
921 wxLayoutConstraints *constr = other->GetConstraints();
922 // If no constraints, it means the window is not dependent
923 // on anything, and therefore we know its value immediately
924 if (constr)
925 {
926 if (constr->centreY.GetDone())
927 return constr->centreY.GetValue();
928 else
929 return -1;
930 }
931 else
932 {
933 int x, y, w, h;
934 other->GetPosition(&x, &y);
935 other->GetSize(&w, &h);
936 return (int)(y + (h/2));
937 }
938 }
939 default:
940 break;
941 }
942 return -1;
943 }
944
945 wxLayoutConstraints::wxLayoutConstraints(void)
946 {
947 left.SetEdge(wxLeft);
948 top.SetEdge(wxTop);
949 right.SetEdge(wxRight);
950 bottom.SetEdge(wxBottom);
951 centreX.SetEdge(wxCentreX);
952 centreY.SetEdge(wxCentreY);
953 width.SetEdge(wxWidth);
954 height.SetEdge(wxHeight);
955 }
956
957 wxLayoutConstraints::~wxLayoutConstraints(void)
958 {
959 }
960
961 bool wxLayoutConstraints::SatisfyConstraints(wxWindow *win, int *nChanges)
962 {
963 int noChanges = 0;
964
965 bool done = width.GetDone();
966 bool newDone = (done ? TRUE : width.SatisfyConstraint(this, win));
967 if (newDone != done)
968 noChanges ++;
969
970 done = height.GetDone();
971 newDone = (done ? TRUE : height.SatisfyConstraint(this, win));
972 if (newDone != done)
973 noChanges ++;
974
975 done = left.GetDone();
976 newDone = (done ? TRUE : left.SatisfyConstraint(this, win));
977 if (newDone != done)
978 noChanges ++;
979
980 done = top.GetDone();
981 newDone = (done ? TRUE : top.SatisfyConstraint(this, win));
982 if (newDone != done)
983 noChanges ++;
984
985 done = right.GetDone();
986 newDone = (done ? TRUE : right.SatisfyConstraint(this, win));
987 if (newDone != done)
988 noChanges ++;
989
990 done = bottom.GetDone();
991 newDone = (done ? TRUE : bottom.SatisfyConstraint(this, win));
992 if (newDone != done)
993 noChanges ++;
994
995 done = centreX.GetDone();
996 newDone = (done ? TRUE : centreX.SatisfyConstraint(this, win));
997 if (newDone != done)
998 noChanges ++;
999
1000 done = centreY.GetDone();
1001 newDone = (done ? TRUE : centreY.SatisfyConstraint(this, win));
1002 if (newDone != done)
1003 noChanges ++;
1004
1005 *nChanges = noChanges;
1006
1007 return (left.GetDone() && top.GetDone() && right.GetDone() && bottom.GetDone() &&
1008 centreX.GetDone() && centreY.GetDone());
1009 }
1010
1011 /*
1012 * Main constrained layout algorithm. Look at all the child
1013 * windows, and their constraints (if any).
1014 * The idea is to keep iterating through the constraints
1015 * until all left, right, bottom and top edges, and widths and heights,
1016 * are known (or no change occurs and we've failed to resolve all
1017 * constraints).
1018 *
1019 * If the user has not specified a dimension or edge, it will be
1020 * be calculated from the other known values. E.g. If we know
1021 * the right hand edge and the left hand edge, we now know the width.
1022 * The snag here is that this means we must specify absolute dimensions
1023 * twice (in constructor and in constraint), if we wish to use the
1024 * constraint notation to just set the position, for example.
1025 * Otherwise, if we only set ONE edge and no dimension, it would never
1026 * find the other edge.
1027 *
1028 * Algorithm:
1029
1030 Mark all constraints as not done.
1031
1032 iterations = 0;
1033 until no change or iterations >= max iterations
1034 For each child:
1035 {
1036 Calculate all constraints
1037 }
1038 iterations ++;
1039
1040 For each child
1041 Set each calculated position and size
1042
1043 */
1044
1045 bool wxOldDoLayout(wxWindow *win)
1046 {
1047 // Make sure this isn't called recursively from below
1048 static wxList doneSoFar;
1049
1050 if (doneSoFar.Member(win))
1051 return TRUE;
1052
1053 doneSoFar.Append(win);
1054
1055 wxNode *node = win->GetChildren()->First();
1056 while (node)
1057 {
1058 wxWindow *child = (wxWindow *)node->Data();
1059 wxLayoutConstraints *constr = child->GetConstraints();
1060 if (constr)
1061 {
1062 constr->left.SetDone(FALSE);
1063 constr->top.SetDone(FALSE);
1064 constr->right.SetDone(FALSE);
1065 constr->bottom.SetDone(FALSE);
1066 constr->width.SetDone(FALSE);
1067 constr->height.SetDone(FALSE);
1068 constr->centreX.SetDone(FALSE);
1069 constr->centreY.SetDone(FALSE);
1070 }
1071 node = node->Next();
1072 }
1073 int noIterations = 0;
1074 int maxIterations = 500;
1075 int noChanges = 1;
1076
1077 while ((noChanges > 0) && (noIterations < maxIterations))
1078 {
1079 noChanges = 0;
1080 wxNode *node = win->GetChildren()->First();
1081 while (node)
1082 {
1083 wxWindow *child = (wxWindow *)node->Data();
1084 wxLayoutConstraints *constr = child->GetConstraints();
1085 if (constr)
1086 {
1087 int tempNoChanges = 0;
1088 (void) constr->SatisfyConstraints(child, &tempNoChanges);
1089 noChanges += tempNoChanges;
1090 }
1091 node = node->Next();
1092 }
1093 noIterations ++;
1094 }
1095 /*
1096 // Would be nice to have a test here to see _which_ constraint(s)
1097 // failed, so we can print a specific diagnostic message.
1098 if (noFailures > 0)
1099 {
1100 wxDebugMsg("wxWindow::Layout() failed.\n");
1101 }
1102 */
1103 // Now set the sizes and positions of the children, and
1104 // recursively call Layout().
1105 node = win->GetChildren()->First();
1106 while (node)
1107 {
1108 wxWindow *child = (wxWindow *)node->Data();
1109 wxLayoutConstraints *constr = child->GetConstraints();
1110 if (constr && constr->left.GetDone() && constr->right.GetDone() &&
1111 constr->width.GetDone() && constr->height.GetDone())
1112 {
1113 int x = constr->left.GetValue();
1114 int y = constr->top.GetValue();
1115 int w = constr->width.GetValue();
1116 int h = constr->height.GetValue();
1117
1118 // If we don't want to resize this window, just move it...
1119 if ((constr->width.GetRelationship() != wxAsIs) ||
1120 (constr->height.GetRelationship() != wxAsIs))
1121 {
1122 // _Should_ call Layout() recursively.
1123 child->SetSize(x, y, w, h);
1124 }
1125 else
1126 {
1127 child->Move(x, y);
1128 }
1129 }
1130 else
1131 child->Layout();
1132 node = node->Next();
1133 }
1134 doneSoFar.DeleteObject(win);
1135
1136 return TRUE;
1137 }
1138
1139 wxSizer::wxSizer(void)
1140 {
1141 sizerBehaviour = wxSizerNone;
1142 borderX = 2;
1143 borderY = 2;
1144 sizerX = 0;
1145 sizerY = 0;
1146 sizerWidth = 0;
1147 sizerHeight = 0;
1148 }
1149
1150 wxSizer::wxSizer(wxWindow *parent, wxSizerBehaviour behav)
1151 {
1152 Create(parent, behav);
1153 }
1154
1155 bool wxSizer::Create(wxWindow *parent, wxSizerBehaviour behav)
1156 {
1157 sizerBehaviour = behav;
1158 borderX = 2;
1159 borderY = 2;
1160 m_sizerParent = parent;
1161 sizerX = 0;
1162 sizerY = 0;
1163 sizerWidth = 0;
1164 sizerHeight = 0;
1165
1166 // A normal window can have just one top-level sizer
1167 // associated with it.
1168 if (!parent->IsKindOf(CLASSINFO(wxSizer)))
1169 {
1170 parent->SetSizer(this);
1171 }
1172 else
1173 ((wxSizer *)parent)->AddSizerChild(this);
1174
1175 switch (sizerBehaviour)
1176 {
1177 case wxSizerExpand:
1178 {
1179 // Defines a set of constraints
1180 // to expand the sizer to fit the parent window
1181 wxLayoutConstraints *c = new wxLayoutConstraints;
1182
1183 c->left.SameAs(parent, wxLeft, 0);
1184 c->top.SameAs(parent, wxTop, 0);
1185 c->right.SameAs(parent, wxRight, 0);
1186 c->bottom.SameAs(parent, wxBottom, 0);
1187
1188 SetConstraints(c);
1189 break;
1190 }
1191 case wxSizerShrink:
1192 case wxSizerNone:
1193 default:
1194 {
1195 }
1196 }
1197 return TRUE;
1198 }
1199
1200 wxSizer::~wxSizer(void)
1201 {
1202 // Remove all children without deleting them,
1203 // or ~wxbWindow will delete proper windows _twice_
1204 wxNode *node = GetChildren()->First();
1205 while (node)
1206 {
1207 wxNode *next = node->Next();
1208 wxWindow *win = (wxWindow *)node->Data();
1209 if (!win->IsKindOf(CLASSINFO(wxSizer)))
1210 {
1211 delete node;
1212 win->SetSizerParent(NULL);
1213 }
1214 else
1215 {
1216 RemoveSizerChild(win);
1217 delete win;
1218 }
1219 node = next;
1220 }
1221
1222 if (m_sizerParent) // && !m_sizerParent->IsKindOf(CLASSINFO(wxSizer)))
1223 {
1224 m_sizerParent->SetSizer(NULL);
1225 m_sizerParent = NULL;
1226 }
1227
1228 }
1229
1230 void wxSizer::SetBorder(int x, int y)
1231 {
1232 borderX = x;
1233 borderY = y;
1234 /* No: the margin is for inside, not outside (expansion)
1235
1236 if ( GetConstraints() )
1237 {
1238 GetConstraints()->left.SetMargin(x);
1239 GetConstraints()->right.SetMargin(x);
1240 GetConstraints()->top.SetMargin(y);
1241 GetConstraints()->bottom.SetMargin(y);
1242 }
1243 */
1244
1245 }
1246
1247 void wxSizer::AddSizerChild(wxWindow *child)
1248 {
1249 child->SetSizerParent(this);
1250 GetChildren()->Append(child);
1251
1252 // Add some constraints for the purpose of storing
1253 // the relative position of the window/sizer
1254 // during layout calculations.
1255 if (!child->GetConstraints())
1256 {
1257 wxLayoutConstraints *c = new wxLayoutConstraints;
1258 c->left.AsIs();
1259 c->top.AsIs();
1260 c->width.AsIs();
1261 c->height.AsIs();
1262 int w, h;
1263 child->GetSize(&w, &h);
1264 c->width.SetValue(w);
1265 c->height.SetValue(h);
1266
1267 child->SetConstraints(c);
1268 }
1269 }
1270
1271 void wxSizer::RemoveSizerChild(wxWindow *child)
1272 {
1273 GetChildren()->DeleteObject(child);
1274 }
1275
1276 void wxSizer::SetSize(const int x, const int y, const int w, const int h, const int WXUNUSED(flags))
1277 {
1278 wxLayoutConstraints *constr = GetConstraints();
1279 if (x != -1)
1280 {
1281 sizerX = x;
1282 if (constr)
1283 constr->left.SetValue(x);
1284 }
1285 if (y != -1)
1286 {
1287 sizerY = y;
1288 if (constr)
1289 constr->top.SetValue(y);
1290 }
1291 if (w != -1)
1292 {
1293 sizerWidth = w;
1294 if (constr)
1295 constr->width.SetValue(w);
1296 }
1297 if (h != -1)
1298 {
1299 sizerHeight = h;
1300 if (constr)
1301 constr->height.SetValue(h);
1302 }
1303 }
1304
1305 void wxSizer::Move(const int x, const int y)
1306 {
1307 wxLayoutConstraints *constr = GetConstraints();
1308 if (x != -1)
1309 {
1310 sizerX = x;
1311 if (constr)
1312 constr->left.SetValue(x);
1313 }
1314 if (y != -1)
1315 {
1316 sizerY = y;
1317 if (constr)
1318 constr->top.SetValue(y);
1319 }
1320 }
1321
1322 void wxSizer::GetSize(int *w, int *h) const
1323 {
1324 *w = sizerWidth;
1325 *h = sizerHeight;
1326 }
1327
1328 void wxSizer::GetPosition(int *x, int *y) const
1329 {
1330 *x = sizerX;
1331 *y = sizerY;
1332 }
1333
1334 bool wxSizer::LayoutPhase1(int *noChanges)
1335 {
1336 *noChanges = 0;
1337 switch (sizerBehaviour)
1338 {
1339 case wxSizerExpand:
1340 {
1341 if (!m_sizerParent)
1342 {
1343 wxMessageBox("wxExpandSizer has no parent!", "Sizer error", wxOK);
1344 return TRUE;
1345 }
1346
1347 // Set the size to fill the parent client area
1348 int pw, ph;
1349 m_sizerParent->GetClientSize(&pw, &ph);
1350 SetSize(GetBorderX(), GetBorderY(), pw - 2*GetBorderX(), ph - 2*GetBorderY());
1351 wxLayoutConstraints *constr = GetConstraints();
1352
1353 // Fill in the constraints
1354 if (constr)
1355 {
1356 constr->left.SetValue(0); constr->left.SetDone(TRUE);
1357 constr->top.SetValue(0); constr->right.SetDone(TRUE);
1358 constr->width.SetValue(pw); constr->width.SetDone(TRUE);
1359 constr->height.SetValue(ph); constr->height.SetDone(TRUE);
1360 }
1361
1362 return TRUE;
1363 break;
1364 }
1365 case wxSizerShrink:
1366 {
1367 wxLayoutConstraints *constr = GetConstraints();
1368
1369 if (constr)
1370 {
1371 // Force the constraint to have as-is width and height
1372 // if we're in shrink-to-fit mode, because if left unconstrained,
1373 // SatisfyConstraints will fail. The shrink-to-fit option
1374 // essentially specifies the width and height as 'whatever I calculate'.
1375 constr->width.AsIs();
1376 constr->height.AsIs();
1377 }
1378 DoPhase(1);
1379 DoPhase(2);
1380 // Find the bounding box and set own size
1381 int maxX = 0;
1382 int maxY = 0;
1383 wxNode *node = GetChildren()->First();
1384 while (node)
1385 {
1386 int x, y, width, height;
1387 wxWindow *win = (wxWindow *)node->Data();
1388 win->GetSizeConstraint(&width, &height);
1389 win->GetPositionConstraint(&x, &y);
1390 if ((x+width) > maxX)
1391 maxX = (x + width);
1392 if ((y+height) > maxY)
1393 maxY = (y + height);
1394 node = node->Next();
1395 }
1396 SetSize(GetBorderX(), GetBorderY(), maxX, maxY);
1397
1398 // If this is the only sizer for the parent, size the parent to this sizer.
1399 if ( m_sizerParent && (m_sizerParent->GetSizer() == this) )
1400 m_sizerParent->SetClientSize(maxX + 2*GetBorderX(), maxY + 2*GetBorderY());
1401
1402 return TRUE;
1403 break;
1404 }
1405 case wxSizerNone:
1406 {
1407 wxLayoutConstraints *constr = GetConstraints();
1408 if (constr)
1409 {
1410 bool success = constr->SatisfyConstraints(this, noChanges);
1411 if (success)
1412 {
1413 int x = constr->left.GetValue();
1414 int y = constr->top.GetValue();
1415 int w = constr->width.GetValue();
1416 int h = constr->height.GetValue();
1417 SetSize(x, y, w, h);
1418 }
1419 return success;
1420 }
1421 else
1422 return TRUE;
1423 break;
1424 }
1425 }
1426 return TRUE;
1427
1428 }
1429
1430 bool wxSizer::LayoutPhase2(int *noChanges)
1431 {
1432 *noChanges = 0;
1433
1434 switch (sizerBehaviour)
1435 {
1436 case wxSizerExpand:
1437 {
1438 // Layout children
1439 DoPhase(1);
1440 DoPhase(2);
1441 return TRUE;
1442 }
1443 case wxSizerShrink:
1444 {
1445 wxLayoutConstraints *constr = GetConstraints();
1446 if (constr)
1447 {
1448 bool success = constr->SatisfyConstraints(this, noChanges);
1449 if (success)
1450 {
1451 int x = constr->left.GetValue();
1452 int y = constr->top.GetValue();
1453 Move(x, y);
1454 }
1455 return success;
1456 }
1457 break;
1458 }
1459 case wxSizerNone:
1460 {
1461 // Layout children
1462 DoPhase(1);
1463 DoPhase(2);
1464
1465 // Is this a dumb fix for lack of constraint evaluation?
1466 wxLayoutConstraints *constr = GetConstraints();
1467 if (constr)
1468 {
1469 bool success = constr->SatisfyConstraints(this, noChanges);
1470 if (success)
1471 {
1472 int x = constr->left.GetValue();
1473 int y = constr->top.GetValue();
1474 int w = constr->width.GetValue();
1475 int h = constr->height.GetValue();
1476 SetSize(x, y, w, h);
1477 }
1478 return success;
1479 }
1480 else
1481 return TRUE;
1482 }
1483 }
1484 return TRUE;
1485 }
1486
1487 /*
1488 * wxRowColSizer
1489 */
1490
1491 wxRowColSizer::wxRowColSizer(void)
1492 {
1493 rowOrCol = TRUE;
1494 rowOrColSize = 20;
1495 xSpacing = 2;
1496 ySpacing = 2;
1497 }
1498
1499 wxRowColSizer::wxRowColSizer(wxWindow *parent, bool rc, int n, wxSizerBehaviour behav)
1500 {
1501 Create(parent, rc, n, behav);
1502 }
1503
1504 bool wxRowColSizer::Create(wxWindow *parent, bool rc, int n, wxSizerBehaviour behav)
1505 {
1506 wxSizer::Create(parent, behav);
1507
1508 rowOrCol = rc;
1509 rowOrColSize = n;
1510 xSpacing = 2;
1511 ySpacing = 2;
1512
1513 return TRUE;
1514 }
1515
1516 wxRowColSizer::~wxRowColSizer(void)
1517 {
1518 }
1519
1520 void wxRowColSizer::SetSize(const int x, const int y, const int w, const int h, const int flags)
1521 {
1522 wxSizer::SetSize(x, y, w, h, flags);
1523 }
1524
1525 bool wxRowColSizer::LayoutPhase1(int *noChanges)
1526 {
1527 *noChanges = 0;
1528 wxLayoutConstraints *constr = GetConstraints();
1529
1530 if (constr)
1531 {
1532 // Force the constraint to have as-is width and height
1533 // if we're in shrink-to-fit mode, because if left unconstrained,
1534 // SatisfyConstraints will fail. The shrink-to-fit option
1535 // essentially specifies the width and height as 'whatever I calculate'.
1536 if (sizerBehaviour == wxSizerShrink)
1537 {
1538 constr->width.AsIs();
1539 constr->height.AsIs();
1540 }
1541
1542 // Only evaluate the constraints FIRST if we're NOT
1543 // in shrink-to-fit mode, i.e. we want to size the rowcol
1544 // first, then lay the children out in the space we've calculated.
1545 if (sizerBehaviour != wxSizerShrink)
1546 {
1547 bool success = constr->SatisfyConstraints(this, noChanges);
1548 if (success)
1549 {
1550 int x = constr->left.GetValue();
1551 int y = constr->top.GetValue();
1552 int w = constr->width.GetValue();
1553 int h = constr->height.GetValue();
1554 SetSize(x, y, w, h);
1555 }
1556 else
1557 return FALSE;
1558
1559 // Continue to do the rest of the phase when the constraints have been
1560 // satisfied, i.e. we're on the last iteration of phase 1 and
1561 // can now do the actual rowcol laying out.
1562 }
1563 }
1564
1565 // If we ARE in shrink-to-fit mode, we must now
1566 // calculate the child sizes BEFORE laying out in rows or columns.
1567 if (sizerBehaviour == wxSizerShrink)
1568 {
1569 DoPhase(1);
1570 DoPhase(2);
1571
1572 // WILL THE WINDOW BE SIZED CORRECTLY AT THIS POINT?
1573 // CHECK CONSTRAINTS IF ANY...
1574 int noRows = 0;
1575 int noCols = 0;
1576 int currentX = borderX;
1577 int currentY = borderY;
1578 int maxX = currentX;
1579 int maxY = currentY;
1580
1581 wxNode *node = GetChildren()->First();
1582 while (node)
1583 {
1584 wxWindow *win = (wxWindow *)node->Data();
1585 int childWidth, childHeight;
1586 if (win->GetConstraints() &&
1587 win->GetConstraints()->width.GetDone() &&
1588 win->GetConstraints()->height.GetDone())
1589 {
1590 childWidth = win->GetConstraints()->width.GetValue();
1591 childHeight = win->GetConstraints()->height.GetValue();
1592 }
1593 else
1594 win->GetSize(&childWidth, &childHeight);
1595
1596 win->MoveConstraint(currentX, currentY);
1597
1598 if ((currentX + childWidth) > maxX)
1599 maxX = (currentX + childWidth);
1600 if ((currentY + childHeight) > maxY)
1601 maxY = (currentY + childHeight);
1602
1603 if (rowOrCol)
1604 {
1605 currentX += childWidth + xSpacing;
1606 noCols ++;
1607
1608 // Reset to start of row
1609 if (noCols == rowOrColSize)
1610 {
1611 currentX = borderX;
1612 currentY += childHeight + ySpacing;
1613 noCols = 0;
1614 }
1615 }
1616 else
1617 {
1618 currentY += childHeight + ySpacing;
1619 noRows ++;
1620
1621 // Reset to start of col
1622 if (noRows == rowOrColSize)
1623 {
1624 currentY = borderY;
1625 currentX += childWidth + xSpacing;
1626 noRows = 0;
1627 }
1628 }
1629
1630 node = node->Next();
1631 }
1632 maxX += borderX;
1633 maxY += borderY;
1634
1635 SetSize(-1, -1, maxX, maxY);
1636 }
1637 return TRUE;
1638 }
1639
1640 bool wxRowColSizer::LayoutPhase2(int *noChanges)
1641 {
1642 *noChanges = 0;
1643
1644 // If shrink-to-fit, it's only at Phase 2 that we know the size of
1645 // the wxRowColSizer, and now we can evaluate the
1646 // constraints and pass result back up to parent.
1647 // This implements a depth-first strategy
1648 if (sizerBehaviour == wxSizerShrink)
1649 {
1650 wxLayoutConstraints *constr = GetConstraints();
1651 if (constr)
1652 {
1653 bool success = constr->SatisfyConstraints(this, noChanges);
1654 if (success)
1655 {
1656 int x = constr->left.GetValue();
1657 int y = constr->top.GetValue();
1658 Move(x, y);
1659 }
1660 return success;
1661 }
1662 else return TRUE;
1663 }
1664 else
1665 {
1666 // Lay out the children: breadth-first strategy.
1667 DoPhase(1);
1668 DoPhase(2);
1669
1670 // Space them
1671 }
1672 return TRUE;
1673 }
1674
1675
1676 /*
1677 * wxSpacingSizer
1678 */
1679
1680 wxSpacingSizer::wxSpacingSizer(void)
1681 {
1682 }
1683
1684 wxSpacingSizer::wxSpacingSizer(wxWindow *parent)
1685 {
1686 Create(parent);
1687 }
1688
1689 wxSpacingSizer::wxSpacingSizer(wxWindow *parent, wxRelationship rel, wxWindow *other, int spacing)
1690 {
1691 Create(parent, rel, other, spacing);
1692 }
1693
1694 bool wxSpacingSizer::Create(wxWindow *parent)
1695 {
1696 wxSizer::Create(parent);
1697 return TRUE;
1698 }
1699
1700 bool wxSpacingSizer::Create(wxWindow *parent, wxRelationship rel, wxWindow *other, int spacing)
1701 {
1702 wxLayoutConstraints *c = new wxLayoutConstraints;
1703
1704 wxSizer::Create(parent);
1705
1706 switch ( rel )
1707 {
1708 case wxLeftOf :
1709 c->width.Absolute (spacing);
1710 c->top.SameAs (other, wxTop);
1711 c->bottom.SameAs (other, wxBottom);
1712 c->right.LeftOf (other);
1713 break;
1714 case wxRightOf :
1715 c->width.Absolute (spacing);
1716 c->top.SameAs (other, wxTop);
1717 c->bottom.SameAs (other, wxBottom);
1718 c->left.RightOf (other);
1719 break;
1720 case wxBelow :
1721 c->height.Absolute (spacing);
1722 c->left.SameAs (other, wxLeft);
1723 c->right.SameAs (other, wxRight);
1724 c->top.Below (other);
1725 break;
1726 case wxAbove :
1727 c->height.Absolute (spacing);
1728 c->left.SameAs (other, wxLeft);
1729 c->right.SameAs (other, wxRight);
1730 c->bottom.Above (other);
1731 break;
1732
1733 default :
1734 break;
1735 }
1736 SetConstraints(c);
1737
1738 return TRUE;
1739 }
1740
1741 wxSpacingSizer::~wxSpacingSizer(void)
1742 {
1743 }
1744
1745
1746
1747 #endif