]> git.saurik.com Git - wxWidgets.git/blobdiff - wxPython/src/_dataobj.i
fixes for the dummy classes (used when wxUSE_GRAPHICS_CONTEXT is 0)
[wxWidgets.git] / wxPython / src / _dataobj.i
index 4a9813dba96e6a503de85796fff2138c1ca46c99..a0c3428c20b11e66e21897c120ff2df8e8fc4a21 100644 (file)
@@ -50,45 +50,47 @@ enum wxDataFormatId
 
 DocStr(wxDataFormat,
 "A wx.DataFormat is an encapsulation of a platform-specific format
-handle which is used by the system for the clipboard and drag and
-drop operations. The applications are usually only interested in,
-for example, pasting data from the clipboard only if the data is
-in a format the program understands.  A data format is is used to
-uniquely identify this format.
-
-On the system level, a data format is usually just a number
-(CLIPFORMAT under Windows or Atom under X11, for example).");
-
-// The standard format IDs are
-
-//     wx.DF_INVALID       An invalid format
-//     wx.DF_TEXT          Text format 
-//     wx.DF_BITMAP        A bitmap (wx.Bitmap)
-//     wx.DF_METAFILE      A metafile (wx.Metafile, Windows only)
-//     wx.DF_FILENAME      A list of filenames
-//     wx.DF_HTML          An HTML string. This is only valid on Windows and non-unicode builds
-
-// Aside the standard formats, the application may also use
-// custom formats which are identified by their names (strings)
-// and not numeric identifiers. Although internally custom format
-// must be created (or registered) first, you shouldn\'t care
-// about it because it is done automatically the first time the
-// wxDataFormat object corresponding to a given format name is
-// created. 
-
-// ");
+handle which is used by the system for the clipboard and drag and drop
+operations. The applications are usually only interested in, for
+example, pasting data from the clipboard only if the data is in a
+format the program understands.  A data format is is used to uniquely
+identify this format.",
+"
+On the system level, a data format is usually just a number, (which
+may be the CLIPFORMAT under Windows or Atom under X11, for example.)
+
+The standard format IDs are:
+
+    ================    =====================================
+    wx.DF_INVALID       An invalid format
+    wx.DF_TEXT          Text format 
+    wx.DF_BITMAP        A bitmap (wx.Bitmap)
+    wx.DF_METAFILE      A metafile (wx.Metafile, Windows only)
+    wx.DF_FILENAME      A list of filenames
+    wx.DF_HTML          An HTML string. This is only valid on
+                        Windows and non-unicode builds
+    ================    =====================================
+
+Besies the standard formats, the application may also use custom
+formats which are identified by their names (strings) and not numeric
+identifiers. Although internally custom format must be created (or
+registered) first, you shouldn\'t care about it because it is done
+automatically the first time the wxDataFormat object corresponding to
+a given format name is created.
+
+");
 
 class wxDataFormat {
 public:
     DocCtorStr(
         wxDataFormat( wxDataFormatId type ),
-        "Constructs a data format object for one of the standard data\n"
-        "formats or an empty data object (use SetType or SetId later in\n"
-        "this case)");
+        "Constructs a data format object for one of the standard data formats
+or an empty data object (use SetType or SetId later in this case)", "");
 
     DocCtorStrName(
         wxDataFormat(const wxString& format),
-        "Constructs a data format object for a custom format identified by its name.",
+        "Constructs a data format object for a custom format identified by its
+name.", "",
         CustomDataFormat);
     
     ~wxDataFormat();    
@@ -104,20 +106,25 @@ public:
     
     DocDeclStr(
         void , SetType(wxDataFormatId format),
-        "Sets the format to the given value, which should be one of wx.DF_XXX constants.");
+        "Sets the format to the given value, which should be one of wx.DF_XXX
+constants.", "");
     
     DocDeclStr(
         wxDataFormatId , GetType() const,
-        "Returns the platform-specific number identifying the format.");
+        "Returns the platform-specific number identifying the format.", "");
     
 
     DocDeclStr(
         wxString , GetId() const,
-        "Returns the name of a custom format (this function will fail for a standard format).");
+        "Returns the name of a custom format (this function will fail for a
+standard format).", "");
     
     DocDeclStr(
         void , SetId(const wxString& format),
-        "Sets the format to be the custom format identified by the given name.");    
+        "Sets the format to be the custom format identified by the given name.", "");    
+
+    %property(Id, GetId, SetId, doc="See `GetId` and `SetId`");
+    %property(Type, GetType, SetType, doc="See `GetType` and `SetType`");
 };
 
 
