1
/////////////////////////////////////////////////////////////////////////////
3
// Purpose: Constraint layout system classes
4
// Author: Julian Smart
7
// RCS-ID: $Id: layout.cpp,v 1.30 2005/03/12 20:57:14 RD Exp $
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)
52
inline void wxGetAsIs(wxWindowBase* win, int* w, int* h)
55
// The old way. Works for me.
60
// Vadim's change. Breaks wxPython's LayoutAnchors
61
win->GetBestSize(w, h);
65
// Proposed compromise. Doesn't work.
67
win->GetSize(&sw, &sh);
68
win->GetBestSize(&bw, &bh);
77
wxIndividualLayoutConstraint::wxIndividualLayoutConstraint()
80
relationship = wxUnconstrained;
86
otherWin = (wxWindowBase *) NULL;
89
void wxIndividualLayoutConstraint::Set(wxRelationship rel, wxWindowBase *otherW, wxEdge otherE, int val, int marg)
93
// If Set is called by the user with wxSameAs then call SameAs to do
94
// it since it will actually use wxPercent instead.
95
SameAs(otherW, otherE, marg);
103
if ( rel == wxPercentOf )
115
void wxIndividualLayoutConstraint::LeftOf(wxWindowBase *sibling, int marg)
117
Set(wxLeftOf, sibling, wxLeft, 0, marg);
120
void wxIndividualLayoutConstraint::RightOf(wxWindowBase *sibling, int marg)
122
Set(wxRightOf, sibling, wxRight, 0, marg);
125
void wxIndividualLayoutConstraint::Above(wxWindowBase *sibling, int marg)
127
Set(wxAbove, sibling, wxTop, 0, marg);
130
void wxIndividualLayoutConstraint::Below(wxWindowBase *sibling, int marg)
132
Set(wxBelow, sibling, wxBottom, 0, marg);
136
// 'Same edge' alignment
138
void wxIndividualLayoutConstraint::SameAs(wxWindowBase *otherW, wxEdge edge, int marg)
140
Set(wxPercentOf, otherW, edge, 100, marg);
143
// The edge is a percentage of the other window's edge
144
void wxIndividualLayoutConstraint::PercentOf(wxWindowBase *otherW, wxEdge wh, int per)
146
Set(wxPercentOf, otherW, wh, per);
150
// Edge has absolute value
152
void wxIndividualLayoutConstraint::Absolute(int val)
155
relationship = wxAbsolute;
158
// Reset constraint if it mentions otherWin
159
bool wxIndividualLayoutConstraint::ResetIfWin(wxWindowBase *otherW)
161
if (otherW == otherWin)
164
relationship = wxAsIs;
169
otherWin = (wxWindowBase *) NULL;
176
// Try to satisfy constraint
177
bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constraints, wxWindowBase *win)
179
if (relationship == wxAbsolute)
189
switch (relationship)
193
// We can know this edge if: otherWin is win's
194
// parent, or otherWin has a satisfied constraint,
195
// or otherWin has no constraint.
196
int edgePos = GetEdge(otherEdge, win, otherWin);
199
value = edgePos - margin;
208
int edgePos = GetEdge(otherEdge, win, otherWin);
211
value = edgePos + margin;
220
int edgePos = GetEdge(otherEdge, win, otherWin);
223
value = (int)(edgePos*(((float)percent)*0.01) + margin);
230
case wxUnconstrained:
232
// We know the left-hand edge position if we know
233
// the right-hand edge and we know the width; OR if
234
// we know the centre and the width.
235
if (constraints->right.GetDone() && constraints->width.GetDone())
237
value = (constraints->right.GetValue() - constraints->width.GetValue() + margin);
241
else if (constraints->centreX.GetDone() && constraints->width.GetDone())
243
value = (int)(constraints->centreX.GetValue() - (constraints->width.GetValue()/2) + margin);
253
win->GetPosition(&value, &y);
264
switch (relationship)
268
// We can know this edge if: otherWin is win's
269
// parent, or otherWin has a satisfied constraint,
270
// or otherWin has no constraint.
271
int edgePos = GetEdge(otherEdge, win, otherWin);
274
value = edgePos - margin;
283
int edgePos = GetEdge(otherEdge, win, otherWin);
286
value = edgePos + margin;
295
int edgePos = GetEdge(otherEdge, win, otherWin);
298
value = (int)(edgePos*(((float)percent)*0.01) - margin);
305
case wxUnconstrained:
307
// We know the right-hand edge position if we know the
308
// left-hand edge and we know the width, OR if we know the
309
// centre edge and the width.
310
if (constraints->left.GetDone() && constraints->width.GetDone())
312
value = (constraints->left.GetValue() + constraints->width.GetValue() - margin);
316
else if (constraints->centreX.GetDone() && constraints->width.GetDone())
318
value = (int)(constraints->centreX.GetValue() + (constraints->width.GetValue()/2) - margin);
329
wxGetAsIs(win, &w, &h);
330
win->GetPosition(&x, &y);
342
switch (relationship)
346
// We can know this edge if: otherWin is win's
347
// parent, or otherWin has a satisfied constraint,
348
// or otherWin has no constraint.
349
int edgePos = GetEdge(otherEdge, win, otherWin);
352
value = edgePos - margin;
361
int edgePos = GetEdge(otherEdge, win, otherWin);
364
value = edgePos + margin;
373
int edgePos = GetEdge(otherEdge, win, otherWin);
376
value = (int)(edgePos*(((float)percent)*0.01) + margin);
383
case wxUnconstrained:
385
// We know the top edge position if we know the bottom edge
386
// and we know the height; OR if we know the centre edge and
388
if (constraints->bottom.GetDone() && constraints->height.GetDone())
390
value = (constraints->bottom.GetValue() - constraints->height.GetValue() + margin);
394
else if (constraints->centreY.GetDone() && constraints->height.GetDone())
396
value = (constraints->centreY.GetValue() - (constraints->height.GetValue()/2) + margin);
406
win->GetPosition(&x, &value);
417
switch (relationship)
421
// We can know this edge if: otherWin is win's parent,
422
// or otherWin has a satisfied constraint, or
423
// otherWin has no constraint.
424
int edgePos = GetEdge(otherEdge, win, otherWin);
427
value = edgePos + margin;
436
int edgePos = GetEdge(otherEdge, win, otherWin);
439
value = edgePos - margin;
448
int edgePos = GetEdge(otherEdge, win, otherWin);
451
value = (int)(edgePos*(((float)percent)*0.01) - margin);
458
case wxUnconstrained:
460
// We know the bottom edge position if we know the top edge
461
// and we know the height; OR if we know the centre edge and
463
if (constraints->top.GetDone() && constraints->height.GetDone())
465
value = (constraints->top.GetValue() + constraints->height.GetValue() - margin);
469
else if (constraints->centreY.GetDone() && constraints->height.GetDone())
471
value = (constraints->centreY.GetValue() + (constraints->height.GetValue()/2) - margin);
482
wxGetAsIs(win, &w, &h);
483
win->GetPosition(&x, &y);
495
switch (relationship)
499
// We can know this edge if: otherWin is win's parent, or
500
// otherWin has a satisfied constraint, or otherWin has no
502
int edgePos = GetEdge(otherEdge, win, otherWin);
505
value = edgePos - margin;
514
int edgePos = GetEdge(otherEdge, win, otherWin);
517
value = edgePos + margin;
526
int edgePos = GetEdge(otherEdge, win, otherWin);
529
value = (int)(edgePos*(((float)percent)*0.01) + margin);
536
case wxUnconstrained:
538
// We know the centre position if we know
539
// the left-hand edge and we know the width, OR
540
// the right-hand edge and the width
541
if (constraints->left.GetDone() && constraints->width.GetDone())
543
value = (int)(constraints->left.GetValue() + (constraints->width.GetValue()/2) + margin);
547
else if (constraints->right.GetDone() && constraints->width.GetDone())
549
value = (int)(constraints->left.GetValue() - (constraints->width.GetValue()/2) + margin);
563
switch (relationship)
567
// We can know this edge if: otherWin is win's parent,
568
// or otherWin has a satisfied constraint, or otherWin
569
// has no constraint.
570
int edgePos = GetEdge(otherEdge, win, otherWin);
573
value = edgePos - margin;
582
int edgePos = GetEdge(otherEdge, win, otherWin);
585
value = edgePos + margin;
594
int edgePos = GetEdge(otherEdge, win, otherWin);
597
value = (int)(edgePos*(((float)percent)*0.01) + margin);
604
case wxUnconstrained:
606
// We know the centre position if we know
607
// the top edge and we know the height, OR
608
// the bottom edge and the height.
609
if (constraints->bottom.GetDone() && constraints->height.GetDone())
611
value = (int)(constraints->bottom.GetValue() - (constraints->height.GetValue()/2) + margin);
615
else if (constraints->top.GetDone() && constraints->height.GetDone())
617
value = (int)(constraints->top.GetValue() + (constraints->height.GetValue()/2) + margin);
631
switch (relationship)
635
int edgePos = GetEdge(otherEdge, win, otherWin);
638
value = (int)(edgePos*(((float)percent)*0.01));
650
wxGetAsIs(win, &value, &h);
656
case wxUnconstrained:
658
// We know the width if we know the left edge and the right edge, OR
659
// if we know the left edge and the centre, OR
660
// if we know the right edge and the centre
661
if (constraints->left.GetDone() && constraints->right.GetDone())
663
value = constraints->right.GetValue() - constraints->left.GetValue();
667
else if (constraints->centreX.GetDone() && constraints->left.GetDone())
669
value = (int)(2*(constraints->centreX.GetValue() - constraints->left.GetValue()));
673
else if (constraints->centreX.GetDone() && constraints->right.GetDone())
675
value = (int)(2*(constraints->right.GetValue() - constraints->centreX.GetValue()));
689
switch (relationship)
693
int edgePos = GetEdge(otherEdge, win, otherWin);
696
value = (int)(edgePos*(((float)percent)*0.01));
708
wxGetAsIs(win, &w, &value);
714
case wxUnconstrained:
716
// We know the height if we know the top edge and the bottom edge, OR
717
// if we know the top edge and the centre, OR
718
// if we know the bottom edge and the centre
719
if (constraints->top.GetDone() && constraints->bottom.GetDone())
721
value = constraints->bottom.GetValue() - constraints->top.GetValue();
725
else if (constraints->top.GetDone() && constraints->centreY.GetDone())
727
value = (int)(2*(constraints->centreY.GetValue() - constraints->top.GetValue()));
731
else if (constraints->bottom.GetDone() && constraints->centreY.GetDone())
733
value = (int)(2*(constraints->bottom.GetValue() - constraints->centreY.GetValue()));
751
// Get the value of this edge or dimension, or if this is not determinable, -1.
752
int wxIndividualLayoutConstraint::GetEdge(wxEdge which,
753
wxWindowBase *thisWin,
754
wxWindowBase *other) const
756
// If the edge or dimension belongs to the parent, then we know the
757
// dimension is obtainable immediately. E.g. a wxExpandSizer may contain a
758
// button (but the button's true parent is a panel, not the sizer)
759
if (other->GetChildren().Find((wxWindow*)thisWin))
774
other->GetClientSizeConstraint(&w, &h);
780
other->GetClientSizeConstraint(&w, &h);
786
other->GetClientSizeConstraint(&w, &h);
792
other->GetClientSizeConstraint(&w, &h);
799
other->GetClientSizeConstraint(&w, &h);
800
if (which == wxCentreX)
813
wxLayoutConstraints *constr = other->GetConstraints();
814
// If no constraints, it means the window is not dependent
815
// on anything, and therefore we know its value immediately
818
if (constr->left.GetDone())
819
return constr->left.GetValue();
826
other->GetPosition(&x, &y);
832
wxLayoutConstraints *constr = other->GetConstraints();
833
// If no constraints, it means the window is not dependent
834
// on anything, and therefore we know its value immediately
837
if (constr->top.GetDone())
838
return constr->top.GetValue();
845
other->GetPosition(&x, &y);
851
wxLayoutConstraints *constr = other->GetConstraints();
852
// If no constraints, it means the window is not dependent
853
// on anything, and therefore we know its value immediately
856
if (constr->right.GetDone())
857
return constr->right.GetValue();
864
other->GetPosition(&x, &y);
865
other->GetSize(&w, &h);
871
wxLayoutConstraints *constr = other->GetConstraints();
872
// If no constraints, it means the window is not dependent
873
// on anything, and therefore we know its value immediately
876
if (constr->bottom.GetDone())
877
return constr->bottom.GetValue();
884
other->GetPosition(&x, &y);
885
other->GetSize(&w, &h);
891
wxLayoutConstraints *constr = other->GetConstraints();
892
// If no constraints, it means the window is not dependent
893
// on anything, and therefore we know its value immediately
896
if (constr->width.GetDone())
897
return constr->width.GetValue();
904
other->GetSize(&w, &h);
910
wxLayoutConstraints *constr = other->GetConstraints();
911
// If no constraints, it means the window is not dependent
912
// on anything, and therefore we know its value immediately
915
if (constr->height.GetDone())
916
return constr->height.GetValue();
923
other->GetSize(&w, &h);
929
wxLayoutConstraints *constr = other->GetConstraints();
930
// If no constraints, it means the window is not dependent
931
// on anything, and therefore we know its value immediately
934
if (constr->centreX.GetDone())
935
return constr->centreX.GetValue();
942
other->GetPosition(&x, &y);
943
other->GetSize(&w, &h);
944
return (int)(x + (w/2));
949
wxLayoutConstraints *constr = other->GetConstraints();
950
// If no constraints, it means the window is not dependent
951
// on anything, and therefore we know its value immediately
954
if (constr->centreY.GetDone())
955
return constr->centreY.GetValue();
962
other->GetPosition(&x, &y);
963
other->GetSize(&w, &h);
964
return (int)(y + (h/2));
973
wxLayoutConstraints::wxLayoutConstraints()
975
left.SetEdge(wxLeft);
977
right.SetEdge(wxRight);
978
bottom.SetEdge(wxBottom);
979
centreX.SetEdge(wxCentreX);
980
centreY.SetEdge(wxCentreY);
981
width.SetEdge(wxWidth);
982
height.SetEdge(wxHeight);
985
bool wxLayoutConstraints::SatisfyConstraints(wxWindowBase *win, int *nChanges)
989
bool done = width.GetDone();
990
bool newDone = (done ? true : width.SatisfyConstraint(this, win));
994
done = height.GetDone();
995
newDone = (done ? true : height.SatisfyConstraint(this, win));
999
done = left.GetDone();
1000
newDone = (done ? true : left.SatisfyConstraint(this, win));
1001
if (newDone != done)
1004
done = top.GetDone();
1005
newDone = (done ? true : top.SatisfyConstraint(this, win));
1006
if (newDone != done)
1009
done = right.GetDone();
1010
newDone = (done ? true : right.SatisfyConstraint(this, win));
1011
if (newDone != done)
1014
done = bottom.GetDone();
1015
newDone = (done ? true : bottom.SatisfyConstraint(this, win));
1016
if (newDone != done)
1019
done = centreX.GetDone();
1020
newDone = (done ? true : centreX.SatisfyConstraint(this, win));
1021
if (newDone != done)
1024
done = centreY.GetDone();
1025
newDone = (done ? true : centreY.SatisfyConstraint(this, win));
1026
if (newDone != done)
1029
*nChanges = noChanges;
1031
return AreSatisfied();
1034
#endif // wxUSE_CONSTRAINTS