]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/wincmn.cpp
my previous commit patched the wrong file
[wxWidgets.git] / src / common / wincmn.cpp
index b9942fa0a85daf51156728b385cf1417f37fd885..a519ffd7f07070bf408fed5141f5a6552ee89b8f 100644 (file)
@@ -379,6 +379,12 @@ wxWindowBase::~wxWindowBase()
 #endif
 }
 
+bool wxWindowBase::IsBeingDeleted() const
+{
+    return m_isBeingDeleted ||
+            (!IsTopLevel() && m_parent && m_parent->IsBeingDeleted());
+}
+
 void wxWindowBase::SendDestroyEvent()
 {
     wxWindowDestroyEvent event;
@@ -618,9 +624,10 @@ wxSize wxWindowBase::DoGetBestSize() const
 // 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 )
@@ -658,23 +665,23 @@ wxSize wxWindowBase::GetWindowBorderSize() const
 
         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:
@@ -1007,7 +1014,7 @@ void wxWindowBase::AddChild(wxWindowBase *child)
     GetChildren().Append((wxWindow*)child);
     child->SetParent(this);
 
-    // adding a child while frozen will assert when thawn, so freeze it as if
+    // 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();
@@ -1019,7 +1026,10 @@ void wxWindowBase::RemoveChild(wxWindowBase *child)
 
     // removing a child while frozen may result in permanently frozen window
     // if used e.g. from Reparent(), so thaw it
-    if ( IsFrozen() && !child->IsTopLevel() )
+    //
+    // 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);
@@ -2397,6 +2407,11 @@ void wxWindowBase::InternalOnPopupMenu(wxCommandEvent& event)
     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)
 {
@@ -2407,8 +2422,24 @@ 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,
@@ -2607,7 +2638,7 @@ bool wxWindowBase::ms_winCaptureChanging = false;
 
 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?") );
 
@@ -2634,11 +2665,14 @@ void wxWindowBase::CaptureMouse()
 
 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;
 
@@ -2660,7 +2694,7 @@ void wxWindowBase::ReleaseMouse()
 
     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)
@@ -2735,8 +2769,8 @@ bool wxWindowBase::TryValidator(wxEvent& wxVALIDATOR_PARAM(event))
     // 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;
         }
@@ -2884,6 +2918,61 @@ bool wxWindowBase::HasFocus() const
            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
 // ----------------------------------------------------------------------------