]> git.saurik.com Git - wxWidgets.git/blobdiff - wxPython/src/helpers.cpp
better report if the subclass factory has import problems
[wxWidgets.git] / wxPython / src / helpers.cpp
index 0ef3c132492922290592ddd551e06f08ccf53d22..dfafce7dc56a492a1f5faa9d965d44ce2ec272e3 100644 (file)
 #include <gdk/gdkx.h>
 #include <gtk/gtk.h>
 #include <gdk/gdkprivate.h>
+#ifdef __WXGTK20__
 #include <wx/gtk/win_gtk.h>
+#else
+#include <wx/gtk1/win_gtk.h>
+#endif
 #define GetXWindow(wxwin) (wxwin)->m_wxwindow ? \
                           GDK_WINDOW_XWINDOW(GTK_PIZZA((wxwin)->m_wxwindow)->bin_window) : \
                           GDK_WINDOW_XWINDOW((wxwin)->m_widget->window)
@@ -276,7 +280,7 @@ void wxPyApp::OnAssertFailure(const wxChar *file,
 
         // do the normal wx assert dialog?
         if (m_assertMode & wxPYAPP_ASSERT_DIALOG)
-            wxApp::OnAssert(file, line, cond, msg);
+            wxApp::OnAssertFailure(file, line, func, cond, msg);
     }
 }
 #endif
@@ -323,11 +327,7 @@ void wxPyApp::MacReopenApp()
 
 /*static*/
 bool wxPyApp::GetMacSupportPCMenuShortcuts() {
-#ifdef __WXMAC__
-    return s_macSupportPCMenuShortcuts;
-#else
     return 0;
-#endif
 }
 
 /*static*/
@@ -367,10 +367,7 @@ wxString wxPyApp::GetMacHelpMenuTitleName() {
 }
 
 /*static*/
