]> git.saurik.com Git - wxWidgets.git/commitdiff
1. wxPostEvent added and documented
authorVadim Zeitlin <vadim@wxwidgets.org>
Sun, 17 Oct 1999 01:18:49 +0000 (01:18 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sun, 17 Oct 1999 01:18:49 +0000 (01:18 +0000)
2. Made it possible to have wxDataObjects which support multiple formats
   painlessly
3. Extensively modified dnd sample to show a "real life" wxDataObject

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@4028 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

24 files changed:
docs/latex/wx/function.tex
docs/latex/wx/wx.hpj
include/wx/app.h
include/wx/event.h
include/wx/gtk/dnd.h
include/wx/gtk1/dnd.h
include/wx/msw/app.h
include/wx/msw/ole/dataobj.h
include/wx/msw/ole/dropsrc.h
samples/dnd/dnd.cpp
samples/dnd/test.dsp [deleted file]
samples/dnd/test.dsw [deleted file]
src/common/event.cpp
src/gtk/app.cpp
src/gtk/data.cpp
src/gtk/dnd.cpp
src/gtk1/app.cpp
src/gtk1/data.cpp
src/gtk1/dnd.cpp
src/msw/app.cpp
src/msw/clipbrd.cpp
src/msw/data.cpp
src/msw/ole/dataobj.cpp
src/msw/ole/dropsrc.cpp

index e260c3d7659a500108ae295a54114d89c7143fae..60d9863169f60f96d94fa90218c80d9d51d0fbbb 100644 (file)
@@ -1058,6 +1058,17 @@ Gets the physical size of the display in pixels.
 
 <wx/gdicmn.h>
 
+\membersection{::wxEnableTopLevelWindows}\label{wxenabletoplevelwindows}
+
+\func{void}{wxEnableTopLevelWindow}{\param{bool}{ enable = TRUE}}
+
+This function enables or disables all top level windows. It is used by
+\helpref{::wxSafeYield}{wxsafeyield}.
+
+\wxheading{Include files}
+
+<wx/utils.h>
+
 \membersection{::wxEntry}\label{wxentry}
 
 This initializes wxWindows in a platform-dependent way. Use this if you
@@ -1101,26 +1112,26 @@ int CTheApp::ExitInstance()
 
 <wx/app.h>
 
-\membersection{::wxError}\label{wxerror}
+\membersection{::wxEndBusyCursor}\label{wxendbusycursor}
 
-\func{void}{wxError}{\param{const wxString\& }{msg}, \param{const wxString\& }{title = "wxWindows Internal Error"}}
+\func{void}{wxEndBusyCursor}{\void}
 
-Displays {\it msg} and continues. This writes to standard error under
-Unix, and pops up a message box under Windows. Used for internal
-wxWindows errors. See also \helpref{wxFatalError}{wxfatalerror}.
+Changes the cursor back to the original cursor, for all windows in the application.
+Use with \helpref{wxBeginBusyCursor}{wxbeginbusycursor}.
+
+See also \helpref{wxIsBusy}{wxisbusy}, \helpref{wxBusyCursor}{wxbusycursor}.
 
 \wxheading{Include files}
 
 <wx/utils.h>
 
-\membersection{::wxEndBusyCursor}\label{wxendbusycursor}
-
-\func{void}{wxEndBusyCursor}{\void}
+\membersection{::wxError}\label{wxerror}
 
-Changes the cursor back to the original cursor, for all windows in the application.
-Use with \helpref{wxBeginBusyCursor}{wxbeginbusycursor}.
+\func{void}{wxError}{\param{const wxString\& }{msg}, \param{const wxString\& }{title = "wxWindows Internal Error"}}
 
-See also \helpref{wxIsBusy}{wxisbusy}, \helpref{wxBusyCursor}{wxbusycursor}.
+Displays {\it msg} and continues. This writes to standard error under
+Unix, and pops up a message box under Windows. Used for internal
+wxWindows errors. See also \helpref{wxFatalError}{wxfatalerror}.
 
 \wxheading{Include files}
 
@@ -1465,6 +1476,25 @@ Now obsolete: use \helpref{wxWindow::Close}{wxwindowclose} instead.
 
 <wx/utils.h>
 
+\membersection{::wxPostEvent}\label{wxpostevent}
+
+\func{void}{wxPostEvent}{\param{wxEvtHandler *}{dest}, \param{wxEvent\& }{event}}
+
+This function posts the event to the specified {\it dest} object. The
+difference between sending an event and posting it is that in the first case
+the event is processed before the function returns (in wxWindows, event sending
+is done with \helpref{ProcessEvent}{wxevthandlerprocessevent} function), but in
+the second, the function returns immediately and the event will be processed
+sometime later - usually during the next even loop iteration.
+
+Note that a copy of the {\it event} is made by the function, so the original
+copy can be deleted as soon as function returns. This function can also be used
+to send events between different threads safely.
+
+\wxheading{Include files}
+
+<wx/app.h>
+
 \membersection{::wxSafeYield}\label{wxsafeyield}
 
 \func{bool}{wxSafeYield}{\param{wxWindow*}{ win = NULL}}
@@ -1480,18 +1510,6 @@ Returns the result of the call to \helpref{::wxYield}{wxyield}.
 
 <wx/utils.h>
 
-\membersection{::wxEnableTopLevelWindows}\label{wxenabletoplevelwindows}
-
-\func{void}{wxEnableTopLevelWindow}{\param{bool}{ enable = TRUE}}
-
-This function enables or disables all top level windows. It is used by
-\helpref{::wxSafeYield}{wxsafeyield}.
-
-\wxheading{Include files}
-
-<wx/utils.h>
-
-
 \membersection{::wxSetDisplayName}\label{wxsetdisplayname}
 
 \func{void}{wxSetDisplayName}{\param{const wxString\& }{displayName}}
@@ -1667,7 +1685,7 @@ function.
 
 \wxheading{Include files}
 
-<wx/utils.h>
+<wx/app.h> or <wx/utils.h>
 
 \section{Macros}\label{macros}
 
index 5bf567ae88d787ec44eb4b000f61a6857265055a..da2647d432a4de79f98f5ad1a56431ed4b598182 100644 (file)
@@ -1,14 +1,14 @@
 [OPTIONS]
-BMROOT=d:\wx2\wxWind~1\docs/latex/wx ; Assume that bitmaps are where the source is
+BMROOT=. ; Assume that bitmaps are where the source is
 TITLE=wxWindows Manual
 CONTENTS=Contents
 COMPRESS=HIGH
 
 [FILES]
-wx.rtf
+Wx.rtf
 
 [CONFIG]
-CreateButton("Up", "&Up", "JumpId(`wx.hlp', `Contents')")
+CreateButton("Up", "&Up", "JumpId(`Wx.hlp', `Contents')")
 BrowseButtons()
 
 [MAP]
index ea63c8060148fde8c96af4ac312d31ada5d0b5b3..0e00618dbe4761b4dcc6dfe1ef9dc4dc6aa9eb51 100644 (file)
@@ -307,6 +307,15 @@ extern void WXDLLEXPORT wxExit();
 // Yield to other apps/messages
 extern bool WXDLLEXPORT wxYield();
 
+// Post a message to the given eventhandler which will be processed during the
+// next event loop iteration
+inline void WXDLLEXPORT wxPostEvent(wxEvtHandler *dest, wxEvent& event)
+{
+    wxCHECK_RET( dest, wxT("need an object to post event to in wxPostEvent") );
+
+    dest->AddPendingEvent(event);
+}
+
 #endif // wxUSE_GUI
 
 // console applications may avoid using DECLARE_APP and IMPLEMENT_APP macros
index 2831bc3f861497d56169e8f3318ea1f347ae30f4..66b6a3bf43248bc1219fba4705388a29393c9f7d 100644 (file)
@@ -1281,6 +1281,10 @@ protected:
  wxEVT_COMPARE_ITEM
 */
 
+// ============================================================================
+// event handler and related classes
+// ============================================================================
+
 typedef void (wxObject::*wxObjectEventFunction)(wxEvent&);
 
 struct WXDLLEXPORT wxEventTableEntry
@@ -1314,31 +1318,22 @@ public:
     void SetNextHandler(wxEvtHandler *handler) { m_nextHandler = handler; }
     void SetPreviousHandler(wxEvtHandler *handler) { m_previousHandler = handler; }
 
-    void SetEvtHandlerEnabled(bool en) { m_enabled = en; }
+    void SetEvtHandlerEnabled(bool enabled) { m_enabled = enabled; }
     bool GetEvtHandlerEnabled() const { return m_enabled; }
 
-#if WXWIN_COMPATIBILITY_2
-    virtual void OnCommand(wxWindow& WXUNUSED(win),
-                           wxCommandEvent& WXUNUSED(event))
-    {
-        wxFAIL_MSG(wxT("shouldn't be called any more"));
-    }
+    // process an event right now
+    virtual bool ProcessEvent(wxEvent& event);
 
-    // Called if child control has no callback function
-    virtual long Default()
-        { return GetNextHandler() ? GetNextHandler()->Default() : 0; };
-#endif // WXWIN_COMPATIBILITY_2
+    // add an event to be processed later
+    void AddPendingEvent(wxEvent& event);
 
-#if WXWIN_COMPATIBILITY
-    virtual bool OnClose();
-#endif
+    // process all pending events
+    void ProcessPendingEvents();
 
+    // add a 
 #if wxUSE_THREADS
     bool ProcessThreadEvent(wxEvent& event);
-    void ProcessPendingEvents();
 #endif
-    virtual bool ProcessEvent(wxEvent& event);
-    virtual bool SearchEventTable(wxEventTable& table, wxEvent& event);
 
     // Dynamic association of a member function handler with the event handler,
     // id and event type
@@ -1352,14 +1347,34 @@ public:
                   wxObject *userData = (wxObject *) NULL )
         { Connect(id, -1, eventType, func, userData); }
 
+    // implementation from now on
+    virtual bool SearchEventTable(wxEventTable& table, wxEvent& event);
     bool SearchDynamicEventTable( wxEvent& event );
 
 #if wxUSE_THREADS
     void ClearEventLocker() { delete m_eventsLocker; m_eventsLocker = NULL; };
 #endif
 
+    // old stuff
+
+#if WXWIN_COMPATIBILITY_2
+    virtual void OnCommand(wxWindow& WXUNUSED(win),
+                           wxCommandEvent& WXUNUSED(event))
+    {
+        wxFAIL_MSG(wxT("shouldn't be called any more"));
+    }
+
+    // Called if child control has no callback function
+    virtual long Default()
+        { return GetNextHandler() ? GetNextHandler()->Default() : 0; };
+#endif // WXWIN_COMPATIBILITY_2
+
+#if WXWIN_COMPATIBILITY
+    virtual bool OnClose();
+#endif
+
 private:
-    static const wxEventTableEntry         sm_eventTableEntries[];
+    static const wxEventTableEntry sm_eventTableEntries[];
 
 protected:
     static const wxEventTable sm_eventTable;
@@ -1369,7 +1384,6 @@ protected:
 protected:
     wxEvtHandler*       m_nextHandler;
     wxEvtHandler*       m_previousHandler;
-    bool                m_enabled;           // Is event handler enabled?
     wxList*             m_dynamicEvents;
     wxList*             m_pendingEvents;
 #if wxUSE_THREADS
@@ -1379,6 +1393,9 @@ protected:
     // optimization: instead of using costly IsKindOf() to decide whether we're
     // a window (which is true in 99% of cases), use this flag
     bool                m_isWindow;
+
+    // Is event handler enabled?
+    bool                m_enabled;
 };
 
 typedef void (wxEvtHandler::*wxEventFunction)(wxEvent&);
@@ -1614,6 +1631,17 @@ const wxEventTableEntry theClass::sm_eventTableEntries[] = { \
 #define EVT_UPDATE_UI(id, func) \
  { wxEVT_UPDATE_UI, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxUpdateUIEventFunction) & func, (wxObject *) NULL },\
 
+// ----------------------------------------------------------------------------
+// Global data
+// ----------------------------------------------------------------------------
+
+// for pending event processing - notice that there is intentionally no
+// WXDLLEXPORT here
+extern wxList *wxPendingEvents;
+#if wxUSE_THREADS
+    extern wxCriticalSection *wxPendingEventsLocker;
+#endif
+
 // ----------------------------------------------------------------------------
 // Helper functions
 // ----------------------------------------------------------------------------
index 2dba9cef4928a0c45912398bf4bf913eb1d04323..0804af75c817af8ea57a98d49537ac8c8fa355bc 100644 (file)
@@ -49,22 +49,22 @@ public:
 
   wxDropTarget();
   ~wxDropTarget();
-    
+
   /* may be overridden to react to events */
   virtual void OnEnter();
   virtual void OnLeave();
-  
+
   /* may be overridden to reject certain formats or drops
      on certain areas. always returns TRUE by default
      indicating that you'd accept the data from the drag. */
   virtual bool OnMove( long x, long y );
-    
-  /* has to be overridden to accept a drop event. call 
+
+  /* has to be overridden to accept a drop event. call
      IsSupported() to ask which formats are available
-     and then call RequestData() to indicate the format 
+     and then call RequestData() to indicate the format
      you request. */
   virtual bool OnDrop( long x, long y );
-  
+
   /* this gets called once the data has actually arrived. get
      it with GetData(). this has to be overridden. */
   virtual bool OnData( long x, long y );
@@ -75,21 +75,21 @@ public:
 
   /* called to query what formats are available */
   bool IsSupported( wxDataFormat format );
-  
+
   /* fill data with data from the dragging source */
   bool GetData( wxDataObject *data );
 
 // implementation
-  
+
   void RegisterWidget( GtkWidget *widget );
   void UnregisterWidget( GtkWidget *widget );
-    
+
   GdkDragContext     *m_dragContext;
   GtkWidget          *m_dragWidget;
   GtkSelectionData   *m_dragData;
   guint               m_dragTime;
   bool                m_firstMotion;     /* gdk has no "gdk_drag_enter" event */
-    
+
   void SetDragContext( GdkDragContext *dc ) { m_dragContext = dc; }
   void SetDragWidget( GtkWidget *w ) { m_dragWidget = w; }
   void SetDragData( GtkSelectionData *sd ) { m_dragData = sd; }
@@ -109,10 +109,10 @@ public:
   virtual bool OnMove( long x, long y );
   virtual bool OnDrop( long x, long y );
   virtual bool OnData( long x, long y );
