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