1. wxPostEvent added and documented

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
This commit is contained in:
Vadim Zeitlin
1999-10-17 01:18:49 +00:00
parent 6d693bb4fc
commit 8e193f384f
24 changed files with 1359 additions and 637 deletions

View File

@@ -1058,6 +1058,17 @@ Gets the physical size of the display in pixels.
<wx/gdicmn.h> <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} \membersection{::wxEntry}\label{wxentry}
This initializes wxWindows in a platform-dependent way. Use this if you This initializes wxWindows in a platform-dependent way. Use this if you
@@ -1101,18 +1112,6 @@ int CTheApp::ExitInstance()
<wx/app.h> <wx/app.h>
\membersection{::wxError}\label{wxerror}
\func{void}{wxError}{\param{const wxString\& }{msg}, \param{const wxString\& }{title = "wxWindows Internal Error"}}
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}
<wx/utils.h>
\membersection{::wxEndBusyCursor}\label{wxendbusycursor} \membersection{::wxEndBusyCursor}\label{wxendbusycursor}
\func{void}{wxEndBusyCursor}{\void} \func{void}{wxEndBusyCursor}{\void}
@@ -1126,6 +1125,18 @@ See also \helpref{wxIsBusy}{wxisbusy}, \helpref{wxBusyCursor}{wxbusycursor}.
<wx/utils.h> <wx/utils.h>
\membersection{::wxError}\label{wxerror}
\func{void}{wxError}{\param{const wxString\& }{msg}, \param{const wxString\& }{title = "wxWindows Internal Error"}}
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}
<wx/utils.h>
\membersection{::wxExecute}\label{wxexecute} \membersection{::wxExecute}\label{wxexecute}
\func{long}{wxExecute}{\param{const wxString\& }{command}, \param{bool }{sync = FALSE}, \param{wxProcess *}{callback = NULL}} \func{long}{wxExecute}{\param{const wxString\& }{command}, \param{bool }{sync = FALSE}, \param{wxProcess *}{callback = NULL}}
@@ -1465,6 +1476,25 @@ Now obsolete: use \helpref{wxWindow::Close}{wxwindowclose} instead.
<wx/utils.h> <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} \membersection{::wxSafeYield}\label{wxsafeyield}
\func{bool}{wxSafeYield}{\param{wxWindow*}{ win = NULL}} \func{bool}{wxSafeYield}{\param{wxWindow*}{ win = NULL}}
@@ -1480,18 +1510,6 @@ Returns the result of the call to \helpref{::wxYield}{wxyield}.
<wx/utils.h> <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} \membersection{::wxSetDisplayName}\label{wxsetdisplayname}
\func{void}{wxSetDisplayName}{\param{const wxString\& }{displayName}} \func{void}{wxSetDisplayName}{\param{const wxString\& }{displayName}}
@@ -1667,7 +1685,7 @@ function.
\wxheading{Include files} \wxheading{Include files}
<wx/utils.h> <wx/app.h> or <wx/utils.h>
\section{Macros}\label{macros} \section{Macros}\label{macros}

View File