-    
+
   /* you have to override OnDropData to get at the text */
   virtual bool OnDropText( long x, long y, const wxChar *text ) = 0;
-    
+
 };
 
 //-------------------------------------------------------------------------
@@ -128,21 +128,21 @@ public:
   wxPrivateDropTarget();
   /* see SetId() below for explanation */
   wxPrivateDropTarget( const wxString &id );
-  
+
   virtual bool OnMove( long x, long y );
   virtual bool OnDrop( long x, long y );
   virtual bool OnData( long x, long y );
-  
+
   /* you have to override OnDropData to get at the data */
   virtual bool OnDropData( long x, long y, void *data, size_t size ) = 0;
-    
+
   /* the string ID identifies the format of clipboard or DnD data. a word
      processor would e.g. add a wxTextDataObject and a wxPrivateDataObject
      to the clipboard - the latter with the Id "application/wxword" or
      "image/png". */
   void SetId( const wxString& id ) { m_id = id; }
   wxString GetId() { return m_id; }
-      
+
 private:
 
     wxString   m_id;
@@ -155,13 +155,13 @@ private:
 class wxFileDropTarget: public wxDropTarget
 {
 public:
-    
+
   wxFileDropTarget() {}
-    
+
   virtual bool OnMove( long x, long y );
   virtual bool OnDrop( long x, long y );
   virtual bool OnData( long x, long y );
-  
+
   /* you have to override OnDropFiles to get at the file names */
   virtual bool OnDropFiles( long x, long y, size_t nFiles, const wxChar * const aszFiles[] ) = 0;
 
@@ -186,43 +186,46 @@ public:
 
   /* constructor. set data later with SetData() */
   wxDropSource( wxWindow *win, const wxIcon &go = wxNullIcon, const wxIcon &stop = wxNullIcon );
-    
+
   /* constructor for setting one data object */
-  wxDropSource( wxDataObject *data, wxWindow *win, const wxIcon &go = wxNullIcon, const wxIcon &stop = wxNullIcon );
-    
+  wxDropSource( wxDataObjectdata, wxWindow *win, const wxIcon &go = wxNullIcon, const wxIcon &stop = wxNullIcon );
+
   /* constructor for setting several data objects via wxDataBroker */
   wxDropSource( wxDataBroker *data, wxWindow *win );
 
   ~wxDropSource();
-    
+
   /* set several dataobjects via wxDataBroker */
   void SetData( wxDataBroker *data );
 
   /* set one dataobject */
+  void SetData( wxDataObject& data );
+
+  // this one isn't portable to wxMSW -- deprecated
   void SetData( wxDataObject *data );
 
   /* start drag action */
   wxDragResult DoDragDrop( bool bAllowMove = FALSE );
-    
+
   /* override to give feedback */
   virtual bool GiveFeedback( wxDragResult WXUNUSED(effect), bool WXUNUSED(bScrolling) ) { return TRUE; }
-  
+
   /* GTK implementation */
-      
+
   void RegisterWindow();
   void UnregisterWindow();
-  
+
     GtkWidget     *m_widget;
     wxWindow      *m_window;
     wxDragResult   m_retValue;
     wxDataBroker  *m_data;
-    
+
     wxCursor      m_defaultCursor;
     wxCursor      m_goaheadCursor;
-    
+
     wxIcon        m_goIcon;
     wxIcon        m_stopIcon;
-    
+
     bool          m_waiting;
 };
 
@@ -230,6 +233,6 @@ public:
 
    // wxUSE_DRAG_AND_DROP
 
-#endif  
+#endif
        //__GTKDNDH__
 
index 2dba9cef4928a0c45912398bf4bf913eb1d04323..0804af75c817af8ea57a98d49537ac8c8fa355bc 100644 (file)
@@ -49,22 +49,22 @@ public:
 
   wxDropTarget();
   ~wxDropTarget();
-    
+
   /* may be overridden to react to events */
   virtual void OnEnter();
   virtual void OnLeave();
-  
+
   /* may be overridden to reject certain formats or drops
      on certain areas. always returns TRUE by default
      indicating that you'd accept the data from the drag. */
   virtual bool OnMove( long x, long y );
-    
-  /* has to be overridden to accept a drop event. call 
+
+  /* has to be overridden to accept a drop event. call
      IsSupported() to ask which formats are available
-     and then call RequestData() to indicate the format 
+     and then call RequestData() to indicate the format
      you request. */
   virtual bool OnDrop( long x, long y );
-  
+
   /* this gets called once the data has actually arrived. get
      it with GetData(). this has to be overridden. */
   virtual bool OnData( long x, long y );
@@ -75,21 +75,21 @@ public:
 
   /* called to query what formats are available */
   bool IsSupported( wxDataFormat format );
-  
+
   /* fill data with data from the dragging source */
   bool GetData( wxDataObject *data );
 
 // implementation
-  
+
   void RegisterWidget( GtkWidget *widget );
   void UnregisterWidget( GtkWidget *widget );
-    
+
   GdkDragContext     *m_dragContext;
   GtkWidget          *m_dragWidget;
   GtkSelectionData   *m_dragData;
   guint               m_dragTime;
   bool                m_firstMotion;     /* gdk has no "gdk_drag_enter" event */
-    
+
   void SetDragContext( GdkDragContext *dc ) { m_dragContext = dc; }
   void SetDragWidget( GtkWidget *w ) { m_dragWidget = w; }
   void SetDragData( GtkSelectionData *sd ) { m_dragData = sd; }
@@ -109,10 +109,10 @@ public:
   virtual bool OnMove( long x, long y );
   virtual bool OnDrop( long x, long y );
   virtual bool OnData( long x, long y );
-    
+
   /* you have to override OnDropData to get at the text */
   virtual bool OnDropText( long x, long y, const wxChar *text ) = 0;
-    
+
 };
 
 //-------------------------------------------------------------------------
@@ -128,21 +128,21 @@ public:
   wxPrivateDropTarget();
   /* see SetId() below for explanation */
   wxPrivateDropTarget( const wxString &id );
-  
+
   virtual bool OnMove( long x, long y );
   virtual bool OnDrop( long x, long y );
   virtual bool OnData( long x, long y );
-  
+
   /* you have to override OnDropData to get at the data */
   virtual bool OnDropData( long x, long y, void *data, size_t size ) = 0;
-    
+
   /* the string ID identifies the format of clipboard or DnD data. a word
      processor would e.g. add a wxTextDataObject and a wxPrivateDataObject
      to the clipboard - the latter with the Id "application/wxword" or
      "image/png". */
   void SetId( const wxString& id ) { m_id = id; }
   wxString GetId() { return m_id; }
-      
+
 private:
 
     wxString   m_id;
@@ -155,13 +155,13 @@ private:
 class wxFileDropTarget: public wxDropTarget
 {
 public:
-    
+
   wxFileDropTarget() {}
-    
+
   virtual bool OnMove( long x, long y );
   virtual bool OnDrop( long x, long y );
   virtual bool OnData( long x, long y );
-  
+
   /* you have to override OnDropFiles to get at the file names */
   virtual bool OnDropFiles( long x, long y, size_t nFiles, const wxChar * const aszFiles[] ) = 0;
 
@@ -186,43 +186,46 @@ public:
 
   /* constructor. set data later with SetData() */
   wxDropSource( wxWindow *win, const wxIcon &go = wxNullIcon, const wxIcon &stop = wxNullIcon );
-    
+
   /* constructor for setting one data object */
-  wxDropSource( wxDataObject *data, wxWindow *win, const wxIcon &go = wxNullIcon, const wxIcon &stop = wxNullIcon );
-    
+  wxDropSource( wxDataObjectdata, wxWindow *win, const wxIcon &go = wxNullIcon, const wxIcon &stop = wxNullIcon );
+
   /* constructor for setting several data objects via wxDataBroker */
   wxDropSource( wxDataBroker *data, wxWindow *win );
 
   ~wxDropSource();
-    
+
   /* set several dataobjects via wxDataBroker */
   void SetData( wxDataBroker *data );
 
   /* set one dataobject */
+  void SetData( wxDataObject& data );
+
+  // this one isn't portable to wxMSW -- deprecated
   void SetData( wxDataObject *data );
 
   /* start drag action */
   wxDragResult DoDragDrop( bool bAllowMove = FALSE );
-    
+
   /* override to give feedback */
   virtual bool GiveFeedback( wxDragResult WXUNUSED(effect), bool WXUNUSED(bScrolling) ) { return TRUE; }
-  
+
   /* GTK implementation */
-      
+
   void RegisterWindow();
   void UnregisterWindow();
-  
+
     GtkWidget     *m_widget;
     wxWindow      *m_window;
     wxDragResult   m_retValue;
     wxDataBroker  *m_data;
-    
+
     wxCursor      m_defaultCursor;
     wxCursor      m_goaheadCursor;
-    
+
     wxIcon        m_goIcon;
     wxIcon        m_stopIcon;
-    
+
     bool          m_waiting;
 };
 
@@ -230,6 +233,6 @@ public:
 
    // wxUSE_DRAG_AND_DROP
 
-#endif  
+#endif
        //__GTKDNDH__
 
index ae15f3f359a05db9473f71c30b05373e1219633e..6eb98de4fafcaeecc72328bdda81d1098e6a93cb 100644 (file)
@@ -83,9 +83,7 @@ public:
     virtual bool ProcessMessage(WXMSG* pMsg);
     void DeletePendingObjects();
     bool ProcessIdle();
-#if wxUSE_THREADS
     void ProcessPendingEvents();
-#endif
     int GetComCtl32Version() const;
 
 public:
index 34cd92557a49505f44ab3c13bdf84fd11d578748..ea49caaa041b1fcd489efe1100ceaa1e0b12eb8d 100644 (file)
@@ -12,7 +12,6 @@
 #ifndef   _WX_OLEDATAOBJ_H
 #define   _WX_OLEDATAOBJ_H
 
-#include "wx/bitmap.h"
 // ----------------------------------------------------------------------------
 // wxDataFormat identifies the single format of data
 // ----------------------------------------------------------------------------
@@ -68,75 +67,85 @@ struct IDataObject;
 // ----------------------------------------------------------------------------
 // wxDataObject is a "smart" and polymorphic piece of data.
 //
-// TODO it's currently "read-only" from COM point of view, i.e. we don't support
-//      SetData. We don't support all advise functions neither (but it's easy to
-//      do if we really want them)
+// TODO it's currently "read-only" from COM point of view, i.e. we don't
+//      support SetData. We don't support all advise functions neither (but
+//      it's easy to do if we really want them)
 // ----------------------------------------------------------------------------
 
 class WXDLLEXPORT wxDataObject
 {
 public:
-  // function to return symbolic name of clipboard format (debug messages)
-  static const char *GetFormatName(wxDataFormat format);
-
-  // ctor & dtor
-  wxDataObject();
-  virtual ~wxDataObject();
-
-  // pure virtuals to override
-    // get the best suited format for our data
-  virtual wxDataFormat GetPreferredFormat() const = 0;
-    // decide if we support this format (should be one of values of
-    // wxDataFormatId enumerations or a user-defined format)
-  virtual bool IsSupportedFormat(wxDataFormat format) const = 0;
-    // get the (total) size of data
-  virtual size_t GetDataSize() const = 0;
-    // copy raw data to provided pointer
-  virtual void GetDataHere(void *pBuf) const = 0;
-
-  // accessors
-    // retrieve IDataObject interface (for other OLE related classes)
-  IDataObject *GetInterface() const { return m_pIDataObject; }
-
-  ////// wxGTK compatibility: hopefully to become the preferred API.
-  virtual wxDataFormat GetFormat() const { return GetPreferredFormat(); }
+    // ctor & dtor
+    wxDataObject();
+    virtual ~wxDataObject();
+
+    // pure virtuals to override
+        // get the best suited format for our data
+    virtual wxDataFormat GetPreferredFormat() const = 0;
+        // get the number of formats we support
+    virtual size_t GetFormatCount() const
+        { return 1; }
+        // return all formats in the provided array (of size GetFormatCount())
+    virtual void GetAllFormats(wxDataFormat *formats) const
+        { formats[0] = GetPreferredFormat(); }
+        // get the (total) size of data for the given format
+    virtual size_t GetDataSize(const wxDataFormat& format) const = 0;
+        // copy raw data (in the specified format) to provided pointer
+    virtual void GetDataHere(const wxDataFormat& format, void *pBuf) const = 0;
+
+    // accessors
+        // retrieve IDataObject interface (for other OLE related classes)
+    IDataObject *GetInterface() const { return m_pIDataObject; }
+        // a simpler name which makes more sense for data objects supporting
+        // only one format
+    wxDataFormat GetFormat() const { return GetPreferredFormat(); }
+
+    // old interface
+        // decide if we support this format (can be either standard or custom
+        // format) -- now uses GetAllFormats()
+    virtual bool IsSupportedFormat(const wxDataFormat& format) const;
+
+#ifdef __WXDEBUG__
+    // function to return symbolic name of clipboard format (for debug messages)
+    static const char *GetFormatName(wxDataFormat format);
+#endif // Debug
 
 private:
-  IDataObject *m_pIDataObject; // pointer to the COM interface
+    IDataObject *m_pIDataObject; // pointer to the COM interface
 };
 
 // ----------------------------------------------------------------------------
 // wxTextDataObject is a specialization of wxDataObject for text data
 // ----------------------------------------------------------------------------
+
 class WXDLLEXPORT wxTextDataObject : public wxDataObject
 {
 public:
-  // ctors
-  wxTextDataObject() { }
-  wxTextDataObject(const wxString& strText) : m_strText(strText) { }
-  void Init(const wxString& strText) { m_strText = strText; }
-
-  // implement base class pure virtuals
-  virtual wxDataFormat GetPreferredFormat() const
-    { return wxDF_TEXT; }
-  virtual bool IsSupportedFormat(wxDataFormat format) const
-    { return format == wxDF_TEXT || format == wxDF_LOCALE; }
-  virtual size_t GetDataSize() const
-    { return m_strText.Len() + 1; } // +1 for trailing '\0'of course
-  virtual void GetDataHere(void *pBuf) const
-    { memcpy(pBuf, m_strText.c_str(), GetDataSize()); }
-
-  ////// wxGTK compatibility: hopefully to become the preferred API.
-  void SetText(const wxString& strText) { m_strText = strText; }
-  wxString GetText() const { return m_strText; }
-  virtual wxDataFormat GetFormat() const { return wxDF_TEXT; }
+    // ctors
+    wxTextDataObject() { }
+    wxTextDataObject(const wxString& strText) : m_strText(strText) { }
+    void Init(const wxString& strText) { m_strText = strText; }
+
+    // implement base class pure virtuals
+    virtual wxDataFormat GetPreferredFormat() const
+        { return wxDF_TEXT; }
+    virtual bool IsSupportedFormat(const wxDataFormat& format) const
+        { return format == wxDF_TEXT || format == wxDF_LOCALE; }
+    virtual size_t GetDataSize(const wxDataFormat& format) const
+        { return m_strText.Len() + 1; } // +1 for trailing '\0'of course
+    virtual void GetDataHere(const wxDataFormat& format, void *pBuf) const
+        { memcpy(pBuf, m_strText.c_str(), GetDataSize(format)); }
+
+    // additional helpers
+    void SetText(const wxString& strText) { m_strText = strText; }
+    wxString GetText() const { return m_strText; }
 
 private:
-  wxString  m_strText;
+    wxString  m_strText;
 };
 
 // ----------------------------------------------------------------------------
