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