+ node = node->GetNext();
+ }
+ }
+}
+
+bool wxWindowBase::Validate()
+{
+#if wxUSE_VALIDATORS
+ wxWindowList::Node *node;
+ for ( node = m_children.GetFirst(); node; node = node->GetNext() )
+ {
+ wxWindowBase *child = node->GetData();
+ wxValidator *validator = child->GetValidator();
+ if ( validator && !validator->Validate((wxWindow *)this) )
+ {
+ return FALSE;
+ }
+ }
+#endif // wxUSE_VALIDATORS
+
+ return TRUE;
+}
+
+bool wxWindowBase::TransferDataToWindow()
+{
+#if wxUSE_VALIDATORS
+ wxWindowList::Node *node;
+ for ( node = m_children.GetFirst(); node; node = node->GetNext() )
+ {
+ wxWindowBase *child = node->GetData();
+ wxValidator *validator = child->GetValidator();
+ if ( validator && !validator->TransferToWindow() )
+ {
+ wxLog *log = wxLog::GetActiveTarget();
+ if ( log )
+ {
+ wxLogWarning(_("Could not transfer data to window"));
+ log->Flush();
+ }
+
+ return FALSE;
+ }
+ }
+#endif // wxUSE_VALIDATORS
+
+ return TRUE;
+}
+
+bool wxWindowBase::TransferDataFromWindow()
+{
+#if wxUSE_VALIDATORS
+ wxWindowList::Node *node;
+ for ( node = m_children.GetFirst(); node; node = node->GetNext() )
+ {
+ wxWindow *child = node->GetData();
+ if ( child->GetValidator() &&
+ !child->GetValidator()->TransferFromWindow() )
+ {
+ return FALSE;
+ }
+ }
+#endif // wxUSE_VALIDATORS
+
+ return TRUE;
+}
+
+void wxWindowBase::InitDialog()
+{
+ wxInitDialogEvent event(GetId());
+ event.SetEventObject( this );
+ GetEventHandler()->ProcessEvent(event);
+}
+
+// ----------------------------------------------------------------------------
+// tooltips
+// ----------------------------------------------------------------------------
+
+#if wxUSE_TOOLTIPS
+
+void wxWindowBase::SetToolTip( const wxString &tip )
+{
+ // don't create the new tooltip if we already have one
+ if ( m_tooltip )
+ {
+ m_tooltip->SetTip( tip );
+ }
+ else
+ {
+ SetToolTip( new wxToolTip( tip ) );
+ }
+
+ // setting empty tooltip text does not remove the tooltip any more - use
+ // SetToolTip((wxToolTip *)NULL) for this
+}
+
+void wxWindowBase::DoSetToolTip(wxToolTip *tooltip)
+{
+ if ( m_tooltip )
+ delete m_tooltip;
+
+ m_tooltip = tooltip;
+}
+
+#endif // wxUSE_TOOLTIPS
+
+// ----------------------------------------------------------------------------
+// constraints and sizers
+// ----------------------------------------------------------------------------
+
+#if wxUSE_CONSTRAINTS
+
+void wxWindowBase::SetConstraints( wxLayoutConstraints *constraints )
+{
+ if ( m_constraints )
+ {
+ UnsetConstraints(m_constraints);
+ delete m_constraints;
+ }
+ m_constraints = constraints;
+ if ( m_constraints )
+ {
+ // Make sure other windows know they're part of a 'meaningful relationship'
+ if ( m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this) )
+ m_constraints->left.GetOtherWindow()->AddConstraintReference(this);
+ if ( m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this) )
+ m_constraints->top.GetOtherWindow()->AddConstraintReference(this);
+ if ( m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this) )
+ m_constraints->right.GetOtherWindow()->AddConstraintReference(this);
+ if ( m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this) )
+ m_constraints->bottom.GetOtherWindow()->AddConstraintReference(this);
+ if ( m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this) )
+ m_constraints->width.GetOtherWindow()->AddConstraintReference(this);
+ if ( m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this) )
+ m_constraints->height.GetOtherWindow()->AddConstraintReference(this);
+ if ( m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this) )
+ m_constraints->centreX.GetOtherWindow()->AddConstraintReference(this);
+ if ( m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this) )
+ m_constraints->centreY.GetOtherWindow()->AddConstraintReference(this);
+ }
+}
+
+// This removes any dangling pointers to this window in other windows'
+// constraintsInvolvedIn lists.
+void wxWindowBase::UnsetConstraints(wxLayoutConstraints *c)
+{
+ if ( c )
+ {
+ if ( c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this) )
+ c->left.GetOtherWindow()->RemoveConstraintReference(this);
+ if ( c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this) )
+ c->top.GetOtherWindow()->RemoveConstraintReference(this);
+ if ( c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this) )
+ c->right.GetOtherWindow()->RemoveConstraintReference(this);
+ if ( c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this) )
+ c->bottom.GetOtherWindow()->RemoveConstraintReference(this);
+ if ( c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this) )
+ c->width.GetOtherWindow()->RemoveConstraintReference(this);
+ if ( c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this) )
+ c->height.GetOtherWindow()->RemoveConstraintReference(this);
+ if ( c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this) )
+ c->centreX.GetOtherWindow()->RemoveConstraintReference(this);
+ if ( c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this) )
+ c->centreY.GetOtherWindow()->RemoveConstraintReference(this);
+ }
+}
+
+// Back-pointer to other windows we're involved with, so if we delete this
+// window, we must delete any constraints we're involved with.
+void wxWindowBase::AddConstraintReference(wxWindowBase *otherWin)
+{
+ if ( !m_constraintsInvolvedIn )
+ m_constraintsInvolvedIn = new wxWindowList;
+ if ( !m_constraintsInvolvedIn->Find(otherWin) )
+ m_constraintsInvolvedIn->Append(otherWin);
+}
+
+// REMOVE back-pointer to other windows we're involved with.
+void wxWindowBase::RemoveConstraintReference(wxWindowBase *otherWin)
+{
+ if ( m_constraintsInvolvedIn )
+ m_constraintsInvolvedIn->DeleteObject(otherWin);
+}
+
+// Reset any constraints that mention this window
+void wxWindowBase::DeleteRelatedConstraints()
+{
+ if ( m_constraintsInvolvedIn )
+ {
+ wxWindowList::Node *node = m_constraintsInvolvedIn->GetFirst();
+ while (node)
+ {
+ wxWindow *win = node->GetData();
+ wxLayoutConstraints *constr = win->GetConstraints();
+
+ // Reset any constraints involving this window
+ if ( constr )
+ {
+ constr->left.ResetIfWin(this);
+ constr->top.ResetIfWin(this);
+ constr->right.ResetIfWin(this);
+ constr->bottom.ResetIfWin(this);
+ constr->width.ResetIfWin(this);
+ constr->height.ResetIfWin(this);
+ constr->centreX.ResetIfWin(this);
+ constr->centreY.ResetIfWin(this);
+ }
+
+ wxWindowList::Node *next = node->GetNext();
+ delete node;
+ node = next;
+ }
+
+ delete m_constraintsInvolvedIn;
+ m_constraintsInvolvedIn = (wxWindowList *) NULL;
+ }
+}
+
+void wxWindowBase::SetSizer(wxSizer *sizer)
+{
+ if (m_windowSizer) delete m_windowSizer;
+
+ m_windowSizer = sizer;
+}
+
+bool wxWindowBase::Layout()
+{
+ // If there is a sizer, use it instead of the constraints
+ if ( GetSizer() )
+ {
+ int w, h;
+ GetClientSize(&w, &h);
+
+ GetSizer()->SetDimension( 0, 0, w, h );
+ }
+ else
+ {
+ wxLayoutConstraints *constr = GetConstraints();
+ bool wasOk = constr && constr->AreSatisfied();
+
+ ResetConstraints(); // Mark all constraints as unevaluated
+
+ // if we're a top level panel (i.e. our parent is frame/dialog), our
+ // own constraints will never be satisfied any more unless we do it
+ // here
+ if ( wasOk )
+ {
+ int noChanges = 1;
+ while ( noChanges > 0 )
+ {
+ constr->SatisfyConstraints(this, &noChanges);
+ }
+ }
+
+ DoPhase(1); // Layout children
+ DoPhase(2); // Layout grand children
+ SetConstraintSizes(); // Recursively set the real window sizes
+ }
+
+ return TRUE;
+}
+
+
+// Do a phase of evaluating constraints: the default behaviour. wxSizers may
+// do a similar thing, but also impose their own 'constraints' and order the
+// evaluation differently.
+bool wxWindowBase::LayoutPhase1(int *noChanges)
+{
+ wxLayoutConstraints *constr = GetConstraints();
+ if ( constr )
+ {
+ return constr->SatisfyConstraints(this, noChanges);
+ }
+ else
+ return TRUE;
+}
+
+bool wxWindowBase::LayoutPhase2(int *noChanges)
+{
+ *noChanges = 0;
+
+ // Layout children
+ DoPhase(1);
+ DoPhase(2);
+ return TRUE;
+}
+
+// Do a phase of evaluating child constraints
+bool wxWindowBase::DoPhase(int phase)
+{
+ int noIterations = 0;
+ int maxIterations = 500;
+ int noChanges = 1;
+ int noFailures = 0;
+ wxWindowList succeeded;
+ while ((noChanges > 0) && (noIterations < maxIterations))
+ {
+ noChanges = 0;
+ noFailures = 0;
+ wxWindowList::Node *node = GetChildren().GetFirst();
+ while (node)
+ {
+ wxWindow *child = node->GetData();
+ if ( !child->IsTopLevel() )
+ {
+ wxLayoutConstraints *constr = child->GetConstraints();
+ if ( constr )
+ {
+ if ( !succeeded.Find(child) )
+ {
+ int tempNoChanges = 0;
+ bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ;
+ noChanges += tempNoChanges;
+ if ( success )
+ {
+ succeeded.Append(child);
+ }
+ }
+ }
+ }
+ node = node->GetNext();
+ }
+
+ noIterations++;
+ }
+
+ return TRUE;
+}
+
+void wxWindowBase::ResetConstraints()
+{
+ wxLayoutConstraints *constr = 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);
+ }
+
+ wxWindowList::Node *node = GetChildren().GetFirst();
+ while (node)
+ {
+ wxWindow *win = node->GetData();
+ if ( !win->IsTopLevel() )
+ win->ResetConstraints();
+ node = node->GetNext();
+ }
+}
+
+// Need to distinguish between setting the 'fake' size for windows and sizers,
+// and setting the real values.
+void wxWindowBase::SetConstraintSizes(bool recurse)
+{
+ wxLayoutConstraints *constr = GetConstraints();
+ if ( constr && constr->AreSatisfied() )
+ {
+ int x = constr->left.GetValue();
+ int y = constr->top.GetValue();
+ int w = constr->width.GetValue();
+ int h = constr->height.GetValue();
+
+ if ( (constr->width.GetRelationship() != wxAsIs ) ||
+ (constr->height.GetRelationship() != wxAsIs) )
+ {
+ SetSize(x, y, w, h);
+ }
+ else
+ {
+ // If we don't want to resize this window, just move it...
+ Move(x, y);
+ }
+ }
+ else if ( constr )
+ {
+ wxLogDebug(wxT("Constraints not satisfied for %s named '%s'."),
+ GetClassInfo()->GetClassName(),
+ GetName().c_str());
+ }
+
+ if ( recurse )
+ {
+ wxWindowList::Node *node = GetChildren().GetFirst();
+ while (node)
+ {
+ wxWindow *win = node->GetData();
+ if ( !win->IsTopLevel() )
+ win->SetConstraintSizes();
+ node = node->GetNext();
+ }
+ }
+}
+
+// Only set the size/position of the constraint (if any)
+void wxWindowBase::SetSizeConstraint(int x, int y, int w, int h)
+{
+ wxLayoutConstraints *constr = GetConstraints();
+ if ( constr )
+ {
+ if ( x != -1 )
+ {
+ constr->left.SetValue(x);
+ constr->left.SetDone(TRUE);
+ }
+ if ( y != -1 )
+ {
+ constr->top.SetValue(y);
+ constr->top.SetDone(TRUE);
+ }
+ if ( w != -1 )
+ {
+ constr->width.SetValue(w);
+ constr->width.SetDone(TRUE);
+ }
+ if ( h != -1 )
+ {
+ constr->height.SetValue(h);
+ constr->height.SetDone(TRUE);
+ }
+ }
+}
+
+void wxWindowBase::MoveConstraint(int x, int y)
+{
+ wxLayoutConstraints *constr = GetConstraints();
+ if ( constr )
+ {
+ if ( x != -1 )
+ {
+ constr->left.SetValue(x);
+ constr->left.SetDone(TRUE);
+ }
+ if ( y != -1 )
+ {
+ constr->top.SetValue(y);
+ constr->top.SetDone(TRUE);
+ }
+ }
+}
+
+void wxWindowBase::GetSizeConstraint(int *w, int *h) const
+{
+ wxLayoutConstraints *constr = GetConstraints();
+ if ( constr )
+ {
+ *w = constr->width.GetValue();
+ *h = constr->height.GetValue();
+ }
+ else
+ GetSize(w, h);
+}
+
+void wxWindowBase::GetClientSizeConstraint(int *w, int *h) const
+{
+ wxLayoutConstraints *constr = GetConstraints();
+ if ( constr )
+ {
+ *w = constr->width.GetValue();
+ *h = constr->height.GetValue();
+ }
+ else
+ GetClientSize(w, h);
+}
+
+void wxWindowBase::GetPositionConstraint(int *x, int *y) const
+{
+ wxLayoutConstraints *constr = GetConstraints();
+ if ( constr )
+ {
+ *x = constr->left.GetValue();
+ *y = constr->top.GetValue();
+ }
+ else
+ GetPosition(x, y);
+}
+
+#endif // wxUSE_CONSTRAINTS
+
+// ----------------------------------------------------------------------------
+// do Update UI processing for child controls
+// ----------------------------------------------------------------------------