+{
+public:
+ DnDFrame(wxFrame *frame, char *title, int x, int y, int w, int h);
+ ~DnDFrame();
+
+ void OnPaint(wxPaintEvent& event);
+ 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);
+ void OnPaste(wxCommandEvent& event);
+
+ void OnCopyBitmap(wxCommandEvent& event);
+ void OnPasteBitmap(wxCommandEvent& event);
+
+#ifdef USE_METAFILES
+ void OnPasteMetafile(wxCommandEvent& event);
+#endif // USE_METAFILES
+
+ void OnCopyFiles(wxCommandEvent& event);
+
+ void OnLeftDown(wxMouseEvent& event);
+ void OnRightDown(wxMouseEvent& event);
+
+ void OnUpdateUIPasteText(wxUpdateUIEvent& event);
+ void OnUpdateUIPasteBitmap(wxUpdateUIEvent& event);
+
+ DECLARE_EVENT_TABLE()
+
+private:
+ wxListBox *m_ctrlFile,
+ *m_ctrlText;
+ wxTextCtrl *m_ctrlLog;
+
+ wxLog *m_pLog,
+ *m_pLogPrev;
+
+ wxString m_strText;
+};
+
+// ----------------------------------------------------------------------------
+// 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)
+ {
+ }
+
+ // this is for debugging - lets us see when exactly an object is freed
+ // (this may be later than you think if it's on the clipboard, for example)
+ virtual ~DnDShape() { }
+
+ // the functions used for drag-and-drop: they dump and restore a shape into
+ // some bitwise-copiable data (might use streams too...)
+ // ------------------------------------------------------------------------
+
+ // 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; }
+
+ void Move(const wxPoint& pos) { m_pos = pos; }
+
+ // to implement in derived classes
+ virtual Kind GetKind() const = 0;
+
+ virtual void Draw(wxDC& dc)
+ {
+ 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)
+ {
+ wxLogMessage("DnDTriangularShape is being created");
+ }
+
+ virtual ~DnDTriangularShape()
+ {
+ wxLogMessage("DnDTriangularShape is being deleted");
+ }
+
+ 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);
+
+#ifdef __WXMSW__
+ dc.FloodFill(GetCentre(), m_col, wxFLOOD_BORDER);
+#endif
+ }
+};
+
+class DnDRectangularShape : public DnDShape
+{
+public:
+ DnDRectangularShape(const wxPoint& pos,
+ const wxSize& size,
+ const wxColour& col)
+ : DnDShape(pos, size, col)
+ {
+ wxLogMessage("DnDRectangularShape is being created");
+ }
+
+ virtual ~DnDRectangularShape()
+ {
+ wxLogMessage("DnDRectangularShape is being deleted");
+ }
+
+ 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);
+
+#ifdef __WXMSW__
+ dc.FloodFill(GetCentre(), m_col, wxFLOOD_BORDER);
+#endif
+ }
+};
+
+class DnDEllipticShape : public DnDShape
+{
+public:
+ DnDEllipticShape(const wxPoint& pos,
+ const wxSize& size,
+ const wxColour& col)
+ : DnDShape(pos, size, col)
+ {
+ wxLogMessage("DnDEllipticShape is being created");
+ }
+
+ virtual ~DnDEllipticShape()
+ {
+ wxLogMessage("DnDEllipticShape is being deleted");
+ }
+
+ virtual Kind GetKind() const { return Ellipse; }
+ virtual void Draw(wxDC& dc)
+ {
+ DnDShape::Draw(dc);
+
+ dc.DrawEllipse(m_pos, m_size);
+
+#ifdef __WXMSW__
+ dc.FloodFill(GetCentre(), m_col, wxFLOOD_BORDER);
+#endif
+ }
+};
+
+// ----------------------------------------------------------------------------
+// A wxDataObject specialisation for the application-specific data
+// ----------------------------------------------------------------------------
+
+static const char *shapeFormatId = "wxShape";
+
+class DnDShapeDataObject : public wxDataObject
+{