git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@8831 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
1139 lines
37 KiB
C++
1139 lines
37 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: 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
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// =============================================================================
|
|
// declarations
|
|
// =============================================================================
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// headers
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#ifdef __GNUG__
|
|
#pragma implementation "layout.h"
|
|
#endif
|
|
|
|
// For compilers that support precompilation, includes "wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
#ifdef __BORLANDC__
|
|
#pragma hdrstop
|
|
#endif
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/defs.h"
|
|
#endif
|
|
|
|
#if wxUSE_CONSTRAINTS
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/window.h"
|
|
#include "wx/utils.h"
|
|
#include "wx/dialog.h"
|
|
#include "wx/msgdlg.h"
|
|
#include "wx/intl.h"
|
|
#endif
|
|
|
|
#include "wx/layout.h"
|
|
|
|
IMPLEMENT_DYNAMIC_CLASS(wxIndividualLayoutConstraint, wxObject)
|
|
IMPLEMENT_DYNAMIC_CLASS(wxLayoutConstraints, wxObject)
|
|
|
|
|
|
wxIndividualLayoutConstraint::wxIndividualLayoutConstraint()
|
|
{
|
|
myEdge = wxTop;
|
|
relationship = wxUnconstrained;
|
|
margin = 0;
|
|
value = 0;
|
|
percent = 0;
|
|
otherEdge = wxTop;
|
|
done = FALSE;
|
|
otherWin = (wxWindowBase *) NULL;
|
|
}
|
|
|
|
wxIndividualLayoutConstraint::~wxIndividualLayoutConstraint()
|
|
{
|
|
}
|
|
|
|
void wxIndividualLayoutConstraint::Set(wxRelationship rel, wxWindowBase *otherW, wxEdge otherE, int val, int marg)
|
|
{
|
|
relationship = rel;
|
|
otherWin = otherW;
|
|
otherEdge = otherE;
|
|
|
|
if ( rel == wxPercentOf )
|
|
{
|
|
percent = val;
|
|
}
|
|
else
|
|
{
|
|
value = val;
|
|
}
|
|
|
|
margin = marg;
|
|
}
|
|
|
|
void wxIndividualLayoutConstraint::LeftOf(wxWindowBase *sibling, int marg)
|
|
{
|
|
Set(wxLeftOf, sibling, wxLeft, 0, marg);
|
|
}
|
|
|
|
void wxIndividualLayoutConstraint::RightOf(wxWindowBase *sibling, int marg)
|
|
{
|
|
Set(wxRightOf, sibling, wxRight, 0, marg);
|
|
}
|
|
|
|
void wxIndividualLayoutConstraint::Above(wxWindowBase *sibling, int marg)
|
|
{
|
|
Set(wxAbove, sibling, wxTop, 0, marg);
|
|
}
|
|
|
|
void wxIndividualLayoutConstraint::Below(wxWindowBase *sibling, int marg)
|
|
{
|
|
Set(wxBelow, sibling, wxBottom, 0, marg);
|
|
}
|
|
|
|
//
|
|
// 'Same edge' alignment
|
|
//
|
|
void wxIndividualLayoutConstraint::SameAs(wxWindowBase *otherW, wxEdge edge, int marg)
|
|
{
|
|
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)
|
|
{
|
|
Set(wxPercentOf, otherW, wh, per);
|
|
}
|
|
|
|
//
|
|
// Edge has absolute value
|
|
//
|
|
void wxIndividualLayoutConstraint::Absolute(int val)
|
|
{
|
|
value = val;
|
|
relationship = wxAbsolute;
|
|
}
|
|
|
|
// Reset constraint if it mentions otherWin
|
|
bool wxIndividualLayoutConstraint::ResetIfWin(wxWindowBase *otherW)
|
|
{
|
|
if (otherW == otherWin)
|
|
{
|
|
myEdge = wxTop;
|
|
relationship = wxAsIs;
|
|
margin = 0;
|
|
value = 0;
|
|
percent = 0;
|
|
otherEdge = wxTop;
|
|
otherWin = (wxWindowBase *) NULL;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
// Try to satisfy constraint
|
|
bool wxIndividualLayoutConstraint::SatisfyConstraint(wxLayoutConstraints *constraints, wxWindowBase *win)
|
|
{
|
|
if (relationship == wxAbsolute)
|
|
{
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
|
|
switch (myEdge)
|
|
{
|
|
case wxLeft:
|
|
{
|
|
switch (relationship)
|
|
{
|
|
case wxLeftOf:
|
|
{
|
|
// We can know this edge if: otherWin is win's
|
|
// parent, or otherWin has a satisfied constraint,
|
|
// or otherWin has no constraint.
|
|
int edgePos = GetEdge(otherEdge, win, otherWin);
|
|
if (edgePos != -1)
|
|
{
|
|
value = edgePos - margin;
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
case wxRightOf:
|
|
{
|
|
int edgePos = GetEdge(otherEdge, win, otherWin);
|
|
if (edgePos != -1)
|
|
{
|
|
value = edgePos + margin;
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
case wxPercentOf:
|
|
{
|
|
int edgePos = GetEdge(otherEdge, win, otherWin);
|
|
if (edgePos != -1)
|
|
{
|
|
value = (int)(edgePos*(((float)percent)*0.01) + margin);
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
case wxUnconstrained:
|
|
{
|
|
// We know the left-hand edge position if we know
|
|
// the right-hand edge and we know the width; OR if
|
|
// we know the centre and the width.
|
|
if (constraints->right.GetDone() && constraints->width.GetDone())
|
|
{
|
|
value = (constraints->right.GetValue() - constraints->width.GetValue() + margin);
|
|
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;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
case wxAsIs:
|
|
{
|
|
int y;
|
|
win->GetPosition(&value, &y);
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case wxRight:
|
|
{
|
|
switch (relationship)
|
|
{
|
|
case wxLeftOf:
|
|
{
|
|
// We can know this edge if: otherWin is win's
|
|
// parent, or otherWin has a satisfied constraint,
|
|
// or otherWin has no constraint.
|
|
int edgePos = GetEdge(otherEdge, win, otherWin);
|
|
if (edgePos != -1)
|
|
{
|
|
value = edgePos - margin;
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
case wxRightOf:
|
|
{
|
|
int edgePos = GetEdge(otherEdge, win, otherWin);
|
|
if (edgePos != -1)
|
|
{
|
|
value = edgePos + margin;
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
case wxPercentOf:
|
|
{
|
|
int edgePos = GetEdge(otherEdge, win, otherWin);
|
|
if (edgePos != -1)
|
|
{
|
|
value = (int)(edgePos*(((float)percent)*0.01) - margin);
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
case wxUnconstrained:
|
|
{
|
|
// We know the right-hand edge position if we know the
|
|
// left-hand edge and we know the width, OR if we know the
|
|
// centre edge and the width.
|
|
if (constraints->left.GetDone() && constraints->width.GetDone())
|
|
{
|
|
value = (constraints->left.GetValue() + constraints->width.GetValue() - margin);
|
|
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;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
case wxAsIs:
|
|
{
|
|
int x, y;
|
|
int w, h;
|
|
win->GetSize(&w, &h);
|
|
win->GetPosition(&x, &y);
|
|
value = x + w;
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case wxTop:
|
|
{
|
|
switch (relationship)
|
|
{
|
|
case wxAbove:
|
|
{
|
|
// We can know this edge if: otherWin is win's
|
|
// parent, or otherWin has a satisfied constraint,
|
|
// or otherWin has no constraint.
|
|
int edgePos = GetEdge(otherEdge, win, otherWin);
|
|
if (edgePos != -1)
|
|
{
|
|
value = edgePos - margin;
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
case wxBelow:
|
|
{
|
|
int edgePos = GetEdge(otherEdge, win, otherWin);
|
|
if (edgePos != -1)
|
|
{
|
|
value = edgePos + margin;
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
case wxPercentOf:
|
|
{
|
|
int edgePos = GetEdge(otherEdge, win, otherWin);
|
|
if (edgePos != -1)
|
|
{
|
|
value = (int)(edgePos*(((float)percent)*0.01) + margin);
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
case wxUnconstrained:
|
|
{
|
|
// We know the top edge position if we know the bottom edge
|
|
// and we know the height; OR if we know the centre edge and
|
|
// the height.
|
|
if (constraints->bottom.GetDone() && constraints->height.GetDone())
|
|
{
|
|
value = (constraints->bottom.GetValue() - constraints->height.GetValue() + margin);
|
|
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;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
case wxAsIs:
|
|
{
|
|
int x;
|
|
win->GetPosition(&x, &value);
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case wxBottom:
|
|
{
|
|
switch (relationship)
|
|
{
|
|
case wxAbove:
|
|
{
|
|
// We can know this edge if: otherWin is win's parent,
|
|
// or otherWin has a satisfied constraint, or
|
|
// otherWin has no constraint.
|
|
int edgePos = GetEdge(otherEdge, win, otherWin);
|
|
if (edgePos != -1)
|
|
{
|
|
value = edgePos + margin;
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
case wxBelow:
|
|
{
|
|
int edgePos = GetEdge(otherEdge, win, otherWin);
|
|
if (edgePos != -1)
|
|
{
|
|
value = edgePos - margin;
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
case wxPercentOf:
|
|
{
|
|
int edgePos = GetEdge(otherEdge, win, otherWin);
|
|
if (edgePos != -1)
|
|
{
|
|
value = (int)(edgePos*(((float)percent)*0.01) - margin);
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
case wxUnconstrained:
|
|
{
|
|
// We know the bottom edge position if we know the top edge
|
|
// and we know the height; OR if we know the centre edge and
|
|
// the height.
|
|
if (constraints->top.GetDone() && constraints->height.GetDone())
|
|
{
|
|
value = (constraints->top.GetValue() + constraints->height.GetValue() - margin);
|
|
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;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
case wxAsIs:
|
|
{
|
|
int x, y;
|
|
int w, h;
|
|
win->GetSize(&w, &h);
|
|
win->GetPosition(&x, &y);
|
|
value = h + y;
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case wxCentreX:
|
|
{
|
|
switch (relationship)
|
|
{
|
|
case wxLeftOf:
|
|
{
|
|
// We can know this edge if: otherWin is win's parent, or
|
|
// otherWin has a satisfied constraint, or otherWin has no
|
|
// constraint.
|
|
int edgePos = GetEdge(otherEdge, win, otherWin);
|
|
if (edgePos != -1)
|
|
{
|
|
value = edgePos - margin;
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
case wxRightOf:
|
|
{
|
|
int edgePos = GetEdge(otherEdge, win, otherWin);
|
|
if (edgePos != -1)
|
|
{
|
|
value = edgePos + margin;
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
case wxPercentOf:
|
|
{
|
|
int edgePos = GetEdge(otherEdge, win, otherWin);
|
|
if (edgePos != -1)
|
|
{
|
|
value = (int)(edgePos*(((float)percent)*0.01) + margin);
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
case wxUnconstrained:
|
|
{
|
|
// We know the centre position if we know
|
|
// the left-hand edge and we know the width, OR
|
|
// the right-hand edge and the width
|
|
if (constraints->left.GetDone() && constraints->width.GetDone())
|
|
{
|
|
value = (int)(constraints->left.GetValue() + (constraints->width.GetValue()/2) + margin);
|
|
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;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case wxCentreY:
|
|
{
|
|
switch (relationship)
|
|
{
|
|
case wxAbove:
|
|
{
|
|
// We can know this edge if: otherWin is win's parent,
|
|
// or otherWin has a satisfied constraint, or otherWin
|
|
// has no constraint.
|
|
int edgePos = GetEdge(otherEdge, win, otherWin);
|
|
if (edgePos != -1)
|
|
{
|
|
value = edgePos - margin;
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
case wxBelow:
|
|
{
|
|
int edgePos = GetEdge(otherEdge, win, otherWin);
|
|
if (edgePos != -1)
|
|
{
|
|
value = edgePos + margin;
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
case wxPercentOf:
|
|
{
|
|
int edgePos = GetEdge(otherEdge, win, otherWin);
|
|
if (edgePos != -1)
|
|
{
|
|
value = (int)(edgePos*(((float)percent)*0.01) + margin);
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
case wxUnconstrained:
|
|
{
|
|
// We know the centre position if we know
|
|
// the top edge and we know the height, OR
|
|
// the bottom edge and the height.
|
|
if (constraints->bottom.GetDone() && constraints->height.GetDone())
|
|
{
|
|
value = (int)(constraints->bottom.GetValue() - (constraints->height.GetValue()/2) + margin);
|
|
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;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case wxWidth:
|
|
{
|
|
switch (relationship)
|
|
{
|
|
case wxPercentOf:
|
|
{
|
|
int edgePos = GetEdge(otherEdge, win, otherWin);
|
|
if (edgePos != -1)
|
|
{
|
|
value = (int)(edgePos*(((float)percent)*0.01));
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
case wxAsIs:
|
|
{
|
|
if (win)
|
|
{
|
|
int h;
|
|
win->GetSize(&value, &h);
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
else return FALSE;
|
|
}
|
|
case wxUnconstrained:
|
|
{
|
|
// We know the width if we know the left edge and the right edge, OR
|
|
// if we know the left edge and the centre, OR
|
|
// if we know the right edge and the centre
|
|
if (constraints->left.GetDone() && constraints->right.GetDone())
|
|
{
|
|
value = constraints->right.GetValue() - constraints->left.GetValue();
|
|
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;
|
|
}
|
|
else if (constraints->centreX.GetDone() && constraints->right.GetDone())
|
|
{
|
|
value = (int)(2*(constraints->right.GetValue() - constraints->centreX.GetValue()));
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case wxHeight:
|
|
{
|
|
switch (relationship)
|
|
{
|
|
case wxPercentOf:
|
|
{
|
|
int edgePos = GetEdge(otherEdge, win, otherWin);
|
|
if (edgePos != -1)
|
|
{
|
|
value = (int)(edgePos*(((float)percent)*0.01));
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
case wxAsIs:
|
|
{
|
|
if (win)
|
|
{
|
|
int w;
|
|
win->GetSize(&w, &value);
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
else return FALSE;
|
|
}
|
|
case wxUnconstrained:
|
|
{
|
|
// We know the height if we know the top edge and the bottom edge, OR
|
|
// if we know the top edge and the centre, OR
|
|
// if we know the bottom edge and the centre
|
|
if (constraints->top.GetDone() && constraints->bottom.GetDone())
|
|
{
|
|
value = constraints->bottom.GetValue() - constraints->top.GetValue();
|
|
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;
|
|
}
|
|
else if (constraints->bottom.GetDone() && constraints->centreY.GetDone())
|
|
{
|
|
value = (int)(2*(constraints->bottom.GetValue() - constraints->centreY.GetValue()));
|
|
done = TRUE;
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
// Get the value of this edge or dimension, or if this is not determinable, -1.
|
|
int wxIndividualLayoutConstraint::GetEdge(wxEdge which,
|
|
wxWindowBase *thisWin,
|
|
wxWindowBase *other) const
|
|
{
|
|
// 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))
|
|
{
|
|
switch (which)
|
|
{
|
|
case wxLeft:
|
|
{
|
|
return 0;
|
|
}
|
|
case wxTop:
|
|
{
|
|
return 0;
|
|
}
|
|
case wxRight:
|
|
{
|
|
int w, h;
|
|
other->GetClientSizeConstraint(&w, &h);
|
|
return w;
|
|
}
|
|
case wxBottom:
|
|
{
|
|
int w, h;
|
|
other->GetClientSizeConstraint(&w, &h);
|
|
return h;
|
|
}
|
|
case wxWidth:
|
|
{
|
|
int w, h;
|
|
other->GetClientSizeConstraint(&w, &h);
|
|
return w;
|
|
}
|
|
case wxHeight:
|
|
{
|
|
int w, h;
|
|
other->GetClientSizeConstraint(&w, &h);
|
|
return h;
|
|
}
|
|
case wxCentreX:
|
|
case wxCentreY:
|
|
{
|
|
int w, h;
|
|
other->GetClientSizeConstraint(&w, &h);
|
|
if (which == wxCentreX)
|
|
return (int)(w/2);
|
|
else
|
|
return (int)(h/2);
|
|
}
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
switch (which)
|
|
{
|
|
case wxLeft:
|
|
{
|
|
wxLayoutConstraints *constr = other->GetConstraints();
|
|
// If no constraints, it means the window is not dependent
|
|
// on anything, and therefore we know its value immediately
|
|
if (constr)
|
|
{
|
|
if (constr->left.GetDone())
|
|
return constr->left.GetValue();
|
|
else
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
int x, y;
|
|
other->GetPosition(&x, &y);
|
|
return x;
|
|
}
|
|
}
|
|
case wxTop:
|
|
{
|
|
wxLayoutConstraints *constr = other->GetConstraints();
|
|
// If no constraints, it means the window is not dependent
|
|
// on anything, and therefore we know its value immediately
|
|
if (constr)
|
|
{
|
|
if (constr->top.GetDone())
|
|
return constr->top.GetValue();
|
|
else
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
int x, y;
|
|
other->GetPosition(&x, &y);
|
|
return y;
|
|
}
|
|
}
|
|
case wxRight:
|
|
{
|
|
wxLayoutConstraints *constr = other->GetConstraints();
|
|
// If no constraints, it means the window is not dependent
|
|
// on anything, and therefore we know its value immediately
|
|
if (constr)
|
|
{
|
|
if (constr->right.GetDone())
|
|
return constr->right.GetValue();
|
|
else
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
int x, y, w, h;
|
|
other->GetPosition(&x, &y);
|
|
other->GetSize(&w, &h);
|
|
return (int)(x + w);
|
|
}
|
|
}
|
|
case wxBottom:
|
|
{
|
|
wxLayoutConstraints *constr = other->GetConstraints();
|
|
// If no constraints, it means the window is not dependent
|
|
// on anything, and therefore we know its value immediately
|
|
if (constr)
|
|
{
|
|
if (constr->bottom.GetDone())
|
|
return constr->bottom.GetValue();
|
|
else
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
int x, y, w, h;
|
|
other->GetPosition(&x, &y);
|
|
other->GetSize(&w, &h);
|
|
return (int)(y + h);
|
|
}
|
|
}
|
|
case wxWidth:
|
|
{
|
|
wxLayoutConstraints *constr = other->GetConstraints();
|
|
// If no constraints, it means the window is not dependent
|
|
// on anything, and therefore we know its value immediately
|
|
if (constr)
|
|
{
|
|
if (constr->width.GetDone())
|
|
return constr->width.GetValue();
|
|
else
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
int w, h;
|
|
other->GetSize(&w, &h);
|
|
return w;
|
|
}
|
|
}
|
|
case wxHeight:
|
|
{
|
|
wxLayoutConstraints *constr = other->GetConstraints();
|
|
// If no constraints, it means the window is not dependent
|
|
// on anything, and therefore we know its value immediately
|
|
if (constr)
|
|
{
|
|
if (constr->height.GetDone())
|
|
return constr->height.GetValue();
|
|
else
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
int w, h;
|
|
other->GetSize(&w, &h);
|
|
return h;
|
|
}
|
|
}
|
|
case wxCentreX:
|
|
{
|
|
wxLayoutConstraints *constr = other->GetConstraints();
|
|
// If no constraints, it means the window is not dependent
|
|
// on anything, and therefore we know its value immediately
|
|
if (constr)
|
|
{
|
|
if (constr->centreX.GetDone())
|
|
return constr->centreX.GetValue();
|
|
else
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
int x, y, w, h;
|
|
other->GetPosition(&x, &y);
|
|
other->GetSize(&w, &h);
|
|
return (int)(x + (w/2));
|
|
}
|
|
}
|
|
case wxCentreY:
|
|
{
|
|
wxLayoutConstraints *constr = other->GetConstraints();
|
|
// If no constraints, it means the window is not dependent
|
|
// on anything, and therefore we know its value immediately
|
|
if (constr)
|
|
{
|
|
if (constr->centreY.GetDone())
|
|
return constr->centreY.GetValue();
|
|
else
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
int x, y, w, h;
|
|
other->GetPosition(&x, &y);
|
|
other->GetSize(&w, &h);
|
|
return (int)(y + (h/2));
|
|
}
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
wxLayoutConstraints::wxLayoutConstraints()
|
|
{
|
|
left.SetEdge(wxLeft);
|
|
top.SetEdge(wxTop);
|
|
right.SetEdge(wxRight);
|
|
bottom.SetEdge(wxBottom);
|
|
centreX.SetEdge(wxCentreX);
|
|
centreY.SetEdge(wxCentreY);
|
|
width.SetEdge(wxWidth);
|
|
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));
|
|
if (newDone != done)
|
|
noChanges ++;
|
|
|
|
done = height.GetDone();
|
|
newDone = (done ? TRUE : height.SatisfyConstraint(this, win));
|
|
if (newDone != done)
|
|
noChanges ++;
|
|
|
|
done = left.GetDone();
|
|
newDone = (done ? TRUE : left.SatisfyConstraint(this, win));
|
|
if (newDone != done)
|
|
noChanges ++;
|
|
|
|
done = top.GetDone();
|
|
newDone = (done ? TRUE : top.SatisfyConstraint(this, win));
|
|
if (newDone != done)
|
|
noChanges ++;
|
|
|
|
done = right.GetDone();
|
|
newDone = (done ? TRUE : right.SatisfyConstraint(this, win));
|
|
if (newDone != done)
|
|
noChanges ++;
|
|
|
|
done = bottom.GetDone();
|
|
newDone = (done ? TRUE : bottom.SatisfyConstraint(this, win));
|
|
if (newDone != done)
|
|
noChanges ++;
|
|
|
|
done = centreX.GetDone();
|
|
newDone = (done ? TRUE : centreX.SatisfyConstraint(this, win));
|
|
if (newDone != done)
|
|
noChanges ++;
|
|
|
|
done = centreY.GetDone();
|
|
newDone = (done ? TRUE : centreY.SatisfyConstraint(this, win));
|
|
if (newDone != done)
|
|
noChanges ++;
|
|
|
|
*nChanges = noChanges;
|
|
|
|
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
|
|
|
|
#endif // wxUSE_CONSTRAINTS
|