-// @@@ TODO: wx{Bitmap|Metafile|...}DataObject
+// TODO: wx{Bitmap|Metafile|...}DataObject
 // ----------------------------------------------------------------------------
 
 // ----------------------------------------------------------------------------
@@ -145,29 +154,29 @@ private:
 
 // TODO: implement OLE side of things. At present, it's just for clipboard
 // use.
+#include "wx/bitmap.h"
+
 class WXDLLEXPORT wxBitmapDataObject : public wxDataObject
 {
 public:
-  // ctors
-  wxBitmapDataObject() {}
-  wxBitmapDataObject(const wxBitmap& bitmap): m_bitmap(bitmap) {}
-  void SetBitmap(const wxBitmap& bitmap) { m_bitmap = bitmap; }
-  wxBitmap GetBitmap() const { return m_bitmap; }
-
-  virtual wxDataFormat GetFormat() const { return wxDF_BITMAP; }
-
-  // implement base class pure virtuals
-  virtual wxDataFormat GetPreferredFormat() const
-    { return wxDF_BITMAP; }
-  virtual bool IsSupportedFormat(wxDataFormat format) const
-    { return format == wxDF_BITMAP; }
-  virtual size_t GetDataSize() const
-    { wxASSERT(FALSE); return 0; } // BEMIMP
-  virtual void GetDataHere(void *pBuf) const
-    { wxASSERT(FALSE); } // BEMIMP
+    // ctors
+    wxBitmapDataObject() { }
+    wxBitmapDataObject(const wxBitmap& bitmap): m_bitmap(bitmap) { }
+
+    // set/get our bitmap
+    void SetBitmap(const wxBitmap& bitmap) { m_bitmap = bitmap; }
+    const wxBitmap GetBitmap() const { return m_bitmap; }
+
+    // implement base class pure virtuals
+    virtual wxDataFormat GetPreferredFormat() const
+        { return wxDF_BITMAP; }
+    virtual bool IsSupportedFormat(const wxDataFormat& format) const
+        { return format == wxDF_BITMAP; }
+    virtual size_t GetDataSize(const wxDataFormat& format) const;
+    virtual void GetDataHere(const wxDataFormat& format, void *pBuf) const;
 
 private:
-  wxBitmap  m_bitmap;
+    wxBitmap m_bitmap;
 };
 
 // ----------------------------------------------------------------------------
index 6835e0a51669f1130db2014d91ccc7a94d5f53f2..dbfe018d66014144b3c1df84a014bb3a75353dfc 100644 (file)
@@ -13,9 +13,9 @@
 #define   _WX_OLEDROPSRC_H
 
 #ifdef __GNUG__
-#pragma interface
+    #pragma interface
 #endif
-#include "wx/window.h"
+
 #if !wxUSE_DRAG_AND_DROP
   #error  "You should #define wxUSE_DRAG_AND_DROP to 1 to compile this file!"
 #endif  //WX_DRAG_DROP
 // ----------------------------------------------------------------------------
 // forward declarations
 // ----------------------------------------------------------------------------
+
 class wxIDropSource;
-class wxDataObject;
+class WXDLLEXPORT wxDataObject;
+class WXDLLEXPORT wxWindow;
+
+// ----------------------------------------------------------------------------
+// constants
+// ----------------------------------------------------------------------------
 
 enum wxDragResult
-  {
+{
     wxDragError,    // error prevented the d&d operation from completing
     wxDragNone,     // drag target didn't accept the data
     wxDragCopy,     // the data was successfully copied
     wxDragMove,     // the data was successfully moved
     wxDragCancel    // the operation was cancelled by user (not an error)
-  };
+};
 
 // ----------------------------------------------------------------------------
 // wxDropSource is used to start the drag-&-drop operation on associated
 // wxDataObject object. It's responsible for giving UI feedback while dragging.
 // ----------------------------------------------------------------------------
+
 class WXDLLEXPORT wxDropSource
 {
 public:
   // ctors: if you use default ctor you must call SetData() later!
   // NB: the "wxWindow *win" parameter is unused and is here only for wxGTK
-  //     compatibility
-  wxDropSource(wxWindow *win = NULL);
-  wxDropSource(wxDataObject& data, wxWindow *win = NULL);
+  //     compatibility, as well as both icon parameters
+  wxDropSource(wxWindow *win = NULL,
+               const wxIcon &go = wxNullIcon,
+               const wxIcon &stop = wxNullIcon );
+  wxDropSource(wxDataObject& data,
+               wxWindow *win = NULL,
+               const wxIcon &go = wxNullIcon,
+               const wxIcon &stop = wxNullIcon );
 
   void SetData(wxDataObject& data);
 
index e78b54aa2b7d52e47ad80fa826426c2d5425880c..5bfcff4ecceca7de5a16512e3e1d552792eae635 100644 (file)
@@ -19,8 +19,8 @@
 #include "wx/wx.h"
 #endif
 
-#ifdef __WXMOTIF__
-    #error Sorry, drag and drop is not yet implemented on wxMotif.
+#if !wxUSE_DRAG_AND_DROP
+    #error This sample requires drag and drop support in the library
 #endif
 
 #include "wx/intl.h"
@@ -31,6 +31,8 @@
 #include "wx/filedlg.h"
 #include "wx/image.h"
 #include "wx/clipbrd.h"
+#include "wx/colordlg.h"
+#include "wx/resource.h"
 
 #if defined(__WXGTK__) || defined(__WXMOTIF__)
     #include "mondrian.xpm"
@@ -74,14 +76,15 @@ private:
 class DnDApp : public wxApp
 {
 public:
-    bool OnInit();
+    virtual bool OnInit();
 };
 
 IMPLEMENT_APP(DnDApp);
 
 // ----------------------------------------------------------------------------
-// Define a new frame type
+// Define a new frame type for the main frame
 // ----------------------------------------------------------------------------
+
 class DnDFrame : public wxFrame
 {
 public:
@@ -92,6 +95,7 @@ public:
     void OnQuit (wxCommandEvent& event);
     void OnAbout(wxCommandEvent& event);
     void OnDrag (wxCommandEvent& event);
+    void OnNewFrame(wxCommandEvent& event);
     void OnHelp (wxCommandEvent& event);
     void OnLogClear(wxCommandEvent& event);
     void OnCopy(wxCommandEvent& event);
@@ -117,6 +121,355 @@ private:
     wxBitmap  m_bitmap;
 };
 
+// ----------------------------------------------------------------------------
+// A shape is an example of application-specific data which may be transported
+// via drag-and-drop or clipboard: in our case, we have different geometric
+// shapes, each one with its own colour and position
+// ----------------------------------------------------------------------------
+
+class DnDShape
+{
+public:
+    enum Kind
+    {
+        None,
+        Triangle,
+        Rectangle,
+        Ellipse
+    };
+
+    DnDShape(const wxPoint& pos,
+             const wxSize& size,
+             const wxColour& col)
+        : m_pos(pos), m_size(size), m_col(col)
+    {
+    }
+
+    // the functions used for drag-and-drop: they dump and restore a shape into
+    // some bitwise-copiable data
+    //
+    // NB: here we profit from the fact that wxPoint, wxSize and wxColour are
+    //     POD (plain old data) and so can be copied directly - but it wouldn't
+    //     work for other types!
+    // ------------------------------------------------------------------------
+
+    // restore from buffer
+    static DnDShape *New(const void *buf);
+
+    virtual size_t GetDataSize() const
+    {
+        return sizeof(ShapeDump);
+    }
+
+    virtual void GetDataHere(void *buf) const
+    {
+        ShapeDump& dump = *(ShapeDump *)buf;
+        dump.x = m_pos.x;
+        dump.y = m_pos.y;
+        dump.w = m_size.x;
+        dump.h = m_size.y;
+        dump.r = m_col.Red();
+        dump.g = m_col.Green();
+        dump.b = m_col.Blue();
+        dump.k = GetKind();
+    }
+
+    // accessors
+    const wxPoint& GetPosition() const { return m_pos; }
+    const wxColour& GetColour() const { return m_col; }
+    const wxSize& GetSize() const { return m_size; }
+
+    // to implement in derived classes
+    virtual Kind GetKind() const = 0;
+
+    virtual void Draw(wxDC& dc) = 0
+    {
+        dc.SetPen(wxPen(m_col, 1, wxSOLID));
+    }
+
+protected:
+    wxPoint GetCentre() const
+        { return wxPoint(m_pos.x + m_size.x / 2, m_pos.y + m_size.y / 2); }
+
+    struct ShapeDump
+    {
+        int x, y,       // position
+            w, h,       // size
+            r, g, b,    // colour
+            k;          // kind
+    };
+
+    wxPoint  m_pos;
+    wxSize   m_size;
+    wxColour m_col;
+};
+
+class DnDTriangularShape : public DnDShape
+{
+public:
+    DnDTriangularShape(const wxPoint& pos,
+                       const wxSize& size,
+                       const wxColour& col)
+        : DnDShape(pos, size, col)
+    {
+    }
+
+    virtual Kind GetKind() const { return Triangle; }
+    virtual void Draw(wxDC& dc)
+    {
+        DnDShape::Draw(dc);
+
+        // well, it's a bit difficult to describe a triangle by position and
+        // size, but we're not doing geometry here, do we? ;-)
+        wxPoint p1(m_pos);
+        wxPoint p2(m_pos.x + m_size.x, m_pos.y);
+        wxPoint p3(m_pos.x, m_pos.y + m_size.y);
+
+        dc.DrawLine(p1, p2);
+        dc.DrawLine(p2, p3);
+        dc.DrawLine(p3, p1);
+
+        dc.FloodFill(GetCentre(), m_col, wxFLOOD_BORDER);
+    }
+};
+
+class DnDRectangularShape : public DnDShape
+{
+public:
+    DnDRectangularShape(const wxPoint& pos,
+                        const wxSize& size,
+                        const wxColour& col)
+        : DnDShape(pos, size, col)
+    {
+    }
+
+    virtual Kind GetKind() const { return Rectangle; }
+    virtual void Draw(wxDC& dc)
+    {
+        DnDShape::Draw(dc);
+
+        wxPoint p1(m_pos);
+        wxPoint p2(p1.x + m_size.x, p1.y);
+        wxPoint p3(p2.x, p2.y + m_size.y);
+        wxPoint p4(p1.x, p3.y);
+
+        dc.DrawLine(p1, p2);
+        dc.DrawLine(p2, p3);
+        dc.DrawLine(p3, p4);
+        dc.DrawLine(p4, p1);
+
+        dc.FloodFill(GetCentre(), m_col, wxFLOOD_BORDER);
+    }
+};
+
+class DnDEllipticShape : public DnDShape
+{
+public:
+    DnDEllipticShape(const wxPoint& pos,
+                     const wxSize& size,
+                     const wxColour& col)
+        : DnDShape(pos, size, col)
+    {
+    }
+
+    virtual Kind GetKind() const { return Ellipse; }
+    virtual void Draw(wxDC& dc)
+    {
+        DnDShape::Draw(dc);
+
+        dc.DrawEllipse(m_pos, m_size);
+
+        dc.FloodFill(GetCentre(), m_col, wxFLOOD_BORDER);
+    }
+};
+
+// ----------------------------------------------------------------------------
+// A wxDataObject specialisation for the application-specific data
+// ----------------------------------------------------------------------------
+
+static const char *shapeFormatId = "wxShape";
+
+class DnDShapeDataObject : public wxDataObject
+{
+public:
+    // ctor doesn't copy the pointer, so it shouldn't go away while this object
+    // is alive
+    DnDShapeDataObject(DnDShape *shape)
+    {
+        m_shape = shape;
+
+        // this string should uniquely identify our format, but is otherwise
+        // arbitrary
+        m_formatShape.SetId(shapeFormatId);
+
+        // we don't draw the shape to a bitmap until it's really needed (i.e.
+        // we're asked to do so)
+        m_hasBitmap = FALSE;
+    }
+
+    // implement base class pure virtuals
+    // ----------------------------------
+
+    virtual wxDataFormat GetPreferredFormat() const
+    {
+        return m_formatShape;
+    }
+
+    virtual size_t GetFormatCount() const
+    {
+        // +1 for our custom format
+        return m_dataobj.GetFormatCount() + 1;
+    }
+
+    virtual void GetAllFormats(wxDataFormat *formats) const
+    {
+        formats[0] = m_formatShape;
+        m_dataobj.GetAllFormats(&formats[1]);
+    }
+
+    virtual size_t GetDataSize(const wxDataFormat& format) const
+    {
+        if ( format == m_formatShape )
+        {
+            return m_shape->GetDataSize();
+        }
+        else
+        {
+            wxASSERT_MSG( format == wxDF_BITMAP, "unsupported format" );
+
+            if ( !m_hasBitmap )
+                CreateBitmap();
+
+            return m_dataobj.GetDataSize(format);
+        }
+    }
+
+    virtual void GetDataHere(const wxDataFormat& format, void *pBuf) const
+    {
+        if ( format == m_formatShape )
+        {
+            m_shape->GetDataHere(pBuf);
+        }
+        else
+        {
+            wxASSERT_MSG( format == wxDF_BITMAP, "unsupported format" );
+
+            if ( !m_hasBitmap )
+                CreateBitmap();
+
+            m_dataobj.GetDataHere(format, pBuf);
+        }
+    }
+
+private:
+    // creates a bitmap and assigns it to m_dataobj (also sets m_hasBitmap)
+    void CreateBitmap() const;
+
+    wxDataFormat        m_formatShape;  // our custom format
+
+    wxBitmapDataObject  m_dataobj;      // it handles bitmaps
+    bool                m_hasBitmap;    // true if m_dataobj has valid bitmap
+
+    DnDShape           *m_shape;        // our data
+};
+
+// ----------------------------------------------------------------------------
+// A dialog to edit shape properties
+// ----------------------------------------------------------------------------
+
+class DnDShapeDialog : public wxDialog
+{
+public:
+    DnDShapeDialog(wxFrame *parent, DnDShape *shape);
+
+    DnDShape *GetShape() const;
+
+    virtual bool TransferDataToWindow();
+    virtual bool TransferDataFromWindow();
+
+    void OnColour(wxCommandEvent& event);
+
+private:
+    // input
+    DnDShape *m_shape;
+
+    // output
+    DnDShape::Kind m_shapeKind;
+    wxPoint  m_pos;
+    wxSize   m_size;
+    wxColour m_col;
+
+    // controls
+    wxRadioBox *m_radio;
+    wxTextCtrl *m_textX,
+               *m_textY,
+               *m_textW,
+               *m_textH;
+
+    DECLARE_EVENT_TABLE()
+};
+
+// ----------------------------------------------------------------------------
+// A frame for the shapes which can be drag-and-dropped between frames
+// ----------------------------------------------------------------------------
+
+class DnDShapeFrame : public wxFrame
+{
+public:
+    DnDShapeFrame(wxFrame *parent);
+    ~DnDShapeFrame();
+
+    void SetShape(DnDShape *shape);
+
+    // callbacks
+    void OnDrag(wxMouseEvent& event);
+    void OnEdit(wxMouseEvent& event);
+    void OnPaint(wxPaintEvent& event);
+    void OnDrop(long x, long y, DnDShape *shape);
+
+private:
+    DnDShape *m_shape;
+
+    DECLARE_EVENT_TABLE()
+};
+
+// ----------------------------------------------------------------------------
+// wxDropTarget derivation for DnDShapes
+// ----------------------------------------------------------------------------
+
+class DnDShapeDropTarget : public wxDropTarget
+{
+public:
+    DnDShapeDropTarget(DnDShapeFrame *frame)
+    {
+        m_frame = frame;
+
+        // the same as used by DnDShapeDataObject
+        m_formatShape.SetId(shapeFormatId);
+    }
+
+    // override base class (pure) virtuals
+    virtual void OnEnter()
+        { m_frame->SetStatusText("Mouse entered the frame"); }
+    virtual void OnLeave()
+        { m_frame->SetStatusText("Mouse left the frame"); }
+    virtual bool OnDrop(long x, long y, const void *pData)
+    {
+        m_frame->OnDrop(x, y, DnDShape::New(pData));
+
+        return TRUE;
+    }
+
+protected:
+    virtual size_t GetFormatCount() const { return 1; }
+    virtual wxDataFormat GetFormat(size_t WXUNUSED(n)) const
+        { return m_formatShape; }
+
+private:
+    DnDShapeFrame *m_frame;
+    wxDataFormat m_formatShape;
+};
+
 // ----------------------------------------------------------------------------
 // IDs for the menu commands
 // ----------------------------------------------------------------------------
@@ -125,6 +478,7 @@ enum
 {
     Menu_Quit = 1,
     Menu_Drag,
+    Menu_NewFrame,
     Menu_About = 101,
     Menu_Help,
     Menu_Clear,
@@ -135,13 +489,15 @@ enum
     Menu_HasText,
     Menu_HasBitmap,
     Menu_ToBeGreyed,   /* for testing */
-    Menu_ToBeDeleted   /* for testing */
+    Menu_ToBeDeleted,  /* for testing */
+    Button_Colour = 1001
 };
 
 BEGIN_EVENT_TABLE(DnDFrame, wxFrame)
     EVT_MENU(Menu_Quit,       DnDFrame::OnQuit)
     EVT_MENU(Menu_About,      DnDFrame::OnAbout)
     EVT_MENU(Menu_Drag,       DnDFrame::OnDrag)
+    EVT_MENU(Menu_NewFrame,   DnDFrame::OnNewFrame)
     EVT_MENU(Menu_Help,       DnDFrame::OnHelp)
     EVT_MENU(Menu_Clear,      DnDFrame::OnLogClear)
     EVT_MENU(Menu_Copy,       DnDFrame::OnCopy)
@@ -156,7 +512,21 @@ BEGIN_EVENT_TABLE(DnDFrame, wxFrame)
     EVT_PAINT(                DnDFrame::OnPaint)
 END_EVENT_TABLE()
 
-    // `Main program' equivalent, creating windows and returning main app frame
+BEGIN_EVENT_TABLE(DnDShapeFrame, wxFrame)
+    EVT_RIGHT_DOWN(DnDShapeFrame::OnDrag)
+    EVT_LEFT_DCLICK(DnDShapeFrame::OnEdit)
+    EVT_PAINT(DnDShapeFrame::OnPaint)
+END_EVENT_TABLE()
+
+BEGIN_EVENT_TABLE(DnDShapeDialog, wxDialog)
+    EVT_BUTTON(Button_Colour, OnColour)
+END_EVENT_TABLE()
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// `Main program' equivalent, creating windows and returning main app frame
 bool DnDApp::OnInit()
 {
 #if wxUSE_LIBPNG
@@ -173,6 +543,8 @@ bool DnDApp::OnInit()
 
     SetTopWindow(frame);
 
+    wxDefaultResourceTable->ParseResourceFile("dnd.wxr");
+
     return TRUE;
 }
 
@@ -186,19 +558,13 @@ DnDFrame::DnDFrame(wxFrame *frame, char *title, int x, int y, int w, int h)
 
     CreateStatusBar();
 
-    // construct sub menu for testing
-    wxMenu *sub_menu = new wxMenu;
-    sub_menu->Append(Menu_Quit, "E&xit");
-    sub_menu->Append(Menu_Quit, "E&xit");
-    sub_menu->Append(Menu_Quit, "E&xit");
-
     // construct menu
     wxMenu *file_menu = new wxMenu;
     file_menu->Append(Menu_Drag, "&Test drag...");
     file_menu->AppendSeparator();
-    file_menu->Append(Menu_Quit, "E&xit");
+    file_menu->Append(Menu_NewFrame, "&New frame\tCtrl-N");
     file_menu->AppendSeparator();
-    file_menu->Append( 0, "More exit menus", sub_menu);
+    file_menu->Append(Menu_Quit, "E&xit");
 
     wxMenu *log_menu = new wxMenu;
     log_menu->Append(Menu_Clear, "Clear");
@@ -217,7 +583,7 @@ DnDFrame::DnDFrame(wxFrame *frame, char *title, int x, int y, int w, int h)
     clip_menu->AppendSeparator();
     clip_menu->Append(Menu_HasText, "Clipboard has &text\tCtrl+T");
     clip_menu->Append(Menu_HasBitmap, "Clipboard has a &bitmap\tCtrl+B");
-    
+
     wxMenuBar *menu_bar = new wxMenuBar;
     menu_bar->Append(file_menu, "&File");
     menu_bar->Append(log_menu,  "&Log");
@@ -238,7 +604,10 @@ DnDFrame::DnDFrame(wxFrame *frame, char *title, int x, int y, int w, int h)
     m_ctrlLog   = new wxTextCtrl(this, -1, "", pos, size,
                                wxTE_MULTILINE | wxTE_READONLY |
                                wxSUNKEN_BORDER );
-    // redirect log messages to the text window (don't forget to delete it!)
+
+    // redirect log messages to the text window and switch on OLE messages
+    // logging
+    wxLog::AddTraceMask(wxTRACE_OleCalls);
     m_pLog = new wxLogTextCtrl(m_ctrlLog);
     m_pLogPrev = wxLog::SetActiveTarget(m_pLog);
 
@@ -289,7 +658,7 @@ void DnDFrame::OnPaint(wxPaintEvent& WXUNUSED(event))
     wxPaintDC dc(this);
     dc.SetFont( wxFont( 24, wxDECORATIVE, wxNORMAL, wxNORMAL, FALSE, "charter" ) );
     dc.DrawText( "Drag text from here!", 20, h-50 );
-    
+
     if (m_bitmap.Ok())
         dc.DrawBitmap( m_bitmap, 280, h-120, TRUE );
 }