@@ -1,14 +1,14 @@
[OPTIONS] [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 TITLE=wxWindows Manual
CONTENTS=Contents CONTENTS=Contents
COMPRESS=HIGH COMPRESS=HIGH
[FILES] [FILES]
wx.rtf Wx.rtf
[CONFIG] [CONFIG]
CreateButton("Up", "&Up", "JumpId(`wx.hlp', `Contents')") CreateButton("Up", "&Up", "JumpId(`Wx.hlp', `Contents')")
BrowseButtons() BrowseButtons()
[MAP] [MAP]

View File

@@ -307,6 +307,15 @@ extern void WXDLLEXPORT wxExit();
// Yield to other apps/messages // Yield to other apps/messages
extern bool WXDLLEXPORT wxYield(); 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 #endif // wxUSE_GUI
// console applications may avoid using DECLARE_APP and IMPLEMENT_APP macros // console applications may avoid using DECLARE_APP and IMPLEMENT_APP macros

View File

@@ -1281,6 +1281,10 @@ protected:
wxEVT_COMPARE_ITEM wxEVT_COMPARE_ITEM
*/ */
// ============================================================================
// event handler and related classes
// ============================================================================
typedef void (wxObject::*wxObjectEventFunction)(wxEvent&); typedef void (wxObject::*wxObjectEventFunction)(wxEvent&);
struct WXDLLEXPORT wxEventTableEntry struct WXDLLEXPORT wxEventTableEntry
@@ -1314,9 +1318,45 @@ public:
void SetNextHandler(wxEvtHandler *handler) { m_nextHandler = handler; } void SetNextHandler(wxEvtHandler *handler) { m_nextHandler = handler; }
void SetPreviousHandler(wxEvtHandler *handler) { m_previousHandler = 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; } bool GetEvtHandlerEnabled() const { return m_enabled; }
// process an event right now
virtual bool ProcessEvent(wxEvent& event);
// add an event to be processed later
void AddPendingEvent(wxEvent& event);
// process all pending events
void ProcessPendingEvents();
// add a
#if wxUSE_THREADS
bool ProcessThreadEvent(wxEvent& event);
#endif
// Dynamic association of a member function handler with the event handler,
// id and event type
void Connect( int id, int lastId, wxEventType eventType,
wxObjectEventFunction func,
wxObject *userData = (wxObject *) NULL );
// Convenience function: take just one id
void Connect( int id, wxEventType eventType,
wxObjectEventFunction func,
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 #if WXWIN_COMPATIBILITY_2
virtual void OnCommand(wxWindow& WXUNUSED(win), virtual void OnCommand(wxWindow& WXUNUSED(win),
wxCommandEvent& WXUNUSED(event)) wxCommandEvent& WXUNUSED(event))
@@ -1333,31 +1373,6 @@ public:
virtual bool OnClose(); virtual bool OnClose();
#endif #endif
#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
void Connect( int id, int lastId, wxEventType eventType,
wxObjectEventFunction func,
wxObject *userData = (wxObject *) NULL );
// Convenience function: take just one id
void Connect( int id, wxEventType eventType,
wxObjectEventFunction func,
wxObject *userData = (wxObject *) NULL )
{ Connect(id, -1, eventType, func, userData); }
bool SearchDynamicEventTable( wxEvent& event );
#if wxUSE_THREADS
void ClearEventLocker() { delete m_eventsLocker; m_eventsLocker = NULL; };
#endif
private: private:
static const wxEventTableEntry sm_eventTableEntries[]; static const wxEventTableEntry sm_eventTableEntries[];
@@ -1369,7 +1384,6 @@ protected:
protected: protected:
wxEvtHandler* m_nextHandler; wxEvtHandler* m_nextHandler;
wxEvtHandler* m_previousHandler; wxEvtHandler* m_previousHandler;
bool m_enabled; // Is event handler enabled?
wxList* m_dynamicEvents; wxList* m_dynamicEvents;
wxList* m_pendingEvents; wxList* m_pendingEvents;
#if wxUSE_THREADS #if wxUSE_THREADS
@@ -1379,6 +1393,9 @@ protected:
// optimization: instead of using costly IsKindOf() to decide whether we're // optimization: instead of using costly IsKindOf() to decide whether we're
// a window (which is true in 99% of cases), use this flag // a window (which is true in 99% of cases), use this flag
bool m_isWindow; bool m_isWindow;
// Is event handler enabled?
bool m_enabled;
}; };
typedef void (wxEvtHandler::*wxEventFunction)(wxEvent&); typedef void (wxEvtHandler::*wxEventFunction)(wxEvent&);
@@ -1614,6 +1631,17 @@ const wxEventTableEntry theClass::sm_eventTableEntries[] = { \
#define EVT_UPDATE_UI(id, func) \ #define EVT_UPDATE_UI(id, func) \
{ wxEVT_UPDATE_UI, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxUpdateUIEventFunction) & func, (wxObject *) NULL },\ { 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 // Helper functions
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@@ -188,7 +188,7 @@ public:
wxDropSource( wxWindow *win, const wxIcon &go = wxNullIcon, const wxIcon &stop = wxNullIcon ); wxDropSource( wxWindow *win, const wxIcon &go = wxNullIcon, const wxIcon &stop = wxNullIcon );
/* constructor for setting one data object */ /* constructor for setting one data object */
wxDropSource( wxDataObject *data, wxWindow *win, const wxIcon &go = wxNullIcon, const wxIcon &stop = wxNullIcon ); wxDropSource( wxDataObject& data, wxWindow *win, const wxIcon &go = wxNullIcon, const wxIcon &stop = wxNullIcon );
/* constructor for setting several data objects via wxDataBroker */ /* constructor for setting several data objects via wxDataBroker */
wxDropSource( wxDataBroker *data, wxWindow *win ); wxDropSource( wxDataBroker *data, wxWindow *win );
@@ -199,6 +199,9 @@ public:
void SetData( wxDataBroker *data ); void SetData( wxDataBroker *data );
/* set one dataobject */ /* set one dataobject */
void SetData( wxDataObject& data );
// this one isn't portable to wxMSW -- deprecated
void SetData( wxDataObject *data ); void SetData( wxDataObject *data );
/* start drag action */ /* start drag action */

View File

@@ -188,7 +188,7 @@ public:
wxDropSource( wxWindow *win, const wxIcon &go = wxNullIcon, const wxIcon &stop = wxNullIcon ); wxDropSource( wxWindow *win, const wxIcon &go = wxNullIcon, const wxIcon &stop = wxNullIcon );
/* constructor for setting one data object */ /* constructor for setting one data object */
wxDropSource( wxDataObject *data, wxWindow *win, const wxIcon &go = wxNullIcon, const wxIcon &stop = wxNullIcon ); wxDropSource( wxDataObject& data, wxWindow *win, const wxIcon &go = wxNullIcon, const wxIcon &stop = wxNullIcon );
/* constructor for setting several data objects via wxDataBroker */ /* constructor for setting several data objects via wxDataBroker */
wxDropSource( wxDataBroker *data, wxWindow *win ); wxDropSource( wxDataBroker *data, wxWindow *win );
@@ -199,6 +199,9 @@ public:
void SetData( wxDataBroker *data ); void SetData( wxDataBroker *data );
/* set one dataobject */ /* set one dataobject */
void SetData( wxDataObject& data );
// this one isn't portable to wxMSW -- deprecated
void SetData( wxDataObject *data ); void SetData( wxDataObject *data );
/* start drag action */ /* start drag action */

View File

@@ -83,9 +83,7 @@ public:
virtual bool ProcessMessage(WXMSG* pMsg); virtual bool ProcessMessage(WXMSG* pMsg);
void DeletePendingObjects(); void DeletePendingObjects();
bool ProcessIdle(); bool ProcessIdle();
#if wxUSE_THREADS
void ProcessPendingEvents(); void ProcessPendingEvents();
#endif
int GetComCtl32Version() const; int GetComCtl32Version() const;
public: public:

View File

@@ -12,7 +12,6 @@
#ifndef _WX_OLEDATAOBJ_H #ifndef _WX_OLEDATAOBJ_H
#define _WX_OLEDATAOBJ_H #define _WX_OLEDATAOBJ_H
#include "wx/bitmap.h"
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxDataFormat identifies the single format of data // wxDataFormat identifies the single format of data
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -68,17 +67,14 @@ struct IDataObject;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxDataObject is a "smart" and polymorphic piece of data. // 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 // TODO it's currently "read-only" from COM point of view, i.e. we don't
// SetData. We don't support all advise functions neither (but it's easy to // support SetData. We don't support all advise functions neither (but
// do if we really want them) // it's easy to do if we really want them)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
class WXDLLEXPORT wxDataObject class WXDLLEXPORT wxDataObject
{ {
public: public:
// function to return symbolic name of clipboard format (debug messages)
static const char *GetFormatName(wxDataFormat format);
// ctor & dtor // ctor & dtor
wxDataObject(); wxDataObject();
virtual ~wxDataObject(); virtual ~wxDataObject();
@@ -86,20 +82,33 @@ public:
// pure virtuals to override // pure virtuals to override
// get the best suited format for our data // get the best suited format for our data
virtual wxDataFormat GetPreferredFormat() const = 0; virtual wxDataFormat GetPreferredFormat() const = 0;
// decide if we support this format (should be one of values of // get the number of formats we support
// wxDataFormatId enumerations or a user-defined format) virtual size_t GetFormatCount() const
virtual bool IsSupportedFormat(wxDataFormat format) const = 0; { return 1; }
// get the (total) size of data // return all formats in the provided array (of size GetFormatCount())
virtual size_t GetDataSize() const = 0; virtual void GetAllFormats(wxDataFormat *formats) const
// copy raw data to provided pointer { formats[0] = GetPreferredFormat(); }
virtual void GetDataHere(void *pBuf) const = 0; // 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 // accessors
// retrieve IDataObject interface (for other OLE related classes) // retrieve IDataObject interface (for other OLE related classes)
IDataObject *GetInterface() const { return m_pIDataObject; } 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(); }
////// wxGTK compatibility: hopefully to become the preferred API. // old interface
virtual wxDataFormat GetFormat() const { return GetPreferredFormat(); } // 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: private:
IDataObject *m_pIDataObject; // pointer to the COM interface IDataObject *m_pIDataObject; // pointer to the COM interface
@@ -108,6 +117,7 @@ private:
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxTextDataObject is a specialization of wxDataObject for text data // wxTextDataObject is a specialization of wxDataObject for text data
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
class WXDLLEXPORT wxTextDataObject : public wxDataObject class WXDLLEXPORT wxTextDataObject : public wxDataObject
{ {
public: public:
@@ -119,24 +129,23 @@ public:
// implement base class pure virtuals // implement base class pure virtuals
virtual wxDataFormat GetPreferredFormat() const virtual wxDataFormat GetPreferredFormat() const
{ return wxDF_TEXT; } { return wxDF_TEXT; }
virtual bool IsSupportedFormat(wxDataFormat format) const virtual bool IsSupportedFormat(const wxDataFormat& format) const
{ return format == wxDF_TEXT || format == wxDF_LOCALE; } { return format == wxDF_TEXT || format == wxDF_LOCALE; }
virtual size_t GetDataSize() const virtual size_t GetDataSize(const wxDataFormat& format) const
{ return m_strText.Len() + 1; } // +1 for trailing '\0'of course { return m_strText.Len() + 1; } // +1 for trailing '\0'of course
virtual void GetDataHere(void *pBuf) const virtual void GetDataHere(const wxDataFormat& format, void *pBuf) const
{ memcpy(pBuf, m_strText.c_str(), GetDataSize()); } { memcpy(pBuf, m_strText.c_str(), GetDataSize(format)); }
////// wxGTK compatibility: hopefully to become the preferred API. // additional helpers
void SetText(const wxString& strText) { m_strText = strText; } void SetText(const wxString& strText) { m_strText = strText; }
wxString GetText() const { return m_strText; } wxString GetText() const { return m_strText; }
virtual wxDataFormat GetFormat() const { return wxDF_TEXT; }
private: private:
wxString m_strText; wxString m_strText;
}; };
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// @@@ TODO: wx{Bitmap|Metafile|...}DataObject // TODO: wx{Bitmap|Metafile|...}DataObject
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -145,26 +154,26 @@ private:
// TODO: implement OLE side of things. At present, it's just for clipboard // TODO: implement OLE side of things. At present, it's just for clipboard
// use. // use.
#include "wx/bitmap.h"
class WXDLLEXPORT wxBitmapDataObject : public wxDataObject class WXDLLEXPORT wxBitmapDataObject : public wxDataObject
{ {
public: public:
// ctors // ctors
wxBitmapDataObject() {} wxBitmapDataObject() { }
wxBitmapDataObject(const wxBitmap& bitmap): m_bitmap(bitmap) {} 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; } // set/get our bitmap
void SetBitmap(const wxBitmap& bitmap) { m_bitmap = bitmap; }
const wxBitmap GetBitmap() const { return m_bitmap; }
// implement base class pure virtuals // implement base class pure virtuals
virtual wxDataFormat GetPreferredFormat() const virtual wxDataFormat GetPreferredFormat() const
{ return wxDF_BITMAP; } { return wxDF_BITMAP; }
virtual bool IsSupportedFormat(wxDataFormat format) const virtual bool IsSupportedFormat(const wxDataFormat& format) const
{ return format == wxDF_BITMAP; } { return format == wxDF_BITMAP; }
virtual size_t GetDataSize() const virtual size_t GetDataSize(const wxDataFormat& format) const;
{ wxASSERT(FALSE); return 0; } // BEMIMP virtual void GetDataHere(const wxDataFormat& format, void *pBuf) const;
virtual void GetDataHere(void *pBuf) const
{ wxASSERT(FALSE); } // BEMIMP
private: private:
wxBitmap m_bitmap; wxBitmap m_bitmap;

View File

@@ -13,9 +13,9 @@
#define _WX_OLEDROPSRC_H #define _WX_OLEDROPSRC_H
#ifdef __GNUG__ #ifdef __GNUG__
#pragma interface #pragma interface
#endif #endif
#include "wx/window.h"
#if !wxUSE_DRAG_AND_DROP #if !wxUSE_DRAG_AND_DROP
#error "You should #define wxUSE_DRAG_AND_DROP to 1 to compile this file!" #error "You should #define wxUSE_DRAG_AND_DROP to 1 to compile this file!"
#endif //WX_DRAG_DROP #endif //WX_DRAG_DROP
@@ -23,30 +23,42 @@
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// forward declarations // forward declarations
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
class wxIDropSource; class wxIDropSource;
class wxDataObject; class WXDLLEXPORT wxDataObject;
class WXDLLEXPORT wxWindow;
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
enum wxDragResult enum wxDragResult
{ {
wxDragError, // error prevented the d&d operation from completing wxDragError, // error prevented the d&d operation from completing
wxDragNone, // drag target didn't accept the data wxDragNone, // drag target didn't accept the data
wxDragCopy, // the data was successfully copied wxDragCopy, // the data was successfully copied
wxDragMove, // the data was successfully moved wxDragMove, // the data was successfully moved
wxDragCancel // the operation was cancelled by user (not an error) wxDragCancel // the operation was cancelled by user (not an error)
}; };
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxDropSource is used to start the drag-&-drop operation on associated // wxDropSource is used to start the drag-&-drop operation on associated
// wxDataObject object. It's responsible for giving UI feedback while dragging. // wxDataObject object. It's responsible for giving UI feedback while dragging.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
class WXDLLEXPORT wxDropSource class WXDLLEXPORT wxDropSource
{ {
public: public:
// ctors: if you use default ctor you must call SetData() later! // ctors: if you use default ctor you must call SetData() later!
// NB: the "wxWindow *win" parameter is unused and is here only for wxGTK // NB: the "wxWindow *win" parameter is unused and is here only for wxGTK
// compatibility // compatibility, as well as both icon parameters
wxDropSource(wxWindow *win = NULL); wxDropSource(wxWindow *win = NULL,
wxDropSource(wxDataObject& data, 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); void SetData(wxDataObject& data);

View File

@@ -19,8 +19,8 @@
#include "wx/wx.h" #include "wx/wx.h"
#endif #endif
#ifdef __WXMOTIF__ #if !wxUSE_DRAG_AND_DROP
#error Sorry, drag and drop is not yet implemented on wxMotif. #error This sample requires drag and drop support in the library
#endif #endif
#include "wx/intl.h" #include "wx/intl.h"
@@ -31,6 +31,8 @@
#include "wx/filedlg.h" #include "wx/filedlg.h"
#include "wx/image.h" #include "wx/image.h"
#include "wx/clipbrd.h" #include "wx/clipbrd.h"
#include "wx/colordlg.h"
#include "wx/resource.h"
#if defined(__WXGTK__) || defined(__WXMOTIF__) #if defined(__WXGTK__) || defined(__WXMOTIF__)
#include "mondrian.xpm" #include "mondrian.xpm"
@@ -74,14 +76,15 @@ private:
class DnDApp : public wxApp class DnDApp : public wxApp
{ {
public: public:
bool OnInit(); virtual bool OnInit();
}; };
IMPLEMENT_APP(DnDApp); IMPLEMENT_APP(DnDApp);
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Define a new frame type // Define a new frame type for the main frame
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
class DnDFrame : public wxFrame class DnDFrame : public wxFrame
{ {
public: public:
@@ -92,6 +95,7 @@ public:
void OnQuit (wxCommandEvent& event); void OnQuit (wxCommandEvent& event);
void OnAbout(wxCommandEvent& event); void OnAbout(wxCommandEvent& event);
void OnDrag (wxCommandEvent& event); void OnDrag (wxCommandEvent& event);
void OnNewFrame(wxCommandEvent& event);
void OnHelp (wxCommandEvent& event); void OnHelp (wxCommandEvent& event);
void OnLogClear(wxCommandEvent& event); void OnLogClear(wxCommandEvent& event);
void OnCopy(wxCommandEvent& event); void OnCopy(wxCommandEvent& event);
@@ -117,6 +121,355 @@ private:
wxBitmap m_bitmap; 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 // IDs for the menu commands
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -125,6 +478,7 @@ enum
{ {
Menu_Quit = 1, Menu_Quit = 1,
Menu_Drag, Menu_Drag,
Menu_NewFrame,
Menu_About = 101, Menu_About = 101,
Menu_Help, Menu_Help,
Menu_Clear, Menu_Clear,
@@ -135,13 +489,15 @@ enum
Menu_HasText, Menu_HasText,
Menu_HasBitmap, Menu_HasBitmap,
Menu_ToBeGreyed, /* for testing */ Menu_ToBeGreyed, /* for testing */
Menu_ToBeDeleted /* for testing */ Menu_ToBeDeleted, /* for testing */
Button_Colour = 1001
}; };
BEGIN_EVENT_TABLE(DnDFrame, wxFrame) BEGIN_EVENT_TABLE(DnDFrame, wxFrame)
EVT_MENU(Menu_Quit, DnDFrame::OnQuit) EVT_MENU(Menu_Quit, DnDFrame::OnQuit)
EVT_MENU(Menu_About, DnDFrame::OnAbout) EVT_MENU(Menu_About, DnDFrame::OnAbout)
EVT_MENU(Menu_Drag, DnDFrame::OnDrag) EVT_MENU(Menu_Drag, DnDFrame::OnDrag)
EVT_MENU(Menu_NewFrame, DnDFrame::OnNewFrame)
EVT_MENU(Menu_Help, DnDFrame::OnHelp) EVT_MENU(Menu_Help, DnDFrame::OnHelp)
EVT_MENU(Menu_Clear, DnDFrame::OnLogClear) EVT_MENU(Menu_Clear, DnDFrame::OnLogClear)
EVT_MENU(Menu_Copy, DnDFrame::OnCopy) EVT_MENU(Menu_Copy, DnDFrame::OnCopy)
@@ -156,7 +512,21 @@ BEGIN_EVENT_TABLE(DnDFrame, wxFrame)
EVT_PAINT( DnDFrame::OnPaint) EVT_PAINT( DnDFrame::OnPaint)
END_EVENT_TABLE() 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() bool DnDApp::OnInit()
{ {
#if wxUSE_LIBPNG #if wxUSE_LIBPNG
@@ -173,6 +543,8 @@ bool DnDApp::OnInit()
SetTopWindow(frame); SetTopWindow(frame);
wxDefaultResourceTable->ParseResourceFile("dnd.wxr");
return TRUE; return TRUE;
} }
@@ -186,19 +558,13 @@ DnDFrame::DnDFrame(wxFrame *frame, char *title, int x, int y, int w, int h)
CreateStatusBar(); 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 // construct menu
wxMenu *file_menu = new wxMenu; wxMenu *file_menu = new wxMenu;
file_menu->Append(Menu_Drag, "&Test drag..."); file_menu->Append(Menu_Drag, "&Test drag...");
file_menu->AppendSeparator(); file_menu->AppendSeparator();
file_menu->Append(Menu_Quit, "E&xit"); file_menu->Append(Menu_NewFrame, "&New frame\tCtrl-N");
file_menu->AppendSeparator(); file_menu->AppendSeparator();
file_menu->Append( 0, "More exit menus", sub_menu); file_menu->Append(Menu_Quit, "E&xit");
wxMenu *log_menu = new wxMenu; wxMenu *log_menu = new wxMenu;
log_menu->Append(Menu_Clear, "Clear"); log_menu->Append(Menu_Clear, "Clear");
@@ -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, m_ctrlLog = new wxTextCtrl(this, -1, "", pos, size,
wxTE_MULTILINE | wxTE_READONLY | wxTE_MULTILINE | wxTE_READONLY |
wxSUNKEN_BORDER ); 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_pLog = new wxLogTextCtrl(m_ctrlLog);
m_pLogPrev = wxLog::SetActiveTarget(m_pLog); m_pLogPrev = wxLog::SetActiveTarget(m_pLog);
@@ -336,6 +705,13 @@ void DnDFrame::OnClipboardHasBitmap(wxCommandEvent& WXUNUSED(event))
wxTheClipboard->Close(); 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)) void DnDFrame::OnDrag(wxCommandEvent& WXUNUSED(event))
{ {
wxString strText = wxGetTextFromUser wxString strText = wxGetTextFromUser
@@ -398,15 +774,12 @@ void DnDFrame::OnLeftDown(wxMouseEvent &WXUNUSED(event) )
if ( !m_strText.IsEmpty() ) if ( !m_strText.IsEmpty() )
{ {
// start drag operation // start drag operation
#ifdef __WXMSW__
wxTextDataObject textData(m_strText); wxTextDataObject textData(m_strText);
wxDropSource dragSource( textData, this ); wxDropSource source(textData, this, wxICON(mondrian));
#else
wxDropSource dragSource( new wxTextDataObject (m_strText), this, wxIcon(mondrian_xpm) );
#endif
const char *pc; const char *pc;
switch ( dragSource.DoDragDrop(TRUE) ) switch ( source.DoDragDrop(TRUE) )
{ {
case wxDragError: pc = "Error!"; break; case wxDragError: pc = "Error!"; break;
case wxDragNone: pc = "Nothing"; break; case wxDragNone: pc = "Nothing"; break;
@@ -485,11 +858,11 @@ void DnDFrame::OnCopyBitmap(wxCommandEvent& WXUNUSED(event))
); );
if (!image.Ok()) if (!image.Ok())
{ {
wxLogMessage( _T("Invalid image file...") ); wxLogError( _T("Invalid image file...") );
return; return;
} }
wxLogMessage( _T("Decoding image file...") ); wxLogStatus( _T("Decoding image file...") );
wxYield(); wxYield();
wxBitmap bitmap( image.ConvertToBitmap() ); wxBitmap bitmap( image.ConvertToBitmap() );
@@ -628,3 +1001,251 @@ bool DnDFile::OnDropFiles( wxDropPointCoord, wxDropPointCoord, size_t nFiles,
return TRUE; 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;
}

View File

@@ -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<73>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

View File

@@ -1,29 +0,0 @@
Microsoft Developer Studio Workspace File, Format Version 5.00
# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GEL<45>SCHT WERDEN!
###############################################################################
Project: "test"=.\test.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@@ -9,6 +9,14 @@
// Licence: wxWindows licence // Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#ifdef __GNUG__ #ifdef __GNUG__
#pragma implementation "event.h" #pragma implementation "event.h"
#endif #endif
@@ -38,6 +46,10 @@
#include "wx/validate.h" #include "wx/validate.h"
#endif // wxUSE_GUI #endif // wxUSE_GUI
// ----------------------------------------------------------------------------
// wxWin macros
// ----------------------------------------------------------------------------
#if !USE_SHARED_LIBRARY #if !USE_SHARED_LIBRARY
IMPLEMENT_DYNAMIC_CLASS(wxEvtHandler, wxObject) IMPLEMENT_DYNAMIC_CLASS(wxEvtHandler, wxObject)
IMPLEMENT_ABSTRACT_CLASS(wxEvent, wxObject) IMPLEMENT_ABSTRACT_CLASS(wxEvent, wxObject)
@@ -84,12 +96,26 @@
#endif // !USE_SHARED_LIBRARY #endif // !USE_SHARED_LIBRARY
// ----------------------------------------------------------------------------
// global variables
// ----------------------------------------------------------------------------
// To put pending event handlers
wxList *wxPendingEvents = (wxList *)NULL;
#if wxUSE_THREADS #if wxUSE_THREADS
/* To put pending event handlers */ // protects wxPendingEvents list
extern wxList *wxPendingEvents; wxCriticalSection *wxPendingEventsLocker = (wxCriticalSection *)NULL;
extern wxCriticalSection *wxPendingEventsLocker;
#endif #endif
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// wxEvent
// ----------------------------------------------------------------------------
/* /*
* General wxWindows events, covering * General wxWindows events, covering
* all interesting things that might happen (button clicking, resizing, * all interesting things that might happen (button clicking, resizing,
@@ -514,10 +540,10 @@ wxEvtHandler::wxEvtHandler()
m_enabled = TRUE; m_enabled = TRUE;
m_dynamicEvents = (wxList *) NULL; m_dynamicEvents = (wxList *) NULL;
m_isWindow = FALSE; m_isWindow = FALSE;
#if wxUSE_THREADS
m_eventsLocker = new wxCriticalSection();
#endif
m_pendingEvents = (wxList *) NULL; m_pendingEvents = (wxList *) NULL;
#if wxUSE_THREADS
m_eventsLocker = new wxCriticalSection;
#endif
} }
wxEvtHandler::~wxEvtHandler() wxEvtHandler::~wxEvtHandler()
@@ -542,63 +568,76 @@ wxEvtHandler::~wxEvtHandler()
delete m_dynamicEvents; delete m_dynamicEvents;
}; };
#if wxUSE_THREADS
if (m_pendingEvents)
delete m_pendingEvents; delete m_pendingEvents;
#if wxUSE_THREADS
delete m_eventsLocker; delete m_eventsLocker;
#endif #endif
} }
#if wxUSE_THREADS #if wxUSE_THREADS
#ifdef __WXGTK__
extern bool g_isIdle;
extern void wxapp_install_idle_handler();
#endif
bool wxEvtHandler::ProcessThreadEvent(wxEvent& event) bool wxEvtHandler::ProcessThreadEvent(wxEvent& event)
{ {
wxEvent *event_main;
wxCriticalSectionLocker locker(*m_eventsLocker); wxCriticalSectionLocker locker(*m_eventsLocker);
// check that we are really in a child thread // check that we are really in a child thread
wxASSERT( !wxThread::IsMain() ); wxASSERT_MSG( !wxThread::IsMain(),
wxT("use ProcessEvent() in main thread") );
if (m_pendingEvents == NULL) AddPendingEvent(event);
m_pendingEvents = new wxList();
event_main = (wxEvent *)event.Clone(); return TRUE;
}
m_pendingEvents->Append(event_main); #endif // wxUSE_THREADS
void wxEvtHandler::AddPendingEvent(wxEvent& event)
{
if ( !m_pendingEvents )
m_pendingEvents = new wxList;
wxEvent *event2 = (wxEvent *)event.Clone();
m_pendingEvents->Append(event2);
wxPendingEventsLocker->Enter(); wxPendingEventsLocker->Enter();
if ( !wxPendingEvents )
wxPendingEvents = new wxList;
wxPendingEvents->Append(this); wxPendingEvents->Append(this);
wxPendingEventsLocker->Leave(); wxPendingEventsLocker->Leave();
// TODO: Wake up idle handler for the other platforms. // TODO: Wake up idle handler for the other platforms.
#ifdef __WXGTK__ #ifdef __WXGTK__
if (g_isIdle) extern bool g_isIdle;
extern void wxapp_install_idle_handler();
if ( g_isIdle )
wxapp_install_idle_handler(); wxapp_install_idle_handler();
#endif #else // this works for wxMSW, but may be for others too?
// might also send a dummy message to the top level window, this would
return TRUE; // probably be cleaner?
wxIdleEvent eventIdle;
wxTheApp->OnIdle(eventIdle);
#endif // platform
} }
void wxEvtHandler::ProcessPendingEvents() void wxEvtHandler::ProcessPendingEvents()
{ {
#if wxUSE_THREADS
wxCriticalSectionLocker locker(*m_eventsLocker); wxCriticalSectionLocker locker(*m_eventsLocker);
#endif
wxNode *node = m_pendingEvents->First(); wxNode *node = m_pendingEvents->First();
wxEvent *event; wxEvent *event;
while (node != NULL) { while ( node )
{
event = (wxEvent *)node->Data(); event = (wxEvent *)node->Data();
ProcessEvent(*event); ProcessEvent(*event);
delete node; delete node;
node = m_pendingEvents->First(); node = m_pendingEvents->First();
} }
} }
#endif
/* /*
* Event table stuff * Event table stuff
@@ -607,25 +646,24 @@ void wxEvtHandler::ProcessPendingEvents()
bool wxEvtHandler::ProcessEvent(wxEvent& event) bool wxEvtHandler::ProcessEvent(wxEvent& event)
{ {
#if wxUSE_GUI #if wxUSE_GUI
/* check that our flag corresponds to reality */ // check that our flag corresponds to reality
wxASSERT( m_isWindow == IsKindOf(CLASSINFO(wxWindow)) ); wxASSERT( m_isWindow == IsKindOf(CLASSINFO(wxWindow)) );
#endif // wxUSE_GUI #endif // wxUSE_GUI
/* An event handler can be enabled or disabled */ // An event handler can be enabled or disabled
if ( GetEvtHandlerEnabled() ) if ( GetEvtHandlerEnabled() )
{ {
#if wxUSE_THREADS #if wxUSE_THREADS
/* Check whether we are in a child thread. */ // Check whether we are in a child thread.
if (!wxThread::IsMain()) if ( !wxThread::IsMain() )
return ProcessThreadEvent(event); return ProcessThreadEvent(event);
#endif #endif // wxUSE_THREADS
/* Handle per-instance dynamic event tables first */
// Handle per-instance dynamic event tables first
if ( m_dynamicEvents && SearchDynamicEventTable(event) ) if ( m_dynamicEvents && SearchDynamicEventTable(event) )
return TRUE; return TRUE;
/* Then static per-class event tables */ // Then static per-class event tables
const wxEventTable *table = GetEventTable(); const wxEventTable *table = GetEventTable();
#if wxUSE_GUI && wxUSE_VALIDATORS #if wxUSE_GUI && wxUSE_VALIDATORS

View File

@@ -48,10 +48,6 @@
wxApp *wxTheApp = (wxApp *) NULL; wxApp *wxTheApp = (wxApp *) NULL;
wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL; wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL;
#if wxUSE_THREADS
extern wxList *wxPendingEvents;
extern wxCriticalSection *wxPendingEventsLocker;
#endif
extern wxResourceCache *wxTheResourceCache; extern wxResourceCache *wxTheResourceCache;
extern bool g_isIdle; extern bool g_isIdle;
@@ -127,7 +123,7 @@ unsigned char g_palette[64*3] =
// local functions // local functions
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
extern void wxFlushResources(void); extern void wxFlushResources();
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// global functions // global functions
@@ -265,6 +261,7 @@ static gint wxapp_wakeup_timerout_callback( gpointer WXUNUSED(data) )
return TRUE; return TRUE;
} }
#endif // wxUSE_THREADS #endif // wxUSE_THREADS
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -427,11 +424,9 @@ void wxApp::OnIdle( wxIdleEvent &event )
s_inOnIdle = TRUE; s_inOnIdle = TRUE;
#if wxUSE_THREADS
/* Resend in the main thread events which have been prepared in other /* Resend in the main thread events which have been prepared in other
threads */ threads */
ProcessPendingEvents(); ProcessPendingEvents();
#endif
/* 'Garbage' collection of windows deleted with Close(). */ /* 'Garbage' collection of windows deleted with Close(). */
DeletePendingObjects(); DeletePendingObjects();
@@ -520,12 +515,16 @@ void wxApp::Dispatch()
gtk_main_iteration(); gtk_main_iteration();
} }
#if wxUSE_THREADS
void wxApp::ProcessPendingEvents() void wxApp::ProcessPendingEvents()
{ {
wxNode *node = wxPendingEvents->First(); #if wxUSE_THREADS
wxCriticalSectionLocker locker(*wxPendingEventsLocker); wxCriticalSectionLocker locker(*wxPendingEventsLocker);
#endif // wxUSE_THREADS
if ( !wxPendingEvents )
return;
wxNode *node = wxPendingEvents->First();
while (node) while (node)
{ {
wxEvtHandler *handler = (wxEvtHandler *)node->Data(); wxEvtHandler *handler = (wxEvtHandler *)node->Data();
@@ -537,7 +536,6 @@ void wxApp::ProcessPendingEvents()
node = wxPendingEvents->First(); node = wxPendingEvents->First();
} }
} }
#endif // wxUSE_THREADS
void wxApp::DeletePendingObjects() void wxApp::DeletePendingObjects()
{ {

View File

@@ -39,12 +39,6 @@ wxWindowList wxTopLevelWindows;
/* List of windows pending deletion */ /* List of windows pending deletion */
wxList wxPendingDelete; 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 /* Current cursor, in order to hang on to
* cursor handle when setting the cursor globally */ * cursor handle when setting the cursor globally */
wxCursor g_globalCursor; wxCursor g_globalCursor;

View File

@@ -745,7 +745,8 @@ wxDropSource::wxDropSource( wxWindow *win, const wxIcon &go, const wxIcon &stop
if (wxNullIcon == stop) m_stopIcon = wxIcon( gv_xpm ); 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; 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; if (win->m_wxwindow) m_widget = win->m_wxwindow;
m_retValue = wxDragCancel; m_retValue = wxDragCancel;
if (data) m_data = new wxDataBroker;
{ m_data->Add(&data);
m_data = new wxDataBroker();
m_data->Add( data );
}
else
{
m_data = (wxDataBroker*) NULL;
}
m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY ); m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
m_goaheadCursor = wxCursor( wxCURSOR_HAND ); m_goaheadCursor = wxCursor( wxCURSOR_HAND );
@@ -786,6 +780,15 @@ wxDropSource::wxDropSource( wxDataBroker *data, wxWindow *win )
m_goaheadCursor = wxCursor( wxCURSOR_HAND ); 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 ) void wxDropSource::SetData( wxDataObject *data )
{ {
if (m_data) delete m_data; if (m_data) delete m_data;
@@ -808,7 +811,7 @@ void wxDropSource::SetData( wxDataBroker *data )
m_data = data; m_data = data;
} }
wxDropSource::~wxDropSource(void) wxDropSource::~wxDropSource()
{ {
if (m_data) delete m_data; if (m_data) delete m_data;

View File

@@ -48,10 +48,6 @@
wxApp *wxTheApp = (wxApp *) NULL; wxApp *wxTheApp = (wxApp *) NULL;
wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL; wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL;
#if wxUSE_THREADS
extern wxList *wxPendingEvents;
extern wxCriticalSection *wxPendingEventsLocker;
#endif
extern wxResourceCache *wxTheResourceCache; extern wxResourceCache *wxTheResourceCache;
extern bool g_isIdle; extern bool g_isIdle;
@@ -127,7 +123,7 @@ unsigned char g_palette[64*3] =
// local functions // local functions
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
extern void wxFlushResources(void); extern void wxFlushResources();
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// global functions // global functions
@@ -265,6 +261,7 @@ static gint wxapp_wakeup_timerout_callback( gpointer WXUNUSED(data) )
return TRUE; return TRUE;
} }
#endif // wxUSE_THREADS #endif // wxUSE_THREADS
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -427,11 +424,9 @@ void wxApp::OnIdle( wxIdleEvent &event )
s_inOnIdle = TRUE; s_inOnIdle = TRUE;
#if wxUSE_THREADS
/* Resend in the main thread events which have been prepared in other /* Resend in the main thread events which have been prepared in other
threads */ threads */
ProcessPendingEvents(); ProcessPendingEvents();
#endif
/* 'Garbage' collection of windows deleted with Close(). */ /* 'Garbage' collection of windows deleted with Close(). */
DeletePendingObjects(); DeletePendingObjects();
@@ -520,12 +515,16 @@ void wxApp::Dispatch()
gtk_main_iteration(); gtk_main_iteration();
} }
#if wxUSE_THREADS
void wxApp::ProcessPendingEvents() void wxApp::ProcessPendingEvents()
{ {
wxNode *node = wxPendingEvents->First(); #if wxUSE_THREADS
wxCriticalSectionLocker locker(*wxPendingEventsLocker); wxCriticalSectionLocker locker(*wxPendingEventsLocker);
#endif // wxUSE_THREADS
if ( !wxPendingEvents )
return;
wxNode *node = wxPendingEvents->First();
while (node) while (node)
{ {
wxEvtHandler *handler = (wxEvtHandler *)node->Data(); wxEvtHandler *handler = (wxEvtHandler *)node->Data();
@@ -537,7 +536,6 @@ void wxApp::ProcessPendingEvents()
node = wxPendingEvents->First(); node = wxPendingEvents->First();
} }
} }
#endif // wxUSE_THREADS
void wxApp::DeletePendingObjects() void wxApp::DeletePendingObjects()
{ {

View File

@@ -39,12 +39,6 @@ wxWindowList wxTopLevelWindows;
/* List of windows pending deletion */ /* List of windows pending deletion */
wxList wxPendingDelete; 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 /* Current cursor, in order to hang on to
* cursor handle when setting the cursor globally */ * cursor handle when setting the cursor globally */
wxCursor g_globalCursor; wxCursor g_globalCursor;

View File

@@ -745,7 +745,8 @@ wxDropSource::wxDropSource( wxWindow *win, const wxIcon &go, const wxIcon &stop
if (wxNullIcon == stop) m_stopIcon = wxIcon( gv_xpm ); 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; 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; if (win->m_wxwindow) m_widget = win->m_wxwindow;
m_retValue = wxDragCancel; m_retValue = wxDragCancel;
if (data) m_data = new wxDataBroker;
{ m_data->Add(&data);
m_data = new wxDataBroker();
m_data->Add( data );
}
else
{
m_data = (wxDataBroker*) NULL;
}
m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY ); m_defaultCursor = wxCursor( wxCURSOR_NO_ENTRY );
m_goaheadCursor = wxCursor( wxCURSOR_HAND ); m_goaheadCursor = wxCursor( wxCURSOR_HAND );
@@ -786,6 +780,15 @@ wxDropSource::wxDropSource( wxDataBroker *data, wxWindow *win )
m_goaheadCursor = wxCursor( wxCURSOR_HAND ); 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 ) void wxDropSource::SetData( wxDataObject *data )
{ {
if (m_data) delete m_data; if (m_data) delete m_data;
@@ -808,7 +811,7 @@ void wxDropSource::SetData( wxDataBroker *data )
m_data = data; m_data = data;
} }
wxDropSource::~wxDropSource(void) wxDropSource::~wxDropSource()
{ {
if (m_data) delete m_data; if (m_data) delete m_data;

View File

@@ -98,10 +98,6 @@ extern wxChar *wxBuffer;
extern wxChar *wxOsVersion; extern wxChar *wxOsVersion;
extern wxList *wxWinHandleList; extern wxList *wxWinHandleList;
extern wxList WXDLLEXPORT wxPendingDelete; extern wxList WXDLLEXPORT wxPendingDelete;
#if wxUSE_THREADS
extern wxList *wxPendingEvents;
extern wxCriticalSection *wxPendingEventsLocker;
#endif
extern void wxSetKeyboardHook(bool doIt); extern void wxSetKeyboardHook(bool doIt);
extern wxCursor *g_globalCursor; extern wxCursor *g_globalCursor;
@@ -179,11 +175,8 @@ bool wxApp::Initialize()
wxGetResource(wxT("wxWindows"), wxT("OsVersion"), &wxOsVersion); wxGetResource(wxT("wxWindows"), wxT("OsVersion"), &wxOsVersion);
#endif #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 #if wxUSE_THREADS
wxPendingEvents = new wxList(); wxPendingEventsLocker = new wxCriticalSection;
wxPendingEventsLocker = new wxCriticalSection();
#endif #endif
wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING); 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 // 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. // create a module for that as it's part of the core.
#if wxUSE_THREADS
delete wxPendingEvents; delete wxPendingEvents;
#if wxUSE_THREADS
delete wxPendingEventsLocker; delete wxPendingEventsLocker;
// If we don't do the following, we get an apparent memory leak. // If we don't do the following, we get an apparent memory leak.
((wxEvtHandler&) wxDefaultValidator).ClearEventLocker(); ((wxEvtHandler&) wxDefaultValidator).ClearEventLocker();
@@ -931,12 +924,17 @@ bool wxApp::ProcessIdle()
return event.MoreRequested(); return event.MoreRequested();
} }
#if wxUSE_THREADS
void wxApp::ProcessPendingEvents() 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); wxCriticalSectionLocker locker(*wxPendingEventsLocker);
#endif
if ( !wxPendingEvents )
return;
wxNode *node = wxPendingEvents->First();
while (node) while (node)
{ {
wxEvtHandler *handler = (wxEvtHandler *)node->Data(); wxEvtHandler *handler = (wxEvtHandler *)node->Data();
@@ -947,8 +945,6 @@ void wxApp::ProcessPendingEvents()
node = wxPendingEvents->First(); node = wxPendingEvents->First();
} }
} }
#endif
void wxApp::ExitMainLoop() void wxApp::ExitMainLoop()
{ {
@@ -1032,10 +1028,11 @@ void wxApp::OnIdle(wxIdleEvent& event)
event.RequestMore(TRUE); event.RequestMore(TRUE);
} }
// If they are pending events, we must process them. // If they are pending events, we must process them: pending events are
#if wxUSE_THREADS // either events to the threads other than main or events posted with
// wxPostEvent() functions
ProcessPendingEvents(); ProcessPendingEvents();
#endif
s_inOnIdle = FALSE; s_inOnIdle = FALSE;
} }
@@ -1168,22 +1165,19 @@ void wxExit()
// Yield to incoming messages // Yield to incoming messages
bool wxYield() 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; MSG msg;
// We want to go back to the main message loop while ( PeekMessage(&msg, (HWND)0, 0, 0, PM_NOREMOVE) &&
// if we see a WM_QUIT. (?) msg.message != 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
{ {
if ( !wxTheApp->DoMessage() ) if ( !wxTheApp->DoMessage() )
break; break;
} }
// If they are pending events, we must process them. // If they are pending events, we must process them.
#if wxUSE_THREADS
wxTheApp->ProcessPendingEvents(); wxTheApp->ProcessPendingEvents();
#endif
return TRUE; return TRUE;
} }

