1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Drag and drop sample
4 // Author: Vadim Zeitlin
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #include "wx/wxprec.h"
22 #if !wxUSE_DRAG_AND_DROP
23 #error This sample requires drag and drop support in the library
26 // under Windows we also support data transfer of metafiles as an extra bonus,
27 // but they're not available under other platforms
32 #define USE_RESOURCES 0
35 #define USE_RESOURCES 0
42 #include "wx/dirdlg.h"
43 #include "wx/filedlg.h"
45 #include "wx/clipbrd.h"
46 #include "wx/colordlg.h"
48 #include "wx/resource.h"
54 #include "wx/metafile.h"
57 #if defined(__WXGTK__) || defined(__WXX11__) || defined(__WXMOTIF__) || defined(__WXMAC__)
58 #include "mondrian.xpm"
60 #include "dnd_copy.xpm"
61 #include "dnd_move.xpm"
62 #include "dnd_none.xpm"
65 // ----------------------------------------------------------------------------
66 // Derive two simple classes which just put in the listbox the strings (text or
67 // file names) we drop on them
68 // ----------------------------------------------------------------------------
70 class DnDText
: public wxTextDropTarget
73 DnDText(wxListBox
*pOwner
) { m_pOwner
= pOwner
; }
75 virtual bool OnDropText(wxCoord x
, wxCoord y
, const wxString
& text
);
81 class DnDFile
: public wxFileDropTarget
84 DnDFile(wxListBox
*pOwner
) { m_pOwner
= pOwner
; }
86 virtual bool OnDropFiles(wxCoord x
, wxCoord y
,
87 const wxArrayString
& filenames
);
93 // ----------------------------------------------------------------------------
94 // Define a custom dtop target accepting URLs
95 // ----------------------------------------------------------------------------
97 class URLDropTarget
: public wxDropTarget
100 URLDropTarget() { SetDataObject(new wxURLDataObject
); }
102 void OnDropURL(wxCoord x
, wxCoord y
, const wxString
& text
)
104 // of course, a real program would do something more useful here...
105 wxMessageBox(text
, _T("wxDnD sample: got URL"),
106 wxICON_INFORMATION
| wxOK
);
109 // URLs can't be moved, only copied
110 virtual wxDragResult
OnDragOver(wxCoord
WXUNUSED(x
), wxCoord
WXUNUSED(y
),
113 return wxDragLink
; // At least IE 5.x needs wxDragLink, the
114 // other browsers on MSW seem okay with it too.
117 // translate this to calls to OnDropURL() just for convenience
118 virtual wxDragResult
OnData(wxCoord x
, wxCoord y
, wxDragResult def
)
123 OnDropURL(x
, y
, ((wxURLDataObject
*)m_dataObject
)->GetURL());
129 // ----------------------------------------------------------------------------
130 // Define a new application type
131 // ----------------------------------------------------------------------------
133 class DnDApp
: public wxApp
136 virtual bool OnInit();
139 IMPLEMENT_APP(DnDApp
);
141 // ----------------------------------------------------------------------------
142 // Define canvas class to show a bitmap
143 // ----------------------------------------------------------------------------
145 class DnDCanvasBitmap
: public wxScrolledWindow
148 DnDCanvasBitmap(wxWindow
*parent
) : wxScrolledWindow(parent
) { }
150 void SetBitmap(const wxBitmap
& bitmap
)
154 SetScrollbars(10, 10,
155 m_bitmap
.GetWidth() / 10, m_bitmap
.GetHeight() / 10);
160 void OnPaint(wxPaintEvent
& event
)
168 dc
.DrawBitmap(m_bitmap
, 0, 0);
175 DECLARE_EVENT_TABLE()
180 // and the same thing fo metafiles
181 class DnDCanvasMetafile
: public wxScrolledWindow
184 DnDCanvasMetafile(wxWindow
*parent
) : wxScrolledWindow(parent
) { }
186 void SetMetafile(const wxMetafile
& metafile
)
188 m_metafile
= metafile
;
190 SetScrollbars(10, 10,
191 m_metafile
.GetWidth() / 10, m_metafile
.GetHeight() / 10);
196 void OnPaint(wxPaintEvent
& event
)
200 if ( m_metafile
.Ok() )
204 m_metafile
.Play(&dc
);
209 wxMetafile m_metafile
;
211 DECLARE_EVENT_TABLE()
214 #endif // USE_METAFILES
216 // ----------------------------------------------------------------------------
217 // Define a new frame type for the main frame
218 // ----------------------------------------------------------------------------
220 class DnDFrame
: public wxFrame
223 DnDFrame(wxFrame
*frame
, char *title
, int x
, int y
, int w
, int h
);
226 void OnPaint(wxPaintEvent
& event
);
227 void OnSize(wxSizeEvent
& event
);
228 void OnQuit (wxCommandEvent
& event
);
229 void OnAbout(wxCommandEvent
& event
);
230 void OnDrag (wxCommandEvent
& event
);
231 void OnNewFrame(wxCommandEvent
& event
);
232 void OnHelp (wxCommandEvent
& event
);
233 void OnLogClear(wxCommandEvent
& event
);
235 void OnCopy(wxCommandEvent
& event
);
236 void OnPaste(wxCommandEvent
& event
);
238 void OnCopyBitmap(wxCommandEvent
& event
);
239 void OnPasteBitmap(wxCommandEvent
& event
);
242 void OnPasteMetafile(wxCommandEvent
& event
);
243 #endif // USE_METAFILES
245 void OnCopyFiles(wxCommandEvent
& event
);
247 void OnLeftDown(wxMouseEvent
& event
);
248 void OnRightDown(wxMouseEvent
& event
);
250 void OnUpdateUIPasteText(wxUpdateUIEvent
& event
);
251 void OnUpdateUIPasteBitmap(wxUpdateUIEvent
& event
);
253 DECLARE_EVENT_TABLE()
256 wxListBox
*m_ctrlFile
,
258 wxTextCtrl
*m_ctrlLog
;
266 // ----------------------------------------------------------------------------
267 // A shape is an example of application-specific data which may be transported
268 // via drag-and-drop or clipboard: in our case, we have different geometric
269 // shapes, each one with its own colour and position
270 // ----------------------------------------------------------------------------
283 DnDShape(const wxPoint
& pos
,
286 : m_pos(pos
), m_size(size
), m_col(col
)
290 // this is for debugging - lets us see when exactly an object is freed
291 // (this may be later than you think if it's on the clipboard, for example)
292 virtual ~DnDShape() { }
294 // the functions used for drag-and-drop: they dump and restore a shape into
295 // some bitwise-copiable data (might use streams too...)
296 // ------------------------------------------------------------------------
298 // restore from buffer
299 static DnDShape
*New(const void *buf
);
301 virtual size_t GetDataSize() const
303 return sizeof(ShapeDump
);
306 virtual void GetDataHere(void *buf
) const
308 ShapeDump
& dump
= *(ShapeDump
*)buf
;
313 dump
.r
= m_col
.Red();
314 dump
.g
= m_col
.Green();
315 dump
.b
= m_col
.Blue();
320 const wxPoint
& GetPosition() const { return m_pos
; }
321 const wxColour
& GetColour() const { return m_col
; }
322 const wxSize
& GetSize() const { return m_size
; }
324 void Move(const wxPoint
& pos
) { m_pos
= pos
; }
326 // to implement in derived classes
327 virtual Kind
GetKind() const = 0;
329 virtual void Draw(wxDC
& dc
)
331 dc
.SetPen(wxPen(m_col
, 1, wxSOLID
));
335 //get a point 1 up and 1 left, otherwise the mid-point of a triangle is on the line
336 wxPoint
GetCentre() const
337 { return wxPoint(m_pos
.x
+ m_size
.x
/ 2 - 1, m_pos
.y
+ m_size
.y
/ 2 - 1); }
341 int x
, y
, // position
352 class DnDTriangularShape
: public DnDShape
355 DnDTriangularShape(const wxPoint
& pos
,
358 : DnDShape(pos
, size
, col
)
360 wxLogMessage(wxT("DnDTriangularShape is being created"));
363 virtual ~DnDTriangularShape()
365 wxLogMessage(wxT("DnDTriangularShape is being deleted"));
368 virtual Kind
GetKind() const { return Triangle
; }
369 virtual void Draw(wxDC
& dc
)
373 // well, it's a bit difficult to describe a triangle by position and
374 // size, but we're not doing geometry here, do we? ;-)
376 wxPoint
p2(m_pos
.x
+ m_size
.x
, m_pos
.y
);
377 wxPoint
p3(m_pos
.x
, m_pos
.y
+ m_size
.y
);
383 //works in multicolor modes; on GTK (at least) will fail in 16-bit color
384 dc
.SetBrush(wxBrush(m_col
, wxSOLID
));
385 dc
.FloodFill(GetCentre(), m_col
, wxFLOOD_BORDER
);
389 class DnDRectangularShape
: public DnDShape
392 DnDRectangularShape(const wxPoint
& pos
,
395 : DnDShape(pos
, size
, col
)
397 wxLogMessage(wxT("DnDRectangularShape is being created"));
400 virtual ~DnDRectangularShape()
402 wxLogMessage(wxT("DnDRectangularShape is being deleted"));
405 virtual Kind
GetKind() const { return Rectangle
; }
406 virtual void Draw(wxDC
& dc
)
411 wxPoint
p2(p1
.x
+ m_size
.x
, p1
.y
);
412 wxPoint
p3(p2
.x
, p2
.y
+ m_size
.y
);
413 wxPoint
p4(p1
.x
, p3
.y
);
420 dc
.SetBrush(wxBrush(m_col
, wxSOLID
));
421 dc
.FloodFill(GetCentre(), m_col
, wxFLOOD_BORDER
);
425 class DnDEllipticShape
: public DnDShape
428 DnDEllipticShape(const wxPoint
& pos
,
431 : DnDShape(pos
, size
, col
)
433 wxLogMessage(wxT("DnDEllipticShape is being created"));
436 virtual ~DnDEllipticShape()
438 wxLogMessage(wxT("DnDEllipticShape is being deleted"));
441 virtual Kind
GetKind() const { return Ellipse
; }
442 virtual void Draw(wxDC
& dc
)
446 dc
.DrawEllipse(m_pos
, m_size
);
448 dc
.SetBrush(wxBrush(m_col
, wxSOLID
));
449 dc
.FloodFill(GetCentre(), m_col
, wxFLOOD_BORDER
);
453 // ----------------------------------------------------------------------------
454 // A wxDataObject specialisation for the application-specific data
455 // ----------------------------------------------------------------------------
457 static const wxChar
*shapeFormatId
= wxT("wxShape");
459 class DnDShapeDataObject
: public wxDataObject
462 // ctor doesn't copy the pointer, so it shouldn't go away while this object
464 DnDShapeDataObject(DnDShape
*shape
= (DnDShape
*)NULL
)
468 // we need to copy the shape because the one we're handled may be
469 // deleted while it's still on the clipboard (for example) - and we
470 // reuse the serialisation methods here to copy it
471 void *buf
= malloc(shape
->DnDShape::GetDataSize());
472 shape
->GetDataHere(buf
);
473 m_shape
= DnDShape::New(buf
);
483 // this string should uniquely identify our format, but is otherwise
485 m_formatShape
.SetId(shapeFormatId
);
487 // we don't draw the shape to a bitmap until it's really needed (i.e.
488 // we're asked to do so)
491 m_hasMetaFile
= FALSE
;
495 virtual ~DnDShapeDataObject() { delete m_shape
; }
497 // after a call to this function, the shape is owned by the caller and it
498 // is responsible for deleting it!
500 // NB: a better solution would be to make DnDShapes ref counted and this
501 // is what should probably be done in a real life program, otherwise
502 // the ownership problems become too complicated really fast
505 DnDShape
*shape
= m_shape
;
507 m_shape
= (DnDShape
*)NULL
;
510 m_hasMetaFile
= FALSE
;
516 // implement base class pure virtuals
517 // ----------------------------------
519 virtual wxDataFormat
GetPreferredFormat(Direction
WXUNUSED(dir
)) const
521 return m_formatShape
;
524 virtual size_t GetFormatCount(Direction dir
) const
526 // our custom format is supported by both GetData() and SetData()
530 // but the bitmap format(s) are only supported for output
531 nFormats
+= m_dobjBitmap
.GetFormatCount(dir
);
534 nFormats
+= m_dobjMetaFile
.GetFormatCount(dir
);
541 virtual void GetAllFormats(wxDataFormat
*formats
, Direction dir
) const
543 formats
[0] = m_formatShape
;
546 // in Get direction we additionally support bitmaps and metafiles
548 m_dobjBitmap
.GetAllFormats(&formats
[1], dir
);
551 // don't assume that m_dobjBitmap has only 1 format
552 m_dobjMetaFile
.GetAllFormats(&formats
[1 +
553 m_dobjBitmap
.GetFormatCount(dir
)], dir
);
558 virtual size_t GetDataSize(const wxDataFormat
& format
) const
560 if ( format
== m_formatShape
)
562 return m_shape
->GetDataSize();
565 else if ( m_dobjMetaFile
.IsSupported(format
) )
567 if ( !m_hasMetaFile
)
570 return m_dobjMetaFile
.GetDataSize(format
);
575 wxASSERT_MSG( m_dobjBitmap
.IsSupported(format
),
576 wxT("unexpected format") );
581 return m_dobjBitmap
.GetDataSize();
585 virtual bool GetDataHere(const wxDataFormat
& format
, void *pBuf
) const
587 if ( format
== m_formatShape
)
589 m_shape
->GetDataHere(pBuf
);
594 else if ( m_dobjMetaFile
.IsSupported(format
) )
596 if ( !m_hasMetaFile
)
599 return m_dobjMetaFile
.GetDataHere(format
, pBuf
);
604 wxASSERT_MSG( m_dobjBitmap
.IsSupported(format
),
605 wxT("unexpected format") );
610 return m_dobjBitmap
.GetDataHere(pBuf
);
614 virtual bool SetData(const wxDataFormat
& format
,
615 size_t len
, const void *buf
)
617 wxCHECK_MSG( format
== m_formatShape
, FALSE
,
618 wxT( "unsupported format") );
621 m_shape
= DnDShape::New(buf
);
623 // the shape has changed
627 m_hasMetaFile
= FALSE
;
634 // creates a bitmap and assigns it to m_dobjBitmap (also sets m_hasBitmap)
635 void CreateBitmap() const;
637 void CreateMetaFile() const;
640 wxDataFormat m_formatShape
; // our custom format
642 wxBitmapDataObject m_dobjBitmap
; // it handles bitmaps
643 bool m_hasBitmap
; // true if m_dobjBitmap has valid bitmap
646 wxMetaFileDataObject m_dobjMetaFile
;// handles metafiles
647 bool m_hasMetaFile
; // true if we have valid metafile
650 DnDShape
*m_shape
; // our data
653 // ----------------------------------------------------------------------------
654 // A dialog to edit shape properties
655 // ----------------------------------------------------------------------------
657 class DnDShapeDialog
: public wxDialog
660 DnDShapeDialog(wxFrame
*parent
, DnDShape
*shape
);
662 DnDShape
*GetShape() const;
664 virtual bool TransferDataToWindow();
665 virtual bool TransferDataFromWindow();
667 void OnColour(wxCommandEvent
& event
);
674 DnDShape::Kind m_shapeKind
;
686 DECLARE_EVENT_TABLE()
689 // ----------------------------------------------------------------------------
690 // A frame for the shapes which can be drag-and-dropped between frames
691 // ----------------------------------------------------------------------------
693 class DnDShapeFrame
: public wxFrame
696 DnDShapeFrame(wxFrame
*parent
);
699 void SetShape(DnDShape
*shape
);
702 void OnNewShape(wxCommandEvent
& event
);
703 void OnEditShape(wxCommandEvent
& event
);
704 void OnClearShape(wxCommandEvent
& event
);
706 void OnCopyShape(wxCommandEvent
& event
);
707 void OnPasteShape(wxCommandEvent
& event
);
709 void OnUpdateUICopy(wxUpdateUIEvent
& event
);
710 void OnUpdateUIPaste(wxUpdateUIEvent
& event
);
712 void OnDrag(wxMouseEvent
& event
);
713 void OnPaint(wxPaintEvent
& event
);
714 void OnDrop(wxCoord x
, wxCoord y
, DnDShape
*shape
);
719 static DnDShapeFrame
*ms_lastDropTarget
;
721 DECLARE_EVENT_TABLE()
724 // ----------------------------------------------------------------------------
725 // wxDropTarget derivation for DnDShapes
726 // ----------------------------------------------------------------------------
728 class DnDShapeDropTarget
: public wxDropTarget
731 DnDShapeDropTarget(DnDShapeFrame
*frame
)
732 : wxDropTarget(new DnDShapeDataObject
)
737 // override base class (pure) virtuals
738 virtual wxDragResult
OnEnter(wxCoord x
, wxCoord y
, wxDragResult def
)
739 { m_frame
->SetStatusText("Mouse entered the frame"); return OnDragOver(x
, y
, def
); }
740 virtual void OnLeave()
741 { m_frame
->SetStatusText("Mouse left the frame"); }
742 virtual wxDragResult
OnData(wxCoord x
, wxCoord y
, wxDragResult def
)
746 wxLogError(wxT("Failed to get drag and drop data"));
751 m_frame
->OnDrop(x
, y
,
752 ((DnDShapeDataObject
*)GetDataObject())->GetShape());
758 DnDShapeFrame
*m_frame
;
761 // ----------------------------------------------------------------------------
762 // functions prototypes
763 // ----------------------------------------------------------------------------
765 static void ShowBitmap(const wxBitmap
& bitmap
);
768 static void ShowMetaFile(const wxMetaFile
& metafile
);
769 #endif // USE_METAFILES
771 // ----------------------------------------------------------------------------
772 // IDs for the menu commands
773 // ----------------------------------------------------------------------------
789 Menu_Shape_New
= 500,
792 Menu_ShapeClipboard_Copy
,
793 Menu_ShapeClipboard_Paste
,
797 BEGIN_EVENT_TABLE(DnDFrame
, wxFrame
)
798 EVT_MENU(Menu_Quit
, DnDFrame::OnQuit
)
799 EVT_MENU(Menu_About
, DnDFrame::OnAbout
)
800 EVT_MENU(Menu_Drag
, DnDFrame::OnDrag
)
801 EVT_MENU(Menu_NewFrame
, DnDFrame::OnNewFrame
)
802 EVT_MENU(Menu_Help
, DnDFrame::OnHelp
)
803 EVT_MENU(Menu_Clear
, DnDFrame::OnLogClear
)
804 EVT_MENU(Menu_Copy
, DnDFrame::OnCopy
)
805 EVT_MENU(Menu_Paste
, DnDFrame::OnPaste
)
806 EVT_MENU(Menu_CopyBitmap
, DnDFrame::OnCopyBitmap
)
807 EVT_MENU(Menu_PasteBitmap
,DnDFrame::OnPasteBitmap
)
809 EVT_MENU(Menu_PasteMFile
, DnDFrame::OnPasteMetafile
)
810 #endif // USE_METAFILES
811 EVT_MENU(Menu_CopyFiles
, DnDFrame::OnCopyFiles
)
813 EVT_UPDATE_UI(Menu_Paste
, DnDFrame::OnUpdateUIPasteText
)
814 EVT_UPDATE_UI(Menu_PasteBitmap
, DnDFrame::OnUpdateUIPasteBitmap
)
816 EVT_LEFT_DOWN( DnDFrame::OnLeftDown
)
817 EVT_RIGHT_DOWN( DnDFrame::OnRightDown
)
818 EVT_PAINT( DnDFrame::OnPaint
)
819 EVT_SIZE( DnDFrame::OnSize
)
822 BEGIN_EVENT_TABLE(DnDShapeFrame
, wxFrame
)
823 EVT_MENU(Menu_Shape_New
, DnDShapeFrame::OnNewShape
)
824 EVT_MENU(Menu_Shape_Edit
, DnDShapeFrame::OnEditShape
)
825 EVT_MENU(Menu_Shape_Clear
, DnDShapeFrame::OnClearShape
)
827 EVT_MENU(Menu_ShapeClipboard_Copy
, DnDShapeFrame::OnCopyShape
)
828 EVT_MENU(Menu_ShapeClipboard_Paste
, DnDShapeFrame::OnPasteShape
)
830 EVT_UPDATE_UI(Menu_ShapeClipboard_Copy
, DnDShapeFrame::OnUpdateUICopy
)
831 EVT_UPDATE_UI(Menu_ShapeClipboard_Paste
, DnDShapeFrame::OnUpdateUIPaste
)
833 EVT_LEFT_DOWN(DnDShapeFrame::OnDrag
)
835 EVT_PAINT(DnDShapeFrame::OnPaint
)
838 BEGIN_EVENT_TABLE(DnDShapeDialog
, wxDialog
)
839 EVT_BUTTON(Button_Colour
, DnDShapeDialog::OnColour
)
842 BEGIN_EVENT_TABLE(DnDCanvasBitmap
, wxScrolledWindow
)
843 EVT_PAINT(DnDCanvasBitmap::OnPaint
)
847 BEGIN_EVENT_TABLE(DnDCanvasMetafile
, wxScrolledWindow
)
848 EVT_PAINT(DnDCanvasMetafile::OnPaint
)
850 #endif // USE_METAFILES
852 // ============================================================================
854 // ============================================================================
856 // `Main program' equivalent, creating windows and returning main app frame
857 bool DnDApp::OnInit()
860 // load our ressources
864 pathList
.Add("./Debug");
865 pathList
.Add("./Release");
868 wxString path
= pathList
.FindValidPath("dnd.wxr");
871 wxLogError(wxT("Can't find the resource file dnd.wxr in the current ")
872 wxT("directory, aborting."));
877 wxDefaultResourceTable
->ParseResourceFile(path
);
880 // switch on trace messages
881 #if defined(__WXGTK__)
882 wxLog::AddTraceMask(_T("clipboard"));
883 #elif defined(__WXMSW__)
884 wxLog::AddTraceMask(wxTRACE_OleCalls
);
888 wxImage::AddHandler( new wxPNGHandler
);
891 // under X we usually want to use the primary selection by default (which
892 // is shared with other apps)
893 wxTheClipboard
->UsePrimarySelection();
895 // create the main frame window
896 DnDFrame
*frame
= new DnDFrame((wxFrame
*) NULL
,
897 "Drag-and-Drop/Clipboard wxWindows Sample",
908 DnDFrame::DnDFrame(wxFrame
*frame
, char *title
, int x
, int y
, int w
, int h
)
909 : wxFrame(frame
, -1, title
, wxPoint(x
, y
), wxSize(w
, h
)),
910 m_strText("wxWindows drag & drop works :-)")
913 // frame icon and status bar
914 SetIcon(wxICON(mondrian
));
919 wxMenu
*file_menu
= new wxMenu
;
920 file_menu
->Append(Menu_Drag
, "&Test drag...");
921 file_menu
->AppendSeparator();
922 file_menu
->Append(Menu_NewFrame
, "&New frame\tCtrl-N");
923 file_menu
->AppendSeparator();
924 file_menu
->Append(Menu_Quit
, "E&xit");
926 wxMenu
*log_menu
= new wxMenu
;
927 log_menu
->Append(Menu_Clear
, "Clear\tCtrl-L");
929 wxMenu
*help_menu
= new wxMenu
;
930 help_menu
->Append(Menu_Help
, "&Help...");
931 help_menu
->AppendSeparator();
932 help_menu
->Append(Menu_About
, "&About");
934 wxMenu
*clip_menu
= new wxMenu
;
935 clip_menu
->Append(Menu_Copy
, "&Copy text\tCtrl-C");
936 clip_menu
->Append(Menu_Paste
, "&Paste text\tCtrl-V");
937 clip_menu
->AppendSeparator();
938 clip_menu
->Append(Menu_CopyBitmap
, "Copy &bitmap\tCtrl-Shift-C");
939 clip_menu
->Append(Menu_PasteBitmap
, "Paste b&itmap\tCtrl-Shift-V");
941 clip_menu
->AppendSeparator();
942 clip_menu
->Append(Menu_PasteMFile
, "Paste &metafile\tCtrl-M");
943 #endif // USE_METAFILES
944 clip_menu
->AppendSeparator();
945 clip_menu
->Append(Menu_CopyFiles
, "Copy &files\tCtrl-F");
947 wxMenuBar
*menu_bar
= new wxMenuBar
;
948 menu_bar
->Append(file_menu
, "&File");
949 menu_bar
->Append(log_menu
, "&Log");
950 menu_bar
->Append(clip_menu
, "&Clipboard");
951 menu_bar
->Append(help_menu
, "&Help");
953 SetMenuBar(menu_bar
);
955 // make a panel with 3 subwindows
957 wxSize
size(400, 200);
959 wxString
strFile("Drop files here!"), strText("Drop text on me");
961 m_ctrlFile
= new wxListBox(this, -1, pos
, size
, 1, &strFile
,
962 wxLB_HSCROLL
| wxLB_ALWAYS_SB
);
963 m_ctrlText
= new wxListBox(this, -1, pos
, size
, 1, &strText
,
964 wxLB_HSCROLL
| wxLB_ALWAYS_SB
);
966 m_ctrlLog
= new wxTextCtrl(this, -1, "", pos
, size
,
967 wxTE_MULTILINE
| wxTE_READONLY
|
970 // redirect log messages to the text window
971 m_pLog
= new wxLogTextCtrl(m_ctrlLog
);
972 m_pLogPrev
= wxLog::SetActiveTarget(m_pLog
);
974 // associate drop targets with the controls
975 m_ctrlFile
->SetDropTarget(new DnDFile(m_ctrlFile
));
976 m_ctrlText
->SetDropTarget(new DnDText(m_ctrlText
));
977 m_ctrlLog
->SetDropTarget(new URLDropTarget
);
979 wxLayoutConstraints
*c
;
982 c
= new wxLayoutConstraints
;
983 c
->left
.SameAs(this, wxLeft
);
984 c
->top
.SameAs(this, wxTop
);
985 c
->right
.PercentOf(this, wxRight
, 50);
986 c
->height
.PercentOf(this, wxHeight
, 30);
987 m_ctrlFile
->SetConstraints(c
);
990 c
= new wxLayoutConstraints
;
991 c
->left
.SameAs (m_ctrlFile
, wxRight
);
992 c
->top
.SameAs (this, wxTop
);
993 c
->right
.SameAs (this, wxRight
);
994 c
->height
.PercentOf(this, wxHeight
, 30);
995 m_ctrlText
->SetConstraints(c
);
997 // Lower text control
998 c
= new wxLayoutConstraints
;
999 c
->left
.SameAs (this, wxLeft
);
1000 c
->right
.SameAs (this, wxRight
);
1001 c
->height
.PercentOf(this, wxHeight
, 50);
1002 c
->top
.SameAs(m_ctrlText
, wxBottom
);
1003 m_ctrlLog
->SetConstraints(c
);
1005 SetAutoLayout(TRUE
);
1008 void DnDFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
1013 void DnDFrame::OnSize(wxSizeEvent
& event
)
1020 void DnDFrame::OnPaint(wxPaintEvent
& WXUNUSED(event
))
1024 GetClientSize( &w
, &h
);
1028 dc
.SetFont( wxFont( 24, wxDECORATIVE
, wxNORMAL
, wxNORMAL
, FALSE
, "charter" ) );
1029 dc
.DrawText( "Drag text from here!", 100, h
-50 );
1032 void DnDFrame::OnUpdateUIPasteText(wxUpdateUIEvent
& event
)
1035 // too many trace messages if we don't do it - this function is called
1040 event
.Enable( wxTheClipboard
->IsSupported(wxDF_TEXT
) );
1043 void DnDFrame::OnUpdateUIPasteBitmap(wxUpdateUIEvent
& event
)
1046 // too many trace messages if we don't do it - this function is called
1051 event
.Enable( wxTheClipboard
->IsSupported(wxDF_BITMAP
) );
1054 void DnDFrame::OnNewFrame(wxCommandEvent
& WXUNUSED(event
))
1056 (new DnDShapeFrame(this))->Show(TRUE
);
1058 wxLogStatus(this, wxT("Double click the new frame to select a shape for it"));
1061 void DnDFrame::OnDrag(wxCommandEvent
& WXUNUSED(event
))
1063 wxString strText
= wxGetTextFromUser
1065 "After you enter text in this dialog, press any mouse\n"
1066 "button in the bottom (empty) part of the frame and \n"
1067 "drag it anywhere - you will be in fact dragging the\n"
1068 "text object containing this text",
1069 "Please enter some text", m_strText
, this
1072 m_strText
= strText
;
1075 void DnDFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
1077 wxMessageBox("Drag-&-Drop Demo\n"
1078 "Please see \"Help|Help...\" for details\n"
1079 "Copyright (c) 1998 Vadim Zeitlin",
1081 wxICON_INFORMATION
| wxOK
,
1085 void DnDFrame::OnHelp(wxCommandEvent
& /* event */)
1087 wxMessageDialog
dialog(this,
1088 "This small program demonstrates drag & drop support in wxWindows. The program window\n"
1089 "consists of 3 parts: the bottom pane is for debug messages, so that you can see what's\n"
1090 "going on inside. The top part is split into 2 listboxes, the left one accepts files\n"
1091 "and the right one accepts text.\n"
1093 "To test wxDropTarget: open wordpad (write.exe), select some text in it and drag it to\n"
1094 "the right listbox (you'll notice the usual visual feedback, i.e. the cursor will change).\n"
1095 "Also, try dragging some files (you can select several at once) from Windows Explorer (or \n"
1096 "File Manager) to the left pane. Hold down Ctrl/Shift keys when you drop text (doesn't \n"
1097 "work with files) and see what changes.\n"
1099 "To test wxDropSource: just press any mouse button on the empty zone of the window and drag\n"
1100 "it to wordpad or any other droptarget accepting text (and of course you can just drag it\n"
1101 "to the right pane). Due to a lot of trace messages, the cursor might take some time to \n"
1102 "change, don't release the mouse button until it does. You can change the string being\n"
1103 "dragged in in \"File|Test drag...\" dialog.\n"
1106 "Please send all questions/bug reports/suggestions &c to \n"
1107 "Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>",
1113 void DnDFrame::OnLogClear(wxCommandEvent
& /* event */ )
1116 m_ctrlText
->Clear();
1117 m_ctrlFile
->Clear();
1120 void DnDFrame::OnLeftDown(wxMouseEvent
&WXUNUSED(event
) )
1122 if ( !m_strText
.IsEmpty() )
1124 // start drag operation
1125 wxTextDataObject
textData(m_strText
);
1127 wxFileDataObject textData;
1128 textData.AddFile( "/file1.txt" );
1129 textData.AddFile( "/file2.txt" );
1131 wxDropSource
source(textData
, this,
1132 wxDROP_ICON(dnd_copy
),
1133 wxDROP_ICON(dnd_move
),
1134 wxDROP_ICON(dnd_none
));
1138 switch ( source
.DoDragDrop(TRUE
) )
1140 case wxDragError
: pc
= "Error!"; break;
1141 case wxDragNone
: pc
= "Nothing"; break;
1142 case wxDragCopy
: pc
= "Copied"; break;
1143 case wxDragMove
: pc
= "Moved"; break;
1144 case wxDragCancel
: pc
= "Cancelled"; break;
1145 default: pc
= "Huh?"; break;
1148 SetStatusText(wxString("Drag result: ") + pc
);
1152 void DnDFrame::OnRightDown(wxMouseEvent
&event
)
1154 wxMenu
menu("Dnd sample menu");
1156 menu
.Append(Menu_Drag
, "&Test drag...");
1157 menu
.AppendSeparator();
1158 menu
.Append(Menu_About
, "&About");
1160 PopupMenu( &menu
, event
.GetX(), event
.GetY() );
1163 DnDFrame::~DnDFrame()
1165 if ( m_pLog
!= NULL
) {
1166 if ( wxLog::SetActiveTarget(m_pLogPrev
) == m_pLog
)
1171 // ---------------------------------------------------------------------------
1173 // ---------------------------------------------------------------------------
1175 void DnDFrame::OnCopyBitmap(wxCommandEvent
& WXUNUSED(event
))
1177 // PNG support is not always compiled in under Windows, so use BMP there
1179 wxFileDialog
dialog(this, "Open a BMP file", "", "", "BMP files (*.bmp)|*.bmp", 0);
1181 wxFileDialog
dialog(this, "Open a PNG file", "", "", "PNG files (*.png)|*.png", 0);
1184 if (dialog
.ShowModal() != wxID_OK
)
1186 wxLogMessage( _T("Aborted file open") );
1190 if (dialog
.GetPath().IsEmpty())
1192 wxLogMessage( _T("Returned empty string.") );
1196 if (!wxFileExists(dialog
.GetPath()))
1198 wxLogMessage( _T("File doesn't exist.") );
1203 image
.LoadFile( dialog
.GetPath(),
1212 wxLogError( _T("Invalid image file...") );
1216 wxLogStatus( _T("Decoding image file...") );
1219 wxBitmap
bitmap( image
);
1221 if ( !wxTheClipboard
->Open() )
1223 wxLogError(_T("Can't open clipboard."));
1228 wxLogMessage( _T("Creating wxBitmapDataObject...") );
1231 if ( !wxTheClipboard
->AddData(new wxBitmapDataObject(bitmap
)) )
1233 wxLogError(_T("Can't copy image to the clipboard."));
1237 wxLogMessage(_T("Image has been put on the clipboard.") );
1238 wxLogMessage(_T("You can paste it now and look at it.") );
1241 wxTheClipboard
->Close();
1244 void DnDFrame::OnPasteBitmap(wxCommandEvent
& WXUNUSED(event
))
1246 if ( !wxTheClipboard
->Open() )
1248 wxLogError(_T("Can't open clipboard."));
1253 if ( !wxTheClipboard
->IsSupported(wxDF_BITMAP
) )
1255 wxLogWarning(_T("No bitmap on clipboard"));
1257 wxTheClipboard
->Close();
1261 wxBitmapDataObject data
;
1262 if ( !wxTheClipboard
->GetData(data
) )
1264 wxLogError(_T("Can't paste bitmap from the clipboard"));
1268 const wxBitmap
& bmp
= data
.GetBitmap();
1270 wxLogMessage(_T("Bitmap %dx%d pasted from the clipboard"),
1271 bmp
.GetWidth(), bmp
.GetHeight());
1275 wxTheClipboard
->Close();
1278 #ifdef USE_METAFILES
1280 void DnDFrame::OnPasteMetafile(wxCommandEvent
& WXUNUSED(event
))
1282 if ( !wxTheClipboard
->Open() )
1284 wxLogError(_T("Can't open clipboard."));
1289 if ( !wxTheClipboard
->IsSupported(wxDF_METAFILE
) )
1291 wxLogWarning(_T("No metafile on clipboard"));
1295 wxMetaFileDataObject data
;
1296 if ( !wxTheClipboard
->GetData(data
) )
1298 wxLogError(_T("Can't paste metafile from the clipboard"));
1302 const wxMetaFile
& mf
= data
.GetMetafile();
1304 wxLogMessage(_T("Metafile %dx%d pasted from the clipboard"),
1305 mf
.GetWidth(), mf
.GetHeight());
1311 wxTheClipboard
->Close();
1314 #endif // USE_METAFILES
1316 // ----------------------------------------------------------------------------
1318 // ----------------------------------------------------------------------------
1320 void DnDFrame::OnCopyFiles(wxCommandEvent
& WXUNUSED(event
))
1323 wxFileDialog
dialog(this, "Select a file to copy", "", "",
1324 "All files (*.*)|*.*", 0);
1326 wxArrayString filenames
;
1327 while ( dialog
.ShowModal() == wxID_OK
)
1329 filenames
.Add(dialog
.GetPath());
1332 if ( !filenames
.IsEmpty() )
1334 wxFileDataObject
*dobj
= new wxFileDataObject
;
1335 size_t count
= filenames
.GetCount();
1336 for ( size_t n
= 0; n
< count
; n
++ )
1338 dobj
->AddFile(filenames
[n
]);
1341 wxClipboardLocker locker
;
1344 wxLogError(wxT("Can't open clipboard"));
1348 if ( !wxTheClipboard
->AddData(dobj
) )
1350 wxLogError(wxT("Can't copy file(s) to the clipboard"));
1354 wxLogStatus(this, wxT("%d file%s copied to the clipboard"),
1355 count
, count
== 1 ? wxT("") : wxT("s"));
1361 wxLogStatus(this, wxT("Aborted"));
1364 wxLogError(wxT("Sorry, not implemented"));
1368 // ---------------------------------------------------------------------------
1370 // ---------------------------------------------------------------------------
1372 void DnDFrame::OnCopy(wxCommandEvent
& WXUNUSED(event
))
1374 if ( !wxTheClipboard
->Open() )
1376 wxLogError(_T("Can't open clipboard."));
1381 if ( !wxTheClipboard
->AddData(new wxTextDataObject(m_strText
)) )
1383 wxLogError(_T("Can't copy data to the clipboard"));
1387 wxLogMessage(_T("Text '%s' put on the clipboard"), m_strText
.c_str());
1390 wxTheClipboard
->Close();
1393 void DnDFrame::OnPaste(wxCommandEvent
& WXUNUSED(event
))
1395 if ( !wxTheClipboard
->Open() )
1397 wxLogError(_T("Can't open clipboard."));
1402 if ( !wxTheClipboard
->IsSupported(wxDF_TEXT
) )
1404 wxLogWarning(_T("No text data on clipboard"));
1406 wxTheClipboard
->Close();
1410 wxTextDataObject text
;
1411 if ( !wxTheClipboard
->GetData(text
) )
1413 wxLogError(_T("Can't paste data from the clipboard"));
1417 wxLogMessage(_T("Text '%s' pasted from the clipboard"),
1418 text
.GetText().c_str());
1421 wxTheClipboard
->Close();
1424 // ----------------------------------------------------------------------------
1425 // Notifications called by the base class
1426 // ----------------------------------------------------------------------------
1428 bool DnDText::OnDropText(wxCoord
, wxCoord
, const wxString
& text
)
1430 m_pOwner
->Append(text
);
1435 bool DnDFile::OnDropFiles(wxCoord
, wxCoord
, const wxArrayString
& filenames
)
1437 size_t nFiles
= filenames
.GetCount();
1439 str
.Printf( _T("%d files dropped"), nFiles
);
1440 m_pOwner
->Append(str
);
1441 for ( size_t n
= 0; n
< nFiles
; n
++ ) {
1442 m_pOwner
->Append(filenames
[n
]);
1448 // ----------------------------------------------------------------------------
1450 // ----------------------------------------------------------------------------
1452 DnDShapeDialog::DnDShapeDialog(wxFrame
*parent
, DnDShape
*shape
)
1454 :wxDialog( parent
, 6001, wxT("Choose Shape"), wxPoint( 10, 10 ),
1456 wxRAISED_BORDER
|wxCAPTION
|wxTHICK_FRAME
|wxSYSTEM_MENU
)
1461 LoadFromResource(parent
, "dialogShape");
1463 m_textX
= (wxTextCtrl
*)wxFindWindowByName("textX", this);
1464 m_textY
= (wxTextCtrl
*)wxFindWindowByName("textY", this);
1465 m_textW
= (wxTextCtrl
*)wxFindWindowByName("textW", this);
1466 m_textH
= (wxTextCtrl
*)wxFindWindowByName("textH", this);
1468 m_radio
= (wxRadioBox
*)wxFindWindowByName("radio", this);
1470 wxBoxSizer
* topSizer
= new wxBoxSizer( wxVERTICAL
);
1473 wxBoxSizer
* shapesSizer
= new wxBoxSizer( wxHORIZONTAL
);
1474 const wxString choices
[] = { wxT("None"), wxT("Triangle"),
1475 wxT("Rectangle"), wxT("Ellipse") };
1477 m_radio
= new wxRadioBox( this, -1, wxT("&Shape"),
1478 wxDefaultPosition
, wxDefaultSize
, 4, choices
, 4,
1479 wxRA_SPECIFY_COLS
);
1480 shapesSizer
->Add( m_radio
, 0, wxGROW
|wxALL
, 5 );
1481 topSizer
->Add( shapesSizer
, 0, wxALL
, 2 );
1484 wxStaticBox
* box
= new wxStaticBox( this, -1, wxT("&Attributes") );
1485 wxStaticBoxSizer
* attrSizer
= new wxStaticBoxSizer( box
, wxHORIZONTAL
);
1486 wxFlexGridSizer
* xywhSizer
= new wxFlexGridSizer( 4, 2 );
1490 st
= new wxStaticText( this, -1, wxT("Position &X:") );
1491 m_textX
= new wxTextCtrl( this, -1, wxEmptyString
, wxDefaultPosition
,
1493 xywhSizer
->Add( st
, 1, wxGROW
|wxALL
, 2 );
1494 xywhSizer
->Add( m_textX
, 1, wxGROW
|wxALL
, 2 );
1496 st
= new wxStaticText( this, -1, wxT("Size &width:") );
1497 m_textW
= new wxTextCtrl( this, -1, wxEmptyString
, wxDefaultPosition
,
1499 xywhSizer
->Add( st
, 1, wxGROW
|wxALL
, 2 );
1500 xywhSizer
->Add( m_textW
, 1, wxGROW
|wxALL
, 2 );
1502 st
= new wxStaticText( this, -1, wxT("&Y:") );
1503 m_textY
= new wxTextCtrl( this, -1, wxEmptyString
, wxDefaultPosition
,
1505 xywhSizer
->Add( st
, 1, wxALL
|wxALIGN_RIGHT
, 2 );
1506 xywhSizer
->Add( m_textY
, 1, wxGROW
|wxALL
, 2 );
1508 st
= new wxStaticText( this, -1, wxT("&height:") );
1509 m_textH
= new wxTextCtrl( this, -1, wxEmptyString
, wxDefaultPosition
,
1511 xywhSizer
->Add( st
, 1, wxALL
|wxALIGN_RIGHT
, 2 );
1512 xywhSizer
->Add( m_textH
, 1, wxGROW
|wxALL
, 2 );
1514 wxButton
* col
= new wxButton( this, Button_Colour
, wxT("&Colour...") );
1515 attrSizer
->Add( xywhSizer
, 1, wxGROW
);
1516 attrSizer
->Add( col
, 0, wxALL
|wxALIGN_CENTRE_VERTICAL
, 2 );
1517 topSizer
->Add( attrSizer
, 0, wxGROW
|wxALL
, 5 );
1520 wxBoxSizer
* buttonSizer
= new wxBoxSizer( wxHORIZONTAL
);
1522 bt
= new wxButton( this, wxID_OK
, wxT("Ok") );
1523 buttonSizer
->Add( bt
, 0, wxALL
, 2 );
1524 bt
= new wxButton( this, wxID_CANCEL
, wxT("Cancel") );
1525 buttonSizer
->Add( bt
, 0, wxALL
, 2 );
1526 topSizer
->Add( buttonSizer
, 0, wxALL
|wxALIGN_RIGHT
, 2 );
1528 SetAutoLayout( TRUE
);
1529 SetSizer( topSizer
);
1530 topSizer
->Fit( this );
1534 DnDShape
*DnDShapeDialog::GetShape() const
1536 switch ( m_shapeKind
)
1539 case DnDShape::None
: return NULL
;
1540 case DnDShape::Triangle
: return new DnDTriangularShape(m_pos
, m_size
, m_col
);
1541 case DnDShape::Rectangle
: return new DnDRectangularShape(m_pos
, m_size
, m_col
);
1542 case DnDShape::Ellipse
: return new DnDEllipticShape(m_pos
, m_size
, m_col
);
1546 bool DnDShapeDialog::TransferDataToWindow()
1551 m_radio
->SetSelection(m_shape
->GetKind());
1552 m_pos
= m_shape
->GetPosition();
1553 m_size
= m_shape
->GetSize();
1554 m_col
= m_shape
->GetColour();
1558 m_radio
->SetSelection(DnDShape::None
);
1559 m_pos
= wxPoint(1, 1);
1560 m_size
= wxSize(100, 100);
1563 m_textX
->SetValue(wxString() << m_pos
.x
);
1564 m_textY
->SetValue(wxString() << m_pos
.y
);
1565 m_textW
->SetValue(wxString() << m_size
.x
);
1566 m_textH
->SetValue(wxString() << m_size
.y
);
1571 bool DnDShapeDialog::TransferDataFromWindow()
1573 m_shapeKind
= (DnDShape::Kind
)m_radio
->GetSelection();
1575 m_pos
.x
= wxAtoi(m_textX
->GetValue());
1576 m_pos
.y
= wxAtoi(m_textY
->GetValue());
1577 m_size
.x
= wxAtoi(m_textW
->GetValue());
1578 m_size
.y
= wxAtoi(m_textH
->GetValue());
1580 if ( !m_pos
.x
|| !m_pos
.y
|| !m_size
.x
|| !m_size
.y
)
1582 wxMessageBox("All sizes and positions should be non null!",
1583 "Invalid shape", wxICON_HAND
| wxOK
, this);
1591 void DnDShapeDialog::OnColour(wxCommandEvent
& WXUNUSED(event
))
1594 data
.SetChooseFull(TRUE
);
1595 for (int i
= 0; i
< 16; i
++)
1597 wxColour
colour(i
*16, i
*16, i
*16);
1598 data
.SetCustomColour(i
, colour
);
1601 wxColourDialog
dialog(this, &data
);
1602 if ( dialog
.ShowModal() == wxID_OK
)
1604 m_col
= dialog
.GetColourData().GetColour();
1608 // ----------------------------------------------------------------------------
1610 // ----------------------------------------------------------------------------
1612 DnDShapeFrame
*DnDShapeFrame::ms_lastDropTarget
= NULL
;
1614 DnDShapeFrame::DnDShapeFrame(wxFrame
*parent
)
1615 : wxFrame(parent
, -1, "Shape Frame",
1616 wxDefaultPosition
, wxSize(250, 150))
1620 wxMenu
*menuShape
= new wxMenu
;
1621 menuShape
->Append(Menu_Shape_New
, "&New default shape\tCtrl-S");
1622 menuShape
->Append(Menu_Shape_Edit
, "&Edit shape\tCtrl-E");
1623 menuShape
->AppendSeparator();
1624 menuShape
->Append(Menu_Shape_Clear
, "&Clear shape\tCtrl-L");
1626 wxMenu
*menuClipboard
= new wxMenu
;
1627 menuClipboard
->Append(Menu_ShapeClipboard_Copy
, "&Copy\tCtrl-C");
1628 menuClipboard
->Append(Menu_ShapeClipboard_Paste
, "&Paste\tCtrl-V");
1630 wxMenuBar
*menubar
= new wxMenuBar
;
1631 menubar
->Append(menuShape
, "&Shape");
1632 menubar
->Append(menuClipboard
, "&Clipboard");
1634 SetMenuBar(menubar
);
1636 SetStatusText("Press Ctrl-S to create a new shape");
1638 SetDropTarget(new DnDShapeDropTarget(this));
1642 SetBackgroundColour(*wxWHITE
);
1645 DnDShapeFrame::~DnDShapeFrame()
1651 void DnDShapeFrame::SetShape(DnDShape
*shape
)
1660 void DnDShapeFrame::OnDrag(wxMouseEvent
& event
)
1669 // start drag operation
1670 DnDShapeDataObject
shapeData(m_shape
);
1671 wxDropSource
source(shapeData
, this);
1673 const char *pc
= NULL
;
1674 switch ( source
.DoDragDrop(TRUE
) )
1678 wxLogError(wxT("An error occured during drag and drop operation"));
1682 SetStatusText("Nothing happened");
1691 if ( ms_lastDropTarget
!= this )
1693 // don't delete the shape if we dropped it on ourselves!
1699 SetStatusText("Drag and drop operation cancelled");
1705 SetStatusText(wxString("Shape successfully ") + pc
);
1707 //else: status text already set
1710 void DnDShapeFrame::OnDrop(wxCoord x
, wxCoord y
, DnDShape
*shape
)
1712 ms_lastDropTarget
= this;
1717 s
.Printf(wxT("Shape dropped at (%ld, %ld)"), pt
.x
, pt
.y
);
1724 void DnDShapeFrame::OnEditShape(wxCommandEvent
& event
)
1726 DnDShapeDialog
dlg(this, m_shape
);
1727 if ( dlg
.ShowModal() == wxID_OK
)
1729 SetShape(dlg
.GetShape());
1733 SetStatusText("You can now drag the shape to another frame");
1738 void DnDShapeFrame::OnNewShape(wxCommandEvent
& event
)
1740 SetShape(new DnDEllipticShape(wxPoint(10, 10), wxSize(80, 60), *wxRED
));
1742 SetStatusText("You can now drag the shape to another frame");
1745 void DnDShapeFrame::OnClearShape(wxCommandEvent
& event
)
1750 void DnDShapeFrame::OnCopyShape(wxCommandEvent
& event
)
1754 wxClipboardLocker clipLocker
;
1757 wxLogError(wxT("Can't open the clipboard"));
1762 wxTheClipboard
->AddData(new DnDShapeDataObject(m_shape
));
1766 void DnDShapeFrame::OnPasteShape(wxCommandEvent
& event
)
1768 wxClipboardLocker clipLocker
;
1771 wxLogError(wxT("Can't open the clipboard"));
1776 DnDShapeDataObject
shapeDataObject(NULL
);
1777 if ( wxTheClipboard
->GetData(shapeDataObject
) )
1779 SetShape(shapeDataObject
.GetShape());
1783 wxLogStatus(wxT("No shape on the clipboard"));
1787 void DnDShapeFrame::OnUpdateUICopy(wxUpdateUIEvent
& event
)
1789 event
.Enable( m_shape
!= NULL
);
1792 void DnDShapeFrame::OnUpdateUIPaste(wxUpdateUIEvent
& event
)
1794 event
.Enable( wxTheClipboard
->IsSupported(wxDataFormat(shapeFormatId
)) );
1797 void DnDShapeFrame::OnPaint(wxPaintEvent
& event
)
1811 // ----------------------------------------------------------------------------
1813 // ----------------------------------------------------------------------------
1815 DnDShape
*DnDShape::New(const void *buf
)
1817 const ShapeDump
& dump
= *(const ShapeDump
*)buf
;
1821 return new DnDTriangularShape(wxPoint(dump
.x
, dump
.y
),
1822 wxSize(dump
.w
, dump
.h
),
1823 wxColour(dump
.r
, dump
.g
, dump
.b
));
1826 return new DnDRectangularShape(wxPoint(dump
.x
, dump
.y
),
1827 wxSize(dump
.w
, dump
.h
),
1828 wxColour(dump
.r
, dump
.g
, dump
.b
));
1831 return new DnDEllipticShape(wxPoint(dump
.x
, dump
.y
),
1832 wxSize(dump
.w
, dump
.h
),
1833 wxColour(dump
.r
, dump
.g
, dump
.b
));
1836 wxFAIL_MSG(wxT("invalid shape!"));
1841 // ----------------------------------------------------------------------------
1842 // DnDShapeDataObject
1843 // ----------------------------------------------------------------------------
1845 #ifdef USE_METAFILES
1847 void DnDShapeDataObject::CreateMetaFile() const
1849 wxPoint pos
= m_shape
->GetPosition();
1850 wxSize size
= m_shape
->GetSize();
1852 wxMetaFileDC
dcMF(wxEmptyString
, pos
.x
+ size
.x
, pos
.y
+ size
.y
);
1854 m_shape
->Draw(dcMF
);
1856 wxMetafile
*mf
= dcMF
.Close();
1858 DnDShapeDataObject
*self
= (DnDShapeDataObject
*)this; // const_cast
1859 self
->m_dobjMetaFile
.SetMetafile(*mf
);
1860 self
->m_hasMetaFile
= TRUE
;
1867 void DnDShapeDataObject::CreateBitmap() const
1869 wxPoint pos
= m_shape
->GetPosition();
1870 wxSize size
= m_shape
->GetSize();
1871 int x
= pos
.x
+ size
.x
,
1873 wxBitmap
bitmap(x
, y
);
1875 dc
.SelectObject(bitmap
);
1876 dc
.SetBrush(wxBrush(wxT("white"), wxSOLID
));
1879 dc
.SelectObject(wxNullBitmap
);
1881 DnDShapeDataObject
*self
= (DnDShapeDataObject
*)this; // const_cast
1882 self
->m_dobjBitmap
.SetBitmap(bitmap
);
1883 self
->m_hasBitmap
= TRUE
;
1886 // ----------------------------------------------------------------------------
1888 // ----------------------------------------------------------------------------
1890 static void ShowBitmap(const wxBitmap
& bitmap
)
1892 wxFrame
*frame
= new wxFrame(NULL
, -1, _T("Bitmap view"));
1893 frame
->CreateStatusBar();
1894 DnDCanvasBitmap
*canvas
= new DnDCanvasBitmap(frame
);
1895 canvas
->SetBitmap(bitmap
);
1897 int w
= bitmap
.GetWidth(),
1898 h
= bitmap
.GetHeight();
1899 frame
->SetStatusText(wxString::Format(_T("%dx%d"), w
, h
));
1901 frame
->SetClientSize(w
> 100 ? 100 : w
, h
> 100 ? 100 : h
);
1905 #ifdef USE_METAFILES
1907 static void ShowMetaFile(const wxMetaFile
& metafile
)
1909 wxFrame
*frame
= new wxFrame(NULL
, -1, _T("Metafile view"));
1910 frame
->CreateStatusBar();
1911 DnDCanvasMetafile
*canvas
= new DnDCanvasMetafile(frame
);
1912 canvas
->SetMetafile(metafile
);
1914 wxSize size
= metafile
.GetSize();
1915 frame
->SetStatusText(wxString::Format(_T("%dx%d"), size
.x
, size
.y
));
1917 frame
->SetClientSize(size
.x
> 100 ? 100 : size
.x
,
1918 size
.y
> 100 ? 100 : size
.y
);
1922 #endif // USE_METAFILES