@@ -336,6 +705,13 @@ void DnDFrame::OnClipboardHasBitmap(wxCommandEvent& WXUNUSED(event))
     wxTheClipboard->Close();
 }
 
+void DnDFrame::OnNewFrame(wxCommandEvent& WXUNUSED(event))
+{
+    (new DnDShapeFrame(this))->Show(TRUE);
+
+    wxLogStatus(this, "Double click the new frame to select a shape for it");
+}
+
 void DnDFrame::OnDrag(wxCommandEvent& WXUNUSED(event))
 {
     wxString strText = wxGetTextFromUser
@@ -395,18 +771,15 @@ void DnDFrame::OnLogClear(wxCommandEvent& /* event */ )
 
 void DnDFrame::OnLeftDown(wxMouseEvent &WXUNUSED(event) )
 {
-    if ( !m_strText.IsEmpty() ) 
+    if ( !m_strText.IsEmpty() )
     {
         // start drag operation
-#ifdef __WXMSW__
         wxTextDataObject textData(m_strText);
-        wxDropSource dragSource( textData, this );
-#else
-        wxDropSource dragSource( new wxTextDataObject (m_strText), this, wxIcon(mondrian_xpm) );
-#endif
+        wxDropSource source(textData, this, wxICON(mondrian));
+
         const char *pc;
 
-        switch ( dragSource.DoDragDrop(TRUE) ) 
+        switch ( source.DoDragDrop(TRUE) )
         {
             case wxDragError:   pc = "Error!";    break;
             case wxDragNone:    pc = "Nothing";   break;
@@ -429,7 +802,7 @@ void DnDFrame::OnRightDown(wxMouseEvent &event )
     menu->Append(Menu_Quit, "E&xit");
     menu->Append(Menu_ToBeDeleted, "To be deleted");
     menu->Append(Menu_ToBeGreyed, "To be greyed");
-    
+
     menu->Delete( Menu_ToBeDeleted );
     menu->Enable( Menu_ToBeGreyed, FALSE );
 
@@ -458,25 +831,25 @@ void DnDFrame::OnCopyBitmap(wxCommandEvent& WXUNUSED(event))
 #endif
 
     if (dialog.ShowModal() != wxID_OK)
-    { 
+    {
         wxLogMessage( _T("Aborted file open") );
         return;
     }
-    
+
     if (dialog.GetPath().IsEmpty())
-    { 
+    {
         wxLogMessage( _T("Returned empty string.") );
         return;
     }
-    
+
     if (!wxFileExists(dialog.GetPath()))
     {
         wxLogMessage( _T("File doesn't exist.") );
         return;
     }
-    
+
     wxImage image;
-    image.LoadFile( dialog.GetPath(), 
+    image.LoadFile( dialog.GetPath(),
 #ifdef __WXMSW__
                     wxBITMAP_TYPE_BMP
 #else
@@ -485,13 +858,13 @@ void DnDFrame::OnCopyBitmap(wxCommandEvent& WXUNUSED(event))
                   );
     if (!image.Ok())
     {
-        wxLogMessage( _T("Invalid image file...") );
+        wxLogError( _T("Invalid image file...") );
         return;
     }
-    
-    wxLogMessage( _T("Decoding image file...") );
+
+    wxLogStatus( _T("Decoding image file...") );
     wxYield();
-    
+
     wxBitmap bitmap( image.ConvertToBitmap() );
 
     if ( !wxTheClipboard->Open() )
@@ -503,7 +876,7 @@ void DnDFrame::OnCopyBitmap(wxCommandEvent& WXUNUSED(event))
 
     wxLogMessage( _T("Creating wxBitmapDataObject...") );
     wxYield();
-    
+
     if ( !wxTheClipboard->AddData(new wxBitmapDataObject(bitmap)) )
     {
         wxLogError(_T("Can't copy image to the clipboard."));
@@ -542,8 +915,8 @@ void DnDFrame::OnPasteBitmap(wxCommandEvent& WXUNUSED(event))
     else
     {
         wxLogMessage(_T("Bitmap pasted from the clipboard") );
-       m_bitmap = data.GetBitmap();
-       Refresh();
+        m_bitmap = data.GetBitmap();
+        Refresh();
     }
 
     wxTheClipboard->Close();
@@ -628,3 +1001,251 @@ bool DnDFile::OnDropFiles( wxDropPointCoord, wxDropPointCoord, size_t nFiles,
 
     return TRUE;
 }
+
+// ----------------------------------------------------------------------------
+// DnDShapeDialog
+// ----------------------------------------------------------------------------
+
+DnDShapeDialog::DnDShapeDialog(wxFrame *parent, DnDShape *shape)
+{
+    m_shape = shape;
+
+    LoadFromResource(parent, "dialogShape");
+
+    m_textX = (wxTextCtrl *)wxFindWindowByName("textX", this);
+    m_textY = (wxTextCtrl *)wxFindWindowByName("textY", this);
+    m_textW = (wxTextCtrl *)wxFindWindowByName("textW", this);
+    m_textH = (wxTextCtrl *)wxFindWindowByName("textH", this);
+
+    m_radio = (wxRadioBox *)wxFindWindowByName("radio", this);
+}
+
+DnDShape *DnDShapeDialog::GetShape() const
+{
+    switch ( m_shapeKind )
+    {
+        default:
+        case DnDShape::None:      return NULL;
+        case DnDShape::Triangle:  return new DnDTriangularShape(m_pos, m_size, m_col);
+        case DnDShape::Rectangle: return new DnDRectangularShape(m_pos, m_size, m_col);
+        case DnDShape::Ellipse:   return new DnDEllipticShape(m_pos, m_size, m_col);
+    }
+}
+
+bool DnDShapeDialog::TransferDataToWindow()
+{
+    if ( m_shape )
+    {
+        m_radio->SetSelection(m_shape->GetKind());
+        m_pos = m_shape->GetPosition();
+        m_size = m_shape->GetSize();
+        m_col = m_shape->GetColour();
+    }
+    else
+    {
+        m_radio->SetSelection(DnDShape::None);
+        m_pos = wxPoint(1, 1);
+        m_size = wxSize(100, 100);
+    }
+
+    m_textX->SetValue(wxString() << m_pos.x);
+    m_textY->SetValue(wxString() << m_pos.y);
+    m_textW->SetValue(wxString() << m_size.x);
+    m_textH->SetValue(wxString() << m_size.y);
+
+    return TRUE;
+}
+
+bool DnDShapeDialog::TransferDataFromWindow()
+{
+    m_shapeKind = (DnDShape::Kind)m_radio->GetSelection();
+
+    m_pos.x = atoi(m_textX->GetValue());
+    m_pos.y = atoi(m_textY->GetValue());
+    m_size.x = atoi(m_textW->GetValue());
+    m_size.y = atoi(m_textH->GetValue());
+
+    if ( !m_pos.x || !m_pos.y || !m_size.x || !m_size.y )
+    {
+        wxMessageBox("All sizes and positions should be non null!",
+                     "Invalid shape", wxICON_HAND | wxOK, this);
+
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+void DnDShapeDialog::OnColour(wxCommandEvent& WXUNUSED(event))
+{
+    wxColourData data;
+    data.SetChooseFull(TRUE);
+    for (int i = 0; i < 16; i++)
+    {
+        wxColour colour(i*16, i*16, i*16);
+        data.SetCustomColour(i, colour);
+    }
+
+    wxColourDialog dialog(this, &data);
+    if ( dialog.ShowModal() == wxID_OK )
+    {
+        m_col = dialog.GetColourData().GetColour();
+    }
+}
+
+// ----------------------------------------------------------------------------
+// DnDShapeFrame
+// ----------------------------------------------------------------------------
+
+DnDShapeFrame::DnDShapeFrame(wxFrame *parent)
+             : wxFrame(parent, -1, "Shape Frame",
+                       wxDefaultPosition, wxSize(250, 150))
+{
+    SetBackgroundColour(*wxWHITE);
+
+    CreateStatusBar();
+
+    SetStatusText("Double click the frame to create a shape");
+
+    SetDropTarget(new DnDShapeDropTarget(this));
+
+    m_shape = NULL;
+}
+
+DnDShapeFrame::~DnDShapeFrame()
+{
+    delete m_shape;
+}
+
+void DnDShapeFrame::SetShape(DnDShape *shape)
+{
+    delete m_shape;
+    m_shape = shape;
+    Refresh();
+}
+
+// callbacks
+void DnDShapeFrame::OnDrag(wxMouseEvent& event)
+{
+    if ( !m_shape )
+    {
+        event.Skip();
+
+        return;
+    }
+
+    // start drag operation
+    DnDShapeDataObject shapeData(m_shape);
+    wxDropSource source(shapeData, this, wxICON(mondrian));
+
+    const char *pc = NULL;
+    switch ( source.DoDragDrop(TRUE) )
+    {
+        default:
+        case wxDragError:
+            wxLogError("An error occured during drag and drop operation");
+            break;
+
+        case wxDragNone:
+            SetStatusText("Nothing happened");
+            break;
+
+        case wxDragCopy:
+            pc = "copied";
+            break;
+
+        case wxDragMove:
+            pc = "moved";
+            SetShape(NULL);
+            break;
+
+        case wxDragCancel:
+            SetStatusText("Drag and drop operation cancelled");
+            break;
+    }
+
+    if ( pc )
+    {
+        SetStatusText(wxString("Shape successfully ") + pc);
+    }
+    //else: status text already set
+}
+
+void DnDShapeFrame::OnEdit(wxMouseEvent& event)
+{
+    DnDShapeDialog dlg(this, m_shape);
+    if ( dlg.ShowModal() == wxID_OK )
+    {
+        SetShape(dlg.GetShape());
+
+        if ( m_shape )
+        {
+            SetStatusText("Right click now drag the shape to another frame");
+        }
+    }
+}
+
+void DnDShapeFrame::OnPaint(wxPaintEvent& event)
+{
+    if ( m_shape )
+        m_shape->Draw(wxPaintDC(this));
+    else
+        event.Skip();
+}
+
+void DnDShapeFrame::OnDrop(long x, long y, DnDShape *shape)
+{
+    wxString s;
+    s.Printf("Drop occured at (%ld, %ld)", x, y);
+    SetStatusText(s);
+
+    SetShape(shape);
+}
+
+// ----------------------------------------------------------------------------
+// DnDShape
+// ----------------------------------------------------------------------------
+
+DnDShape *DnDShape::New(const void *buf)
+{
+    const ShapeDump& dump = *(const ShapeDump *)buf;
+    switch ( dump.k )
+    {
+        case Triangle:
+            return new DnDTriangularShape(wxPoint(dump.x, dump.y),
+                                          wxSize(dump.w, dump.h),
+                                          wxColour(dump.r, dump.g, dump.b));
+
+        case Rectangle:
+            return new DnDRectangularShape(wxPoint(dump.x, dump.y),
+                                           wxSize(dump.w, dump.h),
+                                           wxColour(dump.r, dump.g, dump.b));
+
+        case Ellipse:
+            return new DnDEllipticShape(wxPoint(dump.x, dump.y),
+                                        wxSize(dump.w, dump.h),
+                                        wxColour(dump.r, dump.g, dump.b));
+
+        default:
+            wxFAIL_MSG("invalid shape!");
+            return NULL;
+    }
+}
+
+// ----------------------------------------------------------------------------
+// DnDShapeDataObject
+// ----------------------------------------------------------------------------
+
+void DnDShapeDataObject::CreateBitmap() const
+{
+    wxBitmap bitmap;
+    wxMemoryDC dc;
+    dc.SelectObject(bitmap);
+    m_shape->Draw(dc);
+    dc.SelectObject(wxNullBitmap);
+
+    DnDShapeDataObject *self = (DnDShapeDataObject *)this; // const_cast
+    self->m_dataobj.SetBitmap(bitmap);
+    self->m_hasBitmap = TRUE;
+}
+
diff --git a/samples/dnd/test.dsp b/samples/dnd/test.dsp
deleted file mode 100644 (file)
index cb7e287..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-# Microsoft Developer Studio Project File - Name="test" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 5.00
-# ** NICHT BEARBEITEN **
-
-# TARGTYPE "Win32 (x86) Application" 0x0101
-
-CFG=test - Win32 Release
-!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit\
- NMAKE
-!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den\
- Befehl
-!MESSAGE 
-!MESSAGE NMAKE /f "test.mak".
-!MESSAGE 
-!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben
-!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel:
-!MESSAGE 
-!MESSAGE NMAKE /f "test.mak" CFG="test - Win32 Release"
-!MESSAGE 
-!MESSAGE Für die Konfiguration stehen zur Auswahl:
-!MESSAGE 
-!MESSAGE "test - Win32 Release" (basierend auf  "Win32 (x86) Application")
-!MESSAGE "test - Win32 Debug" (basierend auf  "Win32 (x86) Application")
-!MESSAGE 
-
-# Begin Project
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-MTL=midl.exe
-RSC=rc.exe
-
-!IF  "$(CFG)" == "test - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir ".\Release"
-# PROP BASE Intermediate_Dir ".\Release"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir ".\Release"
-# PROP Intermediate_Dir ".\Release"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
-# ADD CPP /nologo /w /W0 /GX /O2 /I "..\..\include" /D "__WXDEBUG__" /D "__WIN32__" /D "__WXMSW__" /D "__WIN95__" /D "STRICT" /D "__WINDOWS__" /YX /FD /D /c
-# ADD BASE MTL /nologo /D "NDEBUG" /win32
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x407 /d "NDEBUG"
-# ADD RSC /l 0x407 /i "..\..\include" /d "WXDEBUG" /d "__WXMSW__"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib winspool.lib winmm.lib shell32.lib oldnames.lib comctl32.lib ctl3d32.lib odbc32.lib ole32.lib oleaut32.lib uuid.lib rpcrt4.lib advapi32.lib ..\..\debug\wxwin.lib ctl3d32.lib /nologo /subsystem:windows /incremental:yes /pdb:".\Debug/santis.pdb" /debug /machine:I386 /out:".\Debug/santis.exe"
-# SUBTRACT LINK32 /pdb:none
-
-!ELSEIF  "$(CFG)" == "test - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir ".\Debug"
-# PROP BASE Intermediate_Dir ".\Debug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir ".\Debug"
-# PROP Intermediate_Dir ".\Debug"
-# PROP Ignore_Export_Lib 0
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
-# ADD CPP /nologo /w /W0 /GX /Z7 /Od /I "..\..\include" /D "__WXDEBUG__" /D "__WIN32__" /D "__WXMSW__" /D "__WIN95__" /D "STRICT" /D "__WINDOWS__" /YX /FD /D /c
-# ADD BASE MTL /nologo /D "_DEBUG" /win32
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-# ADD BASE RSC /l 0x407 /d "_DEBUG"
-# ADD RSC /l 0x407 /i "..\..\include" /d "WXDEBUG" /d "__WXMSW__"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LINK32=link.exe
-# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib winspool.lib winmm.lib shell32.lib oldnames.lib comctl32.lib ctl3d32.lib odbc32.lib ole32.lib oleaut32.lib uuid.lib rpcrt4.lib advapi32.lib ..\..\debug\wxwin.lib ctl3d32.lib /nologo /subsystem:windows /debug /machine:I386
-# SUBTRACT LINK32 /pdb:none
-
-!ENDIF 
-
-# Begin Target
-
-# Name "test - Win32 Release"
-# Name "test - Win32 Debug"
-# Begin Group "Quellcodedateien"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
-# Begin Source File
-
-SOURCE=.\dnd.cpp
-# End Source File
-# End Group
-# Begin Group "Header-Dateien"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
-# End Group
-# Begin Group "Ressourcendateien"
-
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe"
-# Begin Source File
-
-SOURCE=.\dnd.rc
-
-!IF  "$(CFG)" == "test - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "test - Win32 Debug"
-
-!ENDIF 
-
-# End Source File
-# End Group
-# End Target
-# End Project
diff --git a/samples/dnd/test.dsw b/samples/dnd/test.dsw
deleted file mode 100644 (file)
index 449f529..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-Microsoft Developer Studio Workspace File, Format Version 5.00
-# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELÖSCHT WERDEN!
-
-###############################################################################
-
-Project: "test"=.\test.dsp - Package Owner=<4>
-
-Package=<5>
-{{{
-}}}
-
-Package=<4>
-{{{
-}}}
-
-###############################################################################
-
-Global:
-
-Package=<5>
-{{{
-}}}
-
-Package=<3>
-{{{
-}}}
-
-###############################################################################
-
index c20371c475a258e9e9a104d5271c8d855d526870..5ab57ddde6caad03fc66e38b8eb099e0addcbced 100644 (file)
@@ -9,6 +9,14 @@
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
 #ifdef __GNUG__
     #pragma implementation "event.h"
 #endif
     #include "wx/validate.h"
 #endif // wxUSE_GUI
 
+// ----------------------------------------------------------------------------
+// wxWin macros
+// ----------------------------------------------------------------------------
+
 #if !USE_SHARED_LIBRARY
     IMPLEMENT_DYNAMIC_CLASS(wxEvtHandler, wxObject)
     IMPLEMENT_ABSTRACT_CLASS(wxEvent, wxObject)
 
 #endif // !USE_SHARED_LIBRARY
 
+// ----------------------------------------------------------------------------
+// global variables
+// ----------------------------------------------------------------------------
+
+// To put pending event handlers
+wxList *wxPendingEvents = (wxList *)NULL;
+
 #if wxUSE_THREADS
-/* To put pending event handlers */
-extern wxList *wxPendingEvents;
-extern wxCriticalSection *wxPendingEventsLocker;
+    // protects wxPendingEvents list
+    wxCriticalSection *wxPendingEventsLocker = (wxCriticalSection *)NULL;
 #endif
 
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// wxEvent
+// ----------------------------------------------------------------------------
+
 /*
  * General wxWindows events, covering
  * all interesting things that might happen (button clicking, resizing,
@@ -514,10 +540,10 @@ wxEvtHandler::wxEvtHandler()
     m_enabled = TRUE;
     m_dynamicEvents = (wxList *) NULL;
     m_isWindow = FALSE;
+    m_pendingEvents = (wxList *) NULL;
 #if wxUSE_THREADS
-    m_eventsLocker = new wxCriticalSection();
+    m_eventsLocker = new wxCriticalSection;
 #endif
-    m_pendingEvents = (wxList *) NULL;
 }
 
 wxEvtHandler::~wxEvtHandler()
@@ -542,63 +568,76 @@ wxEvtHandler::~wxEvtHandler()
         delete m_dynamicEvents;
     };
 
-#if wxUSE_THREADS
-    if (m_pendingEvents)
-      delete m_pendingEvents;
+    delete m_pendingEvents;
 
+#if wxUSE_THREADS
     delete m_eventsLocker;
 #endif
 }
 
 #if wxUSE_THREADS
 
-#ifdef __WXGTK__
-extern bool g_isIdle;
-extern void wxapp_install_idle_handler();
-#endif
-
 bool wxEvtHandler::ProcessThreadEvent(wxEvent& event)
 {
-    wxEvent *event_main;
     wxCriticalSectionLocker locker(*m_eventsLocker);
 
     // check that we are really in a child thread
-    wxASSERT( !wxThread::IsMain() );
+    wxASSERT_MSG( !wxThread::IsMain(),
+                  wxT("use ProcessEvent() in main thread") );
+
+    AddPendingEvent(event);
 
-    if (m_pendingEvents == NULL)
-      m_pendingEvents = new wxList();
+    return TRUE;
+}
+
+#endif // wxUSE_THREADS
+
+void wxEvtHandler::AddPendingEvent(wxEvent& event)
+{
+    if ( !m_pendingEvents )
+      m_pendingEvents = new wxList;
 
-    event_main = (wxEvent *)event.Clone();
+    wxEvent *event2 = (wxEvent *)event.Clone();
 
-    m_pendingEvents->Append(event_main);
+    m_pendingEvents->Append(event2);
 
     wxPendingEventsLocker->Enter();
+    if ( !wxPendingEvents )
+        wxPendingEvents = new wxList;
     wxPendingEvents->Append(this);
     wxPendingEventsLocker->Leave();
 
     // TODO: Wake up idle handler for the other platforms.
 #ifdef __WXGTK__
-    if (g_isIdle)
+    extern bool g_isIdle;
+    extern void wxapp_install_idle_handler();
+    if ( g_isIdle )
         wxapp_install_idle_handler();
-#endif
-
-    return TRUE;
+#else // this works for wxMSW, but may be for others too?
+    // might also send a dummy message to the top level window, this would
+    // probably be cleaner?
+    wxIdleEvent eventIdle;
+    wxTheApp->OnIdle(eventIdle);
+#endif // platform
 }
 
 void wxEvtHandler::ProcessPendingEvents()
 {
+#if wxUSE_THREADS
     wxCriticalSectionLocker locker(*m_eventsLocker);
+#endif
+
     wxNode *node = m_pendingEvents->First();
     wxEvent *event;
 
-    while (node != NULL) {
-      event = (wxEvent *)node->Data();
-      ProcessEvent(*event);
-      delete node;
-      node = m_pendingEvents->First();
+    while ( node )
+    {
+        event = (wxEvent *)node->Data();
+        ProcessEvent(*event);
+        delete node;
+        node = m_pendingEvents->First();
     }
 }
-#endif
 
 /*
  * Event table stuff
@@ -607,25 +646,24 @@ void wxEvtHandler::ProcessPendingEvents()
 bool wxEvtHandler::ProcessEvent(wxEvent& event)
 {
 #if wxUSE_GUI
-    /* check that our flag corresponds to reality */
+    // check that our flag corresponds to reality
     wxASSERT( m_isWindow == IsKindOf(CLASSINFO(wxWindow)) );
 #endif // wxUSE_GUI
 
-    /* An event handler can be enabled or disabled */
+    // An event handler can be enabled or disabled
     if ( GetEvtHandlerEnabled() )
     {
 #if wxUSE_THREADS
-        /* Check whether we are in a child thread. */
-        if (!wxThread::IsMain())
+        // Check whether we are in a child thread.
+        if ( !wxThread::IsMain() )
           return ProcessThreadEvent(event);
-#endif
-        /* Handle per-instance dynamic event tables first */
+#endif // wxUSE_THREADS
 
+        // Handle per-instance dynamic event tables first
         if ( m_dynamicEvents && SearchDynamicEventTable(event) )
             return TRUE;
 
-        /* Then static per-class event tables */
-
+        // Then static per-class event tables
         const wxEventTable *table = GetEventTable();
 
 #if wxUSE_GUI && wxUSE_VALIDATORS
index f1eb101c25569b3de7255da2bbd30bdb42d8b16e..fd60e2a12696fa06af6977c75a80ea8e38e14745 100644 (file)
 wxApp *wxTheApp = (wxApp *)  NULL;
 wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL;
 
-#if wxUSE_THREADS
-extern wxList *wxPendingEvents;
-extern wxCriticalSection *wxPendingEventsLocker;
-#endif
 extern wxResourceCache *wxTheResourceCache;
 extern bool g_isIdle;
 
@@ -127,7 +123,7 @@ unsigned char g_palette[64*3] =
 // local functions
 //-----------------------------------------------------------------------------
 
-extern void wxFlushResources(void);
+extern void wxFlushResources();
 
 //-----------------------------------------------------------------------------
 // global functions
@@ -265,6 +261,7 @@ static gint wxapp_wakeup_timerout_callback( gpointer WXUNUSED(data) )
 
     return TRUE;
 }
+
 #endif // wxUSE_THREADS
 
 //-----------------------------------------------------------------------------
@@ -427,11 +424,9 @@ void wxApp::OnIdle( wxIdleEvent &event )
 
     s_inOnIdle = TRUE;
 
-#if wxUSE_THREADS
     /* Resend in the main thread events which have been prepared in other
        threads */
     ProcessPendingEvents();
-#endif
 
     /* 'Garbage' collection of windows deleted with Close(). */
     DeletePendingObjects();
@@ -520,12 +515,16 @@ void wxApp::Dispatch()
     gtk_main_iteration();
 }
 
-#if wxUSE_THREADS
 void wxApp::ProcessPendingEvents()
 {
-    wxNode *node = wxPendingEvents->First();
+#if wxUSE_THREADS
     wxCriticalSectionLocker locker(*wxPendingEventsLocker);
+#endif // wxUSE_THREADS
+
+    if ( !wxPendingEvents )
+        return;
 
+    wxNode *node = wxPendingEvents->First();
     while (node)
     {
         wxEvtHandler *handler = (wxEvtHandler *)node->Data();
@@ -537,7 +536,6 @@ void wxApp::ProcessPendingEvents()
         node = wxPendingEvents->First();
     }
 }
-#endif // wxUSE_THREADS
 
 void wxApp::DeletePendingObjects()
 {
index 3d2f42a3548136df9165cb06893fa9418b59d0e8..db66e05e73daa7d60bb440588d82486db29c0b15 100644 (file)
@@ -39,12 +39,6 @@ wxWindowList wxTopLevelWindows;
 /* List of windows pending deletion */
 wxList wxPendingDelete;
 
-#if wxUSE_THREADS
-/* List of events pending processing */
-wxList *wxPendingEvents = NULL;
-wxCriticalSection *wxPendingEventsLocker = NULL;
-#endif
-
 /* Current cursor, in order to hang on to
  * cursor handle when setting the cursor globally */
 wxCursor g_globalCursor;
index 6f3cd22a25e05e588c46ed49b2c02ecd1827be0b..11fcc9c08033bbdbefece5b9795c3954f4ccb63f 100644 (file)
@@ -651,7 +651,7 @@ source_drag_data_get  (GtkWidget          *WXUNUSED(widget),
                 /* disable GUI threads */
                 wxapp_uninstall_thread_wakeup();
 #endif
-    
+
                 gtk_selection_data_set( selection_data,
                                         selection_data->target,
                                         8,   // 8-bit
@@ -745,7 +745,8 @@ wxDropSource::wxDropSource( wxWindow *win, const wxIcon &go, const wxIcon &stop
     if (wxNullIcon == stop) m_stopIcon = wxIcon( gv_xpm );
 }
 
-wxDropSource::wxDropSource( wxDataObject *data, wxWindow *win, const wxIcon &go, const wxIcon &stop )
+wxDropSource::wxDropSource( wxDataObject& data, wxWindow *win,
+                            const wxIcon &go, const wxIcon &stop )
 {
     m_waiting = TRUE;
 
@@ -754,15 +755,8 @@ wxDropSource::wxDropSource( wxDataObject *data, wxWindow *win, const wxIcon &go,
     if (win->m_wxwindow) m_widget = win->m_wxwindow;
     m_retValue = wxDragCancel;
 
-    if (data)
-    {
-        m_data = new wxDataBroker();
-        m_data->Add( data );
-    }
-    else
-    {
-        m_data = (wxDataBroker*) NULL;
-    }
+    m_data = new wxDataBroker;
+    m_data->Add(&data);
 
     m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
     m_goaheadCursor = wxCursor( wxCURSOR_HAND );
@@ -786,6 +780,15 @@ wxDropSource::wxDropSource( wxDataBroker *data, wxWindow *win )
     m_goaheadCursor = wxCursor( wxCURSOR_HAND );
 }
 
+void wxDropSource::SetData( wxDataObject& data )
+{
+    if ( m_data )
+        delete m_data;
+
+    m_data = new wxDataBroker;
+    m_data->Add(&data);
+}
+
 void wxDropSource::SetData( wxDataObject *data )
 {
     if (m_data) delete m_data;
@@ -808,7 +811,7 @@ void wxDropSource::SetData( wxDataBroker *data )
     m_data = data;
 }
 
-wxDropSource::~wxDropSource(void)
+wxDropSource::~wxDropSource()
 {
     if (m_data) delete m_data;
 
@@ -854,7 +857,7 @@ wxDragResult wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove) )
     /* disable GUI threads */
     wxapp_uninstall_thread_wakeup();
 #endif
-    
+
     /* don't start dragging if no button is down */
     if (button_number)
     {
@@ -883,7 +886,7 @@ wxDragResult wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove) )
     /* re-enable GUI threads */
     wxapp_install_thread_wakeup();
 #endif
-    
+
     g_blockEventsOnDrag = FALSE;
 
     UnregisterWindow();
index f1eb101c25569b3de7255da2bbd30bdb42d8b16e..fd60e2a12696fa06af6977c75a80ea8e38e14745 100644 (file)
 wxApp *wxTheApp = (wxApp *)  NULL;
 wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL;
 
-#if wxUSE_THREADS
-extern wxList *wxPendingEvents;
-extern wxCriticalSection *wxPendingEventsLocker;
-#endif
 extern wxResourceCache *wxTheResourceCache;
 extern bool g_isIdle;
 
@@ -127,7 +123,7 @@ unsigned char g_palette[64*3] =
 // local functions
 //-----------------------------------------------------------------------------
 
-extern void wxFlushResources(void);
+extern void wxFlushResources();
 
 //-----------------------------------------------------------------------------
 // global functions
@@ -265,6 +261,7 @@ static gint wxapp_wakeup_timerout_callback( gpointer WXUNUSED(data) )
 
     return TRUE;
 }
+
 #endif // wxUSE_THREADS
 
 //-----------------------------------------------------------------------------
@@ -427,11 +424,9 @@ void wxApp::OnIdle( wxIdleEvent &event )
 
     s_inOnIdle = TRUE;
 
-#if wxUSE_THREADS
     /* Resend in the main thread events which have been prepared in other
        threads */
     ProcessPendingEvents();
-#endif
 
     /* 'Garbage' collection of windows deleted with Close(). */
     DeletePendingObjects();
@@ -520,12 +515,16 @@ void wxApp::Dispatch()
     gtk_main_iteration();
 }
 
-#if wxUSE_THREADS
 void wxApp::ProcessPendingEvents()
 {
-    wxNode *node = wxPendingEvents->First();
+#if wxUSE_THREADS
     wxCriticalSectionLocker locker(*wxPendingEventsLocker);
+#endif // wxUSE_THREADS
+
+    if ( !wxPendingEvents )
+        return;
 
+    wxNode *node = wxPendingEvents->First();
     while (node)
     {
         wxEvtHandler *handler = (wxEvtHandler *)node->Data();
@@ -537,7 +536,6 @@ void wxApp::ProcessPendingEvents()
         node = wxPendingEvents->First();
     }
 }
-#endif // wxUSE_THREADS
 
 void wxApp::DeletePendingObjects()
 {
index 3d2f42a3548136df9165cb06893fa9418b59d0e8..db66e05e73daa7d60bb440588d82486db29c0b15 100644 (file)
@@ -39,12 +39,6 @@ wxWindowList wxTopLevelWindows;
 /* List of windows pending deletion */
 wxList wxPendingDelete;
 
-#if wxUSE_THREADS
-/* List of events pending processing */
-wxList *wxPendingEvents = NULL;
-wxCriticalSection *wxPendingEventsLocker = NULL;
-#endif
-
 /* Current cursor, in order to hang on to
  * cursor handle when setting the cursor globally */
 wxCursor g_globalCursor;
index 6f3cd22a25e05e588c46ed49b2c02ecd1827be0b..11fcc9c08033bbdbefece5b9795c3954f4ccb63f 100644 (file)
@@ -651,7 +651,7 @@ source_drag_data_get  (GtkWidget          *WXUNUSED(widget),
                 /* disable GUI threads */
                 wxapp_uninstall_thread_wakeup();
 #endif
-    
+
                 gtk_selection_data_set( selection_data,
                                         selection_data->target,
                                         8,   // 8-bit
@@ -745,7 +745,8 @@ wxDropSource::wxDropSource( wxWindow *win, const wxIcon &go, const wxIcon &stop
     if (wxNullIcon == stop) m_stopIcon = wxIcon( gv_xpm );
 }
 
-wxDropSource::wxDropSource( wxDataObject *data, wxWindow *win, const wxIcon &go, const wxIcon &stop )
+wxDropSource::wxDropSource( wxDataObject& data, wxWindow *win,
+                            const wxIcon &go, const wxIcon &stop )
 {
     m_waiting = TRUE;
 
@@ -754,15 +755,8 @@ wxDropSource::wxDropSource( wxDataObject *data, wxWindow *win, const wxIcon &go,
     if (win->m_wxwindow) m_widget = win->m_wxwindow;
     m_retValue = wxDragCancel;
 
-    if (data)
-    {
-        m_data = new wxDataBroker();
-        m_data->Add( data );
-    }
-    else
-    {
-        m_data = (wxDataBroker*) NULL;
-    }
+    m_data = new wxDataBroker;
+    m_data->Add(&data);
 
     m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
     m_goaheadCursor = wxCursor( wxCURSOR_HAND );
@@ -786,6 +780,15 @@ wxDropSource::wxDropSource( wxDataBroker *data, wxWindow *win )
     m_goaheadCursor = wxCursor( wxCURSOR_HAND );
 }
 
+void wxDropSource::SetData( wxDataObject& data )
+{
+    if ( m_data )
+        delete m_data;
+
+    m_data = new wxDataBroker;
+    m_data->Add(&data);
+}
+
 void wxDropSource::SetData( wxDataObject *data )
 {
     if (m_data) delete m_data;
@@ -808,7 +811,7 @@ void wxDropSource::SetData( wxDataBroker *data )
     m_data = data;
 }
 
-wxDropSource::~wxDropSource(void)
+wxDropSource::~wxDropSource()
 {
     if (m_data) delete m_data;
 
@@ -854,7 +857,7 @@ wxDragResult wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove) )
     /* disable GUI threads */
     wxapp_uninstall_thread_wakeup();
 #endif
-    
+
     /* don't start dragging if no button is down */
     if (button_number)
     {
@@ -883,7 +886,7 @@ wxDragResult wxDropSource::DoDragDrop( bool WXUNUSED(bAllowMove) )
     /* re-enable GUI threads */
     wxapp_install_thread_wakeup();
 #endif
-    
+
     g_blockEventsOnDrag = FALSE;
 
     UnregisterWindow();
index 5a67e7a4d6b71c61bde51ab66245b18720a3b71d..145aa72a911d4542d8cc482cc8fbd60d7b5f9ccc 100644 (file)
@@ -98,10 +98,6 @@ extern wxChar *wxBuffer;
 extern wxChar *wxOsVersion;
 extern wxList *wxWinHandleList;
 extern wxList WXDLLEXPORT wxPendingDelete;
-#if wxUSE_THREADS
-extern wxList *wxPendingEvents;
-extern wxCriticalSection *wxPendingEventsLocker;
-#endif
 extern void wxSetKeyboardHook(bool doIt);
 extern wxCursor *g_globalCursor;
 
@@ -179,11 +175,8 @@ bool wxApp::Initialize()
     wxGetResource(wxT("wxWindows"), wxT("OsVersion"), &wxOsVersion);
 #endif
 
-    // I'm annoyed ... I don't know where to put this and I don't want to
-    // create a module for that as it's part of the core.
 #if wxUSE_THREADS
-    wxPendingEvents = new wxList();
-    wxPendingEventsLocker = new wxCriticalSection();
+    wxPendingEventsLocker = new wxCriticalSection;
 #endif
 
     wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING);
@@ -565,8 +558,8 @@ void wxApp::CleanUp()
 
     // GL: I'm annoyed ... I don't know where to put this and I don't want to 
     // create a module for that as it's part of the core.
-#if wxUSE_THREADS
     delete wxPendingEvents;
+#if wxUSE_THREADS
     delete wxPendingEventsLocker;
     // If we don't do the following, we get an apparent memory leak.
     ((wxEvtHandler&) wxDefaultValidator).ClearEventLocker();
@@ -931,12 +924,17 @@ bool wxApp::ProcessIdle()
     return event.MoreRequested();
 }
 
-#if wxUSE_THREADS
 void wxApp::ProcessPendingEvents()
 {
-    wxNode *node = wxPendingEvents->First();
+#if wxUSE_THREADS
+    // ensure that we're the only thread to modify the pending events list
     wxCriticalSectionLocker locker(*wxPendingEventsLocker);
+#endif
 
+    if ( !wxPendingEvents )
+        return;
+
+    wxNode *node = wxPendingEvents->First();
     while (node)
     {
         wxEvtHandler *handler = (wxEvtHandler *)node->Data();
@@ -947,8 +945,6 @@ void wxApp::ProcessPendingEvents()
         node = wxPendingEvents->First();
     }
 }
-#endif
-
 
 void wxApp::ExitMainLoop()
 {
@@ -1032,10 +1028,11 @@ void wxApp::OnIdle(wxIdleEvent& event)
         event.RequestMore(TRUE);
     }
 
-    // If they are pending events, we must process them.
-#if wxUSE_THREADS
+    // If they are pending events, we must process them: pending events are
+    // either events to the threads other than main or events posted with
+    // wxPostEvent() functions
     ProcessPendingEvents();
-#endif
+
     s_inOnIdle = FALSE;
 }
 
@@ -1168,22 +1165,19 @@ void wxExit()
 // Yield to incoming messages
 bool wxYield()
 {
+    // we don't want to process WM_QUIT from here - it should be processed in
+    // the main event loop in order to stop it
+
     MSG msg;
-    // We want to go back to the main message loop
-    // if we see a WM_QUIT. (?)
-#ifdef __WXWINE__
-    while (PeekMessage(&msg, (HWND)NULL, 0, 0, PM_NOREMOVE) && msg.message != WM_QUIT)
-#else
-    while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) && msg.message != WM_QUIT)
-#endif
+    while ( PeekMessage(&msg, (HWND)0, 0, 0, PM_NOREMOVE) &&
+            msg.message != WM_QUIT )
     {
         if ( !wxTheApp->DoMessage() )
             break;
     }
+
     // If they are pending events, we must process them.
-#if wxUSE_THREADS
     wxTheApp->ProcessPendingEvents();
-#endif
 
     return TRUE;
 }
index b741d8fa1ae93c8e6735044b5cda57a3c55c604d..cd94dce908685bbdf0357e581de4515b5fd63f0c 100644 (file)
@@ -142,7 +142,8 @@ bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat)
 #if wxUSE_DRAG_AND_DROP
 static bool wxSetClipboardData(wxDataObject *data)
 {
-    size_t size = data->GetDataSize();
+    wxDataFormat format = data->GetPreferredFormat();
+    size_t size = data->GetDataSize(format);
     HANDLE hGlobal = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, size);
     if ( !hGlobal )
     {
@@ -154,11 +155,10 @@ static bool wxSetClipboardData(wxDataObject *data)
 
     LPVOID lpGlobalMemory = ::GlobalLock(hGlobal);
 
-    data->GetDataHere(lpGlobalMemory);
+    data->GetDataHere(format, lpGlobalMemory);
 
     GlobalUnlock(hGlobal);
 
-    wxDataFormat format = data->GetPreferredFormat();
     if ( !::SetClipboardData(format, hGlobal) )
     {
         wxLogSysError(_("Failed to set clipboard data in format %s"),
index f9d4da15a8c6e30d6b76466f73b5aea86bd6f1ad..616d416e36571ee469343da2da1e4a4ef72fa71a 100644 (file)
@@ -37,12 +37,6 @@ wxWindowList wxTopLevelWindows;
 // List of windows pending deletion
 wxList WXDLLEXPORT wxPendingDelete;
 
-// List of events pending processing
-#if wxUSE_THREADS
-wxList *wxPendingEvents = NULL;
-wxCriticalSection *wxPendingEventsLocker = NULL;
-#endif
-
 // Current cursor, in order to hang on to
 // cursor handle when setting the cursor globally
 wxCursor *g_globalCursor = NULL;
index dbc7f122e63ff8e34490cb28d5ee68eeba1da62b..f1eab4707cf21e5b143d7f6fe89afa2dabbdbbab 100644 (file)
 // functions
 // ----------------------------------------------------------------------------
 
-static const char *GetTymedName(DWORD tymed);
+#ifdef __WXDEBUG__
+    static const char *GetTymedName(DWORD tymed);
+#endif // Debug
 
 // ----------------------------------------------------------------------------
 // wxIEnumFORMATETC interface implementation
 // ----------------------------------------------------------------------------
+
 class wxIEnumFORMATETC : public IEnumFORMATETC
 {
 public:
-  wxIEnumFORMATETC(CLIPFORMAT cf);
+    wxIEnumFORMATETC(const wxDataFormat* formats, ULONG nCount);
+    ~wxIEnumFORMATETC() { delete [] m_formats; }
 
-  DECLARE_IUNKNOWN_METHODS;
+    DECLARE_IUNKNOWN_METHODS;
 
-  // IEnumFORMATETC
-  STDMETHODIMP Next(ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched);
-  STDMETHODIMP Skip(ULONG celt);
-  STDMETHODIMP Reset();
-  STDMETHODIMP Clone(IEnumFORMATETC **ppenum);
+    // IEnumFORMATETC
+    STDMETHODIMP Next(ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched);
+    STDMETHODIMP Skip(ULONG celt);
+    STDMETHODIMP Reset();
+    STDMETHODIMP Clone(IEnumFORMATETC **ppenum);
 
 private:
-  FORMATETC   m_format;   // (unique @@@) format we can provide data in
-  ULONG       m_nCurrent; // current enum position (currently either 0 or 1)
+    CLIPFORMAT *m_formats;  // formats we can provide data in
+    ULONG       m_nCount,   // number of formats we support
+                m_nCurrent; // current enum position
 };
 
 // ----------------------------------------------------------------------------
 // wxIDataObject implementation of IDataObject interface
 // ----------------------------------------------------------------------------
+
 class wxIDataObject : public IDataObject
 {
 public:
-  wxIDataObject(wxDataObject *pDataObject);
+    wxIDataObject(wxDataObject *pDataObject);
 
-  DECLARE_IUNKNOWN_METHODS;
+    DECLARE_IUNKNOWN_METHODS;
 
-  // IDataObject
-  STDMETHODIMP GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium);
-  STDMETHODIMP GetDataHere(FORMATETC *pformatetc, STGMEDIUM *pmedium);
-  STDMETHODIMP QueryGetData(FORMATETC *pformatetc);
-  STDMETHODIMP GetCanonicalFormatEtc(FORMATETC *In, FORMATETC *pOut);
-  STDMETHODIMP SetData(FORMATETC *pfetc, STGMEDIUM *pmedium, BOOL fRelease);
-  STDMETHODIMP EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumFEtc);
-  STDMETHODIMP DAdvise(FORMATETC *pfetc, DWORD ad, IAdviseSink *p, DWORD *pdw);
-  STDMETHODIMP DUnadvise(DWORD dwConnection);
-  STDMETHODIMP EnumDAdvise(IEnumSTATDATA **ppenumAdvise);
+    // IDataObject
+    STDMETHODIMP GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium);
+    STDMETHODIMP GetDataHere(FORMATETC *pformatetc, STGMEDIUM *pmedium);
+    STDMETHODIMP QueryGetData(FORMATETC *pformatetc);
+    STDMETHODIMP GetCanonicalFormatEtc(FORMATETC *In, FORMATETC *pOut);
+    STDMETHODIMP SetData(FORMATETC *pfetc, STGMEDIUM *pmedium, BOOL fRelease);
+    STDMETHODIMP EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumFEtc);
+    STDMETHODIMP DAdvise(FORMATETC *pfetc, DWORD ad, IAdviseSink *p, DWORD *pdw);
+    STDMETHODIMP DUnadvise(DWORD dwConnection);
+    STDMETHODIMP EnumDAdvise(IEnumSTATDATA **ppenumAdvise);
 
 private:
-  wxDataObject *m_pDataObject;      // pointer to C++ class we belong to
+    wxDataObject *m_pDataObject;      // pointer to C++ class we belong to
 };
 
 // ============================================================================
@@ -144,70 +150,90 @@ wxString wxDataFormat::GetId() const
 // ----------------------------------------------------------------------------
 
 BEGIN_IID_TABLE(wxIEnumFORMATETC)
-  ADD_IID(Unknown)
-  ADD_IID(EnumFORMATETC)
+    ADD_IID(Unknown)
+    ADD_IID(EnumFORMATETC)
 END_IID_TABLE;
 
 IMPLEMENT_IUNKNOWN_METHODS(wxIEnumFORMATETC)
 
-wxIEnumFORMATETC::wxIEnumFORMATETC(CLIPFORMAT cf)
+wxIEnumFORMATETC::wxIEnumFORMATETC(const wxDataFormat *formats, ULONG nCount)
 {
-  m_format.cfFormat = cf;
-  m_format.ptd      = NULL;
-  m_format.dwAspect = DVASPECT_CONTENT;
-  m_format.lindex   = -1;
-  m_format.tymed    = TYMED_HGLOBAL;
-  m_cRef = 0;
-  m_nCurrent = 0;
+    m_cRef = 0;
+    m_nCurrent = 0;
+    m_nCount = nCount;
+    m_formats = new CLIPFORMAT[nCount];
+    for ( ULONG n = 0; n < nCount; n++ ) {
+        m_formats[n] = formats[n].GetFormatId();
+    }
 }
 
 STDMETHODIMP wxIEnumFORMATETC::Next(ULONG      celt,
                                     FORMATETC *rgelt,
                                     ULONG     *pceltFetched)
 {
-  wxLogTrace(wxT("wxIEnumFORMATETC::Next"));
+    wxLogTrace(wxTRACE_OleCalls, wxT("wxIEnumFORMATETC::Next"));
 
-  if ( celt > 1 )
-    return S_FALSE;
+    if ( celt > 1 ) {
+        // we only return 1 element at a time - mainly because I'm too lazy to
+        // implement something which you're never asked for anyhow
+        return S_FALSE;
+    }
 
-  if ( m_nCurrent == 0 ) {
-    *rgelt = m_format;
-    m_nCurrent++;
+    if ( m_nCurrent < m_nCount ) {
+        FORMATETC format;
+        format.cfFormat = m_formats[m_nCurrent++];
+        format.ptd      = NULL;
+        format.dwAspect = DVASPECT_CONTENT;
+        format.lindex   = -1;
+        format.tymed    = TYMED_HGLOBAL;
+        *rgelt = format;
 
-    return S_OK;
-  }
-  else
-    return S_FALSE;
+        return S_OK;
+    }
+    else {
+        // bad index
+        return S_FALSE;
+    }
 }
 
 STDMETHODIMP wxIEnumFORMATETC::Skip(ULONG celt)
 {
-  wxLogTrace(wxT("wxIEnumFORMATETC::Skip"));
+    wxLogTrace(wxTRACE_OleCalls, wxT("wxIEnumFORMATETC::Skip"));
+
+    m_nCurrent += celt;
+    if ( m_nCurrent < m_nCount )
+        return S_OK;
 
-  if ( m_nCurrent == 0 )
-    m_nCurrent++;
+    // no, can't skip this many elements
+    m_nCurrent -= celt;
 
-  return S_FALSE;
+    return S_FALSE;
 }
 
 STDMETHODIMP wxIEnumFORMATETC::Reset()
 {
-  wxLogTrace(wxT("wxIEnumFORMATETC::Reset"));
+    wxLogTrace(wxTRACE_OleCalls, wxT("wxIEnumFORMATETC::Reset"));
 
-  m_nCurrent = 0;
+    m_nCurrent = 0;
 
-  return S_OK;
+    return S_OK;
 }
 
 STDMETHODIMP wxIEnumFORMATETC::Clone(IEnumFORMATETC **ppenum)
 {
-  wxLogTrace(wxT("wxIEnumFORMATETC::Clone"));
-
-  wxIEnumFORMATETC *pNew = new wxIEnumFORMATETC(m_format.cfFormat);
-  pNew->AddRef();
-  *ppenum = pNew;
+    wxLogTrace(wxTRACE_OleCalls, wxT("wxIEnumFORMATETC::Clone"));
+
+    // unfortunately, we can't reuse the code in ctor - types are different
+    wxIEnumFORMATETC *pNew = new wxIEnumFORMATETC(NULL, 0);
+    pNew->m_nCount = m_nCount;
+    pNew->m_formats = new CLIPFORMAT[m_nCount];
+    for ( ULONG n = 0; n < m_nCount; n++ ) {
+        pNew->m_formats[n] = m_formats[n];
+    }
+    pNew->AddRef();
+    *ppenum = pNew;
 
-  return S_OK;
+    return S_OK;
 }
 
 // ----------------------------------------------------------------------------
@@ -215,71 +241,118 @@ STDMETHODIMP wxIEnumFORMATETC::Clone(IEnumFORMATETC **ppenum)
 // ----------------------------------------------------------------------------
 
 BEGIN_IID_TABLE(wxIDataObject)
-  ADD_IID(Unknown)
-  ADD_IID(DataObject)
+    ADD_IID(Unknown)
+    ADD_IID(DataObject)
 END_IID_TABLE;
 
 IMPLEMENT_IUNKNOWN_METHODS(wxIDataObject)
 
 wxIDataObject::wxIDataObject(wxDataObject *pDataObject)
 {
-  m_cRef = 0;
-  m_pDataObject = pDataObject;
+    m_cRef = 0;
+    m_pDataObject = pDataObject;
 }
 
 // get data functions
 STDMETHODIMP wxIDataObject::GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
 {
-  wxLogTrace(wxT("wxIDataObject::GetData"));
+    wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::GetData"));
 
-  // is data is in our format?
-  HRESULT hr = QueryGetData(pformatetcIn);
-  if ( FAILED(hr) )
-    return hr;
+    // is data is in our format?
+    HRESULT hr = QueryGetData(pformatetcIn);
+    if ( FAILED(hr) )
+        return hr;
 
-  // alloc memory
-  HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
-                                m_pDataObject->GetDataSize());
-  if ( hGlobal == NULL ) {
-    wxLogLastError("GlobalAlloc");
-    return E_OUTOFMEMORY;
-  }
+    // for the bitmaps and metafiles we use the handles instead of global memory
+    // to pass the data
+    wxDataFormat format = (wxDataFormatId)pformatetcIn->cfFormat;
 
-  // copy data
-  pmedium->tymed          = TYMED_HGLOBAL;
-  pmedium->hGlobal        = hGlobal;
-  pmedium->pUnkForRelease = NULL;
+    switch ( format )
+    {
+        case wxDF_BITMAP:
+            pmedium->tymed = TYMED_GDI;
+            break;
+
+        case wxDF_METAFILE:
+            pmedium->tymed = TYMED_MFPICT;
+            break;
+
+        default:
+            // alloc memory
+            size_t size = m_pDataObject->GetDataSize(format);
+            if ( !size ) {
+                // it probably means that the method is just not implemented
+                wxLogDebug(wxT("Invalid data size - can't be 0"));
+
+                return DV_E_FORMATETC;
+            }
+
+            HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, size);
+            if ( hGlobal == NULL ) {
+                wxLogLastError("GlobalAlloc");
+                return E_OUTOFMEMORY;
+            }
+
+            // copy data
+            pmedium->tymed   = TYMED_HGLOBAL;
+            pmedium->hGlobal = hGlobal;
+    }
 
-  hr = GetDataHere(pformatetcIn, pmedium);
-  if ( FAILED(hr) ) {
-    GlobalFree(hGlobal);
-    return hr;
-  }
+    pmedium->pUnkForRelease = NULL;
+
+    // do copy the data
+    hr = GetDataHere(pformatetcIn, pmedium);
+    if ( FAILED(hr) ) {
+        // free resources we allocated
+        if ( pmedium->tymed == TYMED_HGLOBAL ) {
+            GlobalFree(pmedium->hGlobal);
+        }
+
+        return hr;
+    }
 
-  return S_OK;
+    return S_OK;
 }
 
 STDMETHODIMP wxIDataObject::GetDataHere(FORMATETC *pformatetc,
                                         STGMEDIUM *pmedium)
 {
-  wxLogTrace(wxT("wxIDataObject::GetDataHere"));
-
-  // put data in caller provided medium
-  if ( pmedium->tymed != TYMED_HGLOBAL )
-    return DV_E_TYMED;
-
-  // copy data
-  void *pBuf = GlobalLock(pmedium->hGlobal);
-  if ( pBuf == NULL ) {
-    wxLogLastError(wxT("GlobalLock"));
-    return E_OUTOFMEMORY;
-  }
+    wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::GetDataHere"));
 
-  m_pDataObject->GetDataHere(pBuf);
-
-  GlobalUnlock(pmedium->hGlobal);
+    // put data in caller provided medium
+    switch ( pmedium->tymed )
+    {
+        case TYMED_GDI:
+            m_pDataObject->GetDataHere(wxDF_BITMAP, &pmedium->hBitmap);
+            break;
+
+        case TYMED_MFPICT:
+            // this should be copied on bitmaps - but I don't have time for
+            // this now
+            wxFAIL_MSG(wxT("TODO - no support for metafiles in wxDataObject"));
+            break;
+
+        case TYMED_HGLOBAL:
+            {
+                // copy data
+                void *pBuf = GlobalLock(pmedium->hGlobal);
+                if ( pBuf == NULL ) {
+                    wxLogLastError(wxT("GlobalLock"));
+                    return E_OUTOFMEMORY;
+                }
+
+                wxDataFormat format = (wxDataFormatId)pformatetc->cfFormat;
+                m_pDataObject->GetDataHere(format, pBuf);
+
+                GlobalUnlock(pmedium->hGlobal);
+            }
+            break;
+
+        default:
+            return DV_E_TYMED;
+    }
 
-  return S_OK;
+    return S_OK;
 }
 
 // set data functions (not implemented)
@@ -287,7 +360,8 @@ STDMETHODIMP wxIDataObject::SetData(FORMATETC *pformatetc,
                                     STGMEDIUM *pmedium,
                                     BOOL       fRelease)
 {
-  wxLogTrace(wxT("wxIDataObject::SetData"));
+  wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::SetData"));
+
   return E_NOTIMPL;
 }
 
@@ -296,39 +370,53 @@ STDMETHODIMP wxIDataObject::QueryGetData(FORMATETC *pformatetc)
 {
   // do we accept data in this format?
   if ( pformatetc == NULL ) {
-    wxLogTrace(wxT("wxIDataObject::QueryGetData: invalid ptr."));
+    wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::QueryGetData: invalid ptr."));
+
     return E_INVALIDARG;
   }
 
   // the only one allowed by current COM implementation
   if ( pformatetc->lindex != -1 ) {
-    wxLogTrace(wxT("wxIDataObject::QueryGetData: bad lindex %d"),
+    wxLogTrace(wxTRACE_OleCalls,
+               wxT("wxIDataObject::QueryGetData: bad lindex %d"),
                pformatetc->lindex);
     return DV_E_LINDEX;
   }
 
   // we don't support anything other (THUMBNAIL, ICON, DOCPRINT...)
   if ( pformatetc->dwAspect != DVASPECT_CONTENT ) {
-    wxLogTrace(wxT("wxIDataObject::QueryGetData: bad dwAspect %d"),
+    wxLogTrace(wxTRACE_OleCalls,
+               wxT("wxIDataObject::QueryGetData: bad dwAspect %d"),
                pformatetc->dwAspect);
     return DV_E_DVASPECT;
   }
 
-  // @@ we only transfer data by global memory (bad for large amounts of it!)
-  if ( !(pformatetc->tymed & TYMED_HGLOBAL) ) {
-    wxLogTrace(wxT("wxIDataObject::QueryGetData: %s != TYMED_HGLOBAL."),
-               GetTymedName(pformatetc->tymed));
+  // we only transfer data by global memory, except for some particular cases
+  wxDataFormat format = (wxDataFormatId)pformatetc->cfFormat;
+  DWORD tymed = pformatetc->tymed;
+  if ( (format == wxDF_BITMAP && !(tymed & TYMED_GDI)) ||
+       !(tymed & TYMED_HGLOBAL) ) {
+    // it's not what we're waiting for
+#ifdef __WXDEBUG__
+    wxLogTrace(wxTRACE_OleCalls,
+               wxT("wxIDataObject::QueryGetData: %s & %s == 0."),
+               GetTymedName(tymed),
+               GetTymedName(format == wxDF_BITMAP ? TYMED_GDI : TYMED_HGLOBAL));
+#endif // Debug
     return DV_E_TYMED;
   }
 
   // and now check the type of data requested
-  if ( m_pDataObject->IsSupportedFormat((wxDataFormatId)pformatetc->cfFormat) ) {
-    wxLogTrace(wxT("wxIDataObject::QueryGetData: %s ok"),
-               wxDataObject::GetFormatName((wxDataFormatId)pformatetc->cfFormat));
+  if ( m_pDataObject->IsSupportedFormat(format) ) {
+#ifdef __WXDEBUG__
+    wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::QueryGetData: %s ok"),
+               wxDataObject::GetFormatName(format));
+#endif // Debug
     return S_OK;
   }
   else {
-    wxLogTrace(wxT("wxIDataObject::QueryGetData: %s unsupported"),
+    wxLogTrace(wxTRACE_OleCalls,
+               wxT("wxIDataObject::QueryGetData: %s unsupported"),
                wxDataObject::GetFormatName((wxDataFormatId)pformatetc->cfFormat));
     return DV_E_FORMATETC;
   }
@@ -337,30 +425,47 @@ STDMETHODIMP wxIDataObject::QueryGetData(FORMATETC *pformatetc)
 STDMETHODIMP wxIDataObject::GetCanonicalFormatEtc(FORMATETC *pFormatetcIn,
                                                   FORMATETC *pFormatetcOut)
 {
-  wxLogTrace(wxT("wxIDataObject::GetCanonicalFormatEtc"));
+    wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::GetCanonicalFormatEtc"));
+
+    // TODO we might want something better than this trivial implementation here
+    if ( pFormatetcOut != NULL )
+        pFormatetcOut->ptd = NULL;
 
-  // @@ implementation is trivial, we might want something better here
-  if ( pFormatetcOut != NULL )
-    pFormatetcOut->ptd = NULL;
-  return DATA_S_SAMEFORMATETC;
+    return DATA_S_SAMEFORMATETC;
 }
 
 STDMETHODIMP wxIDataObject::EnumFormatEtc(DWORD dwDirection,
                                           IEnumFORMATETC **ppenumFormatEtc)
 {
-  wxLogTrace(wxT("wxIDataObject::EnumFormatEtc"));
+    wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::EnumFormatEtc"));
 
-  if ( dwDirection == DATADIR_SET ) {
-    // we don't allow setting of data anyhow
-    return E_NOTIMPL;
-  }
+    if ( dwDirection == DATADIR_SET ) {
+        // we don't allow setting of data anyhow
+        return E_NOTIMPL;
+    }
 
-  wxIEnumFORMATETC *pEnum =
-    new wxIEnumFORMATETC(m_pDataObject->GetPreferredFormat());
-  pEnum->AddRef();
-  *ppenumFormatEtc = pEnum;
+    size_t nFormatCount = m_pDataObject->GetFormatCount();
+    wxDataFormat format, *formats;
+    if ( nFormatCount == 1 ) {
+        // this is the most common case, this is why we consider it separately
+        formats = &format;
+        format = m_pDataObject->GetPreferredFormat();
+    }
+    else {
+        // bad luck, build the array with all formats
+        formats = new wxDataFormat[nFormatCount];
+        m_pDataObject->GetAllFormats(formats);
+    }
+
+    wxIEnumFORMATETC *pEnum = new wxIEnumFORMATETC(formats, nFormatCount);
+    pEnum->AddRef();
+    *ppenumFormatEtc = pEnum;
+
+    if ( formats != &format ) {
+        delete [] formats;
+    }
 
-  return S_OK;
+    return S_OK;
 }
 
 // advise sink functions (not implemented)
@@ -397,9 +502,32 @@ wxDataObject::~wxDataObject()
   m_pIDataObject->Release();
 }
 
-const char *wxDataObject::GetFormatName(wxDataFormat format)
+bool wxDataObject::IsSupportedFormat(const wxDataFormat& format) const
 {
+    size_t nFormatCount = GetFormatCount();
+    if ( nFormatCount == 1 ) {
+        return format == GetPreferredFormat();
+    }
+    else {
+        wxDataFormat *formats = new wxDataFormat[nFormatCount];
+        GetAllFormats(formats);
+
+        size_t n;
+        for ( n = 0; n < nFormatCount; n++ ) {
+            if ( formats[n] == format )
+                break;
+        }
+
+        delete [] formats;
+
+        // found?
+        return n < nFormatCount;
+    }
+}
+
 #ifdef __WXDEBUG__
+const char *wxDataObject::GetFormatName(wxDataFormat format)
+{
   // case 'xxx' is not a valid value for switch of enum 'wxDataFormat'
   #ifdef __VISUALC__
     #pragma warning(disable:4063)
@@ -431,11 +559,8 @@ const char *wxDataObject::GetFormatName(wxDataFormat format)
   #ifdef __VISUALC__
     #pragma warning(default:4063)
   #endif // VC++
-
-#else // !Debug
-  return "";
-#endif // Debug
 }
+#endif // Debug
 
 // ----------------------------------------------------------------------------
 // wxPrivateDataObject
@@ -478,9 +603,34 @@ void wxPrivateDataObject::WriteData( const void *data, void *dest ) const
     memcpy( dest, data, GetSize() );
 }
 
+// ----------------------------------------------------------------------------
+// wxBitmapDataObject
+// ----------------------------------------------------------------------------
+
+// the bitmaps aren't passed by value as other types of data (i.e. by copyign
+// the data into a global memory chunk and passing it to the clipboard or
+// another application or whatever), but by handle, so these generic functions
+// don't make much sense to them.
+
+size_t wxBitmapDataObject::GetDataSize(const wxDataFormat& format) const
+{
+    // no data to copy anyhow
+    return 0;
+}
+
+void wxBitmapDataObject::GetDataHere(const wxDataFormat& format,
+                                     void *pBuf) const
+{
+    // we put a bitmap handle into pBuf
+    *(WXHBITMAP *)pBuf = m_bitmap.GetHBITMAP();
+}
+
 // ----------------------------------------------------------------------------
 // private functions
 // ----------------------------------------------------------------------------
+
+#ifdef __WXDEBUG__
+
 static const char *GetTymedName(DWORD tymed)
 {
   static char s_szBuf[128];
@@ -498,7 +648,7 @@ static const char *GetTymedName(DWORD tymed)
   }
 }
 
-// TODO: OLE parts of wxBitmap/File/MetafileDataObject
+#endif // Debug
 
 #endif
 
index 6e6e2886d5c899c0b7b236a89f3877f45fccfbad..3384ac00578b4347a40266cc451c8017e3d78655 100644 (file)
@@ -160,13 +160,18 @@ void wxDropSource::Init()
   m_pIDropSource->AddRef();
 }
 
-wxDropSource::wxDropSource(wxWindow* WXUNUSED(win))
+wxDropSource::wxDropSource(wxWindow* WXUNUSED(win),
+                           const wxIcon & WXUNUSED(go),
+                           const wxIcon & WXUNUSED(stop))
 {
   Init();
   m_pData = NULL;
 }
 
-wxDropSource::wxDropSource(wxDataObject& data, wxWindow* WXUNUSED(win))
+wxDropSource::wxDropSource(wxDataObject& data,
+                           wxWindow* WXUNUSED(win),
+                           const wxIcon & WXUNUSED(go),
+                           const wxIcon & WXUNUSED(stop))
 {
   Init();
   SetData(data);