View File

@@ -142,7 +142,8 @@ bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat)
#if wxUSE_DRAG_AND_DROP #if wxUSE_DRAG_AND_DROP
static bool wxSetClipboardData(wxDataObject *data) 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); HANDLE hGlobal = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, size);
if ( !hGlobal ) if ( !hGlobal )
{ {
@@ -154,11 +155,10 @@ static bool wxSetClipboardData(wxDataObject *data)
LPVOID lpGlobalMemory = ::GlobalLock(hGlobal); LPVOID lpGlobalMemory = ::GlobalLock(hGlobal);
data->GetDataHere(lpGlobalMemory); data->GetDataHere(format, lpGlobalMemory);
GlobalUnlock(hGlobal); GlobalUnlock(hGlobal);
wxDataFormat format = data->GetPreferredFormat();
if ( !::SetClipboardData(format, hGlobal) ) if ( !::SetClipboardData(format, hGlobal) )
{ {
wxLogSysError(_("Failed to set clipboard data in format %s"), wxLogSysError(_("Failed to set clipboard data in format %s"),

View File

@@ -37,12 +37,6 @@ wxWindowList wxTopLevelWindows;
// List of windows pending deletion // List of windows pending deletion
wxList WXDLLEXPORT wxPendingDelete; 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 // Current cursor, in order to hang on to
// cursor handle when setting the cursor globally // cursor handle when setting the cursor globally
wxCursor *g_globalCursor = NULL; wxCursor *g_globalCursor = NULL;

View File

@@ -54,15 +54,19 @@
// functions // functions
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
static const char *GetTymedName(DWORD tymed); #ifdef __WXDEBUG__
static const char *GetTymedName(DWORD tymed);
#endif // Debug
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxIEnumFORMATETC interface implementation // wxIEnumFORMATETC interface implementation
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
class wxIEnumFORMATETC : public IEnumFORMATETC class wxIEnumFORMATETC : public IEnumFORMATETC
{ {
public: public:
wxIEnumFORMATETC(CLIPFORMAT cf); wxIEnumFORMATETC(const wxDataFormat* formats, ULONG nCount);
~wxIEnumFORMATETC() { delete [] m_formats; }
DECLARE_IUNKNOWN_METHODS; DECLARE_IUNKNOWN_METHODS;
@@ -73,13 +77,15 @@ public:
STDMETHODIMP Clone(IEnumFORMATETC **ppenum); STDMETHODIMP Clone(IEnumFORMATETC **ppenum);
private: private:
FORMATETC m_format; // (unique @@@) format we can provide data in CLIPFORMAT *m_formats; // formats we can provide data in
ULONG m_nCurrent; // current enum position (currently either 0 or 1) ULONG m_nCount, // number of formats we support
m_nCurrent; // current enum position
}; };
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxIDataObject implementation of IDataObject interface // wxIDataObject implementation of IDataObject interface
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
class wxIDataObject : public IDataObject class wxIDataObject : public IDataObject
{ {
public: public:
@@ -150,49 +156,63 @@ END_IID_TABLE;
IMPLEMENT_IUNKNOWN_METHODS(wxIEnumFORMATETC) 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_cRef = 0;
m_nCurrent = 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, STDMETHODIMP wxIEnumFORMATETC::Next(ULONG celt,
FORMATETC *rgelt, FORMATETC *rgelt,
ULONG *pceltFetched) ULONG *pceltFetched)
{ {
wxLogTrace(wxT("wxIEnumFORMATETC::Next")); wxLogTrace(wxTRACE_OleCalls, wxT("wxIEnumFORMATETC::Next"));
if ( celt > 1 ) 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; return S_FALSE;
}
if ( m_nCurrent == 0 ) { if ( m_nCurrent < m_nCount ) {
*rgelt = m_format; FORMATETC format;
m_nCurrent++; 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; return S_OK;
} }
else else {
// bad index
return S_FALSE; return S_FALSE;
}
} }
STDMETHODIMP wxIEnumFORMATETC::Skip(ULONG celt) STDMETHODIMP wxIEnumFORMATETC::Skip(ULONG celt)
{ {
wxLogTrace(wxT("wxIEnumFORMATETC::Skip")); wxLogTrace(wxTRACE_OleCalls, wxT("wxIEnumFORMATETC::Skip"));
if ( m_nCurrent == 0 ) m_nCurrent += celt;
m_nCurrent++; if ( m_nCurrent < m_nCount )
return S_OK;
// no, can't skip this many elements
m_nCurrent -= celt;
return S_FALSE; return S_FALSE;
} }
STDMETHODIMP wxIEnumFORMATETC::Reset() STDMETHODIMP wxIEnumFORMATETC::Reset()
{ {
wxLogTrace(wxT("wxIEnumFORMATETC::Reset")); wxLogTrace(wxTRACE_OleCalls, wxT("wxIEnumFORMATETC::Reset"));
m_nCurrent = 0; m_nCurrent = 0;
@@ -201,9 +221,15 @@ STDMETHODIMP wxIEnumFORMATETC::Reset()
STDMETHODIMP wxIEnumFORMATETC::Clone(IEnumFORMATETC **ppenum) STDMETHODIMP wxIEnumFORMATETC::Clone(IEnumFORMATETC **ppenum)
{ {
wxLogTrace(wxT("wxIEnumFORMATETC::Clone")); wxLogTrace(wxTRACE_OleCalls, wxT("wxIEnumFORMATETC::Clone"));
wxIEnumFORMATETC *pNew = new wxIEnumFORMATETC(m_format.cfFormat); // 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(); pNew->AddRef();
*ppenum = pNew; *ppenum = pNew;
@@ -230,16 +256,38 @@ wxIDataObject::wxIDataObject(wxDataObject *pDataObject)
// get data functions // get data functions
STDMETHODIMP wxIDataObject::GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium) STDMETHODIMP wxIDataObject::GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
{ {
wxLogTrace(wxT("wxIDataObject::GetData")); wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::GetData"));
// is data is in our format? // is data is in our format?
HRESULT hr = QueryGetData(pformatetcIn); HRESULT hr = QueryGetData(pformatetcIn);
if ( FAILED(hr) ) if ( FAILED(hr) )
return hr; return hr;
// for the bitmaps and metafiles we use the handles instead of global memory
// to pass the data
wxDataFormat format = (wxDataFormatId)pformatetcIn->cfFormat;
switch ( format )
{
case wxDF_BITMAP:
pmedium->tymed = TYMED_GDI;
break;
case wxDF_METAFILE:
pmedium->tymed = TYMED_MFPICT;
break;
default:
// alloc memory // alloc memory
HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, size_t size = m_pDataObject->GetDataSize(format);
m_pDataObject->GetDataSize()); 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 ) { if ( hGlobal == NULL ) {
wxLogLastError("GlobalAlloc"); wxLogLastError("GlobalAlloc");
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
@@ -248,11 +296,18 @@ STDMETHODIMP wxIDataObject::GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
// copy data // copy data
pmedium->tymed = TYMED_HGLOBAL; pmedium->tymed = TYMED_HGLOBAL;
pmedium->hGlobal = hGlobal; pmedium->hGlobal = hGlobal;
}
pmedium->pUnkForRelease = NULL; pmedium->pUnkForRelease = NULL;
// do copy the data
hr = GetDataHere(pformatetcIn, pmedium); hr = GetDataHere(pformatetcIn, pmedium);
if ( FAILED(hr) ) { if ( FAILED(hr) ) {
GlobalFree(hGlobal); // free resources we allocated
if ( pmedium->tymed == TYMED_HGLOBAL ) {
GlobalFree(pmedium->hGlobal);
}
return hr; return hr;
} }
@@ -262,12 +317,23 @@ STDMETHODIMP wxIDataObject::GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
STDMETHODIMP wxIDataObject::GetDataHere(FORMATETC *pformatetc, STDMETHODIMP wxIDataObject::GetDataHere(FORMATETC *pformatetc,
STGMEDIUM *pmedium) STGMEDIUM *pmedium)
{ {
wxLogTrace(wxT("wxIDataObject::GetDataHere")); wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::GetDataHere"));
// put data in caller provided medium // put data in caller provided medium
if ( pmedium->tymed != TYMED_HGLOBAL ) switch ( pmedium->tymed )
return DV_E_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 // copy data
void *pBuf = GlobalLock(pmedium->hGlobal); void *pBuf = GlobalLock(pmedium->hGlobal);
if ( pBuf == NULL ) { if ( pBuf == NULL ) {
@@ -275,9 +341,16 @@ STDMETHODIMP wxIDataObject::GetDataHere(FORMATETC *pformatetc,
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
} }
m_pDataObject->GetDataHere(pBuf); wxDataFormat format = (wxDataFormatId)pformatetc->cfFormat;
m_pDataObject->GetDataHere(format, pBuf);
GlobalUnlock(pmedium->hGlobal); GlobalUnlock(pmedium->hGlobal);
}
break;
default:
return DV_E_TYMED;
}
return S_OK; return S_OK;
} }
@@ -287,7 +360,8 @@ STDMETHODIMP wxIDataObject::SetData(FORMATETC *pformatetc,
STGMEDIUM *pmedium, STGMEDIUM *pmedium,
BOOL fRelease) BOOL fRelease)
{ {
wxLogTrace(wxT("wxIDataObject::SetData")); wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::SetData"));
return E_NOTIMPL; return E_NOTIMPL;
} }
@@ -296,39 +370,53 @@ STDMETHODIMP wxIDataObject::QueryGetData(FORMATETC *pformatetc)
{ {
// do we accept data in this format? // do we accept data in this format?
if ( pformatetc == NULL ) { if ( pformatetc == NULL ) {
wxLogTrace(wxT("wxIDataObject::QueryGetData: invalid ptr.")); wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::QueryGetData: invalid ptr."));
return E_INVALIDARG; return E_INVALIDARG;
} }
// the only one allowed by current COM implementation // the only one allowed by current COM implementation
if ( pformatetc->lindex != -1 ) { if ( pformatetc->lindex != -1 ) {
wxLogTrace(wxT("wxIDataObject::QueryGetData: bad lindex %d"), wxLogTrace(wxTRACE_OleCalls,
wxT("wxIDataObject::QueryGetData: bad lindex %d"),
pformatetc->lindex); pformatetc->lindex);
return DV_E_LINDEX; return DV_E_LINDEX;
} }
// we don't support anything other (THUMBNAIL, ICON, DOCPRINT...) // we don't support anything other (THUMBNAIL, ICON, DOCPRINT...)
if ( pformatetc->dwAspect != DVASPECT_CONTENT ) { if ( pformatetc->dwAspect != DVASPECT_CONTENT ) {
wxLogTrace(wxT("wxIDataObject::QueryGetData: bad dwAspect %d"), wxLogTrace(wxTRACE_OleCalls,
wxT("wxIDataObject::QueryGetData: bad dwAspect %d"),
pformatetc->dwAspect); pformatetc->dwAspect);
return DV_E_DVASPECT; return DV_E_DVASPECT;
} }
// @@ we only transfer data by global memory (bad for large amounts of it!) // we only transfer data by global memory, except for some particular cases
if ( !(pformatetc->tymed & TYMED_HGLOBAL) ) { wxDataFormat format = (wxDataFormatId)pformatetc->cfFormat;
wxLogTrace(wxT("wxIDataObject::QueryGetData: %s != TYMED_HGLOBAL."), DWORD tymed = pformatetc->tymed;
GetTymedName(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; return DV_E_TYMED;
} }
// and now check the type of data requested // and now check the type of data requested
if ( m_pDataObject->IsSupportedFormat((wxDataFormatId)pformatetc->cfFormat) ) { if ( m_pDataObject->IsSupportedFormat(format) ) {
wxLogTrace(wxT("wxIDataObject::QueryGetData: %s ok"), #ifdef __WXDEBUG__
wxDataObject::GetFormatName((wxDataFormatId)pformatetc->cfFormat)); wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::QueryGetData: %s ok"),
wxDataObject::GetFormatName(format));
#endif // Debug
return S_OK; return S_OK;
} }
else { else {
wxLogTrace(wxT("wxIDataObject::QueryGetData: %s unsupported"), wxLogTrace(wxTRACE_OleCalls,
wxT("wxIDataObject::QueryGetData: %s unsupported"),
wxDataObject::GetFormatName((wxDataFormatId)pformatetc->cfFormat)); wxDataObject::GetFormatName((wxDataFormatId)pformatetc->cfFormat));
return DV_E_FORMATETC; return DV_E_FORMATETC;
} }
@@ -337,29 +425,46 @@ STDMETHODIMP wxIDataObject::QueryGetData(FORMATETC *pformatetc)
STDMETHODIMP wxIDataObject::GetCanonicalFormatEtc(FORMATETC *pFormatetcIn, STDMETHODIMP wxIDataObject::GetCanonicalFormatEtc(FORMATETC *pFormatetcIn,
FORMATETC *pFormatetcOut) FORMATETC *pFormatetcOut)
{ {
wxLogTrace(wxT("wxIDataObject::GetCanonicalFormatEtc")); wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::GetCanonicalFormatEtc"));
// @@ implementation is trivial, we might want something better here // TODO we might want something better than this trivial implementation here
if ( pFormatetcOut != NULL ) if ( pFormatetcOut != NULL )
pFormatetcOut->ptd = NULL; pFormatetcOut->ptd = NULL;
return DATA_S_SAMEFORMATETC; return DATA_S_SAMEFORMATETC;
} }
STDMETHODIMP wxIDataObject::EnumFormatEtc(DWORD dwDirection, STDMETHODIMP wxIDataObject::EnumFormatEtc(DWORD dwDirection,
IEnumFORMATETC **ppenumFormatEtc) IEnumFORMATETC **ppenumFormatEtc)
{ {
wxLogTrace(wxT("wxIDataObject::EnumFormatEtc")); wxLogTrace(wxTRACE_OleCalls, wxT("wxIDataObject::EnumFormatEtc"));
if ( dwDirection == DATADIR_SET ) { if ( dwDirection == DATADIR_SET ) {
// we don't allow setting of data anyhow // we don't allow setting of data anyhow
return E_NOTIMPL; return E_NOTIMPL;
} }
wxIEnumFORMATETC *pEnum = size_t nFormatCount = m_pDataObject->GetFormatCount();
new wxIEnumFORMATETC(m_pDataObject->GetPreferredFormat()); 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(); pEnum->AddRef();
*ppenumFormatEtc = pEnum; *ppenumFormatEtc = pEnum;
if ( formats != &format ) {
delete [] formats;
}
return S_OK; return S_OK;
} }
@@ -397,9 +502,32 @@ wxDataObject::~wxDataObject()
m_pIDataObject->Release(); m_pIDataObject->Release();
} }
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) const char *wxDataObject::GetFormatName(wxDataFormat format)
{ {
#ifdef __WXDEBUG__
// case 'xxx' is not a valid value for switch of enum 'wxDataFormat' // case 'xxx' is not a valid value for switch of enum 'wxDataFormat'
#ifdef __VISUALC__ #ifdef __VISUALC__
#pragma warning(disable:4063) #pragma warning(disable:4063)
@@ -431,11 +559,8 @@ const char *wxDataObject::GetFormatName(wxDataFormat format)
#ifdef __VISUALC__ #ifdef __VISUALC__
#pragma warning(default:4063) #pragma warning(default:4063)
#endif // VC++ #endif // VC++
#else // !Debug
return "";
#endif // Debug
} }
#endif // Debug
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxPrivateDataObject // wxPrivateDataObject
@@ -478,9 +603,34 @@ void wxPrivateDataObject::WriteData( const void *data, void *dest ) const
memcpy( dest, data, GetSize() ); 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 // private functions
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#ifdef __WXDEBUG__
static const char *GetTymedName(DWORD tymed) static const char *GetTymedName(DWORD tymed)
{ {
static char s_szBuf[128]; 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 #endif

View File

@@ -160,13 +160,18 @@ void wxDropSource::Init()
m_pIDropSource->AddRef(); m_pIDropSource->AddRef();
} }
wxDropSource::wxDropSource(wxWindow* WXUNUSED(win)) wxDropSource::wxDropSource(wxWindow* WXUNUSED(win),
const wxIcon & WXUNUSED(go),
const wxIcon & WXUNUSED(stop))
{ {
Init(); Init();
m_pData = NULL; 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(); Init();
SetData(data); SetData(data);