#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
EVT_HELP(wxID_ANY, wxWindowBase::OnHelp)
#endif // wxUSE_HELP
+ EVT_SIZE(wxWindowBase::InternalOnSize)
END_EVENT_TABLE()
// ============================================================================
m_exStyle =
m_windowStyle = 0;
- m_backgroundStyle = wxBG_STYLE_SYSTEM;
+ m_backgroundStyle = wxBG_STYLE_ERASE;
#if wxUSE_CONSTRAINTS
// no constraints whatsoever
bool wxWindowBase::CreateBase(wxWindowBase *parent,
wxWindowID id,
const wxPoint& WXUNUSED(pos),
- const wxSize& WXUNUSED(size),
+ const wxSize& size,
long style,
- const wxValidator& wxVALIDATOR_PARAM(validator),
const wxString& name)
{
-#if wxUSE_STATBOX
- // wxGTK doesn't allow to create controls with static box as the parent so
- // this will result in a crash when the program is ported to wxGTK so warn
- // the user about it
-
- // if you get this assert, the correct solution is to create the controls
- // as siblings of the static box
- wxASSERT_MSG( !parent || !wxDynamicCast(parent, wxStaticBox),
- _T("wxStaticBox can't be used as a window parent!") );
-#endif // wxUSE_STATBOX
-
// ids are limited to 16 bits under MSW so if you care about portability,
// it's not a good idea to use ids out of this range (and negative ids are
// reserved for wxWidgets own usage)
wxASSERT_MSG( id == wxID_ANY || (id >= 0 && id < 32767) ||
(id >= wxID_AUTO_LOWEST && id <= wxID_AUTO_HIGHEST),
- _T("invalid id value") );
+ wxT("invalid id value") );
// generate a new id if the user doesn't care about it
if ( id == wxID_ANY )
// flags by updating the window dynamically and we don't need this here
m_windowStyle = style;
+ // assume the user doesn't want this window to shrink beneath its initial
+ // size, this worked like this in wxWidgets 2.8 and before and generally
+ // often makes sense for child windows (for top level ones it definitely
+ // does not as the user should be able to resize the window)
+ //
+ // note that we can't use IsTopLevel() from ctor
+ if ( !wxTopLevelWindows.Find((wxWindow *)this) )
+ SetMinSize(size);
+
SetName(name);
SetParent(parent);
+ return true;
+}
+
+bool wxWindowBase::CreateBase(wxWindowBase *parent,
+ wxWindowID id,
+ const wxPoint& pos,
+ const wxSize& size,
+ long style,
+ const wxValidator& wxVALIDATOR_PARAM(validator),
+ const wxString& name)
+{
+ if ( !CreateBase(parent, id, pos, size, style, name) )
+ return false;
+
#if wxUSE_VALIDATORS
SetValidator(validator);
#endif // wxUSE_VALIDATORS
bool wxWindowBase::ToggleWindowStyle(int flag)
{
- wxASSERT_MSG( flag, _T("flags with 0 value can't be toggled") );
+ wxASSERT_MSG( flag, wxT("flags with 0 value can't be toggled") );
bool rc;
long style = GetWindowStyleFlag();
void wxWindowBase::DoCentre(int dir)
{
wxCHECK_RET( !(dir & wxCENTRE_ON_SCREEN) && GetParent(),
- _T("this method only implements centering child windows") );
+ wxT("this method only implements centering child windows") );
SetSize(GetRect().CentreIn(GetParent()->GetClientSize(), dir));
}
}
// On Mac, scrollbars are explicitly children.
-#ifdef __WXMAC__
+#if defined( __WXMAC__ ) && !defined(__WXUNIVERSAL__)
static bool wxHasRealChildren(const wxWindowBase* win)
{
int realChildCount = 0;
node = node->GetNext() )
{
wxWindow *win = node->GetData();
- if ( !win->IsTopLevel() && win->IsShown() && !win->IsKindOf(CLASSINFO(wxScrollBar)))
+ if ( !win->IsTopLevel() && win->IsShown()
+#if wxUSE_SCROLLBAR
+ && !win->IsKindOf(CLASSINFO(wxScrollBar))
+#endif
+ )
realChildCount ++;
}
return (realChildCount > 0);
}
#endif // wxUSE_CONSTRAINTS
else if ( !GetChildren().empty()
-#ifdef __WXMAC__
+#if defined( __WXMAC__ ) && !defined(__WXUNIVERSAL__)
&& wxHasRealChildren(this)
#endif
)
}
else // ! has children
{
- // for a generic window there is no natural best size so, if the
- // minimal size is not set, use the current size but take care to
- // remember it as minimal size for the next time because our best size
- // should be constant: otherwise we could get into a situation when the
- // window is initially at some size, then expanded to a larger size and
- // then, when the containing window is shrunk back (because our initial
- // best size had been used for computing the parent min size), we can't
- // be shrunk back any more because our best size is now bigger
wxSize size = GetMinSize();
if ( !size.IsFullySpecified() )
{
- size.SetDefaults(GetSize());
- wxConstCast(this, wxWindowBase)->SetMinSize(size);
+ // if the window doesn't define its best size we assume that it can
+ // be arbitrarily small -- usually this is not the case, of course,
+ // but we have no way to know what the limit is, it should really
+ // override DoGetBestClientSize() itself to tell us
+ size.SetDefaults(wxSize(1, 1));
}
// return as-is, unadjusted by the client size difference.
break;
default:
- wxFAIL_MSG( _T("unexpected wxGetMetricOrDefault() argument") );
+ wxFAIL_MSG( wxT("unexpected wxGetMetricOrDefault() argument") );
rc = 0;
}
}
break;
default:
- wxFAIL_MSG(_T("Unknown border style."));
+ wxFAIL_MSG(wxT("Unknown border style."));
break;
}
{
// 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::DoGetBorderSize() const
+{
+ // there is one case in which we can implement it for all ports easily:
+ // do it as some classes used by both wxUniv and native ports (e.g.
+ // wxGenericStaticText) do override DoGetBestClientSize() and so this
+ // method must work for them and that ensures that it does, at least in
+ // the default case)
+ if ( GetBorder() == wxBORDER_NONE )
+ return wxSize(0, 0);
+
+ wxFAIL_MSG( "must be overridden if called" );
+
+ return wxDefaultSize;
+}
+
+wxSize wxWindowBase::GetBestSize() const
+{
+ if ( !m_windowSizer && m_bestSizeCache.IsFullySpecified() )
+ return m_bestSizeCache;
+
+ // call DoGetBestClientSize() first, if a derived class overrides it wants
+ // it to be used
+ wxSize size = DoGetBestClientSize();
+ if ( size != wxDefaultSize )
+ {
+ size += DoGetBorderSize();
+
+ CacheBestSize(size);
+ return size;
+ }
+
+ 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)
{
break;
default:
- wxFAIL_MSG(_T("unexpected window variant"));
+ wxFAIL_MSG(wxT("unexpected window variant"));
break;
}
{
wxCHECK_RET( (minW == wxDefaultCoord || maxW == wxDefaultCoord || minW <= maxW) &&
(minH == wxDefaultCoord || maxH == wxDefaultCoord || minH <= maxH),
- _T("min width/height must be less than max width/height!") );
+ wxT("min width/height must be less than max width/height!") );
m_minWidth = minW;
m_maxWidth = maxW;
parent->SendSizeEvent(flags);
}
+bool wxWindowBase::HasScrollbar(int orient) const
+{
+ // if scrolling in the given direction is disabled, we can't have the
+ // corresponding scrollbar no matter what
+ if ( !CanScroll(orient) )
+ return false;
+
+ const wxSize sizeVirt = GetVirtualSize();
+ const wxSize sizeClient = GetClientSize();
+
+ return orient == wxHORIZONTAL ? sizeVirt.x > sizeClient.x
+ : sizeVirt.y > sizeClient.y;
+}
+
// ----------------------------------------------------------------------------
// show/hide/enable/disable the window
// ----------------------------------------------------------------------------
// this should never happen and it will lead to a crash later if it does
// because RemoveChild() will remove only one node from the children list
// and the other(s) one(s) will be left with dangling pointers in them
- wxASSERT_MSG( !GetChildren().Find((wxWindow*)child), _T("AddChild() called twice") );
+ wxASSERT_MSG( !GetChildren().Find((wxWindow*)child), wxT("AddChild() called twice") );
GetChildren().Append((wxWindow*)child);
child->SetParent(this);
SetEventHandler(handlerToPush);
-#ifdef __WXDEBUG__
+#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" );
+ "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" );
+ "the first handler of the wxWindow stack should "
+ "have non-NULL next handler" );
wxEvtHandler* pLast = handlerToPush;
- while (pLast && pLast != this)
+ 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
+ "the last handler of the wxWindow stack should "
+ "have this window as next handler" );
+#endif // wxDEBUG_LEVEL
}
wxEvtHandler *wxWindowBase::PopEventHandler(bool deleteHandler)
handlerCur = handlerNext;
}
- wxFAIL_MSG( _T("where has the event handler gone?") );
+ wxFAIL_MSG( wxT("where has the event handler gone?") );
return false;
}
{
if ( !m_backgroundColour.IsOk() )
{
- wxASSERT_MSG( !m_hasBgCol, _T("we have invalid explicit bg colour?") );
+ wxASSERT_MSG( !m_hasBgCol, wxT("we have invalid explicit bg colour?") );
// get our default background colour
wxColour colBg = GetDefaultAttributes().colBg;
return false;
m_hasBgCol = colour.IsOk();
- if ( m_backgroundStyle != wxBG_STYLE_CUSTOM )
- m_backgroundStyle = m_hasBgCol ? wxBG_STYLE_COLOUR : wxBG_STYLE_SYSTEM;
m_inheritBgCol = m_hasBgCol;
m_backgroundColour = colour;
// logic is the same as in GetBackgroundColour()
if ( !m_font.IsOk() )
{
- wxASSERT_MSG( !m_hasFont, _T("we have invalid explicit font?") );
+ wxASSERT_MSG( !m_hasFont, wxT("we have invalid explicit font?") );
wxFont font = GetDefaultAttributes().font;
if ( !font.IsOk() )
#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
// 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,
- _T("Adding a window to the same sizer twice?") );
+ wxT("Adding a window to the same sizer twice?") );
m_containingSizer = sizer;
}
return true;
}
+void wxWindowBase::InternalOnSize(wxSizeEvent& event)
+{
+ if ( GetAutoLayout() )
+ Layout();
+
+ event.Skip();
+}
+
#if wxUSE_CONSTRAINTS
// first phase of the constraints evaluation: set our own constraints
// ----------------------------------------------------------------------------
// propagate the colour change event to the subwindows
-void wxWindowBase::OnSysColourChanged(wxSysColourChangedEvent& event)
+void wxWindowBase::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(event))
{
wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
while ( node )
if ( !win->IsTopLevel() )
{
wxSysColourChangedEvent event2;
- event.SetEventObject(win);
+ event2.SetEventObject(win);
win->GetEventHandler()->ProcessEvent(event2);
}
#endif // wxUSE_MENUS
-// methods for drawing the sizers in a visible way
-#ifdef __WXDEBUG__
+// methods for drawing the sizers in a visible way: this is currently only
+// enabled for "full debug" builds with wxDEBUG_LEVEL==2 as it doesn't work
+// that well and also because we don't want to leave it enabled in default
+// builds used for production
+#if wxDEBUG_LEVEL > 1
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);
}
}
-#endif // __WXDEBUG__
+#endif // wxDEBUG_LEVEL
// process special middle clicks
void wxWindowBase::OnMiddleClick( wxMouseEvent& event )
{
if ( event.ControlDown() && event.AltDown() )
{
-#ifdef __WXDEBUG__
+#if wxDEBUG_LEVEL > 1
// Ctrl-Alt-Shift-mclick makes the sizers visible in debug builds
if ( event.ShiftDown() )
{
DrawSizers(this);
- return;
}
+ else
#endif // __WXDEBUG__
- ::wxInfoMessageBox((wxWindow*)this);
+ {
+ // just Ctrl-Alt-middle click shows information about wx version
+ ::wxInfoMessageBox((wxWindow*)this);
+ }
}
else
{
void wxWindowBase::CaptureMouse()
{
- wxLogTrace(_T("mousecapture"), _T("CaptureMouse(%p)"), static_cast<void*>(this));
+ wxLogTrace(wxT("mousecapture"), wxT("CaptureMouse(%p)"), static_cast<void*>(this));
- wxASSERT_MSG( !ms_winCaptureChanging, _T("recursive CaptureMouse call?") );
+ wxASSERT_MSG( !ms_winCaptureChanging, wxT("recursive CaptureMouse call?") );
ms_winCaptureChanging = true;
void wxWindowBase::ReleaseMouse()
{
- wxLogTrace(_T("mousecapture"), _T("ReleaseMouse(%p)"), static_cast<void*>(this));
+ wxLogTrace(wxT("mousecapture"), wxT("ReleaseMouse(%p)"), static_cast<void*>(this));
- wxASSERT_MSG( !ms_winCaptureChanging, _T("recursive ReleaseMouse call?") );
+ wxASSERT_MSG( !ms_winCaptureChanging, wxT("recursive ReleaseMouse call?") );
wxASSERT_MSG( GetCapture() == this,
"attempt to release mouse, but this window hasn't captured it" );
ms_winCaptureChanging = false;
- wxLogTrace(_T("mousecapture"),
- (const wxChar *) _T("After ReleaseMouse() mouse is captured by %p"),
+ wxLogTrace(wxT("mousecapture"),
+ (const wxChar *) wxT("After ReleaseMouse() mouse is captured by %p"),
static_cast<void*>(GetCapture()));
}
// correctly if it loses capture unexpectedly; see the discussion here:
// http://sourceforge.net/tracker/index.php?func=detail&aid=1153662&group_id=9863&atid=109863
// http://article.gmane.org/gmane.comp.lib.wxwidgets.devel/82376
- wxFAIL_MSG( _T("window that captured the mouse didn't process wxEVT_MOUSE_CAPTURE_LOST") );
+ wxFAIL_MSG( wxT("window that captured the mouse didn't process wxEVT_MOUSE_CAPTURE_LOST") );
}
}
// 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);
}
// ----------------------------------------------------------------------------
wxWindow *wxWindowBase::DoGetSibling(WindowOrder order) const
{
wxCHECK_MSG( GetParent(), NULL,
- _T("GetPrev/NextSibling() don't work for TLWs!") );
+ wxT("GetPrev/NextSibling() don't work for TLWs!") );
wxWindowList& siblings = GetParent()->GetChildren();
wxWindowList::compatibility_iterator i = siblings.Find((wxWindow *)this);
- wxCHECK_MSG( i, NULL, _T("window not a child of its parent?") );
+ wxCHECK_MSG( i, NULL, wxT("window not a child of its parent?") );
if ( order == OrderBefore )
i = i->GetPrevious();
{
// check that we're not a top level window
wxCHECK_RET( GetParent(),
- _T("MoveBefore/AfterInTabOrder() don't work for TLWs!") );
+ wxT("MoveBefore/AfterInTabOrder() don't work for TLWs!") );
// detect the special case when we have nothing to do anyhow and when the
// code below wouldn't work
// find the target window in the siblings list
wxWindowList& siblings = GetParent()->GetChildren();
wxWindowList::compatibility_iterator i = siblings.Find(win);
- wxCHECK_RET( i, _T("MoveBefore/AfterInTabOrder(): win is not a sibling") );
+ wxCHECK_RET( i, wxT("MoveBefore/AfterInTabOrder(): win is not a sibling") );
// unfortunately, when wxUSE_STL == 1 DetachNode() is not implemented so we
// can't just move the node around
private:
wxWindowBase * const m_win;
- DECLARE_NO_COPY_CLASS(DragAcceptFilesTarget)
+ wxDECLARE_NO_COPY_CLASS(DragAcceptFilesTarget);
};