#include "wx/settings.h"
#include "wx/dialog.h"
#include "wx/msgdlg.h"
+ #include "wx/msgout.h"
#include "wx/statusbr.h"
#include "wx/toolbar.h"
#include "wx/dcclient.h"
#include "wx/sysopt.h"
#endif
-// For reporting compile- and runtime version of GTK+ in the ctrl+alt+mclick dialog.
-// The gtk includes don't pull any other headers in, at least not on my system - MR
-#ifdef __WXGTK__
- #ifdef __WXGTK20__
- #include <gtk/gtkversion.h>
- #else
- #include <gtk/gtkfeatures.h>
- #endif
-#endif
-
#include "wx/platinfo.h"
// Windows List
bool wxWindowBase::Destroy()
{
+ SendDestroyEvent();
+
delete this;
return true;
wxWindow *child = node->GetData();
- // note that we really want to call delete and not ->Destroy() here
- // because we want to delete the child immediately, before we are
- // deleted, and delayed deletion would result in problems as our (top
- // level) child could outlive its parent
- delete child;
+ // note that we really want to delete it immediately so don't call the
+ // possible overridden Destroy() version which might not delete the
+ // child immediately resulting in problems with our (top level) child
+ // outliving its parent
+ child->wxWindowBase::Destroy();
wxASSERT_MSG( !GetChildren().Find(child),
wxT("child didn't remove itself using RemoveChild()") );
{
// merge the best size with the min size, giving priority to the min size
wxSize min = GetMinSize();
+
if (min.x == wxDefaultCoord || min.y == wxDefaultCoord)
{
wxSize best = GetBestSize();
if (min.x == wxDefaultCoord) min.x = best.x;
if (min.y == wxDefaultCoord) min.y = best.y;
}
+
return min;
}
+wxSize wxWindowBase::GetBestSize() const
+{
+ if ((!m_windowSizer) && (m_bestSizeCache.IsFullySpecified()))
+ return m_bestSizeCache;
+
+ return DoGetBestSize();
+}
+
+void wxWindowBase::SetMinSize(const wxSize& minSize)
+{
+ m_minWidth = minSize.x;
+ m_minHeight = minSize.y;
+}
+
+void wxWindowBase::SetMaxSize(const wxSize& maxSize)
+{
+ m_maxWidth = maxSize.x;
+ m_maxHeight = maxSize.y;
+}
void wxWindowBase::SetInitialSize(const wxSize& size)
{
// event handler stuff
// ----------------------------------------------------------------------------
-void wxWindowBase::PushEventHandler(wxEvtHandler *handler)
+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?" );
- handler->SetNextHandler(handlerOld);
+ // now use wxEvtHandler double-linked list to implement a stack:
+ handlerToPush->SetNextHandler(handlerOld);
- if ( handlerOld )
- GetEventHandler()->SetPreviousHandler(handler);
+ if (handlerOld != this)
+ handlerOld->SetPreviousHandler(handlerToPush);
- SetEventHandler(handler);
+ SetEventHandler(handlerToPush);
+
+#ifdef __WXDEBUG__
+ // 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
}
wxEvtHandler *wxWindowBase::PopEventHandler(bool deleteHandler)
{
- wxEvtHandler *handlerA = GetEventHandler();
- if ( handlerA )
- {
- wxEvtHandler *handlerB = handlerA->GetNextHandler();
- handlerA->SetNextHandler(NULL);
+ // we need to pop the wxWindow stack, i.e. we need to remove the first handler
- if ( handlerB )
- handlerB->SetPreviousHandler(NULL);
- SetEventHandler(handlerB);
+ 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" );
- if ( deleteHandler )
- {
- delete handlerA;
- handlerA = NULL;
- }
+ 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);
+ secondHandler->SetPreviousHandler(NULL);
+
+ // now firstHandler is completely unlinked; set secondHandler as the new window event handler
+ SetEventHandler(secondHandler);
+
+ if ( deleteHandler )
+ {
+ delete firstHandler;
+ firstHandler = NULL;
}
- return handlerA;
+ return firstHandler;
}
-bool wxWindowBase::RemoveEventHandler(wxEvtHandler *handler)
+bool wxWindowBase::RemoveEventHandler(wxEvtHandler *handlerToRemove)
{
- wxCHECK_MSG( handler, false, _T("RemoveEventHandler(NULL) called") );
+ 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;
+ }
- wxEvtHandler *handlerPrev = NULL,
- *handlerCur = GetEventHandler();
- while ( handlerCur )
+ // NOTE: the wxWindow event handler list is always terminated with "this" handler
+ wxEvtHandler *handlerCur = GetEventHandler()->GetNextHandler();
+ while ( handlerCur != this )
{
wxEvtHandler *handlerNext = handlerCur->GetNextHandler();
- if ( handlerCur == handler )
+ if ( handlerCur == handlerToRemove )
{
- if ( handlerPrev )
- {
- handlerPrev->SetNextHandler(handlerNext);
- }
- else
- {
- SetEventHandler(handlerNext);
- }
-
- if ( handlerNext )
- {
- handlerNext->SetPreviousHandler ( handlerPrev );
- }
-
- handler->SetNextHandler(NULL);
- handler->SetPreviousHandler(NULL);
+ handlerCur->Unlink();
+ wxASSERT_MSG( handlerCur != GetEventHandler(),
+ "the case Remove == Pop should was already handled" );
return true;
}
- handlerPrev = handlerCur;
handlerCur = handlerNext;
}
bool wxWindowBase::HandleWindowEvent(wxEvent& event) const
{
+ // SafelyProcessEvent() will handle exceptions nicely
return GetEventHandler()->SafelyProcessEvent(event);
}
static void DrawSizers(wxWindowBase *win);
-static void DrawBorder(wxWindowBase *win, const wxRect& rect, bool fill = false)
+static void DrawBorder(wxWindowBase *win, const wxRect& rect, bool fill, const wxPen* pen)
{
wxClientDC dc((wxWindow *)win);
- dc.SetPen(*wxRED_PEN);
- dc.SetBrush(fill ? wxBrush(*wxRED, wxBRUSHSTYLE_CROSSDIAG_HATCH) : *wxTRANSPARENT_BRUSH);
+ dc.SetPen(*pen);
+ dc.SetBrush(fill ? wxBrush(pen->GetColour(), wxBRUSHSTYLE_CROSSDIAG_HATCH) :
+ *wxTRANSPARENT_BRUSH);
dc.DrawRectangle(rect.Deflate(1, 1));
}
wxSizerItem *item = *i;
if ( item->IsSizer() )
{
- DrawBorder(win, item->GetRect().Deflate(2));
+ DrawBorder(win, item->GetRect().Deflate(2), false, wxRED_PEN);
DrawSizer(win, item->GetSizer());
}
else if ( item->IsSpacer() )
{
- DrawBorder(win, item->GetRect().Deflate(2), true);
+ DrawBorder(win, item->GetRect().Deflate(2), true, wxBLUE_PEN);
}
else if ( item->IsWindow() )
{
DrawSizers(item->GetWindow());
}
+ else
+ wxFAIL_MSG("inconsistent wxSizerItem status!");
}
}
static void DrawSizers(wxWindowBase *win)
{
+ DrawBorder(win, win->GetClientSize(), false, wxGREEN_PEN);
+
wxSizer *sizer = win->GetSizer();
if ( sizer )
{
- DrawBorder(win, win->GetClientSize());
DrawSizer(win, sizer);
}
else // no sizer, still recurse into the children
{
DrawSizers(*i);
}
+
+ // show all kind of sizes of this window; see the "window sizing" topic
+ // overview for more info about the various differences:
+ wxSize fullSz = win->GetSize();
+ wxSize clientSz = win->GetClientSize();
+ wxSize bestSz = win->GetBestSize();
+ wxSize minSz = win->GetMinSize();
+ wxSize maxSz = win->GetMaxSize();
+ wxSize virtualSz = win->GetVirtualSize();
+
+ wxMessageOutputDebug dbgout;
+ dbgout.Printf(
+ "%-10s => fullsz=%4d;%-4d clientsz=%4d;%-4d bestsz=%4d;%-4d minsz=%4d;%-4d maxsz=%4d;%-4d virtualsz=%4d;%-4d\n",
+ win->GetName(),
+ fullSz.x, fullSz.y,
+ clientSz.x, clientSz.y,
+ bestSz.x, bestSz.y,
+ minSz.x, minSz.y,
+ maxSz.x, maxSz.y,
+ virtualSz.x, virtualSz.y);
}
}
// event processing
// ----------------------------------------------------------------------------
-bool wxWindowBase::TryValidator(wxEvent& wxVALIDATOR_PARAM(event))
+bool wxWindowBase::TryBefore(wxEvent& event)
{
#if wxUSE_VALIDATORS
// Can only use the validator of the window which
}
#endif // wxUSE_VALIDATORS
- return false;
+ return wxEvtHandler::TryBefore(event);
}
-bool wxWindowBase::TryParent(wxEvent& event)
+bool wxWindowBase::TryAfter(wxEvent& event)
{
// carry on up the parent-child hierarchy if the propagation count hasn't
// reached zero yet
}
}
- return wxEvtHandler::TryParent(event);
+ return wxEvtHandler::TryAfter(event);
}
// ----------------------------------------------------------------------------
private:
wxWindowBase * const m_win;
- DECLARE_NO_COPY_CLASS(DragAcceptFilesTarget)
+ wxDECLARE_NO_COPY_CLASS(DragAcceptFilesTarget);
};