X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/d427503c3696486ef84cd0e5081884ccd8d6b434..bad6c5e264fe9a7ac9e931d071d72acdabb3401e:/src/common/layout.cpp diff --git a/src/common/layout.cpp b/src/common/layout.cpp index 3718e78c12..d479f3476e 100644 --- a/src/common/layout.cpp +++ b/src/common/layout.cpp @@ -1,12 +1,12 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: layout.cpp +// Name: src/common/layout.cpp // Purpose: Constraint layout system classes // Author: Julian Smart // Modified by: // Created: 04/01/98 // RCS-ID: $Id$ -// Copyright: (c) Julian Smart and Markus Holzem -// Licence: wxWindows license +// Copyright: (c) Julian Smart +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // ============================================================================= @@ -17,10 +17,6 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ - #pragma implementation "layout.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -28,10 +24,10 @@ #pragma hdrstop #endif -#include "wx/defs.h" - #if wxUSE_CONSTRAINTS +#include "wx/layout.h" + #ifndef WX_PRECOMP #include "wx/window.h" #include "wx/utils.h" @@ -40,60 +36,33 @@ #include "wx/intl.h" #endif -#include "wx/layout.h" - -#if !USE_SHARED_LIBRARY - IMPLEMENT_DYNAMIC_CLASS(wxIndividualLayoutConstraint, wxObject) - IMPLEMENT_DYNAMIC_CLASS(wxLayoutConstraints, wxObject) - IMPLEMENT_DYNAMIC_CLASS(wxSizer, wxObject) - IMPLEMENT_DYNAMIC_CLASS(wxRowColSizer, wxSizer) - IMPLEMENT_DYNAMIC_CLASS(wxSpacingSizer, wxSizer) -#endif -/* -TODO: - - Non shrink-to-fit row-col behaviour. - - Give justification styles, so can e.g. centre - the rows & cols, distribute the available space... - - Shrink-to-fit: should resize outer window (e.g. dialog box) - if directly associated with this kind of window. - - How to deal with a rowcol that stretches in one direction - but shrinks-to-fit in other. E.g. a horizontal toolbar: the width - stretches to fit the frame, but the height is constant - or wraps around contents. The algorithm currently assumes - both dimensions have the same behaviour. Could assume a constant - height (absolute value). - - rowcol where each row or column is aligned (length of - largest element determines spacing) - - Groupbox sizer - - Analyze aesthetic dialog boxes and implement using sizers. - - What reuseable components can we provide? E.g. Ok/Cancel/Help - group of buttons. - - use wxStaticItems for aesthetic dialogs. +IMPLEMENT_DYNAMIC_CLASS(wxIndividualLayoutConstraint, wxObject) +IMPLEMENT_DYNAMIC_CLASS(wxLayoutConstraints, wxObject) -*/ -// Find margin sizes if a sizer, or zero otherwise -int wxSizerMarginX(wxWindowBase *win) +inline void wxGetAsIs(wxWindowBase* win, int* w, int* h) { - if ( win->IsKindOf(CLASSINFO(wxSizer)) ) - { - wxSizer *sizer = (wxSizer *)win; - return sizer->GetBorderX(); - } - else - return 0; -} +#if 1 + // The old way. Works for me. + win->GetSize(w, h); +#endif -int wxSizerMarginY(wxWindowBase *win) -{ - if ( win->IsKindOf(CLASSINFO(wxSizer)) ) - { - wxSizer *sizer = (wxSizer *)win; - return sizer->GetBorderY(); - } - else - return 0; +#if 0 + // Vadim's change. Breaks wxPython's LayoutAnchors + win->GetBestSize(w, h); +#endif + +#if 0 + // Proposed compromise. Doesn't work. + int sw, sh, bw, bh; + win->GetSize(&sw, &sh); + win->GetBestSize(&bw, &bh); + if (w) + *w = wxMax(sw, bw); + if (h) + *h = wxMax(sh, bh); +#endif } @@ -105,21 +74,34 @@ wxIndividualLayoutConstraint::wxIndividualLayoutConstraint() value = 0; percent = 0; otherEdge = wxTop; - done = FALSE; - otherWin = (wxWindowBase *) NULL; -} - -wxIndividualLayoutConstraint::~wxIndividualLayoutConstraint() -{ + done = false; + otherWin = NULL; } void wxIndividualLayoutConstraint::Set(wxRelationship rel, wxWindowBase *otherW, wxEdge otherE, int val, int marg) { - relationship = rel; - otherWin = otherW; - otherEdge = otherE; - value = val; - margin = marg; + if (rel == wxSameAs) + { + // If Set is called by the user with wxSameAs then call SameAs to do + // it since it will actually use wxPercent instead. + SameAs(otherW, otherE, marg); + return; + } + + relationship = rel; + otherWin = otherW; + otherEdge = otherE; + + if ( rel == wxPercentOf ) + { + percent = val; + } + else + { + value = val; + } + + margin = marg; } void wxIndividualLayoutConstraint::LeftOf(wxWindowBase *sibling, int marg) @@ -146,19 +128,14 @@ void wxIndividualLayoutConstraint::Below(wxWindowBase *sibling, int marg) // 'Same edge' alignment // void wxIndividualLayoutConstraint::SameAs(wxWindowBase *otherW, wxEdge edge, int marg) -{ - Set(wxPercentOf, otherW, edge, 0, marg); - percent = 100; +{ + Set(wxPercentOf, otherW, edge, 100, marg); } // The edge is a percentage of the other window's edge void wxIndividualLayoutConstraint::PercentOf(wxWindowBase *otherW, wxEdge wh, int per) -{ - otherWin = otherW; - relationship = wxPercentOf; - percent = per; - - otherEdge = wh; +{ + Set(wxPercentOf, otherW, wh, per); } // @@ -166,7 +143,8 @@ void wxIndividualLayoutConstraint::PercentOf(wxWindowBase *otherW, wxEdge wh, in // void wxIndividualLayoutConstraint::Absolute(int val) { - value = val; relationship = wxAbsolute; + value = val; + relationship = wxAbsolute; } // Reset constraint if it mentions otherWin @@ -180,11 +158,11 @@ bool wxIndividualLayoutConstraint::ResetIfWin(wxWindowBase *otherW) value = 0; percent = 0; otherEdge = wxTop; - otherWin = (wxWindowBase *) NULL; - return TRUE; + otherWin = NULL; + return true; } - else - return FALSE; + + return false; } // Try to satisfy constraint @@ -192,8 +170,8 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr { if (relationship == wxAbsolute) { - done = TRUE; - return TRUE; + done = true; + return true; } switch (myEdge) @@ -211,11 +189,11 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (edgePos != -1) { value = edgePos - margin; - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } case wxRightOf: { @@ -223,11 +201,11 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (edgePos != -1) { value = edgePos + margin; - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } case wxPercentOf: { @@ -235,11 +213,11 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (edgePos != -1) { value = (int)(edgePos*(((float)percent)*0.01) + margin); - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } case wxUnconstrained: { @@ -249,24 +227,24 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (constraints->right.GetDone() && constraints->width.GetDone()) { value = (constraints->right.GetValue() - constraints->width.GetValue() + margin); - done = TRUE; - return TRUE; + done = true; + return true; } else if (constraints->centreX.GetDone() && constraints->width.GetDone()) { value = (int)(constraints->centreX.GetValue() - (constraints->width.GetValue()/2) + margin); - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } case wxAsIs: { int y; win->GetPosition(&value, &y); - done = TRUE; - return TRUE; + done = true; + return true; } default: break; @@ -286,11 +264,11 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (edgePos != -1) { value = edgePos - margin; - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } case wxRightOf: { @@ -298,11 +276,11 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (edgePos != -1) { value = edgePos + margin; - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } case wxPercentOf: { @@ -310,11 +288,11 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (edgePos != -1) { value = (int)(edgePos*(((float)percent)*0.01) - margin); - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } case wxUnconstrained: { @@ -324,27 +302,27 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (constraints->left.GetDone() && constraints->width.GetDone()) { value = (constraints->left.GetValue() + constraints->width.GetValue() - margin); - done = TRUE; - return TRUE; + done = true; + return true; } else if (constraints->centreX.GetDone() && constraints->width.GetDone()) { value = (int)(constraints->centreX.GetValue() + (constraints->width.GetValue()/2) - margin); - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } case wxAsIs: { int x, y; int w, h; - win->GetSize(&w, &h); + wxGetAsIs(win, &w, &h); win->GetPosition(&x, &y); value = x + w; - done = TRUE; - return TRUE; + done = true; + return true; } default: break; @@ -364,11 +342,11 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (edgePos != -1) { value = edgePos - margin; - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } case wxBelow: { @@ -376,11 +354,11 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (edgePos != -1) { value = edgePos + margin; - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } case wxPercentOf: { @@ -388,11 +366,11 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (edgePos != -1) { value = (int)(edgePos*(((float)percent)*0.01) + margin); - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } case wxUnconstrained: { @@ -402,24 +380,24 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (constraints->bottom.GetDone() && constraints->height.GetDone()) { value = (constraints->bottom.GetValue() - constraints->height.GetValue() + margin); - done = TRUE; - return TRUE; + done = true; + return true; } else if (constraints->centreY.GetDone() && constraints->height.GetDone()) { value = (constraints->centreY.GetValue() - (constraints->height.GetValue()/2) + margin); - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } case wxAsIs: { int x; win->GetPosition(&x, &value); - done = TRUE; - return TRUE; + done = true; + return true; } default: break; @@ -439,11 +417,11 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (edgePos != -1) { value = edgePos + margin; - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } case wxBelow: { @@ -451,11 +429,11 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (edgePos != -1) { value = edgePos - margin; - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } case wxPercentOf: { @@ -463,11 +441,11 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (edgePos != -1) { value = (int)(edgePos*(((float)percent)*0.01) - margin); - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } case wxUnconstrained: { @@ -477,27 +455,27 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (constraints->top.GetDone() && constraints->height.GetDone()) { value = (constraints->top.GetValue() + constraints->height.GetValue() - margin); - done = TRUE; - return TRUE; + done = true; + return true; } else if (constraints->centreY.GetDone() && constraints->height.GetDone()) { value = (constraints->centreY.GetValue() + (constraints->height.GetValue()/2) - margin); - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } case wxAsIs: { int x, y; int w, h; - win->GetSize(&w, &h); + wxGetAsIs(win, &w, &h); win->GetPosition(&x, &y); value = h + y; - done = TRUE; - return TRUE; + done = true; + return true; } default: break; @@ -517,11 +495,11 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (edgePos != -1) { value = edgePos - margin; - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } case wxRightOf: { @@ -529,11 +507,11 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (edgePos != -1) { value = edgePos + margin; - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } case wxPercentOf: { @@ -541,11 +519,11 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (edgePos != -1) { value = (int)(edgePos*(((float)percent)*0.01) + margin); - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } case wxUnconstrained: { @@ -555,17 +533,17 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (constraints->left.GetDone() && constraints->width.GetDone()) { value = (int)(constraints->left.GetValue() + (constraints->width.GetValue()/2) + margin); - done = TRUE; - return TRUE; + done = true; + return true; } else if (constraints->right.GetDone() && constraints->width.GetDone()) { value = (int)(constraints->left.GetValue() - (constraints->width.GetValue()/2) + margin); - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } default: break; @@ -585,11 +563,11 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (edgePos != -1) { value = edgePos - margin; - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } case wxBelow: { @@ -597,11 +575,11 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (edgePos != -1) { value = edgePos + margin; - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } case wxPercentOf: { @@ -609,11 +587,11 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (edgePos != -1) { value = (int)(edgePos*(((float)percent)*0.01) + margin); - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } case wxUnconstrained: { @@ -623,17 +601,17 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (constraints->bottom.GetDone() && constraints->height.GetDone()) { value = (int)(constraints->bottom.GetValue() - (constraints->height.GetValue()/2) + margin); - done = TRUE; - return TRUE; + done = true; + return true; } else if (constraints->top.GetDone() && constraints->height.GetDone()) { value = (int)(constraints->top.GetValue() + (constraints->height.GetValue()/2) + margin); - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } default: break; @@ -650,22 +628,22 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (edgePos != -1) { value = (int)(edgePos*(((float)percent)*0.01)); - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } case wxAsIs: { if (win) { int h; - win->GetSize(&value, &h); - done = TRUE; - return TRUE; + wxGetAsIs(win, &value, &h); + done = true; + return true; } - else return FALSE; + else return false; } case wxUnconstrained: { @@ -675,23 +653,23 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (constraints->left.GetDone() && constraints->right.GetDone()) { value = constraints->right.GetValue() - constraints->left.GetValue(); - done = TRUE; - return TRUE; + done = true; + return true; } else if (constraints->centreX.GetDone() && constraints->left.GetDone()) { value = (int)(2*(constraints->centreX.GetValue() - constraints->left.GetValue())); - done = TRUE; - return TRUE; + done = true; + return true; } else if (constraints->centreX.GetDone() && constraints->right.GetDone()) { value = (int)(2*(constraints->right.GetValue() - constraints->centreX.GetValue())); - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } default: break; @@ -708,22 +686,22 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (edgePos != -1) { value = (int)(edgePos*(((float)percent)*0.01)); - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } case wxAsIs: { if (win) { int w; - win->GetSize(&w, &value); - done = TRUE; - return TRUE; + wxGetAsIs(win, &w, &value); + done = true; + return true; } - else return FALSE; + else return false; } case wxUnconstrained: { @@ -733,23 +711,23 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr if (constraints->top.GetDone() && constraints->bottom.GetDone()) { value = constraints->bottom.GetValue() - constraints->top.GetValue(); - done = TRUE; - return TRUE; + done = true; + return true; } else if (constraints->top.GetDone() && constraints->centreY.GetDone()) { value = (int)(2*(constraints->centreY.GetValue() - constraints->top.GetValue())); - done = TRUE; - return TRUE; + done = true; + return true; } else if (constraints->bottom.GetDone() && constraints->centreY.GetDone()) { value = (int)(2*(constraints->bottom.GetValue() - constraints->centreY.GetValue())); - done = TRUE; - return TRUE; + done = true; + return true; } else - return FALSE; + return false; } default: break; @@ -759,7 +737,7 @@ bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constr default: break; } - return FALSE; + return false; } // Get the value of this edge or dimension, or if this is not determinable, -1. @@ -770,41 +748,41 @@ int wxIndividualLayoutConstraint::GetEdge(wxEdge which, // If the edge or dimension belongs to the parent, then we know the // dimension is obtainable immediately. E.g. a wxExpandSizer may contain a // button (but the button's true parent is a panel, not the sizer) - if (other->GetChildren().Find(thisWin)) + if (other->GetChildren().Find((wxWindow*)thisWin)) { switch (which) { case wxLeft: { - return wxSizerMarginX(other); + return 0; } case wxTop: { - return wxSizerMarginY(other); + return 0; } case wxRight: { int w, h; other->GetClientSizeConstraint(&w, &h); - return w - wxSizerMarginX(other); + return w; } case wxBottom: { int w, h; other->GetClientSizeConstraint(&w, &h); - return h - wxSizerMarginY(other); + return h; } case wxWidth: { int w, h; other->GetClientSizeConstraint(&w, &h); - return w - 2*wxSizerMarginX(other); + return w; } case wxHeight: { int w, h; other->GetClientSizeConstraint(&w, &h); - return h - 2*wxSizerMarginY(other); + return h; } case wxCentreX: case wxCentreY: @@ -996,51 +974,47 @@ wxLayoutConstraints::wxLayoutConstraints() height.SetEdge(wxHeight); } -wxLayoutConstraints::~wxLayoutConstraints() -{ -} - bool wxLayoutConstraints::SatisfyConstraints(wxWindowBase *win, int *nChanges) { int noChanges = 0; bool done = width.GetDone(); - bool newDone = (done ? TRUE : width.SatisfyConstraint(this, win)); + bool newDone = (done ? true : width.SatisfyConstraint(this, win)); if (newDone != done) noChanges ++; done = height.GetDone(); - newDone = (done ? TRUE : height.SatisfyConstraint(this, win)); + newDone = (done ? true : height.SatisfyConstraint(this, win)); if (newDone != done) noChanges ++; done = left.GetDone(); - newDone = (done ? TRUE : left.SatisfyConstraint(this, win)); + newDone = (done ? true : left.SatisfyConstraint(this, win)); if (newDone != done) noChanges ++; done = top.GetDone(); - newDone = (done ? TRUE : top.SatisfyConstraint(this, win)); + newDone = (done ? true : top.SatisfyConstraint(this, win)); if (newDone != done) noChanges ++; done = right.GetDone(); - newDone = (done ? TRUE : right.SatisfyConstraint(this, win)); + newDone = (done ? true : right.SatisfyConstraint(this, win)); if (newDone != done) noChanges ++; done = bottom.GetDone(); - newDone = (done ? TRUE : bottom.SatisfyConstraint(this, win)); + newDone = (done ? true : bottom.SatisfyConstraint(this, win)); if (newDone != done) noChanges ++; done = centreX.GetDone(); - newDone = (done ? TRUE : centreX.SatisfyConstraint(this, win)); + newDone = (done ? true : centreX.SatisfyConstraint(this, win)); if (newDone != done) noChanges ++; done = centreY.GetDone(); - newDone = (done ? TRUE : centreY.SatisfyConstraint(this, win)); + newDone = (done ? true : centreY.SatisfyConstraint(this, win)); if (newDone != done) noChanges ++; @@ -1049,720 +1023,4 @@ bool wxLayoutConstraints::SatisfyConstraints(wxWindowBase *win, int *nChanges) return AreSatisfied(); } -/* - * Main constrained layout algorithm. Look at all the child - * windows, and their constraints (if any). - * The idea is to keep iterating through the constraints - * until all left, right, bottom and top edges, and widths and heights, - * are known (or no change occurs and we've failed to resolve all - * constraints). - * - * If the user has not specified a dimension or edge, it will be - * be calculated from the other known values. E.g. If we know - * the right hand edge and the left hand edge, we now know the width. - * The snag here is that this means we must specify absolute dimensions - * twice (in constructor and in constraint), if we wish to use the - * constraint notation to just set the position, for example. - * Otherwise, if we only set ONE edge and no dimension, it would never - * find the other edge. - * - * Algorithm: - - Mark all constraints as not done. - - iterations = 0; - until no change or iterations >= max iterations - For each child: - { - Calculate all constraints - } - iterations ++; - - For each child - Set each calculated position and size - - */ - -#if WXWIN_COMPATIBILITY -bool wxOldDoLayout(wxWindowBase *win) -{ - // Make sure this isn't called recursively from below - static wxList doneSoFar; - - if (doneSoFar.Member(win)) - return TRUE; - - doneSoFar.Append(win); - - wxNode *node = win->GetChildren().First(); - while (node) - { - wxWindowBase *child = (wxWindowBase *)node->Data(); - wxLayoutConstraints *constr = child->GetConstraints(); - if (constr) - { - constr->left.SetDone(FALSE); - constr->top.SetDone(FALSE); - constr->right.SetDone(FALSE); - constr->bottom.SetDone(FALSE); - constr->width.SetDone(FALSE); - constr->height.SetDone(FALSE); - constr->centreX.SetDone(FALSE); - constr->centreY.SetDone(FALSE); - } - node = node->Next(); - } - int noIterations = 0; - int maxIterations = 500; - int noChanges = 1; - - while ((noChanges > 0) && (noIterations < maxIterations)) - { - noChanges = 0; - wxNode *node = win->GetChildren().First(); - while (node) - { - wxWindowBase *child = (wxWindowBase *)node->Data(); - wxLayoutConstraints *constr = child->GetConstraints(); - if (constr) - { - int tempNoChanges = 0; - (void)constr->SatisfyConstraints(child, &tempNoChanges); - noChanges += tempNoChanges; - } - node = node->Next(); - } - noIterations ++; - } -/* - // Would be nice to have a test here to see _which_ constraint(s) - // failed, so we can print a specific diagnostic message. - if (noFailures > 0) - { - wxDebugMsg(_("wxWindowBase::Layout() failed.\n")); - } -*/ - // Now set the sizes and positions of the children, and - // recursively call Layout(). - node = win->GetChildren().First(); - while (node) - { - wxWindowBase *child = (wxWindowBase *)node->Data(); - wxLayoutConstraints *constr = child->GetConstraints(); - if (constr && constr->left.GetDone() && constr->right.GetDone() && - constr->width.GetDone() && constr->height.GetDone()) - { - int x = constr->left.GetValue(); - int y = constr->top.GetValue(); - int w = constr->width.GetValue(); - int h = constr->height.GetValue(); - - // If we don't want to resize this window, just move it... - if ((constr->width.GetRelationship() != wxAsIs) || - (constr->height.GetRelationship() != wxAsIs)) - { - // _Should_ call Layout() recursively. - child->SetSize(x, y, w, h); - } - else - { - child->Move(x, y); - } - } - else - child->Layout(); - node = node->Next(); - } - doneSoFar.DeleteObject(win); - - return TRUE; -} -#endif // WXWIN_COMPATIBILITY - -wxSizer::wxSizer() -{ - sizerBehaviour = wxSizerNone; - borderX = 2; - borderY = 2; - sizerX = 0; - sizerY = 0; - sizerWidth = 0; - sizerHeight = 0; -} - -wxSizer::wxSizer(wxWindowBase *parent, wxSizerBehaviour behav) -{ - Create(parent, behav); -} - -bool wxSizer::Create(wxWindowBase *parent, wxSizerBehaviour behav) -{ - sizerBehaviour = behav; - borderX = 2; - borderY = 2; - m_sizerParent = parent; - sizerX = 0; - sizerY = 0; - sizerWidth = 0; - sizerHeight = 0; - - // A normal window can have just one top-level sizer - // associated with it. - if (!parent->IsKindOf(CLASSINFO(wxSizer))) - { - parent->SetSizer(this); - } - else - ((wxSizer *)parent)->AddSizerChild(this); - - switch (sizerBehaviour) - { - case wxSizerExpand: - { - // Defines a set of constraints - // to expand the sizer to fit the parent window - wxLayoutConstraints *c = new wxLayoutConstraints; - - c->left.SameAs(parent, wxLeft, 0); - c->top.SameAs(parent, wxTop, 0); - c->right.SameAs(parent, wxRight, 0); - c->bottom.SameAs(parent, wxBottom, 0); - - SetConstraints(c); - break; - } - case wxSizerShrink: - case wxSizerNone: - default: - { - } - } - return TRUE; -} - -wxSizer::~wxSizer() -{ - // Remove all children without deleting them, - // or ~wxbWindow will delete proper windows _twice_ - wxNode *node = GetChildren().First(); - while (node) - { - wxNode *next = node->Next(); - wxWindowBase *win = (wxWindowBase *)node->Data(); - if (!win->IsKindOf(CLASSINFO(wxSizer))) - { - delete node; - win->SetSizerParent((wxWindowBase *) NULL); - } - else - { - RemoveSizerChild(win); - delete win; - } - node = next; - } - - if (m_sizerParent) // && !m_sizerParent->IsKindOf(CLASSINFO(wxSizer))) - { - m_sizerParent->SetSizer((wxSizer *) NULL); - m_sizerParent = (wxWindowBase *) NULL; - } - -} - -void wxSizer::SetBorder(int x, int y) -{ - borderX = x; - borderY = y; - /* No: the margin is for inside, not outside (expansion) - - if ( GetConstraints() ) - { - GetConstraints()->left.SetMargin(x); - GetConstraints()->right.SetMargin(x); - GetConstraints()->top.SetMargin(y); - GetConstraints()->bottom.SetMargin(y); - } - */ - -} - -void wxSizer::AddSizerChild(wxWindowBase *child) -{ - child->SetSizerParent(this); - GetChildren().Append(child); - - // Add some constraints for the purpose of storing - // the relative position of the window/sizer - // during layout calculations. - if (!child->GetConstraints()) - { - wxLayoutConstraints *c = new wxLayoutConstraints; - c->left.AsIs(); - c->top.AsIs(); - c->width.AsIs(); - c->height.AsIs(); - int w, h; - child->GetSize(&w, &h); - c->width.SetValue(w); - c->height.SetValue(h); - - child->SetConstraints(c); - } -} - -void wxSizer::RemoveSizerChild(wxWindowBase *child) -{ - GetChildren().DeleteObject(child); -} - -void wxSizer::DoSetSize(int x, int y, int w, int h, int WXUNUSED(flags)) -{ - wxLayoutConstraints *constr = GetConstraints(); - if (x != -1) - { - sizerX = x; - if (constr) - constr->left.SetValue(x); - } - if (y != -1) - { - sizerY = y; - if (constr) - constr->top.SetValue(y); - } - if (w != -1) - { - sizerWidth = w; - if (constr) - constr->width.SetValue(w); - } - if (h != -1) - { - sizerHeight = h; - if (constr) - constr->height.SetValue(h); - } -} - -void wxSizer::DoGetSize(int *w, int *h) const -{ - *w = sizerWidth; - *h = sizerHeight; -} - -void wxSizer::DoGetPosition(int *x, int *y) const -{ - *x = sizerX; - *y = sizerY; -} - -bool wxSizer::LayoutPhase1(int *noChanges) -{ - *noChanges = 0; - switch (sizerBehaviour) - { - case wxSizerExpand: - { - if (!m_sizerParent) - { - wxMessageBox(_("wxExpandSizer has no parent!"), _("Sizer error"), wxOK); - return TRUE; - } - - // Set the size to fill the parent client area - int pw, ph; - m_sizerParent->GetClientSize(&pw, &ph); - SetSize(GetBorderX(), GetBorderY(), pw - 2*GetBorderX(), ph - 2*GetBorderY()); - wxLayoutConstraints *constr = GetConstraints(); - - // Fill in the constraints - if (constr) - { - constr->left.SetValue(0); constr->left.SetDone(TRUE); - constr->top.SetValue(0); constr->right.SetDone(TRUE); - constr->width.SetValue(pw); constr->width.SetDone(TRUE); - constr->height.SetValue(ph); constr->height.SetDone(TRUE); - } - - return TRUE; - break; - } - case wxSizerShrink: - { - wxLayoutConstraints *constr = GetConstraints(); - - if (constr) - { - // Force the constraint to have as-is width and height - // if we're in shrink-to-fit mode, because if left unconstrained, - // SatisfyConstraints will fail. The shrink-to-fit option - // essentially specifies the width and height as 'whatever I calculate'. - constr->width.AsIs(); - constr->height.AsIs(); - } - DoPhase(1); - DoPhase(2); - // Find the bounding box and set own size - int maxX = 0; - int maxY = 0; - - wxNode *node = GetChildren().First(); - while (node) - { - int x, y, width, height; - wxWindowBase *win = (wxWindowBase *)node->Data(); - win->GetSizeConstraint(&width, &height); - win->GetPositionConstraint(&x, &y); - if ((x+width) > maxX) - maxX = (x + width); - if ((y+height) > maxY) - maxY = (y + height); - - node = node->Next(); - } - SetSize(GetBorderX(), GetBorderY(), maxX, maxY); - - // If this is the only sizer for the parent, size the parent to this sizer. - if ( m_sizerParent && (m_sizerParent->GetSizer() == this) ) - m_sizerParent->SetClientSize(maxX + 2*GetBorderX(), maxY + 2*GetBorderY()); - - return TRUE; - break; - } - case wxSizerNone: - { - wxLayoutConstraints *constr = GetConstraints(); - if (constr) - { - bool success = constr->SatisfyConstraints(this, noChanges); - if (success) - { - int x = constr->left.GetValue(); - int y = constr->top.GetValue(); - int w = constr->width.GetValue(); - int h = constr->height.GetValue(); - SetSize(x, y, w, h); - } - return success; - } - else - return TRUE; - break; - } - } - return TRUE; - -} - -bool wxSizer::LayoutPhase2(int *noChanges) -{ - *noChanges = 0; - - switch (sizerBehaviour) - { - case wxSizerExpand: - { - // Layout children - DoPhase(1); - DoPhase(2); - return TRUE; - } - case wxSizerShrink: - { - wxLayoutConstraints *constr = GetConstraints(); - if (constr) - { - bool success = constr->SatisfyConstraints(this, noChanges); - if (success) - { - int x = constr->left.GetValue(); - int y = constr->top.GetValue(); - Move(x, y); - } - return success; - } - break; - } - case wxSizerNone: - { - // Layout children - DoPhase(1); - DoPhase(2); - - // Is this a dumb fix for lack of constraint evaluation? - wxLayoutConstraints *constr = GetConstraints(); - if (constr) - { - bool success = constr->SatisfyConstraints(this, noChanges); - if (success) - { - int x = constr->left.GetValue(); - int y = constr->top.GetValue(); - int w = constr->width.GetValue(); - int h = constr->height.GetValue(); - SetSize(x, y, w, h); - } - return success; - } - else - return TRUE; - } - } - return TRUE; -} - -/* - * wxRowColSizer - */ - -wxRowColSizer::wxRowColSizer() -{ - rowOrCol = TRUE; - rowOrColSize = 20; - xSpacing = 2; - ySpacing = 2; -} - -wxRowColSizer::wxRowColSizer(wxWindowBase *parent, bool rc, int n, wxSizerBehaviour behav) -{ - Create(parent, rc, n, behav); -} - -bool wxRowColSizer::Create(wxWindowBase *parent, bool rc, int n, wxSizerBehaviour behav) -{ - wxSizer::Create(parent, behav); - - rowOrCol = rc; - rowOrColSize = n; - xSpacing = 2; - ySpacing = 2; - - return TRUE; -} - -wxRowColSizer::~wxRowColSizer() -{ -} - -bool wxRowColSizer::LayoutPhase1(int *noChanges) -{ - *noChanges = 0; - wxLayoutConstraints *constr = GetConstraints(); - - if (constr) - { - // Force the constraint to have as-is width and height - // if we're in shrink-to-fit mode, because if left unconstrained, - // SatisfyConstraints will fail. The shrink-to-fit option - // essentially specifies the width and height as 'whatever I calculate'. - if (sizerBehaviour == wxSizerShrink) - { - constr->width.AsIs(); - constr->height.AsIs(); - } - - // Only evaluate the constraints FIRST if we're NOT - // in shrink-to-fit mode, i.e. we want to size the rowcol - // first, then lay the children out in the space we've calculated. - if (sizerBehaviour != wxSizerShrink) - { - bool success = constr->SatisfyConstraints(this, noChanges); - if (success) - { - int x = constr->left.GetValue(); - int y = constr->top.GetValue(); - int w = constr->width.GetValue(); - int h = constr->height.GetValue(); - SetSize(x, y, w, h); - } - else - return FALSE; - - // Continue to do the rest of the phase when the constraints have been - // satisfied, i.e. we're on the last iteration of phase 1 and - // can now do the actual rowcol laying out. - } - } - - // If we ARE in shrink-to-fit mode, we must now - // calculate the child sizes BEFORE laying out in rows or columns. - if (sizerBehaviour == wxSizerShrink) - { - DoPhase(1); - DoPhase(2); - - // WILL THE WINDOW BE SIZED CORRECTLY AT THIS POINT? - // CHECK CONSTRAINTS IF ANY... - int noRows = 0; - int noCols = 0; - int currentX = borderX; - int currentY = borderY; - int maxX = currentX; - int maxY = currentY; - - wxNode *node = GetChildren().First(); - while (node) - { - wxWindowBase *win = (wxWindowBase *)node->Data(); - int childWidth, childHeight; - if (win->GetConstraints() && - win->GetConstraints()->width.GetDone() && - win->GetConstraints()->height.GetDone()) - { - childWidth = win->GetConstraints()->width.GetValue(); - childHeight = win->GetConstraints()->height.GetValue(); - } - else - win->GetSize(&childWidth, &childHeight); - - win->MoveConstraint(currentX, currentY); - - if ((currentX + childWidth) > maxX) - maxX = (currentX + childWidth); - if ((currentY + childHeight) > maxY) - maxY = (currentY + childHeight); - - if (rowOrCol) - { - currentX += childWidth + xSpacing; - noCols ++; - - // Reset to start of row - if (noCols == rowOrColSize) - { - currentX = borderX; - currentY += childHeight + ySpacing; - noCols = 0; - } - } - else - { - currentY += childHeight + ySpacing; - noRows ++; - - // Reset to start of col - if (noRows == rowOrColSize) - { - currentY = borderY; - currentX += childWidth + xSpacing; - noRows = 0; - } - } - - node = node->Next(); - } - maxX += borderX; - maxY += borderY; - - SetSize(-1, -1, maxX, maxY); - } - return TRUE; -} - -bool wxRowColSizer::LayoutPhase2(int *noChanges) -{ - *noChanges = 0; - - // If shrink-to-fit, it's only at Phase 2 that we know the size of - // the wxRowColSizer, and now we can evaluate the - // constraints and pass result back up to parent. - // This implements a depth-first strategy - if (sizerBehaviour == wxSizerShrink) - { - wxLayoutConstraints *constr = GetConstraints(); - if (constr) - { - bool success = constr->SatisfyConstraints(this, noChanges); - if (success) - { - int x = constr->left.GetValue(); - int y = constr->top.GetValue(); - Move(x, y); - } - return success; - } - else return TRUE; - } - else - { - // Lay out the children: breadth-first strategy. - DoPhase(1); - DoPhase(2); - - // Space them - } - return TRUE; -} - - -/* - * wxSpacingSizer - */ - -wxSpacingSizer::wxSpacingSizer() -{ -} - -wxSpacingSizer::wxSpacingSizer(wxWindowBase *parent) -{ - Create(parent); -} - -wxSpacingSizer::wxSpacingSizer(wxWindowBase *parent, wxRelationship rel, wxWindowBase *other, int spacing) -{ - Create(parent, rel, other, spacing); -} - -bool wxSpacingSizer::Create(wxWindowBase *parent) -{ - wxSizer::Create(parent); - return TRUE; -} - -bool wxSpacingSizer::Create(wxWindowBase *parent, wxRelationship rel, wxWindowBase *other, int spacing) -{ - wxLayoutConstraints *c = new wxLayoutConstraints; - - wxSizer::Create(parent); - - switch ( rel ) - { - case wxLeftOf : - c->width.Absolute (spacing); - c->top.SameAs (other, wxTop); - c->bottom.SameAs (other, wxBottom); - c->right.LeftOf (other); - break; - case wxRightOf : - c->width.Absolute (spacing); - c->top.SameAs (other, wxTop); - c->bottom.SameAs (other, wxBottom); - c->left.RightOf (other); - break; - case wxBelow : - c->height.Absolute (spacing); - c->left.SameAs (other, wxLeft); - c->right.SameAs (other, wxRight); - c->top.Below (other); - break; - case wxAbove : - c->height.Absolute (spacing); - c->left.SameAs (other, wxLeft); - c->right.SameAs (other, wxRight); - c->bottom.Above (other); - break; - - default : - break; - } - SetConstraints(c); - - return TRUE; -} - -wxSpacingSizer::~wxSpacingSizer() -{ -} - #endif // wxUSE_CONSTRAINTS