@@ -125,27 +132,72 @@ public:
 const wxDataFormat wxFormatInvalid;
 %mutable;
 
-
 //---------------------------------------------------------------------------
 
 
-// wxDataObject represents a piece of data which knows which formats it
-// supports and knows how to render itself in each of them - GetDataHere(),
-// and how to restore data from the buffer (SetData()).
-//
-// Although this class may be used directly (i.e. custom classes may be
-// derived from it), in many cases it might be simpler to use either
-// wxDataObjectSimple or wxDataObjectComposite classes.
-//
-// A data object may be "read only", i.e. support only GetData() functions or
-// "read-write", i.e. support both GetData() and SetData() (in principle, it
-// might be "write only" too, but this is rare). Moreover, it doesn't have to
-// support the same formats in Get() and Set() directions: for example, a data
-// object containing JPEG image might accept BMPs in GetData() because JPEG
-// image may be easily transformed into BMP but not in SetData(). Accordingly,
-// all methods dealing with formats take an additional "direction" argument
-// which is either SET or GET and which tells the function if the format needs
-// to be supported by SetData() or GetDataHere().
+DocStr(wxDataObject,
+"A wx.DataObject represents data that can be copied to or from the
+clipboard, or dragged and dropped. The important thing about
+wx.DataObject is that this is a 'smart' piece of data unlike usual
+'dumb' data containers such as memory buffers or files. Being 'smart'
+here means that the data object itself should know what data formats
+it supports and how to render itself in each of supported formats.
+
+**NOTE**: This class is an abstract base class and can not be used
+directly from Python.  If you need a custom type of data object then
+you should instead derive from `wx.PyDataObjectSimple` or use
+`wx.CustomDataObject`.
+", "
+Not surprisingly, being 'smart' comes at a price of added
+complexity. This is reasonable for the situations when you really need
+to support multiple formats, but may be annoying if you only want to
+do something simple like cut and paste text.
+
+To provide a solution for both cases, wxWidgets has two predefined
+classes which derive from wx.DataObject: `wx.DataObjectSimple` and
+`wx.DataObjectComposite`.  `wx.DataObjectSimple` is the simplest
+wx.DataObject possible and only holds data in a single format (such as
+text or bitmap) and `wx.DataObjectComposite` is the simplest way to
+implement a wx.DataObject which supports multiple simultaneous formats
+because it achievs this by simply holding several
+`wx.DataObjectSimple` objects.
+
+Please note that the easiest way to use drag and drop and the
+clipboard with multiple formats is by using `wx.DataObjectComposite`,
+but it is not the most efficient one as each `wx.DataObjectSimple`
+would contain the whole data in its respective formats. Now imagine
+that you want to paste 200 pages of text in your proprietary format,
+as well as Word, RTF, HTML, Unicode and plain text to the clipboard
+and even today's computers are in trouble. For this case, you will
+have to derive from wx.DataObject directly and make it enumerate its
+formats and provide the data in the requested format on
+demand. (**TODO**: This is currently not possible from Python.  Make
+it so.)
+
+Note that the platform transfer mechanisms for the clipboard and drag
+and drop, do not copy any data out of the source application until
+another application actually requests the data. This is in contrast to
+the 'feel' offered to the user of a program who would normally think
+that the data resides in the clipboard after having pressed 'Copy' -
+in reality it is only declared to be available.
+");
+
+// [other docs...]
+// There are several predefined data object classes derived from
+// wxDataObjectSimple: wxFileDataObject, wxTextDataObject and
+// wxBitmapDataObject which can be used without change.
+
+// You may also derive your own data object classes from
+// wxCustomDataObject for user-defined types. The format of user-defined
+// data is given as mime-type string literal, such as 'application/word'
+// or 'image/png'. These strings are used as they are under Unix (so far
+// only GTK) to identify a format and are translated into their Windows
+// equivalent under Win32 (using the OLE IDataObject for data exchange to
+// and from the clipboard and for drag and drop). Note that the format
+// string translation under Windows is not yet finished.
+
+
+
 class wxDataObject {      
 public:
     enum Direction {
@@ -157,66 +209,208 @@ public:
     // wxDataObject();  // ***  It's an ABC.
     ~wxDataObject();
 
-    // get the best suited format for rendering our data
-    virtual wxDataFormat GetPreferredFormat(Direction dir = Get) const;
+    DocDeclStr(
+        virtual wxDataFormat , GetPreferredFormat(Direction dir = Get) const,
+        "Returns the preferred format for either rendering the data (if dir is
+Get, its default value) or for setting it. Usually this will be the
+native format of the wx.DataObject.", "");
+    
 
-    // get the number of formats we support
-    virtual size_t GetFormatCount(Direction dir = Get) const;
+    DocDeclStr(
+        virtual size_t , GetFormatCount(Direction dir = Get) const,
+        "Returns the number of available formats for rendering or setting the
+data.", "");
+    
 
-    // returns True if this format is supported
-    bool IsSupported(const wxDataFormat& format, Direction dir = Get) const;
+    DocDeclStr(
+        bool , IsSupported(const wxDataFormat& format, Direction dir = Get) const,
+        "Returns True if this format is supported.", "");
+    
 
-    // get the (total) size of data for the given format
-    virtual size_t GetDataSize(const wxDataFormat& format) const;
+    DocDeclStr(
+        virtual size_t , GetDataSize(const wxDataFormat& format) const,
+        "Get the (total) size of data for the given format", "");
+    
 
 
-    //-------------------------------------------------------------------
-    // TODO:  Fix these three methods to do the right Pythonic things...
-    //-------------------------------------------------------------------
+    %extend {
+        DocAStr(GetAllFormats,
+                "GetAllFormats(self, int dir=Get) -> [formats]",
+                "Returns a list of all the wx.DataFormats that this dataobject supports
+in the given direction.", "");
+        PyObject* GetAllFormats(Direction dir = Get) {
+            size_t count = self->GetFormatCount(dir);
+            wxDataFormat* formats = new wxDataFormat[count];
+            self->GetAllFormats(formats, dir);
+
+            wxPyBlock_t blocked = wxPyBeginBlockThreads();
+            PyObject* list = PyList_New(count);
+            for (size_t i=0; i<count; i++) {
+                wxDataFormat* format = new wxDataFormat(formats[i]);
+                PyObject* obj = wxPyConstructObject((void*)format, wxT("wxDataFormat"), true);
+                PyList_SET_ITEM(list, i, obj); // PyList_SET_ITEM steals a reference
+            }            
+            wxPyEndBlockThreads(blocked);
+            delete [] formats;
+            return list;
+        }
+    }
 
-    // return all formats in the provided array (of size GetFormatCount())
-    virtual void GetAllFormats(wxDataFormat *formats,
-                               Direction dir = Get) const;
+    
 
     // copy raw data (in the specified format) to the provided buffer, return
     // True if data copied successfully, False otherwise
-    virtual bool GetDataHere(const wxDataFormat& format, void *buf) const;
+    // virtual bool GetDataHere(const wxDataFormat& format, void *buf) const;
 
+    %extend {
+        DocAStr(GetDataHere,
+                "GetDataHere(self, DataFormat format) -> String",
+                "Get the data bytes in the specified format, returns None on failure.", "
+:todo: This should use the python buffer interface isntead...");
+        PyObject* GetDataHere(const wxDataFormat& format) {
+            PyObject* rval = NULL;
+            size_t size = self->GetDataSize(format);            
+            wxPyBlock_t blocked = wxPyBeginBlockThreads();
+            if (size) {
+                char* buf = new char[size];
+                if (self->GetDataHere(format, buf)) 
+                    rval = PyString_FromStringAndSize(buf, size);
+                delete [] buf;
+            }
+            if (! rval) {
+                rval = Py_None;
+                Py_INCREF(rval);
+            }
+            wxPyEndBlockThreads(blocked);
+            return rval;
+        }
+    }
+
+    
     // get data from the buffer of specified length (in the given format),
     // return True if the data was read successfully, False otherwise
-    virtual bool SetData(const wxDataFormat& format,
-                         size_t len, const void * buf);
+    //virtual bool SetData(const wxDataFormat& format,
+    //                     size_t len, const void * buf);
+    DocAStr(SetData,
+            "SetData(self, DataFormat format, String data) -> bool",
+            "Set the data in the specified format from the bytes in the the data string.
+", "
+:todo: This should use the python buffer interface isntead...");
+    %extend {
+        bool SetData(const wxDataFormat& format, PyObject* data) {
+            bool rval;
+            wxPyBlock_t blocked = wxPyBeginBlockThreads();
+            if (PyString_Check(data)) {
+                rval = self->SetData(format, PyString_Size(data), PyString_AsString(data));
+            }
+            else {
+                // raise a TypeError if not a string
+                PyErr_SetString(PyExc_TypeError, "String expected.");
+                rval = false;
+            }
+            wxPyEndBlockThreads(blocked);
+            return rval;
+        }
+    }
+    
+    %property(AllFormats, GetAllFormats, doc="See `GetAllFormats`");
+    %property(DataHere, GetDataHere, doc="See `GetDataHere`");
+    %property(DataSize, GetDataSize, doc="See `GetDataSize`");
+    %property(FormatCount, GetFormatCount, doc="See `GetFormatCount`");
+    %property(PreferredFormat, GetPreferredFormat, doc="See `GetPreferredFormat`");
+
 };
 
     
 //---------------------------------------------------------------------------
 
 
+DocStr(wxDataObjectSimple,
+"wx.DataObjectSimple is a `wx.DataObject` which only supports one
+format.  This is the simplest possible `wx.DataObject` implementation.
+
+This is still an \"abstract base class\" meaning that you can't use it
+directly.  You either need to use one of the predefined base classes,
+or derive your own class from `wx.PyDataObjectSimple`.
+", "");
 
-// wxDataObjectSimple is a wxDataObject which only supports one format (in
-// both Get and Set directions, but you may return False from GetDataHere() or
-// SetData() if one of them is not supported). This is the simplest possible
-// wxDataObject implementation.
-//
-// This is still an "abstract base class" (although it doesn't have any pure
-// virtual functions), to use it you should derive from it and implement
-// GetDataSize(), GetDataHere() and SetData() functions because the base class
-// versions don't do anything - they just return "not implemented".
-//
-// This class should be used when you provide data in only one format (no
-// conversion to/from other formats), either a standard or a custom one.
-// Otherwise, you should use wxDataObjectComposite or wxDataObject directly.
 class wxDataObjectSimple : public wxDataObject {
 public:
-    wxDataObjectSimple(const wxDataFormat& format = wxFormatInvalid);
+    DocCtorStr(
+        wxDataObjectSimple(const wxDataFormat& format = wxFormatInvalid),
+        "Constructor accepts the supported format (none by default) which may
+also be set later with `SetFormat`.","");
 
-    // get/set the format we support
-    const wxDataFormat& GetFormat();
-    void SetFormat(const wxDataFormat& format);
 
+    DocDeclStr(
+        const wxDataFormat& , GetFormat(),
+        "Returns the (one and only one) format supported by this object. It is
+assumed that the format is supported in both directions.", "");
+    
+    DocDeclStr(
+        void , SetFormat(const wxDataFormat& format),
+        "Sets the supported format.", "");   
+
+    DocDeclStr(
+        virtual size_t , GetDataSize() const,
+        "Get the size of our data.", "");
+
+
+    
+    %extend {
+        DocAStr(GetDataHere,
+                "GetDataHere(self) -> String",
+                "Returns the data bytes from the data object as a string, returns None
+on failure.  Must be implemented in the derived class if the object
+supports rendering its data.", "");
+        PyObject* GetDataHere() {
+            PyObject* rval = NULL;
+            size_t size = self->GetDataSize();            
+            wxPyBlock_t blocked = wxPyBeginBlockThreads();
+            if (size) {
+                char* buf = new char[size];
+                if (self->GetDataHere(buf)) 
+                    rval = PyString_FromStringAndSize(buf, size);
+                delete [] buf;
+            }
+            if (! rval) {
+                rval = Py_None;
+                Py_INCREF(rval);
+            }
+            wxPyEndBlockThreads(blocked);
+            return rval;
+        }
+    }
+
+    
+    %extend {
+        DocAStr(SetData,
+                "SetData(self, String data) -> bool",
+                "Copy the data value to the data object.  Must be implemented in the
+derived class if the object supports setting its data.
+", "");
+        bool SetData(PyObject* data) {
+            bool rval;
+            wxPyBlock_t blocked = wxPyBeginBlockThreads();
+            if (PyString_Check(data)) {
+                rval = self->SetData(PyString_Size(data), PyString_AsString(data));
+            }
+            else {
+                // raise a TypeError if not a string
+                PyErr_SetString(PyExc_TypeError, "String expected.");
+                rval = false;
+            }
+            wxPyEndBlockThreads(blocked);
+            return rval;
+        }
+    }
+    
+    %property(Format, GetFormat, SetFormat, doc="See `GetFormat` and `SetFormat`");
 };
 
 
+
+
 %{  // Create a new class for wxPython to use
 class wxPyDataObjectSimple : public wxDataObjectSimple {
 public:
@@ -225,7 +419,7 @@ public:
 
     DEC_PYCALLBACK_SIZET__const(GetDataSize);
     bool GetDataHere(void *buf) const;
-    bool SetData(size_t len, const void *buf) const;
+    bool SetData(size_t len, const void *buf);
     PYPRIVATE;
 };
 
@@ -237,8 +431,8 @@ bool wxPyDataObjectSimple::GetDataHere(void *buf) const {
     // return either a string or None and then act appropriately with the
     // C++ version.
 
-    bool rval = False;
-    wxPyBeginBlockThreads();
+    bool rval = false;
+    wxPyBlock_t blocked = wxPyBeginBlockThreads();
     if (wxPyCBH_findCallback(m_myInst, "GetDataHere")) {
         PyObject* ro;
         ro = wxPyCBH_callCallbackObj(m_myInst, Py_BuildValue("()"));
@@ -249,21 +443,21 @@ bool wxPyDataObjectSimple::GetDataHere(void *buf) const {
             Py_DECREF(ro);
         }
     }
-    wxPyEndBlockThreads();
+    wxPyEndBlockThreads(blocked);
     return rval;
 }
 
-bool wxPyDataObjectSimple::SetData(size_t len, const void *buf) const{
+bool wxPyDataObjectSimple::SetData(size_t len, const void *buf) {
     // For this one we simply need to make a string from buf and len
     // and send it to the Python method.
-    bool rval = False;
-    wxPyBeginBlockThreads();
+    bool rval = false;
+    wxPyBlock_t blocked = wxPyBeginBlockThreads();
     if (wxPyCBH_findCallback(m_myInst, "SetData")) {
         PyObject* data = PyString_FromStringAndSize((char*)buf, len);
         rval = wxPyCBH_callCallback(m_myInst, Py_BuildValue("(O)", data));
         Py_DECREF(data);
     }
-    wxPyEndBlockThreads();
+    wxPyEndBlockThreads(blocked);
     return rval;
 }
 %}
@@ -271,6 +465,36 @@ bool wxPyDataObjectSimple::SetData(size_t len, const void *buf) const{
 
 
 // Now define it for SWIG
+DocStr(wxPyDataObjectSimple,
+"wx.PyDataObjectSimple is a version of `wx.DataObjectSimple` that is
+Python-aware and knows how to reflect calls to its C++ virtual methods
+to methods in the Python derived class.  You should derive from this
+class and overload `GetDataSize`, `GetDataHere` and `SetData` when you
+need to create your own simple single-format type of `wx.DataObject`.
+", "
+Here is a simple example::
+
+    class MyDataObject(wx.PyDataObjectSimple):
+        def __init__(self):
+            wx.PyDataObjectSimple.__init__(
+                self, wx.CustomDataFormat('MyDOFormat'))
+            self.data = ''
+
+        def GetDataSize(self):
+            return len(self.data)
+        def GetDataHere(self):
+            return self.data  # returns a string  
+        def SetData(self, data):
+            self.data = data
+            return True
+
+Note that there is already a `wx.CustomDataObject` class that behaves
+very similarly to this example.  The value of creating your own
+derived class like this is to be able to do additional things when the
+data is requested or given via the clipboard or drag and drop
+operation, such as generate the data value or decode it into needed
+data structures.
+");
 class wxPyDataObjectSimple : public wxDataObjectSimple {
 public:
     %pythonAppend wxPyDataObjectSimple   "self._setCallbackInfo(self, PyDataObjectSimple)"
@@ -283,33 +507,93 @@ public:
 //---------------------------------------------------------------------------
 
 
-// wxDataObjectComposite is the simplest way to implement wxDataObject
-// supporting multiple formats. It contains several wxDataObjectSimple and
-// supports all formats supported by any of them.
-//
+DocStr(wxDataObjectComposite,
+"wx.DataObjectComposite is the simplest `wx.DataObject` derivation
+which may be sued to support multiple formats. It contains several
+'wx.DataObjectSimple` objects and supports any format supported by at
+least one of them. Only one of these data objects is *preferred* (the
+first one if not explicitly changed by using the second parameter of
+`Add`) and its format determines the preferred format of the composite
+data object as well.
+
+See `wx.DataObject` documentation for the reasons why you might prefer
+to use wx.DataObject directly instead of wx.DataObjectComposite for
+efficiency reasons.
+", "");
+
 class wxDataObjectComposite : public wxDataObject {
 public:
     wxDataObjectComposite();
 
-    %apply SWIGTYPE *DISOWN { wxDataObjectSimple *dataObject };
-    void Add(wxDataObjectSimple *dataObject, int preferred = False);
-    %clear wxDataObjectSimple *dataObject;
+    %disownarg( wxDataObjectSimple *dataObject );
+    
+    DocDeclStr(
+        void , Add(wxDataObjectSimple *dataObject, bool preferred = false),
+        "Adds the dataObject to the list of supported objects and it becomes
+the preferred object if preferred is True.", "");
+    
+    %cleardisown( wxDataObjectSimple *dataObject );
+
+    DocDeclStr(
+        wxDataFormat , GetReceivedFormat() const,
+        "Report the format passed to the `SetData` method.  This should be the
+format of the data object within the composite that recieved data from
+the clipboard or the DnD operation.  You can use this method to find
+out what kind of data object was recieved.", "");
+    
+    %property(ReceivedFormat, GetReceivedFormat, doc="See `GetReceivedFormat`");
 };
 
 //---------------------------------------------------------------------------
 
-// wxTextDataObject contains text data
+DocStr(wxTextDataObject,
+"wx.TextDataObject is a specialization of `wx.DataObject` for text
+data. It can be used without change to paste data into the `wx.Clipboard`
+or a `wx.DropSource`.
+
+Alternativly, you may wish to derive a new class from the
+`wx.PyTextDataObject` class for providing text on-demand in order to
+minimize memory consumption when offering data in several formats,
+such as plain text and RTF, because by default the text is stored in a
+string in this class, but it might as well be generated on demand when
+requested. For this, `GetTextLength` and `GetText` will have to be
+overridden.", "");
 class wxTextDataObject : public wxDataObjectSimple {
 public:
-    wxTextDataObject(const wxString& text = wxPyEmptyString);
+    DocCtorStr(
+        wxTextDataObject(const wxString& text = wxPyEmptyString),
+        "Constructor, may be used to initialise the text (otherwise `SetText`
+should be used later).", "");
 
-    size_t GetTextLength();
-    wxString GetText();
-    void SetText(const wxString& text);
+    DocDeclStr(
+        size_t , GetTextLength(),
+        "Returns the data size.  By default, returns the size of the text data
+set in the constructor or using `SetText`.  This can be overridden (via
+`wx.PyTextDataObject`) to provide text size data on-demand. It is
+recommended to return the text length plus 1 for a trailing zero, but
+this is not strictly required.", "");
+    
+    DocDeclStr(
+        wxString , GetText(),
+        "Returns the text associated with the data object.", "");
+    
+    DocDeclStr(
+        void , SetText(const wxString& text),
+        "Sets the text associated with the data object. This method is called
+when the data object receives the data and, by default, copies the
+text into the member variable. If you want to process the text on the
+fly you may wish to override this function (via
+`wx.PyTextDataObject`.)", "");
+    
+    %property(Text, GetText, SetText, doc="See `GetText` and `SetText`");
+    %property(TextLength, GetTextLength, doc="See `GetTextLength`");
 };
 
 
 
+
+
+
 %{  // Create a new class for wxPython to use
 class wxPyTextDataObject : public wxTextDataObject {
 public:
@@ -330,6 +614,15 @@ IMP_PYCALLBACK__STRING(wxPyTextDataObject, wxTextDataObject, SetText);
 
 
 // Now define it for SWIG
+
+DocStr(wxPyTextDataObject,
+"wx.PyTextDataObject is a version of `wx.TextDataObject` that is
+Python-aware and knows how to reflect calls to its C++ virtual methods
+to methods in the Python derived class.  You should derive from this
+class and overload `GetTextLength`, `GetText`, and `SetText` when you
+want to be able to provide text on demand instead of preloading it
+into the data object.", "");
+
 class wxPyTextDataObject : public wxTextDataObject {
 public:
     %pythonAppend wxPyTextDataObject   "self._setCallbackInfo(self, PyTextDataObject)"
@@ -340,17 +633,41 @@ public:
 
 //---------------------------------------------------------------------------
 
-// wxBitmapDataObject contains a bitmap
+DocStr(wxBitmapDataObject,
+"wx.BitmapDataObject is a specialization of wxDataObject for bitmap
+data. It can be used without change to paste data into the `wx.Clipboard`
+or a `wx.DropSource`.
+", "
+:see: `wx.PyBitmapDataObject` if you wish to override `GetBitmap` to increase efficiency.");
+
 class wxBitmapDataObject : public wxDataObjectSimple {
 public:
-    wxBitmapDataObject(const wxBitmap& bitmap = wxNullBitmap);
+    DocCtorStr(
+        wxBitmapDataObject(const wxBitmap& bitmap = wxNullBitmap),
+        "Constructor, optionally passing a bitmap (otherwise use `SetBitmap`
+later).", "");
 
-    wxBitmap GetBitmap() const;
-    void SetBitmap(const wxBitmap& bitmap);
+    DocDeclStr(
+        wxBitmap , GetBitmap() const,
+        "Returns the bitmap associated with the data object.  You may wish to
+override this method (by deriving from `wx.PyBitmapDataObject`) when
+offering data on-demand, but this is not required by wxWidgets'
+internals. Use this method to get data in bitmap form from the
+`wx.Clipboard`.", "");
+    
+    DocDeclStr(
+        void , SetBitmap(const wxBitmap& bitmap),
+        "Sets the bitmap associated with the data object. This method is called
+when the data object receives data. Usually there will be no reason to
+override this function.", "");
+    
+    %property(Bitmap, GetBitmap, SetBitmap, doc="See `GetBitmap` and `SetBitmap`");
 };
 
 
 
+
+
 %{  // Create a new class for wxPython to use
 class wxPyBitmapDataObject : public wxBitmapDataObject {
 public:
@@ -364,7 +681,7 @@ public:
 
 wxBitmap wxPyBitmapDataObject::GetBitmap() const {
     wxBitmap* rval = &wxNullBitmap;
-    wxPyBeginBlockThreads();
+    wxPyBlock_t blocked = wxPyBeginBlockThreads();
     if (wxPyCBH_findCallback(m_myInst, "GetBitmap")) {
         PyObject* ro;
         wxBitmap* ptr;
@@ -375,24 +692,30 @@ wxBitmap wxPyBitmapDataObject::GetBitmap() const {
             Py_DECREF(ro);
         }
     }
-    wxPyEndBlockThreads();
+    wxPyEndBlockThreads(blocked);
     return *rval;
 }
-
 void wxPyBitmapDataObject::SetBitmap(const wxBitmap& bitmap) {
-    wxPyBeginBlockThreads();
+    wxPyBlock_t blocked = wxPyBeginBlockThreads();
     if (wxPyCBH_findCallback(m_myInst, "SetBitmap")) {
-        PyObject* bo = wxPyConstructObject((void*)&bitmap, wxT("wxBitmap"), False);
+        PyObject* bo = wxPyConstructObject((void*)&bitmap, wxT("wxBitmap"), false);
         wxPyCBH_callCallback(m_myInst, Py_BuildValue("(O)", bo));
         Py_DECREF(bo);
     }
-    wxPyEndBlockThreads();
+    wxPyEndBlockThreads(blocked);
 }
 %}
 
 
 
-// Now define it for SWIG
+
+DocStr(wxPyBitmapDataObject,
+"wx.PyBitmapDataObject is a version of `wx.BitmapDataObject` that is
+Python-aware and knows how to reflect calls to its C++ virtual methods
+to methods in the Python derived class. To be able to provide bitmap
+data on demand derive from this class and overload `GetBitmap`.", "");
+
 class wxPyBitmapDataObject : public wxBitmapDataObject {
 public:
     %pythonAppend wxPyBitmapDataObject   "self._setCallbackInfo(self, PyBitmapDataObject)"
@@ -404,72 +727,117 @@ public:
 //---------------------------------------------------------------------------
 
 
-// wxFileDataObject contains a list of filenames
+DocStr(wxFileDataObject,
+"wx.FileDataObject is a specialization of `wx.DataObjectSimple` for
+file names. The program works with it just as if it were a list of
+absolute file names, but internally it uses the same format as
+Explorer and other compatible programs under Windows or GNOME/KDE
+filemanager under Unix which makes it possible to receive files from
+them using this class.", "");
+
 class wxFileDataObject : public wxDataObjectSimple
 {
 public:
-    wxFileDataObject();
+    DocCtorStr(
+        wxFileDataObject(),
+        "", "");
 
-    const wxArrayString& GetFilenames();
-    void AddFile(const wxString &filename);
+    DocDeclAStr(
+        const wxArrayString& , GetFilenames(),
+        "GetFilenames(self) -> [names]",
+        "Returns a list of file names.", "");
+    
+    DocDeclStr(
+        void , AddFile(const wxString &filename),
+        "Adds a file to the list of files represented by this data object.", "");
+    
+    %property(Filenames, GetFilenames, doc="See `GetFilenames`");
 };
 
-
 //---------------------------------------------------------------------------
 
-// wxCustomDataObject contains arbitrary untyped user data.
-// It is understood that this data can be copied bitwise.
+DocStr(wxCustomDataObject,
+"wx.CustomDataObject is a specialization of `wx.DataObjectSimple` for
+some application-specific data in arbitrary format.  Python strings
+are used for getting and setting data, but any picklable object can
+easily be transfered via strings.  A copy of the data is stored in the
+data object.", "");
+
 class wxCustomDataObject : public wxDataObjectSimple {
 public:
-    wxCustomDataObject(const wxDataFormat& format = wxFormatInvalid);
-
-    //void TakeData(size_t size, void *data);
-    //bool SetData(size_t size, const void *buf);
+    %nokwargs wxCustomDataObject;
+    wxCustomDataObject(const wxDataFormat& format);
     %extend {
-        void TakeData(PyObject* data) {
-            if (PyString_Check(data)) {
-                // for Python we just call SetData here since we always need it to make a copy.
-                self->SetData(PyString_Size(data), PyString_AsString(data));
-            }
-            else {
-                // raise a TypeError if not a string
-                PyErr_SetString(PyExc_TypeError, "String expected.");
-            }
+        wxCustomDataObject(const wxString& formatName) {
+            return new wxCustomDataObject(wxDataFormat(formatName));
         }
+    }
+    wxCustomDataObject();
+    
+    
+    %extend {
+        DocAStr(SetData,
+                "SetData(self, String data) -> bool",
+                "Copy the data value to the data object.", "");
         bool SetData(PyObject* data) {
+            bool rval;
+            wxPyBlock_t blocked = wxPyBeginBlockThreads();
             if (PyString_Check(data)) {
-                return self->SetData(PyString_Size(data), PyString_AsString(data));
+                rval = self->SetData(PyString_Size(data), PyString_AsString(data));
             }
             else {
                 // raise a TypeError if not a string
                 PyErr_SetString(PyExc_TypeError, "String expected.");
-                return False;
+                rval = false;
             }
+            wxPyEndBlockThreads(blocked);
+            return rval;
         }
     }
+    %pythoncode { TakeData = SetData }
+    
+    DocDeclStr(
+        size_t , GetSize(),
+        "Get the size of the data.", "");
+    
 
-    size_t GetSize();
-
-    //void *GetData();
     %extend {
+        DocAStr(GetData,
+                "GetData(self) -> String",
+                "Returns the data bytes from the data object as a string.", "");
         PyObject* GetData() {
-            return PyString_FromStringAndSize((char*)self->GetData(), self->GetSize());
+            PyObject* obj;
+            wxPyBlock_t blocked = wxPyBeginBlockThreads();
+            obj = PyString_FromStringAndSize((char*)self->GetData(), self->GetSize());
+            wxPyEndBlockThreads(blocked);
+            return obj;
         }
     }
-};
 
+    %property(Data, GetData, SetData, doc="See `GetData` and `SetData`");
+    %property(Size, GetSize, doc="See `GetSize`");
+
+};
 
-// TODO: Implement wxPyCustomDataObject allowing GetSize, GetData and SetData
-// to be overloaded.
 
 //---------------------------------------------------------------------------
 
-class wxURLDataObject : public wxDataObjectComposite {
+DocStr(wxURLDataObject,
+"This data object holds a URL in a format that is compatible with some
+browsers such that it is able to be dragged to or from them.", "");
+class wxURLDataObject : public wxDataObject/*Composite*/ {
 public:
-    wxURLDataObject();
+    wxURLDataObject(const wxString& url = wxPyEmptyString);
 
-    wxString GetURL();
-    void SetURL(const wxString& url);
+    DocDeclStr(
+        wxString , GetURL(),
+        "Returns a string containing the current URL.", "");
+    
+    DocDeclStr(
+        void , SetURL(const wxString& url),
+        "Set the URL.", "");
+    
+    %property(URL, GetURL, SetURL, doc="See `GetURL` and `SetURL`");
 };
 
 //---------------------------------------------------------------------------