+ // removing a child while frozen may result in permanently frozen window
+ // if used e.g. from Reparent(), so thaw it
+ //
+ // NB: IsTopLevel() doesn't return true any more when a TLW child is being
+ // removed from its ~wxWindowBase, so check for IsBeingDeleted() too
+ if ( IsFrozen() && !child->IsBeingDeleted() && !child->IsTopLevel() )
+ child->Thaw();
+
+ GetChildren().DeleteObject((wxWindow *)child);
+ child->SetParent(NULL);
+}
+
+void wxWindowBase::SetParent(wxWindowBase *parent)
+{
+ // This assert catches typos which may result in using "this" instead of
+ // "parent" when creating the window. This doesn't happen often but when it
+ // does the results are unpleasant because the program typically just
+ // crashes when due to a stack overflow or something similar and this
+ // assert doesn't cost much (OTOH doing a more general check that the
+ // parent is not one of our children would be more expensive and probably
+ // not worth it).
+ wxASSERT_MSG( parent != this, wxS("Can't use window as its own parent") );
+
+ m_parent = (wxWindow *)parent;
+}
+
+bool wxWindowBase::Reparent(wxWindowBase *newParent)
+{
+ wxWindow *oldParent = GetParent();
+ if ( newParent == oldParent )
+ {
+ // nothing done
+ return false;
+ }
+
+ const bool oldEnabledState = IsEnabled();
+
+ // unlink this window from the existing parent.
+ if ( oldParent )
+ {
+ oldParent->RemoveChild(this);
+ }
+ else
+ {
+ wxTopLevelWindows.DeleteObject((wxWindow *)this);
+ }
+
+ // add it to the new one
+ if ( newParent )
+ {
+ newParent->AddChild(this);
+ }
+ else
+ {
+ wxTopLevelWindows.Append((wxWindow *)this);
+ }
+
+ // We need to notify window (and its subwindows) if by changing the parent
+ // we also change our enabled/disabled status.
+ const bool newEnabledState = IsEnabled();
+ if ( newEnabledState != oldEnabledState )
+ {
+ NotifyWindowOnEnableChange(newEnabledState);
+ }
+
+ return true;
+}
+
+// ----------------------------------------------------------------------------
+// event handler stuff
+// ----------------------------------------------------------------------------
+
+void wxWindowBase::SetEventHandler(wxEvtHandler *handler)
+{
+ wxCHECK_RET(handler != NULL, "SetEventHandler(NULL) called");
+
+ m_eventHandler = handler;
+}
+
+void wxWindowBase::SetNextHandler(wxEvtHandler *WXUNUSED(handler))
+{
+ // disable wxEvtHandler chain mechanism for wxWindows:
+ // wxWindow uses its own stack mechanism which doesn't mix well with wxEvtHandler's one
+
+ wxFAIL_MSG("wxWindow cannot be part of a wxEvtHandler chain");
+}
+void wxWindowBase::SetPreviousHandler(wxEvtHandler *WXUNUSED(handler))
+{
+ // we can't simply wxFAIL here as in SetNextHandler: in fact the last
+ // handler of our stack when is destroyed will be Unlink()ed and thus
+ // will call this function to update the pointer of this window...
+
+ //wxFAIL_MSG("wxWindow cannot be part of a wxEvtHandler chain");
+}
+
+void wxWindowBase::PushEventHandler(wxEvtHandler *handlerToPush)
+{
+ wxCHECK_RET( handlerToPush != NULL, "PushEventHandler(NULL) called" );
+
+ // the new handler is going to be part of the wxWindow stack of event handlers:
+ // it can't be part also of an event handler double-linked chain:
+ wxASSERT_MSG(handlerToPush->IsUnlinked(),
+ "The handler being pushed in the wxWindow stack shouldn't be part of "
+ "a wxEvtHandler chain; call Unlink() on it first");
+
+ wxEvtHandler *handlerOld = GetEventHandler();
+ wxCHECK_RET( handlerOld, "an old event handler is NULL?" );
+
+ // now use wxEvtHandler double-linked list to implement a stack:
+ handlerToPush->SetNextHandler(handlerOld);
+
+ if (handlerOld != this)
+ handlerOld->SetPreviousHandler(handlerToPush);
+
+ SetEventHandler(handlerToPush);
+
+#if wxDEBUG_LEVEL
+ // final checks of the operations done above:
+ wxASSERT_MSG( handlerToPush->GetPreviousHandler() == NULL,
+ "the first handler of the wxWindow stack should "
+ "have no previous handlers set" );
+ wxASSERT_MSG( handlerToPush->GetNextHandler() != NULL,
+ "the first handler of the wxWindow stack should "
+ "have non-NULL next handler" );
+
+ wxEvtHandler* pLast = handlerToPush;
+ while ( pLast && pLast != this )
+ pLast = pLast->GetNextHandler();
+ wxASSERT_MSG( pLast->GetNextHandler() == NULL,
+ "the last handler of the wxWindow stack should "
+ "have this window as next handler" );
+#endif // wxDEBUG_LEVEL
+}
+
+wxEvtHandler *wxWindowBase::PopEventHandler(bool deleteHandler)
+{
+ // we need to pop the wxWindow stack, i.e. we need to remove the first handler
+
+ wxEvtHandler *firstHandler = GetEventHandler();
+ wxCHECK_MSG( firstHandler != NULL, NULL, "wxWindow cannot have a NULL event handler" );
+ wxCHECK_MSG( firstHandler != this, NULL, "cannot pop the wxWindow itself" );
+ wxCHECK_MSG( firstHandler->GetPreviousHandler() == NULL, NULL,
+ "the first handler of the wxWindow stack should have no previous handlers set" );
+
+ wxEvtHandler *secondHandler = firstHandler->GetNextHandler();
+ wxCHECK_MSG( secondHandler != NULL, NULL,
+ "the first handler of the wxWindow stack should have non-NULL next handler" );
+
+ firstHandler->SetNextHandler(NULL);
+
+ // It is harmless but useless to unset the previous handler of the window
+ // itself as it's always NULL anyhow, so don't do this.
+ if ( secondHandler != this )
+ secondHandler->SetPreviousHandler(NULL);
+
+ // now firstHandler is completely unlinked; set secondHandler as the new window event handler
+ SetEventHandler(secondHandler);
+
+ if ( deleteHandler )
+ {
+ wxDELETE(firstHandler);
+ }
+
+ return firstHandler;
+}
+
+bool wxWindowBase::RemoveEventHandler(wxEvtHandler *handlerToRemove)
+{
+ wxCHECK_MSG( handlerToRemove != NULL, false, "RemoveEventHandler(NULL) called" );
+ wxCHECK_MSG( handlerToRemove != this, false, "Cannot remove the window itself" );
+
+ if (handlerToRemove == GetEventHandler())
+ {
+ // removing the first event handler is equivalent to "popping" the stack
+ PopEventHandler(false);
+ return true;
+ }
+
+ // NOTE: the wxWindow event handler list is always terminated with "this" handler
+ wxEvtHandler *handlerCur = GetEventHandler()->GetNextHandler();
+ while ( handlerCur != this && handlerCur )
+ {
+ wxEvtHandler *handlerNext = handlerCur->GetNextHandler();
+
+ if ( handlerCur == handlerToRemove )
+ {
+ handlerCur->Unlink();
+
+ wxASSERT_MSG( handlerCur != GetEventHandler(),
+ "the case Remove == Pop should was already handled" );
+ return true;
+ }
+
+ handlerCur = handlerNext;
+ }
+
+ wxFAIL_MSG( wxT("where has the event handler gone?") );
+
+ return false;
+}
+
+bool wxWindowBase::HandleWindowEvent(wxEvent& event) const
+{
+ // SafelyProcessEvent() will handle exceptions nicely
+ return GetEventHandler()->SafelyProcessEvent(event);
+}
+
+// ----------------------------------------------------------------------------
+// colours, fonts &c
+// ----------------------------------------------------------------------------
+
+void wxWindowBase::InheritAttributes()
+{
+ const wxWindowBase * const parent = GetParent();
+ if ( !parent )
+ return;
+
+ // we only inherit attributes which had been explicitly set for the parent
+ // which ensures that this only happens if the user really wants it and
+ // not by default which wouldn't make any sense in modern GUIs where the
+ // controls don't all use the same fonts (nor colours)
+ if ( parent->m_inheritFont && !m_hasFont )
+ SetFont(parent->GetFont());
+
+ // in addition, there is a possibility to explicitly forbid inheriting
+ // colours at each class level by overriding ShouldInheritColours()
+ if ( ShouldInheritColours() )
+ {
+ if ( parent->m_inheritFgCol && !m_hasFgCol )
+ SetForegroundColour(parent->GetForegroundColour());
+
+ // inheriting (solid) background colour is wrong as it totally breaks
+ // any kind of themed backgrounds
+ //
+ // instead, the controls should use the same background as their parent
+ // (ideally by not drawing it at all)
+#if 0
+ if ( parent->m_inheritBgCol && !m_hasBgCol )
+ SetBackgroundColour(parent->GetBackgroundColour());
+#endif // 0
+ }
+}
+
+/* static */ wxVisualAttributes
+wxWindowBase::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
+{
+ // it is important to return valid values for all attributes from here,
+ // GetXXX() below rely on this
+ wxVisualAttributes attrs;
+ attrs.font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
+ attrs.colFg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
+
+ // On Smartphone/PocketPC, wxSYS_COLOUR_WINDOW is a better reflection of
+ // the usual background colour than wxSYS_COLOUR_BTNFACE.
+ // It's a pity that wxSYS_COLOUR_WINDOW isn't always a suitable background
+ // colour on other platforms.
+
+#if defined(__WXWINCE__) && (defined(__SMARTPHONE__) || defined(__POCKETPC__))
+ attrs.colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
+#else
+ attrs.colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
+#endif
+ return attrs;
+}
+
+wxColour wxWindowBase::GetBackgroundColour() const
+{
+ if ( !m_backgroundColour.IsOk() )
+ {
+ wxASSERT_MSG( !m_hasBgCol, wxT("we have invalid explicit bg colour?") );
+
+ // get our default background colour
+ wxColour colBg = GetDefaultAttributes().colBg;
+
+ // we must return some valid colour to avoid redoing this every time
+ // and also to avoid surprising the applications written for older
+ // wxWidgets versions where GetBackgroundColour() always returned
+ // something -- so give them something even if it doesn't make sense
+ // for this window (e.g. it has a themed background)
+ if ( !colBg.IsOk() )
+ colBg = GetClassDefaultAttributes().colBg;
+
+ return colBg;
+ }
+ else
+ return m_backgroundColour;
+}
+
+wxColour wxWindowBase::GetForegroundColour() const
+{
+ // logic is the same as above
+ if ( !m_hasFgCol && !m_foregroundColour.IsOk() )
+ {
+ wxColour colFg = GetDefaultAttributes().colFg;
+
+ if ( !colFg.IsOk() )
+ colFg = GetClassDefaultAttributes().colFg;
+
+ return colFg;
+ }
+ else
+ return m_foregroundColour;
+}
+
+bool wxWindowBase::SetBackgroundStyle(wxBackgroundStyle style)
+{
+ // The checks below shouldn't be triggered if we're not really changing the
+ // style.
+ if ( style == m_backgroundStyle )
+ return true;
+
+ // Transparent background style can be only set before creation because of
+ // wxGTK limitation.
+ wxCHECK_MSG( (style != wxBG_STYLE_TRANSPARENT) || !GetHandle(),
+ false,
+ "wxBG_STYLE_TRANSPARENT style can only be set before "
+ "Create()-ing the window." );
+
+ // And once it is set, wxBG_STYLE_TRANSPARENT can't be unset.
+ wxCHECK_MSG( (m_backgroundStyle != wxBG_STYLE_TRANSPARENT) ||
+ (style == wxBG_STYLE_TRANSPARENT),
+ false,
+ "wxBG_STYLE_TRANSPARENT can't be unset once it was set." );
+
+ m_backgroundStyle = style;
+
+ return true;
+}
+
+bool wxWindowBase::IsTransparentBackgroundSupported(wxString *reason) const
+{
+ if ( reason )
+ *reason = _("This platform does not support background transparency.");
+
+ return false;
+}
+
+bool wxWindowBase::SetBackgroundColour( const wxColour &colour )
+{
+ if ( colour == m_backgroundColour )
+ return false;
+
+ m_hasBgCol = colour.IsOk();
+
+ m_inheritBgCol = m_hasBgCol;
+ m_backgroundColour = colour;
+ SetThemeEnabled( !m_hasBgCol && !m_foregroundColour.IsOk() );
+ return true;
+}
+
+bool wxWindowBase::SetForegroundColour( const wxColour &colour )
+{
+ if (colour == m_foregroundColour )
+ return false;
+
+ m_hasFgCol = colour.IsOk();
+ m_inheritFgCol = m_hasFgCol;
+ m_foregroundColour = colour;
+ SetThemeEnabled( !m_hasFgCol && !m_backgroundColour.IsOk() );
+ return true;
+}
+
+bool wxWindowBase::SetCursor(const wxCursor& cursor)
+{
+ // setting an invalid cursor is ok, it means that we don't have any special
+ // cursor
+ if ( m_cursor.IsSameAs(cursor) )
+ {
+ // no change
+ return false;
+ }
+
+ m_cursor = cursor;
+
+ return true;
+}
+
+wxFont wxWindowBase::GetFont() const
+{
+ // logic is the same as in GetBackgroundColour()
+ if ( !m_font.IsOk() )
+ {
+ wxASSERT_MSG( !m_hasFont, wxT("we have invalid explicit font?") );
+
+ wxFont font = GetDefaultAttributes().font;
+ if ( !font.IsOk() )
+ font = GetClassDefaultAttributes().font;
+
+ return font;
+ }
+ else
+ return m_font;
+}
+
+bool wxWindowBase::SetFont(const wxFont& font)
+{
+ if ( font == m_font )
+ {
+ // no change
+ return false;
+ }
+
+ m_font = font;
+ m_hasFont = font.IsOk();
+ m_inheritFont = m_hasFont;
+
+ InvalidateBestSize();
+
+ return true;
+}
+
+#if wxUSE_PALETTE
+
+void wxWindowBase::SetPalette(const wxPalette& pal)
+{
+ m_hasCustomPalette = true;
+ m_palette = pal;
+
+ // VZ: can anyone explain me what do we do here?
+ wxWindowDC d((wxWindow *) this);
+ d.SetPalette(pal);
+}
+
+wxWindow *wxWindowBase::GetAncestorWithCustomPalette() const
+{
+ wxWindow *win = (wxWindow *)this;
+ while ( win && !win->HasCustomPalette() )
+ {
+ win = win->GetParent();
+ }
+
+ return win;
+}
+
+#endif // wxUSE_PALETTE
+
+#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,
+ wxT("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 stuff
+// ----------------------------------------------------------------------------
+
+wxRect wxWindowBase::GetUpdateClientRect() const
+{
+ wxRegion rgnUpdate = GetUpdateRegion();
+ rgnUpdate.Intersect(GetClientRect());
+ wxRect rectUpdate = rgnUpdate.GetBox();
+ wxPoint ptOrigin = GetClientAreaOrigin();
+ rectUpdate.x -= ptOrigin.x;
+ rectUpdate.y -= ptOrigin.y;
+
+ return rectUpdate;
+}
+
+bool wxWindowBase::DoIsExposed(int x, int y) const
+{
+ return m_updateRegion.Contains(x, y) != wxOutRegion;
+}
+
+bool wxWindowBase::DoIsExposed(int x, int y, int w, int h) const
+{
+ return m_updateRegion.Contains(x, y, w, h) != wxOutRegion;
+}
+
+void wxWindowBase::ClearBackground()
+{
+ // wxGTK uses its own version, no need to add never used code
+#ifndef __WXGTK__
+ wxClientDC dc((wxWindow *)this);
+ wxBrush brush(GetBackgroundColour(), wxBRUSHSTYLE_SOLID);
+ dc.SetBackground(brush);
+ dc.Clear();
+#endif // __WXGTK__
+}
+
+// ----------------------------------------------------------------------------
+// find child window by id or name
+// ----------------------------------------------------------------------------
+
+wxWindow *wxWindowBase::FindWindow(long id) const
+{
+ if ( id == m_windowId )
+ return (wxWindow *)this;
+
+ wxWindowBase *res = NULL;
+ wxWindowList::compatibility_iterator 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) const
+{
+ if ( name == m_windowName )
+ return (wxWindow *)this;
+
+ wxWindowBase *res = NULL;
+ wxWindowList::compatibility_iterator node;
+ for ( node = m_children.GetFirst(); node && !res; node = node->GetNext() )
+ {
+ wxWindow *child = node->GetData();
+ res = child->FindWindow(name);
+ }
+
+ return (wxWindow *)res;
+}
+
+
+// find any window by id or name or label: If parent is non-NULL, look through
+// children for a label or title matching the specified string. If NULL, look
+// through all top-level windows.
+//
+// to avoid duplicating code we reuse the same helper function but with
+// different comparators
+
+typedef bool (*wxFindWindowCmp)(const wxWindow *win,
+ const wxString& label, long id);
+
+static
+bool wxFindWindowCmpLabels(const wxWindow *win, const wxString& label,
+ long WXUNUSED(id))
+{
+ return win->GetLabel() == label;
+}
+
+static
+bool wxFindWindowCmpNames(const wxWindow *win, const wxString& label,
+ long WXUNUSED(id))
+{
+ return win->GetName() == label;
+}
+
+static
+bool wxFindWindowCmpIds(const wxWindow *win, const wxString& WXUNUSED(label),
+ long id)
+{
+ return win->GetId() == id;
+}
+
+// recursive helper for the FindWindowByXXX() functions
+static
+wxWindow *wxFindWindowRecursively(const wxWindow *parent,
+ const wxString& label,
+ long id,
+ wxFindWindowCmp cmp)
+{
+ if ( parent )
+ {
+ // see if this is the one we're looking for
+ if ( (*cmp)(parent, label, id) )
+ return (wxWindow *)parent;
+
+ // It wasn't, so check all its children
+ for ( wxWindowList::compatibility_iterator node = parent->GetChildren().GetFirst();
+ node;
+ node = node->GetNext() )
+ {
+ // recursively check each child
+ wxWindow *win = (wxWindow *)node->GetData();
+ wxWindow *retwin = wxFindWindowRecursively(win, label, id, cmp);
+ if (retwin)
+ return retwin;
+ }
+ }
+
+ // Not found
+ return NULL;
+}
+
+// helper for FindWindowByXXX()
+static
+wxWindow *wxFindWindowHelper(const wxWindow *parent,
+ const wxString& label,
+ long id,
+ wxFindWindowCmp cmp)
+{
+ if ( parent )
+ {
+ // just check parent and all its children
+ return wxFindWindowRecursively(parent, label, id, cmp);
+ }
+
+ // start at very top of wx's windows
+ for ( wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst();
+ node;
+ node = node->GetNext() )
+ {
+ // recursively check each window & its children
+ wxWindow *win = node->GetData();
+ wxWindow *retwin = wxFindWindowRecursively(win, label, id, cmp);
+ if (retwin)
+ return retwin;
+ }
+
+ return NULL;
+}
+
+/* static */
+wxWindow *
+wxWindowBase::FindWindowByLabel(const wxString& title, const wxWindow *parent)
+{
+ return wxFindWindowHelper(parent, title, 0, wxFindWindowCmpLabels);
+}
+
+/* static */
+wxWindow *
+wxWindowBase::FindWindowByName(const wxString& title, const wxWindow *parent)
+{
+ wxWindow *win = wxFindWindowHelper(parent, title, 0, wxFindWindowCmpNames);
+
+ if ( !win )
+ {
+ // fall back to the label
+ win = FindWindowByLabel(title, parent);
+ }
+
+ return win;
+}
+
+/* static */
+wxWindow *
+wxWindowBase::FindWindowById( long id, const wxWindow* parent )
+{
+ return wxFindWindowHelper(parent, wxEmptyString, id, wxFindWindowCmpIds);
+}
+
+// ----------------------------------------------------------------------------
+// dialog oriented functions
+// ----------------------------------------------------------------------------
+
+#if WXWIN_COMPATIBILITY_2_8
+void wxWindowBase::MakeModal(bool modal)
+{
+ // Disable all other windows
+ if ( IsTopLevel() )
+ {
+ wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst();
+ while (node)
+ {
+ wxWindow *win = node->GetData();
+ if (win != this)
+ win->Enable(!modal);
+
+ node = node->GetNext();
+ }
+ }
+}
+#endif // WXWIN_COMPATIBILITY_2_8
+
+#if wxUSE_VALIDATORS
+
+namespace
+{
+
+// This class encapsulates possibly recursive iteration on window children done
+// by Validate() and TransferData{To,From}Window() and allows to avoid code
+// duplication in all three functions.
+class ValidationTraverserBase
+{
+public:
+ wxEXPLICIT ValidationTraverserBase(wxWindowBase* win)
+ : m_win(static_cast<wxWindow*>(win))
+ {
+ }
+
+ // Traverse all the direct children calling OnDo() on them and also all
+ // grandchildren if wxWS_EX_VALIDATE_RECURSIVELY is used, calling
+ // OnRecurse() for them.
+ bool DoForAllChildren()
+ {
+ const bool recurse = m_win->HasExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY);
+
+ wxWindowList& children = m_win->GetChildren();
+ for ( wxWindowList::iterator i = children.begin();
+ i != children.end();
+ ++i )
+ {
+ wxWindow* const child = static_cast<wxWindow*>(*i);
+ wxValidator* const validator = child->GetValidator();
+ if ( validator && !OnDo(validator) )
+ {
+ return false;
+ }
+
+ // Notice that validation should never recurse into top level
+ // children, e.g. some other dialog which might happen to be
+ // currently shown.
+ if ( recurse && !child->IsTopLevel() && !OnRecurse(child) )
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+protected:
+ // Called for each child, validator is guaranteed to be non-NULL.
+ virtual bool OnDo(wxValidator* validator) = 0;
+
+ // Called for each child if we need to recurse into its children.
+ virtual bool OnRecurse(wxWindow* child) = 0;
+
+
+ // The window whose children we're traversing.
+ wxWindow* const m_win;
+
+ wxDECLARE_NO_COPY_CLASS(ValidationTraverserBase);
+};
+
+} // anonymous namespace
+
+#endif // wxUSE_VALIDATORS
+
+bool wxWindowBase::Validate()
+{
+#if wxUSE_VALIDATORS
+ class ValidateTraverser : public ValidationTraverserBase
+ {
+ public:
+ wxEXPLICIT ValidateTraverser(wxWindowBase* win)
+ : ValidationTraverserBase(win)
+ {
+ }
+
+ virtual bool OnDo(wxValidator* validator)
+ {
+ return validator->Validate(m_win);
+ }
+
+ virtual bool OnRecurse(wxWindow* child)
+ {
+ return child->Validate();
+ }
+ };
+
+ return ValidateTraverser(this).DoForAllChildren();
+#else // !wxUSE_VALIDATORS
+ return true;
+#endif // wxUSE_VALIDATORS/!wxUSE_VALIDATORS
+}
+
+bool wxWindowBase::TransferDataToWindow()
+{
+#if wxUSE_VALIDATORS
+ class DataToWindowTraverser : public ValidationTraverserBase
+ {
+ public:
+ wxEXPLICIT DataToWindowTraverser(wxWindowBase* win)
+ : ValidationTraverserBase(win)
+ {
+ }
+
+ virtual bool OnDo(wxValidator* validator)
+ {
+ if ( !validator->TransferToWindow() )
+ {
+ wxLogWarning(_("Could not transfer data to window"));
+#if wxUSE_LOG
+ wxLog::FlushActive();
+#endif // wxUSE_LOG
+
+ return false;
+ }
+
+ return true;
+ }
+
+ virtual bool OnRecurse(wxWindow* child)
+ {
+ return child->TransferDataToWindow();
+ }
+ };
+
+ return DataToWindowTraverser(this).DoForAllChildren();
+#else // !wxUSE_VALIDATORS
+ return true;
+#endif // wxUSE_VALIDATORS/!wxUSE_VALIDATORS
+}
+
+bool wxWindowBase::TransferDataFromWindow()
+{
+#if wxUSE_VALIDATORS
+ class DataFromWindowTraverser : public ValidationTraverserBase
+ {
+ public:
+ DataFromWindowTraverser(wxWindowBase* win)
+ : ValidationTraverserBase(win)
+ {
+ }
+
+ virtual bool OnDo(wxValidator* validator)
+ {
+ return validator->TransferFromWindow();
+ }
+
+ virtual bool OnRecurse(wxWindow* child)
+ {
+ return child->TransferDataFromWindow();
+ }
+ };
+
+ return DataFromWindowTraverser(this).DoForAllChildren();
+#else // !wxUSE_VALIDATORS
+ return true;
+#endif // wxUSE_VALIDATORS/!wxUSE_VALIDATORS
+}
+
+void wxWindowBase::InitDialog()
+{
+ wxInitDialogEvent event(GetId());
+ event.SetEventObject( this );
+ GetEventHandler()->ProcessEvent(event);
+}
+
+// ----------------------------------------------------------------------------
+// context-sensitive help support
+// ----------------------------------------------------------------------------
+
+#if wxUSE_HELP
+
+// associate this help text with this window
+void wxWindowBase::SetHelpText(const wxString& text)
+{
+ wxHelpProvider *helpProvider = wxHelpProvider::Get();
+ if ( helpProvider )
+ {
+ helpProvider->AddHelp(this, text);
+ }
+}
+
+#if WXWIN_COMPATIBILITY_2_8
+// associate this help text with all windows with the same id as this
+// one
+void wxWindowBase::SetHelpTextForId(const wxString& text)
+{
+ wxHelpProvider *helpProvider = wxHelpProvider::Get();
+ if ( helpProvider )
+ {
+ helpProvider->AddHelp(GetId(), text);
+ }
+}
+#endif // WXWIN_COMPATIBILITY_2_8
+
+// get the help string associated with this window (may be empty)
+// default implementation forwards calls to the help provider
+wxString
+wxWindowBase::GetHelpTextAtPoint(const wxPoint & WXUNUSED(pt),
+ wxHelpEvent::Origin WXUNUSED(origin)) const
+{
+ wxString text;
+ wxHelpProvider *helpProvider = wxHelpProvider::Get();
+ if ( helpProvider )
+ {
+ text = helpProvider->GetHelp(this);
+ }
+
+ return text;
+}
+
+// show help for this window
+void wxWindowBase::OnHelp(wxHelpEvent& event)
+{
+ wxHelpProvider *helpProvider = wxHelpProvider::Get();
+ if ( helpProvider )
+ {
+ wxPoint pos = event.GetPosition();
+ const wxHelpEvent::Origin origin = event.GetOrigin();
+ if ( origin == wxHelpEvent::Origin_Keyboard )
+ {
+ // if the help event was generated from keyboard it shouldn't
+ // appear at the mouse position (which is still the only position
+ // associated with help event) if the mouse is far away, although
+ // we still do use the mouse position if it's over the window
+ // because we suppose the user looks approximately at the mouse
+ // already and so it would be more convenient than showing tooltip
+ // at some arbitrary position which can be quite far from it
+ const wxRect rectClient = GetClientRect();
+ if ( !rectClient.Contains(ScreenToClient(pos)) )
+ {
+ // position help slightly under and to the right of this window
+ pos = ClientToScreen(wxPoint(
+ 2*GetCharWidth(),
+ rectClient.height + GetCharHeight()
+ ));
+ }
+ }
+
+ if ( helpProvider->ShowHelpAtPoint(this, pos, origin) )
+ {
+ // skip the event.Skip() below
+ return;
+ }
+ }
+
+ event.Skip();
+}
+
+#endif // wxUSE_HELP
+
+// ----------------------------------------------------------------------------
+// tooltips
+// ----------------------------------------------------------------------------
+
+#if wxUSE_TOOLTIPS
+
+wxString wxWindowBase::GetToolTipText() const
+{
+ return m_tooltip ? m_tooltip->GetTip() : wxString();
+}
+
+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(NULL) for this
+}
+
+void wxWindowBase::DoSetToolTip(wxToolTip *tooltip)
+{
+ if ( m_tooltip != tooltip )
+ {
+ if ( m_tooltip )
+ delete m_tooltip;
+
+ m_tooltip = tooltip;
+ }
+}
+
+bool wxWindowBase::CopyToolTip(wxToolTip *tip)
+{
+ SetToolTip(tip ? new wxToolTip(tip->GetTip()) : NULL);
+
+ return tip != NULL;
+}
+
+#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->left.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((wxWindow *)otherWin) )
+ m_constraintsInvolvedIn->Append((wxWindow *)otherWin);
+}
+
+// REMOVE back-pointer to other windows we're involved with.
+void wxWindowBase::RemoveConstraintReference(wxWindowBase *otherWin)
+{
+ if ( m_constraintsInvolvedIn )
+ m_constraintsInvolvedIn->DeleteObject((wxWindow *)otherWin);
+}
+
+// Reset any constraints that mention this window
+void wxWindowBase::DeleteRelatedConstraints()
+{
+ if ( m_constraintsInvolvedIn )
+ {
+ wxWindowList::compatibility_iterator 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::compatibility_iterator next = node->GetNext();
+ m_constraintsInvolvedIn->Erase(node);
+ node = next;
+ }
+
+ wxDELETE(m_constraintsInvolvedIn);
+ }
+}
+
+#endif // wxUSE_CONSTRAINTS
+
+void wxWindowBase::SetSizer(wxSizer *sizer, bool deleteOld)
+{
+ if ( sizer == m_windowSizer)
+ return;
+
+ if ( m_windowSizer )
+ {
+ m_windowSizer->SetContainingWindow(NULL);
+
+ if ( deleteOld )
+ delete m_windowSizer;
+ }
+
+ m_windowSizer = sizer;
+ if ( m_windowSizer )
+ {
+ m_windowSizer->SetContainingWindow((wxWindow *)this);
+ }
+
+ SetAutoLayout(m_windowSizer != NULL);
+}
+
+void wxWindowBase::SetSizerAndFit(wxSizer *sizer, bool deleteOld)
+{
+ SetSizer( sizer, deleteOld );
+ sizer->SetSizeHints( (wxWindow*) this );
+}
+
+
+void wxWindowBase::SetContainingSizer(wxSizer* sizer)
+{
+ // adding a window to a sizer twice is going to result in fatal and
+ // hard to debug problems later because when deleting the second
+ // associated wxSizerItem we're going to dereference a dangling
+ // pointer; so try to detect this as early as possible
+ wxASSERT_MSG( !sizer || m_containingSizer != sizer,
+ wxT("Adding a window to the same sizer twice?") );
+
+ m_containingSizer = sizer;
+}
+
+#if wxUSE_CONSTRAINTS
+
+void wxWindowBase::SatisfyConstraints()
+{
+ wxLayoutConstraints *constr = GetConstraints();
+ bool wasOk = constr && constr->AreSatisfied();
+
+ ResetConstraints(); // Mark all constraints as unevaluated
+
+ int noChanges = 1;
+
+ // 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 )
+ {
+ while ( noChanges > 0 )
+ {
+ LayoutPhase1(&noChanges);
+ }
+ }
+
+ LayoutPhase2(&noChanges);
+}
+
+#endif // wxUSE_CONSTRAINTS
+
+bool wxWindowBase::Layout()
+{
+ // If there is a sizer, use it instead of the constraints
+ if ( GetSizer() )
+ {
+ int w = 0, h = 0;
+ GetVirtualSize(&w, &h);
+ GetSizer()->SetDimension( 0, 0, w, h );
+ }
+#if wxUSE_CONSTRAINTS
+ else
+ {
+ SatisfyConstraints(); // Find the right constraints values
+ SetConstraintSizes(); // Recursively set the real window sizes
+ }
+#endif
+
+ return true;
+}
+
+void wxWindowBase::InternalOnSize(wxSizeEvent& event)
+{
+ if ( GetAutoLayout() )
+ Layout();
+
+ event.Skip();
+}