#if wxUSE_ACCESSIBILITY
delete m_accessible;
#endif
+
+#if wxUSE_HELP
+ // NB: this has to be called unconditionally, because we don't know
+ // whether this window has associated help text or not
+ wxHelpProvider *helpProvider = wxHelpProvider::Get();
+ if ( helpProvider )
+ helpProvider->RemoveHelp(this);
+#endif
+}
+
+bool wxWindowBase::IsBeingDeleted() const
+{
+ return m_isBeingDeleted ||
+ (!IsTopLevel() && m_parent && m_parent->IsBeingDeleted());
}
void wxWindowBase::SendDestroyEvent()
// return false if window wasn't closed because the application vetoed the
// close event
- return GetEventHandler()->ProcessEvent(event) && !event.GetVeto();
+ return HandleWindowEvent(event) && !event.GetVeto();
}
bool wxWindowBase::DestroyChildren()
// helper of GetWindowBorderSize(): as many ports don't implement support for
// wxSYS_BORDER/EDGE_X/Y metrics in their wxSystemSettings, use hard coded
// fallbacks in this case
-static int wxGetMetricOrDefault(wxSystemMetric what)
+static int wxGetMetricOrDefault(wxSystemMetric what, const wxWindowBase* win)
{
- int rc = wxSystemSettings::GetMetric(what);
+ int rc = wxSystemSettings::GetMetric(
+ what, static_cast<wxWindow*>(const_cast<wxWindowBase*>(win)));
if ( rc == -1 )
{
switch ( what )
case wxBORDER_SIMPLE:
case wxBORDER_STATIC:
- size.x = wxGetMetricOrDefault(wxSYS_BORDER_X);
- size.y = wxGetMetricOrDefault(wxSYS_BORDER_Y);
+ size.x = wxGetMetricOrDefault(wxSYS_BORDER_X, this);
+ size.y = wxGetMetricOrDefault(wxSYS_BORDER_Y, this);
break;
case wxBORDER_SUNKEN:
case wxBORDER_RAISED:
- size.x = wxMax(wxGetMetricOrDefault(wxSYS_EDGE_X),
- wxGetMetricOrDefault(wxSYS_BORDER_X));
- size.y = wxMax(wxGetMetricOrDefault(wxSYS_EDGE_Y),
- wxGetMetricOrDefault(wxSYS_BORDER_Y));
+ size.x = wxMax(wxGetMetricOrDefault(wxSYS_EDGE_X, this),
+ wxGetMetricOrDefault(wxSYS_BORDER_X, this));
+ size.y = wxMax(wxGetMetricOrDefault(wxSYS_EDGE_Y, this),
+ wxGetMetricOrDefault(wxSYS_BORDER_Y, this));
break;
case wxBORDER_DOUBLE:
- size.x = wxGetMetricOrDefault(wxSYS_EDGE_X) +
- wxGetMetricOrDefault(wxSYS_BORDER_X);
- size.y = wxGetMetricOrDefault(wxSYS_EDGE_Y) +
- wxGetMetricOrDefault(wxSYS_BORDER_Y);
+ size.x = wxGetMetricOrDefault(wxSYS_EDGE_X, this) +
+ wxGetMetricOrDefault(wxSYS_BORDER_X, this);
+ size.y = wxGetMetricOrDefault(wxSYS_EDGE_Y, this) +
+ wxGetMetricOrDefault(wxSYS_BORDER_Y, this);
break;
default:
return wxPoint(0,0);
}
+wxSize wxWindowBase::ClientToWindowSize(const wxSize& size) const
+{
+ const wxSize diff(GetSize() - GetClientSize());
+
+ return wxSize(size.x == -1 ? -1 : size.x + diff.x,
+ size.y == -1 ? -1 : size.y + diff.y);
+}
+
+wxSize wxWindowBase::WindowToClientSize(const wxSize& size) const
+{
+ const wxSize diff(GetSize() - GetClientSize());
+
+ return wxSize(size.x == -1 ? -1 : size.x - diff.x,
+ size.y == -1 ? -1 : size.y - diff.y);
+}
+
void wxWindowBase::SetWindowVariant( wxWindowVariant variant )
{
if ( m_windowVariant != variant )
ClientToScreen(x, y);
}
+void wxWindowBase::SendSizeEvent(int flags)
+{
+ wxSizeEvent event(GetSize(), GetId());
+ event.SetEventObject(this);
+ if ( flags & wxSEND_EVENT_POST )
+ wxPostEvent(this, event);
+ else
+ HandleWindowEvent(event);
+}
+
+void wxWindowBase::SendSizeEventToParent(int flags)
+{
+ wxWindow * const parent = GetParent();
+ if ( parent && !parent->IsBeingDeleted() )
+ parent->SendSizeEvent(flags);
+}
+
// ----------------------------------------------------------------------------
// show/hide/enable/disable the window
// ----------------------------------------------------------------------------
return false;
}
+// ----------------------------------------------------------------------------
+// Freeze/Thaw
+// ----------------------------------------------------------------------------
+
+void wxWindowBase::Freeze()
+{
+ if ( !m_freezeCount++ )
+ {
+ // physically freeze this window:
+ DoFreeze();
+
+ // and recursively freeze all children:
+ for ( wxWindowList::iterator i = GetChildren().begin();
+ i != GetChildren().end(); ++i )
+ {
+ wxWindow *child = *i;
+ if ( child->IsTopLevel() )
+ continue;
+
+ child->Freeze();
+ }
+ }
+}
+
+void wxWindowBase::Thaw()
+{
+ wxASSERT_MSG( m_freezeCount, "Thaw() without matching Freeze()" );
+
+ if ( !--m_freezeCount )
+ {
+ // recursively thaw all children:
+ for ( wxWindowList::iterator i = GetChildren().begin();
+ i != GetChildren().end(); ++i )
+ {
+ wxWindow *child = *i;
+ if ( child->IsTopLevel() )
+ continue;
+
+ child->Thaw();
+ }
+
+ // physically thaw this window:
+ DoThaw();
+ }
+}
+
// ----------------------------------------------------------------------------
// reparenting the window
// ----------------------------------------------------------------------------
GetChildren().Append((wxWindow*)child);
child->SetParent(this);
+
+ // adding a child while frozen will assert when thawed, so freeze it as if
+ // it had been already present when we were frozen
+ if ( IsFrozen() && !child->IsTopLevel() )
+ child->Freeze();
}
void wxWindowBase::RemoveChild(wxWindowBase *child)
{
wxCHECK_RET( child, wxT("can't remove a NULL child") );
+ // 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);
}
// wxGTK uses its own version, no need to add never used code
#ifndef __WXGTK__
wxClientDC dc((wxWindow *)this);
- wxBrush brush(GetBackgroundColour(), wxSOLID);
+ wxBrush brush(GetBackgroundColour(), wxBRUSHSTYLE_SOLID);
dc.SetBackground(brush);
dc.Clear();
#endif // __WXGTK__
}
}
+#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)
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
wxHelpProvider *helpProvider = wxHelpProvider::Get();
if ( helpProvider )
{
- if ( helpProvider->ShowHelpAtPoint(this, event.GetPosition(), event.GetOrigin()) )
+ 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;
gs_popupMenuSelection = event.GetId();
}
+void wxWindowBase::InternalOnPopupMenuUpdate(wxUpdateUIEvent& WXUNUSED(event))
+{
+ // nothing to do but do not skip it
+}
+
int
wxWindowBase::DoGetPopupMenuSelectionFromUser(wxMenu& menu, int x, int y)
{
NULL,
this);
+ // it is common to construct the menu passed to this function dynamically
+ // using some fixed range of ids which could clash with the ids used
+ // elsewhere in the program, which could result in some menu items being
+ // unintentionally disabled or otherwise modified by update UI handlers
+ // elsewhere in the program code and this is difficult to avoid in the
+ // program itself, so instead we just temporarily suspend UI updating while
+ // this menu is shown
+ Connect(wxEVT_UPDATE_UI,
+ wxUpdateUIEventHandler(wxWindowBase::InternalOnPopupMenuUpdate),
+ NULL,
+ this);
+
PopupMenu(&menu, x, y);
+ Disconnect(wxEVT_UPDATE_UI,
+ wxUpdateUIEventHandler(wxWindowBase::InternalOnPopupMenuUpdate),
+ NULL,
+ this);
Disconnect(wxEVT_COMMAND_MENU_SELECTED,
wxCommandEventHandler(wxWindowBase::InternalOnPopupMenu),
NULL,
{
wxClientDC dc((wxWindow *)win);
dc.SetPen(*wxRED_PEN);
- dc.SetBrush(fill ? wxBrush(*wxRED, wxCROSSDIAG_HATCH): *wxTRANSPARENT_BRUSH);
+ dc.SetBrush(fill ? wxBrush(*wxRED, wxBRUSHSTYLE_CROSSDIAG_HATCH) : *wxTRANSPARENT_BRUSH);
dc.DrawRectangle(rect.Deflate(1, 1));
}
void wxWindowBase::CaptureMouse()
{
- wxLogTrace(_T("mousecapture"), _T("CaptureMouse(%p)"), wx_static_cast(void*, this));
+ wxLogTrace(_T("mousecapture"), _T("CaptureMouse(%p)"), static_cast<void*>(this));
wxASSERT_MSG( !ms_winCaptureChanging, _T("recursive CaptureMouse call?") );
void wxWindowBase::ReleaseMouse()
{
- wxLogTrace(_T("mousecapture"), _T("ReleaseMouse(%p)"), wx_static_cast(void*, this));
+ wxLogTrace(_T("mousecapture"), _T("ReleaseMouse(%p)"), static_cast<void*>(this));
wxASSERT_MSG( !ms_winCaptureChanging, _T("recursive ReleaseMouse call?") );
- wxASSERT_MSG( GetCapture() == this, wxT("attempt to release mouse, but this window hasn't captured it") );
+ wxASSERT_MSG( GetCapture() == this,
+ "attempt to release mouse, but this window hasn't captured it" );
+ wxASSERT_MSG( ms_winCaptureCurrent == this,
+ "attempt to release mouse, but this window hasn't captured it" );
ms_winCaptureChanging = true;
wxLogTrace(_T("mousecapture"),
(const wxChar *) _T("After ReleaseMouse() mouse is captured by %p"),
- wx_static_cast(void*, GetCapture()));
+ static_cast<void*>(GetCapture()));
}
static void DoNotifyWindowAboutCaptureLost(wxWindow *win)
// is receiving the event
if ( event.GetEventObject() == this )
{
- wxValidator *validator = GetValidator();
- if ( validator && validator->ProcessEvent(event) )
+ wxValidator * const validator = GetValidator();
+ if ( validator && validator->ProcessEventHere(event) )
{
return true;
}
return false;
#else // !wxHAS_NATIVE_TAB_TRAVERSAL
wxNavigationKeyEvent eventNav;
+ wxWindow *focused = FindFocus();
+ eventNav.SetCurrentFocus(focused);
+ eventNav.SetEventObject(focused);
eventNav.SetFlags(flags);
- eventNav.SetEventObject(FindFocus());
return GetEventHandler()->ProcessEvent(eventNav);
#endif // wxHAS_NATIVE_TAB_TRAVERSAL/!wxHAS_NATIVE_TAB_TRAVERSAL
}
+bool wxWindowBase::HandleAsNavigationKey(const wxKeyEvent& event)
+{
+ if ( event.GetKeyCode() != WXK_TAB )
+ return false;
+
+ int flags = wxNavigationKeyEvent::FromTab;
+
+ if ( event.ShiftDown() )
+ flags |= wxNavigationKeyEvent::IsBackward;
+ else
+ flags |= wxNavigationKeyEvent::IsForward;
+
+ if ( event.ControlDown() )
+ flags |= wxNavigationKeyEvent::WinChange;
+
+ Navigate(flags);
+ return true;
+}
+
void wxWindowBase::DoMoveInTabOrder(wxWindow *win, WindowOrder move)
{
// check that we're not a top level window
win == wxConstCast(this, wxWindowBase)->GetMainWindowOfCompositeControl();
}
+// ----------------------------------------------------------------------------
+// drag and drop
+// ----------------------------------------------------------------------------
+
+#if wxUSE_DRAG_AND_DROP && !defined(__WXMSW__)
+
+namespace
+{
+
+class DragAcceptFilesTarget : public wxFileDropTarget
+{
+public:
+ DragAcceptFilesTarget(wxWindowBase *win) : m_win(win) {}
+
+ virtual bool OnDropFiles(wxCoord x, wxCoord y,
+ const wxArrayString& filenames)
+ {
+ wxDropFilesEvent event(wxEVT_DROP_FILES,
+ filenames.size(),
+ wxCArrayString(filenames).Release());
+ event.SetEventObject(m_win);
+ event.m_pos.x = x;
+ event.m_pos.y = y;
+
+ return m_win->HandleWindowEvent(event);
+ }
+
+private:
+ wxWindowBase * const m_win;
+
+ DECLARE_NO_COPY_CLASS(DragAcceptFilesTarget)
+};
+
+
+} // anonymous namespace
+
+// Generic version of DragAcceptFiles(). It works by installing a simple
+// wxFileDropTarget-to-EVT_DROP_FILES adaptor and therefore cannot be used
+// together with explicit SetDropTarget() calls.
+void wxWindowBase::DragAcceptFiles(bool accept)
+{
+ if ( accept )
+ {
+ wxASSERT_MSG( !GetDropTarget(),
+ "cannot use DragAcceptFiles() and SetDropTarget() together" );
+ SetDropTarget(new DragAcceptFilesTarget(this));
+ }
+ else
+ {
+ SetDropTarget(NULL);
+ }
+}
+
+#endif // wxUSE_DRAG_AND_DROP && !defined(__WXMSW__)
+
// ----------------------------------------------------------------------------
// global functions
// ----------------------------------------------------------------------------