-void wxPyApp::SetMacSupportPCMenuShortcuts(bool val) {
-#ifdef __WXMAC__
-    s_macSupportPCMenuShortcuts = val;
-#endif
+void wxPyApp::SetMacSupportPCMenuShortcuts(bool) {
 }
 
 /*static*/
@@ -495,6 +492,8 @@ void wxPyApp::_BootstrapApp()
         Py_DECREF(argTuple);
         Py_DECREF(method);
         if (retval == NULL)
+            // Don't PyErr_Print here, let the exception in this case go back
+            // up to the wx.PyApp.__init__ scope.
             goto error;
 
         pyint = PyNumber_Int(retval);
@@ -713,7 +712,19 @@ PyObject* __wxPySetDictionary(PyObject* /* self */, PyObject* args)
     _AddInfoString("wx-assertions-off");
 #endif
     _AddInfoString(wxPy_SWIG_VERSION);    
-    
+#ifdef __WXMAC__
+    #if wxMAC_USE_CORE_GRAPHICS
+        _AddInfoString("mac-cg");
+    #else
+        _AddInfoString("mac-qd");
+    #endif
+    #if wxMAC_USE_NATIVE_TOOLBAR
+        _AddInfoString("mac-native-tb");
+    #else
+        _AddInfoString("mac-no-native-tb");
+    #endif
+#endif
+        
 #undef _AddInfoString
 
     PyObject* PlatInfoTuple = PyList_AsTuple(PlatInfo);
@@ -1713,7 +1724,7 @@ PyObject* wxPyCBH_callCallbackObj(const wxPyCallbackHelper& cbh, PyObject* argTu
 
 
 void wxPyCBH_delete(wxPyCallbackHelper* cbh) {
-    if (cbh->m_incRef) {
+    if (cbh->m_incRef && Py_IsInitialized()) {
         wxPyBlock_t blocked = wxPyBeginBlockThreads();
         Py_XDECREF(cbh->m_self);
         Py_XDECREF(cbh->m_class);
@@ -1815,6 +1826,7 @@ PyObject* wxPy_ConvertList(wxListBase* listbase) {
         wxObj = node->GetData();
         pyObj = wxPyMake_wxObject(wxObj,false);
         PyList_Append(pyList, pyObj);
+        Py_DECREF(pyObj);  // the Append also does an INCREF, that's one more than we need.
         node = node->GetNext();
     }
     wxPyEndBlockThreads(blocked);
@@ -2051,37 +2063,73 @@ char** string_LIST_helper(PyObject* source) {
     return temp;
 }
 
-//--------------------------------
-// Part of patch from Tim Hochberg
-static inline bool wxPointFromObjects(PyObject* o1, PyObject* o2, wxPoint* point) {
-    if (PyInt_Check(o1) && PyInt_Check(o2)) {
-        point->x = PyInt_AS_LONG(o1);
-        point->y = PyInt_AS_LONG(o2);
-        return true;
-    }
-    if (PyFloat_Check(o1) && PyFloat_Check(o2)) {
+//---------------------------------------------------------------------------
+// NOTE: The following functions could really use some refactoring using
+// templates to make things somewhat simpler...
+
+inline bool wxPointFromObjects(PyObject* o1, PyObject* o2, wxPoint* point)
+{
+    // get the x value
+    if (PyInt_Check(o1))
+        point->x = (int)PyInt_AS_LONG(o1);
+    else if (PyFloat_Check(o1))
         point->x = (int)PyFloat_AS_DOUBLE(o1);
+    else if (PyNumber_Check(o1))
+        point->x = (int)PyInt_AsLong(o1);
+    else
+        return false;
+
+    // get the y value
+    if (PyInt_Check(o2))
+        point->y = (int)PyInt_AS_LONG(o2);
+    else if (PyFloat_Check(o2))
         point->y = (int)PyFloat_AS_DOUBLE(o2);
-        return true;
-    }
-    if (wxPySwigInstance_Check(o1) || wxPySwigInstance_Check(o2)) {  // TODO: Why???
-        // Disallow instances because they can cause havok
+    else if (PyNumber_Check(o2))
+        point->y = (int)PyInt_AsLong(o2);
+    else
         return false;
-    }
-    if (PyNumber_Check(o1) && PyNumber_Check(o2)) {
-        // I believe this excludes instances, so this should be safe without INCREFFing o1 and o2
-        point->x = PyInt_AsLong(o1);
-        point->y = PyInt_AsLong(o2);
-        return true;
-    }
-    return false;
+
+    return true;
+
+// NOTE: This function used to have this code in it, but I don't know why it
+// is a problem nor what havok it will cause, so removing for now...
+//     if (wxPySwigInstance_Check(o1) || wxPySwigInstance_Check(o2)) {  
+//         // Disallow instances because they can cause havok
+//         return false;
+//     }
+}
+
+
+inline bool wxPoint2DFromObjects(PyObject* o1, PyObject* o2, wxPoint2D* point)
+{
+    // get the x value
+    if (PyInt_Check(o1))
+        point->m_x = (double)PyInt_AS_LONG(o1);
+    else if (PyFloat_Check(o1))
+        point->m_x = (double)PyFloat_AS_DOUBLE(o1);
+    else if (PyNumber_Check(o1))
+        point->m_x = (double)PyFloat_AsDouble(o1);
+    else
+        return false;
+
+    // get the y value
+    if (PyInt_Check(o2))
+        point->m_y = (double)PyInt_AS_LONG(o2);
+    else if (PyFloat_Check(o2))
+        point->m_y = (double)PyFloat_AS_DOUBLE(o2);
+    else if (PyNumber_Check(o2))
+        point->m_y = (double)PyFloat_AsDouble(o2);
+    else
+        return false;
+
+    return true;
 }
 
 
-wxPoint* wxPoint_LIST_helper(PyObject* source, int *count) {
-    // Putting all of the declarations here allows
-    // us to put the error handling all in one place.
-    int x;
+
+wxPoint* wxPoint_LIST_helper(PyObject* source, int *count)
+{
+    int idx;
     wxPoint* temp;
     PyObject *o, *o1, *o2;
     bool isFast = PyList_Check(source) || PyTuple_Check(source);
@@ -2101,13 +2149,13 @@ wxPoint* wxPoint_LIST_helper(PyObject* source, int *count) {
         PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
         return NULL;
     }
-    for (x=0; x<*count; x++) {
+    for (idx=0; idx<*count; idx++) {
         // Get an item: try fast way first.
         if (isFast) {
-            o = PySequence_Fast_GET_ITEM(source, x);
+            o = PySequence_Fast_GET_ITEM(source, idx);
         }
         else {
-            o = PySequence_GetItem(source, x);
+            o = PySequence_GetItem(source, idx);
             if (o == NULL) {
                 goto error1;
             }
@@ -2118,7 +2166,7 @@ wxPoint* wxPoint_LIST_helper(PyObject* source, int *count) {
             (PyList_Check(o) && PyList_GET_SIZE(o) == 2)) {
             o1 = PySequence_Fast_GET_ITEM(o, 0);
             o2 = PySequence_Fast_GET_ITEM(o, 1);
-            if (!wxPointFromObjects(o1, o2, &temp[x])) {
+            if (!wxPointFromObjects(o1, o2, &temp[idx])) {
                 goto error2;
             }
         }
@@ -2127,12 +2175,12 @@ wxPoint* wxPoint_LIST_helper(PyObject* source, int *count) {
             if (! wxPyConvertSwigPtr(o, (void **)&pt, wxT("wxPoint"))) {
                 goto error2;
             }
-            temp[x] = *pt;
+            temp[idx] = *pt;
         }
         else if (PySequence_Check(o) && PySequence_Length(o) == 2) {
             o1 = PySequence_GetItem(o, 0);
             o2 = PySequence_GetItem(o, 1);
-            if (!wxPointFromObjects(o1, o2, &temp[x])) {
+            if (!wxPointFromObjects(o1, o2, &temp[idx])) {
                 goto error3;
             }
             Py_DECREF(o1);
@@ -2159,8 +2207,91 @@ error0:
     PyErr_SetString(PyExc_TypeError, "Expected a sequence of length-2 sequences or wxPoints.");
     return NULL;
 }
-// end of patch
-//------------------------------
+
+
+
+wxPoint2D* wxPoint2D_LIST_helper(PyObject* source, size_t *count)
+{
+    size_t idx;
+    wxPoint2D* temp;
+    PyObject *o, *o1, *o2;
+    bool isFast = PyList_Check(source) || PyTuple_Check(source);
+
+    if (!PySequence_Check(source)) {
+        goto error0;
+    }
+
+    // The length of the sequence is returned in count.
+    *count = PySequence_Length(source);
+    if (*count < 0) {
+        goto error0;
+    }
+
+    temp = new wxPoint2D[*count];
+    if (!temp) {
+        PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
+        return NULL;
+    }
+    for (idx=0; idx<*count; idx++) {
+        // Get an item: try fast way first.
+        if (isFast) {
+            o = PySequence_Fast_GET_ITEM(source, idx);
+        }
+        else {
+            o = PySequence_GetItem(source, idx);
+            if (o == NULL) {
+                goto error1;
+            }
+        }
+
+        // Convert o to wxPoint.
+        if ((PyTuple_Check(o) && PyTuple_GET_SIZE(o) == 2) ||
+            (PyList_Check(o) && PyList_GET_SIZE(o) == 2)) {
+            o1 = PySequence_Fast_GET_ITEM(o, 0);
+            o2 = PySequence_Fast_GET_ITEM(o, 1);
+            if (!wxPoint2DFromObjects(o1, o2, &temp[idx])) {
+                goto error2;
+            }
+        }
+        else if (wxPySwigInstance_Check(o)) {
+            wxPoint2D* pt;
+            if (! wxPyConvertSwigPtr(o, (void **)&pt, wxT("wxPoint2D"))) {
+                goto error2;
+            }
+            temp[idx] = *pt;
+        }
+        else if (PySequence_Check(o) && PySequence_Length(o) == 2) {
+            o1 = PySequence_GetItem(o, 0);
+            o2 = PySequence_GetItem(o, 1);
+            if (!wxPoint2DFromObjects(o1, o2, &temp[idx])) {
+                goto error3;
+            }
+            Py_DECREF(o1);
+            Py_DECREF(o2);
+        }
+        else {
+            goto error2;
+        }
+        // Clean up.
+        if (!isFast)
+            Py_DECREF(o);
+    }
+    return temp;
+
+error3:
+    Py_DECREF(o1);
+    Py_DECREF(o2);
+error2:
+    if (!isFast)
+        Py_DECREF(o);
+error1:
+    delete [] temp;
+error0:
+    PyErr_SetString(PyExc_TypeError, "Expected a sequence of length-2 sequences or wxPoint2Ds.");
+    return NULL;
+}
+   
+//---------------------------------------------------------------------------
 
 
 wxBitmap** wxBitmap_LIST_helper(PyObject* source) {
@@ -2510,7 +2641,7 @@ bool wxColour_helper(PyObject* source, wxColour** obj) {
             return true;
         }
     }
-    // last chance: 3-tuple of integers is expected
+    // last chance: 3-tuple or 4-tuple of integers is expected
     else if (PySequence_Check(source) && PyObject_Length(source) == 3) {
         PyObject* o1 = PySequence_GetItem(source, 0);
         PyObject* o2 = PySequence_GetItem(source, 1);
@@ -2527,10 +2658,29 @@ bool wxColour_helper(PyObject* source, wxColour** obj) {
         Py_DECREF(o3);
         return true;
     }
+    else if (PySequence_Check(source) && PyObject_Length(source) == 4) {
+        PyObject* o1 = PySequence_GetItem(source, 0);
+        PyObject* o2 = PySequence_GetItem(source, 1);
+        PyObject* o3 = PySequence_GetItem(source, 2);
+        PyObject* o4 = PySequence_GetItem(source, 3);
+        if (!PyNumber_Check(o1) || !PyNumber_Check(o2) || !PyNumber_Check(o3) || !PyNumber_Check(o4)) {
+            Py_DECREF(o1);
+            Py_DECREF(o2);
+            Py_DECREF(o3);
+            Py_DECREF(o4);
+            goto error;
+        }
+        **obj = wxColour(PyInt_AsLong(o1), PyInt_AsLong(o2), PyInt_AsLong(o3), PyInt_AsLong(o4));
+        Py_DECREF(o1);
+        Py_DECREF(o2);
+        Py_DECREF(o3);
+        Py_DECREF(o4);
+        return true;
+    }
 
  error:
     PyErr_SetString(PyExc_TypeError,
-                    "Expected a wxColour object or a string containing a colour name or '#RRGGBB'.");
+                    "Expected a wxColour object, a string containing a colour name or '#RRGGBB', or a 3- or 4-tuple of integers.");
     return false;
 }
 
@@ -2579,15 +2729,60 @@ bool wxPoint2D_helper(PyObject* source, wxPoint2D** obj) {
         return true;
     }
  error:
-    PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of floats or a wxPoint2D object.");
+    PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of floats or a wx.Point2D object.");
     return false;
 }
 
 
-//----------------------------------------------------------------------
 
-PyObject* wxArrayString2PyList_helper(const wxArrayString& arr) {
+bool wxRect2D_helper(PyObject* source, wxRect2D** obj) {
+
+    if (source == Py_None) {
+        **obj = wxRect2D(-1,-1,-1,-1);
+        return true;
+    }
+
+    // If source is an object instance then it may already be the right type
+    if (wxPySwigInstance_Check(source)) {
+        wxRect2D* ptr;
+        if (! wxPyConvertSwigPtr(source, (void **)&ptr, wxT("wxRect2D")))
+            goto error;
+        *obj = ptr;
+        return true;
+    }
+    // otherwise a length-4 sequence of floats is expected
+    if (PySequence_Check(source) && PySequence_Length(source) == 4) {
+        PyObject* o1 = PySequence_GetItem(source, 0);
+        PyObject* o2 = PySequence_GetItem(source, 1);
+        PyObject* o3 = PySequence_GetItem(source, 2);
+        PyObject* o4 = PySequence_GetItem(source, 3);
+        // This should really check for floats, not numbers -- but that would break code.
+        if (!PyNumber_Check(o1) || !PyNumber_Check(o2) ||
+            !PyNumber_Check(o3) || !PyNumber_Check(o4)) {
+            Py_DECREF(o1);
+            Py_DECREF(o2);
+            Py_DECREF(o3);
+            Py_DECREF(o4);
+            goto error;
+        }
+        **obj = wxRect2D(PyFloat_AsDouble(o1), PyFloat_AsDouble(o2),
+                         PyFloat_AsDouble(o3), PyFloat_AsDouble(o4));
+        Py_DECREF(o1);
+        Py_DECREF(o2);
+        Py_DECREF(o3);
+        Py_DECREF(o4);
+        return true;
+    }
+ error:
+    PyErr_SetString(PyExc_TypeError, "Expected a 4-tuple of floats or a wx.Rect2D object.");
+    return false;
+}
+
+
+//----------------------------------------------------------------------
 
+PyObject* wxArrayString2PyList_helper(const wxArrayString& arr)
+{
     PyObject* list = PyList_New(0);
     for (size_t i=0; i < arr.GetCount(); i++) {
 #if wxUSE_UNICODE
@@ -2602,8 +2797,8 @@ PyObject* wxArrayString2PyList_helper(const wxArrayString& arr) {
 }
 
 
-PyObject* wxArrayInt2PyList_helper(const wxArrayInt& arr) {
-
+PyObject* wxArrayInt2PyList_helper(const wxArrayInt& arr)
+{
     PyObject* list = PyList_New(0);
     for (size_t i=0; i < arr.GetCount(); i++) {
         PyObject* number = PyInt_FromLong(arr[i]);
@@ -2614,6 +2809,18 @@ PyObject* wxArrayInt2PyList_helper(const wxArrayInt& arr) {
 }
 
 
+PyObject* wxArrayDouble2PyList_helper(const wxArrayDouble& arr)
+{
+    PyObject* list = PyList_New(0);
+    for (size_t i=0; i < arr.GetCount(); i++) {
+        PyObject* number = PyFloat_FromDouble(arr[i]);
+        PyList_Append(list, number);
+        Py_DECREF(number);
+    }
+    return list;
+}
+
+
 //----------------------------------------------------------------------
 // wxPyImageHandler methods
 //
@@ -2753,6 +2960,62 @@ int wxPyImageHandler::GetImageCount( wxInputStream& stream ) {
 }
 
 
+//----------------------------------------------------------------------
+// Function to test if the Display (or whatever is the platform equivallent)
+// can be connected to.  This is accessable from wxPython as a staticmethod of
+// wx.App called DisplayAvailable().
+
+
+bool wxPyTestDisplayAvailable()
+{
+#ifdef __WXGTK__
+    Display* display;
+    display = XOpenDisplay(NULL);
+    if (display == NULL)
+        return false;
+    XCloseDisplay(display);
+    return true;
+#endif
+
+#ifdef __WXMAC__
+    // This is adapted from Python's Mac/Modules/MacOS.c in the
+    // MacOS_WMAvailable function.
+    bool rv;
+    ProcessSerialNumber psn;
+               
+    /*
+    ** This is a fairly innocuous call to make if we don't have a window
+    ** manager, or if we have no permission to talk to it. It will print
+    ** a message on stderr, but at least it won't abort the process.
+    ** It appears the function caches the result itself, and it's cheap, so
+    ** no need for us to cache.
+    */
+#ifdef kCGNullDirectDisplay
+    /* On 10.1 CGMainDisplayID() isn't available, and
+    ** kCGNullDirectDisplay isn't defined.
+    */
+    if (CGMainDisplayID() == 0) {
+        rv = false;
+    } else 
+#endif
+    {
+        // Also foreground the application on the first call as a side-effect.
+        if (GetCurrentProcess(&psn) < 0 || SetFrontProcess(&psn) < 0) {
+            rv = false;
+        } else {
+            rv = true;
+        }
+    }
+    return rv;
+#endif
+
+#ifdef __WXMSW__
+    // TODO...
+    return true;
+#endif
+}
+
+
 //----------------------------------------------------------------------
 //----------------------------------------------------------------------