Replaced old wxSizer,

Converted two of wxGTK's standard dialogs to use them,
  Applied two fixes to wxDC code,
  Made wxRadiobox a little smaller,
  Added sizer.h to wx.h


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@3325 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robert Roebling
1999-08-09 17:00:51 +00:00
parent d597fcb781
commit 3417c2cd3d
19 changed files with 303 additions and 1346 deletions

View File

@@ -47,57 +47,8 @@
#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.
*/
// Find margin sizes if a sizer, or zero otherwise
int wxSizerMarginX(wxWindowBase *win)
{
if ( win->IsKindOf(CLASSINFO(wxSizer)) )
{
wxSizer *sizer = (wxSizer *)win;
return sizer->GetBorderX();
}
else
return 0;
}
int wxSizerMarginY(wxWindowBase *win)
{
if ( win->IsKindOf(CLASSINFO(wxSizer)) )
{
wxSizer *sizer = (wxSizer *)win;
return sizer->GetBorderY();
}
else
return 0;
}
wxIndividualLayoutConstraint::wxIndividualLayoutConstraint()
{
@@ -778,35 +729,35 @@ int wxIndividualLayoutConstraint::GetEdge(wxEdge 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:
@@ -1181,590 +1132,4 @@ bool wxOldDoLayout(wxWindowBase *win)
}
#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