+// ----------------------------------------------------------------------------
+// reparenting the window
+// ----------------------------------------------------------------------------
+
+void wxWindowBase::AddChild(wxWindowBase *child)
+{
+ wxCHECK_RET( child, _T("can't add a NULL child") );
+
+ GetChildren().Append(child);
+ child->SetParent(this);
+}
+
+void wxWindowBase::RemoveChild(wxWindowBase *child)
+{
+ wxCHECK_RET( child, _T("can't remove a NULL child") );
+
+ GetChildren().DeleteObject(child);
+ child->SetParent((wxWindow *)NULL);
+}
+
+bool wxWindowBase::Reparent(wxWindowBase *newParent)
+{
+ wxWindow *oldParent = GetParent();
+ if ( newParent == oldParent )
+ {
+ // nothing done
+ return FALSE;
+ }
+
+ // unlink this window from the existing parent.
+ if ( oldParent )
+ {
+ oldParent->RemoveChild(this);
+ }
+ else
+ {
+ wxTopLevelWindows.DeleteObject(this);
+ }
+
+ // add it to the new one
+ if ( newParent )
+ {
+ newParent->AddChild(this);
+ }
+ else
+ {
+ wxTopLevelWindows.Append(this);
+ }
+
+ return TRUE;
+}
+
+// ----------------------------------------------------------------------------
+// event handler stuff
+// ----------------------------------------------------------------------------
+
+void wxWindowBase::PushEventHandler(wxEvtHandler *handler)
+{
+ handler->SetNextHandler(GetEventHandler());
+ SetEventHandler(handler);
+}
+
+wxEvtHandler *wxWindowBase::PopEventHandler(bool deleteHandler)
+{
+ wxEvtHandler *handlerA = GetEventHandler();
+ if ( handlerA )
+ {
+ wxEvtHandler *handlerB = handlerA->GetNextHandler();
+ handlerA->SetNextHandler((wxEvtHandler *)NULL);
+ SetEventHandler(handlerB);
+ if ( deleteHandler )
+ {
+ delete handlerA;
+ handlerA = (wxEvtHandler *)NULL;
+ }
+ }
+
+ return handlerA;
+}
+
+// ----------------------------------------------------------------------------
+// cursors, fonts &c
+// ----------------------------------------------------------------------------
+
+bool wxWindowBase::SetBackgroundColour( const wxColour &colour )
+{
+ if ( !colour.Ok() || (colour == m_backgroundColour) )
+ return FALSE;
+
+ m_backgroundColour = colour;
+
+ return TRUE;
+}
+
+bool wxWindowBase::SetForegroundColour( const wxColour &colour )
+{
+ if ( !colour.Ok() || (colour == m_foregroundColour) )
+ return FALSE;
+
+ m_foregroundColour = colour;
+
+ return TRUE;
+}
+
+bool wxWindowBase::SetCursor(const wxCursor& cursor)
+{
+ // don't try to set invalid cursor, always fall back to the default
+ const wxCursor& cursorOk = cursor.Ok() ? cursor : *wxSTANDARD_CURSOR;
+
+ if ( cursorOk == m_cursor )
+ {
+ // no change
+ return FALSE;
+ }
+
+ m_cursor = cursorOk;
+
+ return TRUE;
+}
+
+bool wxWindowBase::SetFont(const wxFont& font)
+{
+ // don't try to set invalid font, always fall back to the default
+ const wxFont& fontOk = font.Ok() ? font : *wxSWISS_FONT;
+
+ if ( fontOk == m_font )
+ {
+ // no change
+ return FALSE;
+ }
+
+ m_font = fontOk;
+
+ return TRUE;
+}
+
+#if wxUSE_CARET
+void wxWindowBase::SetCaret(wxCaret *caret)
+{
+ if ( m_caret )
+ {
+ delete m_caret;
+ }
+
+ m_caret = caret;
+
+ if ( m_caret )
+ {
+ wxASSERT_MSG( m_caret->GetWindow() == this,
+ _T("caret should be created associated to this window") );
+ }
+}
+#endif // wxUSE_CARET
+
+#if wxUSE_VALIDATORS
+// ----------------------------------------------------------------------------
+// validators
+// ----------------------------------------------------------------------------
+
+void wxWindowBase::SetValidator(const wxValidator& validator)
+{
+ if ( m_windowValidator )
+ delete m_windowValidator;
+
+ m_windowValidator = (wxValidator *)validator.Clone();
+
+ if ( m_windowValidator )
+ m_windowValidator->SetWindow(this) ;
+}
+#endif // wxUSE_VALIDATORS
+
+// ----------------------------------------------------------------------------
+// update region testing
+// ----------------------------------------------------------------------------
+
+bool wxWindowBase::IsExposed(int x, int y) const
+{
+ return m_updateRegion.Contains(x, y) != wxOutRegion;
+}
+
+bool wxWindowBase::IsExposed(int x, int y, int w, int h) const
+{
+ return m_updateRegion.Contains(x, y, w, h) != wxOutRegion;
+}
+
+// ----------------------------------------------------------------------------
+// find window by id or name
+// ----------------------------------------------------------------------------
+
+wxWindow *wxWindowBase::FindWindow( long id )
+{
+ if ( id == m_windowId )
+ return (wxWindow *)this;
+
+ wxWindowBase *res = (wxWindow *)NULL;
+ wxWindowList::Node *node;
+ for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
+ {
+ wxWindowBase *child = node->GetData();
+ res = child->FindWindow( id );
+ }
+
+ return (wxWindow *)res;
+}
+
+wxWindow *wxWindowBase::FindWindow( const wxString& name )
+{
+ if ( name == m_windowName )
+ return (wxWindow *)this;
+
+ wxWindowBase *res = (wxWindow *)NULL;
+ wxWindowList::Node *node;
+ for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
+ {
+ wxWindow *child = node->GetData();
+ res = child->FindWindow(name);
+ }
+
+ return (wxWindow *)res;
+}
+
+// ----------------------------------------------------------------------------
+// dialog oriented functions
+// ----------------------------------------------------------------------------
+
+void wxWindowBase::MakeModal(bool modal)
+{
+ // Disable all other windows
+ if ( IsTopLevel() )
+ {
+ wxWindowList::Node *node = wxTopLevelWindows.GetFirst();
+ while (node)
+ {
+ wxWindow *win = node->GetData();
+ if (win != this)
+ win->Enable(!modal);
+
+ 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)
+{
+ m_windowSizer = sizer;
+ if ( sizer )
+ sizer->SetSizerParent(this);
+}
+
+bool wxWindowBase::Layout()
+{
+ if ( GetConstraints() )
+ {
+ int w, h;
+ GetClientSize(&w, &h);
+ GetConstraints()->width.SetValue(w);
+ GetConstraints()->height.SetValue(h);
+ }
+
+ // If top level (one sizer), evaluate the sizer's constraints.
+ if ( GetSizer() )
+ {
+ int noChanges;
+ GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
+ GetSizer()->LayoutPhase1(&noChanges);
+ GetSizer()->LayoutPhase2(&noChanges);
+ GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
+ return TRUE;
+ }
+ else
+ {
+ // Otherwise, evaluate child constraints
+ ResetConstraints(); // Mark all constraints as unevaluated
+ DoPhase(1); // Just one phase need if no sizers involved
+ DoPhase(2);
+ 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->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))
+ {
+ // Calls Layout() recursively. AAAGH. How can we stop that.
+ // Simply take Layout() out of non-top level OnSizes.
+ SizerSetSize(x, y, w, h);
+ }
+ else
+ {
+ SizerMove(x, y);
+ }
+ }
+ else if ( constr )
+ {
+ wxChar *windowClass = GetClassInfo()->GetClassName();
+
+ wxString winName;
+ if ( GetName() == _T("") )
+ winName = _T("unnamed");
+ else
+ winName = GetName();
+ wxLogDebug( _T("Constraint(s) not satisfied for window of type %s, name %s:\n"),
+ (const wxChar *)windowClass,
+ (const wxChar *)winName);
+ if ( !constr->left.GetDone()) wxLogDebug( _T(" unsatisfied 'left' constraint.\n") );
+ if ( !constr->right.GetDone()) wxLogDebug( _T(" unsatisfied 'right' constraint.\n") );
+ if ( !constr->width.GetDone()) wxLogDebug( _T(" unsatisfied 'width' constraint.\n") );
+ if ( !constr->height.GetDone()) wxLogDebug( _T(" unsatisfied 'height' constraint.\n") );
+ wxLogDebug( _T("Please check constraints: try adding AsIs() constraints.\n") );
+ }
+
+ if ( recurse )
+ {
+ wxWindowList::Node *node = GetChildren().GetFirst();
+ while (node)
+ {
+ wxWindow *win = node->GetData();
+ if ( !win->IsTopLevel() )
+ win->SetConstraintSizes();
+ node = node->GetNext();
+ }
+ }
+}
+
+// This assumes that all sizers are 'on' the same window, i.e. the parent of
+// this window.
+void wxWindowBase::TransformSizerToActual(int *x, int *y) const
+{
+ if ( !m_sizerParent || m_sizerParent->IsTopLevel() )
+ return;
+
+ int xp, yp;
+ m_sizerParent->GetPosition(&xp, &yp);
+ m_sizerParent->TransformSizerToActual(&xp, &yp);
+ *x += xp;
+ *y += yp;
+}
+
+void wxWindowBase::SizerSetSize(int x, int y, int w, int h)
+{
+ int xx = x;
+ int yy = y;
+ TransformSizerToActual(&xx, &yy);
+ SetSize(xx, yy, w, h);
+}
+
+void wxWindowBase::SizerMove(int x, int y)
+{
+ int xx = x;
+ int yy = y;
+ TransformSizerToActual(&xx, &yy);
+ Move(xx, yy);
+}
+
+// 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
+// ----------------------------------------------------------------------------