1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Constraint layout system classes
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // =============================================================================
14 // =============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "layout.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
38 #include "wx/window.h"
40 #include "wx/dialog.h"
41 #include "wx/msgdlg.h"
45 #include "wx/layout.h"
47 IMPLEMENT_DYNAMIC_CLASS(wxIndividualLayoutConstraint
, wxObject
)
48 IMPLEMENT_DYNAMIC_CLASS(wxLayoutConstraints
, wxObject
)
51 wxIndividualLayoutConstraint::wxIndividualLayoutConstraint()
54 relationship
= wxUnconstrained
;
60 otherWin
= (wxWindowBase
*) NULL
;
63 void wxIndividualLayoutConstraint::Set(wxRelationship rel
, wxWindowBase
*otherW
, wxEdge otherE
, int val
, int marg
)
67 // If Set is called by the user with wxSameAs then call SameAs to do
68 // it since it will actually use wxPercent instead.
69 SameAs(otherW
, otherE
, marg
);
77 if ( rel
== wxPercentOf
)
89 void wxIndividualLayoutConstraint::LeftOf(wxWindowBase
*sibling
, int marg
)
91 Set(wxLeftOf
, sibling
, wxLeft
, 0, marg
);
94 void wxIndividualLayoutConstraint::RightOf(wxWindowBase
*sibling
, int marg
)
96 Set(wxRightOf
, sibling
, wxRight
, 0, marg
);
99 void wxIndividualLayoutConstraint::Above(wxWindowBase
*sibling
, int marg
)
101 Set(wxAbove
, sibling
, wxTop
, 0, marg
);
104 void wxIndividualLayoutConstraint::Below(wxWindowBase
*sibling
, int marg
)
106 Set(wxBelow
, sibling
, wxBottom
, 0, marg
);
110 // 'Same edge' alignment
112 void wxIndividualLayoutConstraint::SameAs(wxWindowBase
*otherW
, wxEdge edge
, int marg
)
114 Set(wxPercentOf
, otherW
, edge
, 100, marg
);
117 // The edge is a percentage of the other window's edge
118 void wxIndividualLayoutConstraint::PercentOf(wxWindowBase
*otherW
, wxEdge wh
, int per
)
120 Set(wxPercentOf
, otherW
, wh
, per
);
124 // Edge has absolute value
126 void wxIndividualLayoutConstraint::Absolute(int val
)
129 relationship
= wxAbsolute
;
132 // Reset constraint if it mentions otherWin
133 bool wxIndividualLayoutConstraint::ResetIfWin(wxWindowBase
*otherW
)
135 if (otherW
== otherWin
)
138 relationship
= wxAsIs
;
143 otherWin
= (wxWindowBase
*) NULL
;
150 // Try to satisfy constraint
151 bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints
*constraints
, wxWindowBase
*win
)
153 if (relationship
== wxAbsolute
)
163 switch (relationship
)
167 // We can know this edge if: otherWin is win's
168 // parent, or otherWin has a satisfied constraint,
169 // or otherWin has no constraint.
170 int edgePos
= GetEdge(otherEdge
, win
, otherWin
);
173 value
= edgePos
- margin
;
182 int edgePos
= GetEdge(otherEdge
, win
, otherWin
);
185 value
= edgePos
+ margin
;
194 int edgePos
= GetEdge(otherEdge
, win
, otherWin
);
197 value
= (int)(edgePos
*(((float)percent
)*0.01) + margin
);
204 case wxUnconstrained
:
206 // We know the left-hand edge position if we know
207 // the right-hand edge and we know the width; OR if
208 // we know the centre and the width.
209 if (constraints
->right
.GetDone() && constraints
->width
.GetDone())
211 value
= (constraints
->right
.GetValue() - constraints
->width
.GetValue() + margin
);
215 else if (constraints
->centreX
.GetDone() && constraints
->width
.GetDone())
217 value
= (int)(constraints
->centreX
.GetValue() - (constraints
->width
.GetValue()/2) + margin
);
227 win
->GetPosition(&value
, &y
);
238 switch (relationship
)
242 // We can know this edge if: otherWin is win's
243 // parent, or otherWin has a satisfied constraint,
244 // or otherWin has no constraint.
245 int edgePos
= GetEdge(otherEdge
, win
, otherWin
);
248 value
= edgePos
- margin
;
257 int edgePos
= GetEdge(otherEdge
, win
, otherWin
);
260 value
= edgePos
+ margin
;
269 int edgePos
= GetEdge(otherEdge
, win
, otherWin
);
272 value
= (int)(edgePos
*(((float)percent
)*0.01) - margin
);
279 case wxUnconstrained
:
281 // We know the right-hand edge position if we know the
282 // left-hand edge and we know the width, OR if we know the
283 // centre edge and the width.
284 if (constraints
->left
.GetDone() && constraints
->width
.GetDone())
286 value
= (constraints
->left
.GetValue() + constraints
->width
.GetValue() - margin
);
290 else if (constraints
->centreX
.GetDone() && constraints
->width
.GetDone())
292 value
= (int)(constraints
->centreX
.GetValue() + (constraints
->width
.GetValue()/2) - margin
);
303 win
->GetBestSize(&w
, &h
);
304 win
->GetPosition(&x
, &y
);
316 switch (relationship
)
320 // We can know this edge if: otherWin is win's
321 // parent, or otherWin has a satisfied constraint,
322 // or otherWin has no constraint.
323 int edgePos
= GetEdge(otherEdge
, win
, otherWin
);
326 value
= edgePos
- margin
;
335 int edgePos
= GetEdge(otherEdge
, win
, otherWin
);
338 value
= edgePos
+ margin
;
347 int edgePos
= GetEdge(otherEdge
, win
, otherWin
);
350 value
= (int)(edgePos
*(((float)percent
)*0.01) + margin
);
357 case wxUnconstrained
:
359 // We know the top edge position if we know the bottom edge
360 // and we know the height; OR if we know the centre edge and
362 if (constraints
->bottom
.GetDone() && constraints
->height
.GetDone())
364 value
= (constraints
->bottom
.GetValue() - constraints
->height
.GetValue() + margin
);
368 else if (constraints
->centreY
.GetDone() && constraints
->height
.GetDone())
370 value
= (constraints
->centreY
.GetValue() - (constraints
->height
.GetValue()/2) + margin
);
380 win
->GetPosition(&x
, &value
);
391 switch (relationship
)
395 // We can know this edge if: otherWin is win's parent,
396 // or otherWin has a satisfied constraint, or
397 // otherWin has no constraint.
398 int edgePos
= GetEdge(otherEdge
, win
, otherWin
);
401 value
= edgePos
+ margin
;
410 int edgePos
= GetEdge(otherEdge
, win
, otherWin
);
413 value
= edgePos
- margin
;
422 int edgePos
= GetEdge(otherEdge
, win
, otherWin
);
425 value
= (int)(edgePos
*(((float)percent
)*0.01) - margin
);
432 case wxUnconstrained
:
434 // We know the bottom edge position if we know the top edge
435 // and we know the height; OR if we know the centre edge and
437 if (constraints
->top
.GetDone() && constraints
->height
.GetDone())
439 value
= (constraints
->top
.GetValue() + constraints
->height
.GetValue() - margin
);
443 else if (constraints
->centreY
.GetDone() && constraints
->height
.GetDone())
445 value
= (constraints
->centreY
.GetValue() + (constraints
->height
.GetValue()/2) - margin
);
456 win
->GetBestSize(&w
, &h
);
457 win
->GetPosition(&x
, &y
);
469 switch (relationship
)
473 // We can know this edge if: otherWin is win's parent, or
474 // otherWin has a satisfied constraint, or otherWin has no
476 int edgePos
= GetEdge(otherEdge
, win
, otherWin
);
479 value
= edgePos
- margin
;
488 int edgePos
= GetEdge(otherEdge
, win
, otherWin
);
491 value
= edgePos
+ margin
;
500 int edgePos
= GetEdge(otherEdge
, win
, otherWin
);
503 value
= (int)(edgePos
*(((float)percent
)*0.01) + margin
);
510 case wxUnconstrained
:
512 // We know the centre position if we know
513 // the left-hand edge and we know the width, OR
514 // the right-hand edge and the width
515 if (constraints
->left
.GetDone() && constraints
->width
.GetDone())
517 value
= (int)(constraints
->left
.GetValue() + (constraints
->width
.GetValue()/2) + margin
);
521 else if (constraints
->right
.GetDone() && constraints
->width
.GetDone())
523 value
= (int)(constraints
->left
.GetValue() - (constraints
->width
.GetValue()/2) + margin
);
537 switch (relationship
)
541 // We can know this edge if: otherWin is win's parent,
542 // or otherWin has a satisfied constraint, or otherWin
543 // has no constraint.
544 int edgePos
= GetEdge(otherEdge
, win
, otherWin
);
547 value
= edgePos
- margin
;
556 int edgePos
= GetEdge(otherEdge
, win
, otherWin
);
559 value
= edgePos
+ margin
;
568 int edgePos
= GetEdge(otherEdge
, win
, otherWin
);
571 value
= (int)(edgePos
*(((float)percent
)*0.01) + margin
);
578 case wxUnconstrained
:
580 // We know the centre position if we know
581 // the top edge and we know the height, OR
582 // the bottom edge and the height.
583 if (constraints
->bottom
.GetDone() && constraints
->height
.GetDone())
585 value
= (int)(constraints
->bottom
.GetValue() - (constraints
->height
.GetValue()/2) + margin
);
589 else if (constraints
->top
.GetDone() && constraints
->height
.GetDone())
591 value
= (int)(constraints
->top
.GetValue() + (constraints
->height
.GetValue()/2) + margin
);
605 switch (relationship
)
609 int edgePos
= GetEdge(otherEdge
, win
, otherWin
);
612 value
= (int)(edgePos
*(((float)percent
)*0.01));
624 win
->GetBestSize(&value
, &h
);
630 case wxUnconstrained
:
632 // We know the width if we know the left edge and the right edge, OR
633 // if we know the left edge and the centre, OR
634 // if we know the right edge and the centre
635 if (constraints
->left
.GetDone() && constraints
->right
.GetDone())
637 value
= constraints
->right
.GetValue() - constraints
->left
.GetValue();
641 else if (constraints
->centreX
.GetDone() && constraints
->left
.GetDone())
643 value
= (int)(2*(constraints
->centreX
.GetValue() - constraints
->left
.GetValue()));
647 else if (constraints
->centreX
.GetDone() && constraints
->right
.GetDone())
649 value
= (int)(2*(constraints
->right
.GetValue() - constraints
->centreX
.GetValue()));
663 switch (relationship
)
667 int edgePos
= GetEdge(otherEdge
, win
, otherWin
);
670 value
= (int)(edgePos
*(((float)percent
)*0.01));
682 win
->GetBestSize(&w
, &value
);
688 case wxUnconstrained
:
690 // We know the height if we know the top edge and the bottom edge, OR
691 // if we know the top edge and the centre, OR
692 // if we know the bottom edge and the centre
693 if (constraints
->top
.GetDone() && constraints
->bottom
.GetDone())
695 value
= constraints
->bottom
.GetValue() - constraints
->top
.GetValue();
699 else if (constraints
->top
.GetDone() && constraints
->centreY
.GetDone())
701 value
= (int)(2*(constraints
->centreY
.GetValue() - constraints
->top
.GetValue()));
705 else if (constraints
->bottom
.GetDone() && constraints
->centreY
.GetDone())
707 value
= (int)(2*(constraints
->bottom
.GetValue() - constraints
->centreY
.GetValue()));
725 // Get the value of this edge or dimension, or if this is not determinable, -1.
726 int wxIndividualLayoutConstraint::GetEdge(wxEdge which
,
727 wxWindowBase
*thisWin
,
728 wxWindowBase
*other
) const
730 // If the edge or dimension belongs to the parent, then we know the
731 // dimension is obtainable immediately. E.g. a wxExpandSizer may contain a
732 // button (but the button's true parent is a panel, not the sizer)
733 if (other
->GetChildren().Find((wxWindow
*)thisWin
))
748 other
->GetClientSizeConstraint(&w
, &h
);
754 other
->GetClientSizeConstraint(&w
, &h
);
760 other
->GetClientSizeConstraint(&w
, &h
);
766 other
->GetClientSizeConstraint(&w
, &h
);
773 other
->GetClientSizeConstraint(&w
, &h
);
774 if (which
== wxCentreX
)
787 wxLayoutConstraints
*constr
= other
->GetConstraints();
788 // If no constraints, it means the window is not dependent
789 // on anything, and therefore we know its value immediately
792 if (constr
->left
.GetDone())
793 return constr
->left
.GetValue();
800 other
->GetPosition(&x
, &y
);
806 wxLayoutConstraints
*constr
= other
->GetConstraints();
807 // If no constraints, it means the window is not dependent
808 // on anything, and therefore we know its value immediately
811 if (constr
->top
.GetDone())
812 return constr
->top
.GetValue();
819 other
->GetPosition(&x
, &y
);
825 wxLayoutConstraints
*constr
= other
->GetConstraints();
826 // If no constraints, it means the window is not dependent
827 // on anything, and therefore we know its value immediately
830 if (constr
->right
.GetDone())
831 return constr
->right
.GetValue();
838 other
->GetPosition(&x
, &y
);
839 other
->GetSize(&w
, &h
);
845 wxLayoutConstraints
*constr
= other
->GetConstraints();
846 // If no constraints, it means the window is not dependent
847 // on anything, and therefore we know its value immediately
850 if (constr
->bottom
.GetDone())
851 return constr
->bottom
.GetValue();
858 other
->GetPosition(&x
, &y
);
859 other
->GetSize(&w
, &h
);
865 wxLayoutConstraints
*constr
= other
->GetConstraints();
866 // If no constraints, it means the window is not dependent
867 // on anything, and therefore we know its value immediately
870 if (constr
->width
.GetDone())
871 return constr
->width
.GetValue();
878 other
->GetSize(&w
, &h
);
884 wxLayoutConstraints
*constr
= other
->GetConstraints();
885 // If no constraints, it means the window is not dependent
886 // on anything, and therefore we know its value immediately
889 if (constr
->height
.GetDone())
890 return constr
->height
.GetValue();
897 other
->GetSize(&w
, &h
);
903 wxLayoutConstraints
*constr
= other
->GetConstraints();
904 // If no constraints, it means the window is not dependent
905 // on anything, and therefore we know its value immediately
908 if (constr
->centreX
.GetDone())
909 return constr
->centreX
.GetValue();
916 other
->GetPosition(&x
, &y
);
917 other
->GetSize(&w
, &h
);
918 return (int)(x
+ (w
/2));
923 wxLayoutConstraints
*constr
= other
->GetConstraints();
924 // If no constraints, it means the window is not dependent
925 // on anything, and therefore we know its value immediately
928 if (constr
->centreY
.GetDone())
929 return constr
->centreY
.GetValue();
936 other
->GetPosition(&x
, &y
);
937 other
->GetSize(&w
, &h
);
938 return (int)(y
+ (h
/2));
947 wxLayoutConstraints::wxLayoutConstraints()
949 left
.SetEdge(wxLeft
);
951 right
.SetEdge(wxRight
);
952 bottom
.SetEdge(wxBottom
);
953 centreX
.SetEdge(wxCentreX
);
954 centreY
.SetEdge(wxCentreY
);
955 width
.SetEdge(wxWidth
);
956 height
.SetEdge(wxHeight
);
959 bool wxLayoutConstraints::SatisfyConstraints(wxWindowBase
*win
, int *nChanges
)
963 bool done
= width
.GetDone();
964 bool newDone
= (done
? true : width
.SatisfyConstraint(this, win
));
968 done
= height
.GetDone();
969 newDone
= (done
? true : height
.SatisfyConstraint(this, win
));
973 done
= left
.GetDone();
974 newDone
= (done
? true : left
.SatisfyConstraint(this, win
));
978 done
= top
.GetDone();
979 newDone
= (done
? true : top
.SatisfyConstraint(this, win
));
983 done
= right
.GetDone();
984 newDone
= (done
? true : right
.SatisfyConstraint(this, win
));
988 done
= bottom
.GetDone();
989 newDone
= (done
? true : bottom
.SatisfyConstraint(this, win
));
993 done
= centreX
.GetDone();
994 newDone
= (done
? true : centreX
.SatisfyConstraint(this, win
));
998 done
= centreY
.GetDone();
999 newDone
= (done
? true : centreY
.SatisfyConstraint(this, win
));
1000 if (newDone
!= done
)
1003 *nChanges
= noChanges
;
1005 return AreSatisfied();
1008 #endif // wxUSE_CONSTRAINTS