1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Drag and drop sample
4 // Author: Vadim Zeitlin
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #include "wx/wxprec.h"
23 #include "wx/dataobj.h"
25 #include "wx/clipbrd.h"
26 #include "wx/colordlg.h"
27 #include "wx/metafile.h"
28 #include "wx/dirctrl.h"
30 #if defined(__WXGTK__) || defined(__WXX11__) || defined(__WXMOTIF__) || defined(__WXMAC__)
31 #include "../sample.xpm"
32 #if wxUSE_DRAG_AND_DROP
33 #include "dnd_copy.xpm"
34 #include "dnd_move.xpm"
35 #include "dnd_none.xpm"
39 #if wxUSE_DRAG_AND_DROP
41 // ----------------------------------------------------------------------------
42 // Derive two simple classes which just put in the listbox the strings (text or
43 // file names) we drop on them
44 // ----------------------------------------------------------------------------
46 class DnDText
: public wxTextDropTarget
49 DnDText(wxListBox
*pOwner
) { m_pOwner
= pOwner
; }
51 virtual bool OnDropText(wxCoord x
, wxCoord y
, const wxString
& text
);
57 class DnDFile
: public wxFileDropTarget
60 DnDFile(wxListBox
*pOwner
= NULL
) { m_pOwner
= pOwner
; }
62 virtual bool OnDropFiles(wxCoord x
, wxCoord y
,
63 const wxArrayString
& filenames
);
69 // ----------------------------------------------------------------------------
70 // Define a custom dtop target accepting URLs
71 // ----------------------------------------------------------------------------
73 class URLDropTarget
: public wxDropTarget
76 URLDropTarget() { SetDataObject(new wxURLDataObject
); }
78 void OnDropURL(wxCoord
WXUNUSED(x
), wxCoord
WXUNUSED(y
), const wxString
& text
)
80 // of course, a real program would do something more useful here...
81 wxMessageBox(text
, wxT("wxDnD sample: got URL"),
82 wxICON_INFORMATION
| wxOK
);
85 // URLs can't be moved, only copied
86 virtual wxDragResult
OnDragOver(wxCoord
WXUNUSED(x
), wxCoord
WXUNUSED(y
),
87 wxDragResult
WXUNUSED(def
))
89 return wxDragLink
; // At least IE 5.x needs wxDragLink, the
90 // other browsers on MSW seem okay with it too.
93 // translate this to calls to OnDropURL() just for convenience
94 virtual wxDragResult
OnData(wxCoord x
, wxCoord y
, wxDragResult def
)
99 OnDropURL(x
, y
, ((wxURLDataObject
*)m_dataObject
)->GetURL());
105 #endif // wxUSE_DRAG_AND_DROP
107 // ----------------------------------------------------------------------------
108 // Define a new application type
109 // ----------------------------------------------------------------------------
111 class DnDApp
: public wxApp
114 virtual bool OnInit();
117 IMPLEMENT_APP(DnDApp
)
119 #if wxUSE_DRAG_AND_DROP || wxUSE_CLIPBOARD
121 // ----------------------------------------------------------------------------
122 // Define canvas class to show a bitmap
123 // ----------------------------------------------------------------------------
125 class DnDCanvasBitmap
: public wxScrolledWindow
128 DnDCanvasBitmap(wxWindow
*parent
) : wxScrolledWindow(parent
) { }
130 void SetBitmap(const wxBitmap
& bitmap
)
134 SetScrollbars(10, 10,
135 m_bitmap
.GetWidth() / 10, m_bitmap
.GetHeight() / 10);
140 void OnPaint(wxPaintEvent
& WXUNUSED(event
))
148 dc
.DrawBitmap(m_bitmap
, 0, 0);
155 DECLARE_EVENT_TABLE()
160 // and the same thing fo metafiles
161 class DnDCanvasMetafile
: public wxScrolledWindow
164 DnDCanvasMetafile(wxWindow
*parent
) : wxScrolledWindow(parent
) { }
166 void SetMetafile(const wxMetafile
& metafile
)
168 m_metafile
= metafile
;
170 SetScrollbars(10, 10,
171 m_metafile
.GetWidth() / 10, m_metafile
.GetHeight() / 10);
176 void OnPaint(wxPaintEvent
&)
180 if ( m_metafile
.Ok() )
184 m_metafile
.Play(&dc
);
189 wxMetafile m_metafile
;
191 DECLARE_EVENT_TABLE()
194 #endif // wxUSE_METAFILE
196 // ----------------------------------------------------------------------------
197 // Define a new frame type for the main frame
198 // ----------------------------------------------------------------------------
200 class DnDFrame
: public wxFrame
206 void OnPaint(wxPaintEvent
& event
);
207 void OnSize(wxSizeEvent
& event
);
208 void OnQuit(wxCommandEvent
& event
);
209 void OnAbout(wxCommandEvent
& event
);
210 void OnDrag(wxCommandEvent
& event
);
211 void OnDragMoveByDefault(wxCommandEvent
& event
);
212 void OnDragMoveAllow(wxCommandEvent
& event
);
213 void OnNewFrame(wxCommandEvent
& event
);
214 void OnHelp (wxCommandEvent
& event
);
216 void OnLogClear(wxCommandEvent
& event
);
219 void OnCopy(wxCommandEvent
& event
);
220 void OnPaste(wxCommandEvent
& event
);
222 void OnCopyBitmap(wxCommandEvent
& event
);
223 void OnPasteBitmap(wxCommandEvent
& event
);
226 void OnPasteMetafile(wxCommandEvent
& event
);
227 #endif // wxUSE_METAFILE
229 void OnCopyFiles(wxCommandEvent
& event
);
231 void OnUsePrimary(wxCommandEvent
& event
);
233 void OnLeftDown(wxMouseEvent
& event
);
234 void OnRightDown(wxMouseEvent
& event
);
236 #if wxUSE_DRAG_AND_DROP
237 void OnBeginDrag(wxTreeEvent
& event
);
238 #endif // wxUSE_DRAG_AND_DROP
240 void OnUpdateUIMoveByDefault(wxUpdateUIEvent
& event
);
242 void OnUpdateUIPasteText(wxUpdateUIEvent
& event
);
243 void OnUpdateUIPasteBitmap(wxUpdateUIEvent
& event
);
246 #if wxUSE_DRAG_AND_DROP
247 // show the result of a dnd operation in the status bar
248 void LogDragResult(wxDragResult result
);
249 #endif // wxUSE_DRAG_AND_DROP
253 wxListBox
*m_ctrlFile
,
255 wxGenericDirCtrl
*m_ctrlDir
;
258 wxTextCtrl
*m_ctrlLog
;
264 // move the text by default (or copy)?
265 bool m_moveByDefault
;
267 // allow moving the text at all?
274 DECLARE_EVENT_TABLE()
277 // ----------------------------------------------------------------------------
278 // A shape is an example of application-specific data which may be transported
279 // via drag-and-drop or clipboard: in our case, we have different geometric
280 // shapes, each one with its own colour and position
281 // ----------------------------------------------------------------------------
283 #if wxUSE_DRAG_AND_DROP
296 DnDShape(const wxPoint
& pos
,
299 : m_pos(pos
), m_size(size
), m_col(col
)
303 // this is for debugging - lets us see when exactly an object is freed
304 // (this may be later than you think if it's on the clipboard, for example)
305 virtual ~DnDShape() { }
307 // the functions used for drag-and-drop: they dump and restore a shape into
308 // some bitwise-copiable data (might use streams too...)
309 // ------------------------------------------------------------------------
311 // restore from buffer
312 static DnDShape
*New(const void *buf
);
314 virtual size_t GetDataSize() const
316 return sizeof(ShapeDump
);
319 virtual void GetDataHere(void *buf
) const
321 ShapeDump
& dump
= *(ShapeDump
*)buf
;
326 dump
.r
= m_col
.Red();
327 dump
.g
= m_col
.Green();
328 dump
.b
= m_col
.Blue();
333 const wxPoint
& GetPosition() const { return m_pos
; }
334 const wxColour
& GetColour() const { return m_col
; }
335 const wxSize
& GetSize() const { return m_size
; }
337 void Move(const wxPoint
& pos
) { m_pos
= pos
; }
339 // to implement in derived classes
340 virtual Kind
GetKind() const = 0;
342 virtual void Draw(wxDC
& dc
)
344 dc
.SetPen(wxPen(m_col
, 1, wxSOLID
));
348 //get a point 1 up and 1 left, otherwise the mid-point of a triangle is on the line
349 wxPoint
GetCentre() const
350 { return wxPoint(m_pos
.x
+ m_size
.x
/ 2 - 1, m_pos
.y
+ m_size
.y
/ 2 - 1); }
354 wxCoord x
, y
, // position
357 unsigned char r
, g
, b
; // colour
365 class DnDTriangularShape
: public DnDShape
368 DnDTriangularShape(const wxPoint
& pos
,
371 : DnDShape(pos
, size
, col
)
373 wxLogMessage(wxT("DnDTriangularShape is being created"));
376 virtual ~DnDTriangularShape()
378 wxLogMessage(wxT("DnDTriangularShape is being deleted"));
381 virtual Kind
GetKind() const { return Triangle
; }
382 virtual void Draw(wxDC
& dc
)
386 // well, it's a bit difficult to describe a triangle by position and
387 // size, but we're not doing geometry here, do we? ;-)
389 wxPoint
p2(m_pos
.x
+ m_size
.x
, m_pos
.y
);
390 wxPoint
p3(m_pos
.x
, m_pos
.y
+ m_size
.y
);
396 //works in multicolor modes; on GTK (at least) will fail in 16-bit color
397 dc
.SetBrush(wxBrush(m_col
, wxSOLID
));
398 dc
.FloodFill(GetCentre(), m_col
, wxFLOOD_BORDER
);
402 class DnDRectangularShape
: public DnDShape
405 DnDRectangularShape(const wxPoint
& pos
,
408 : DnDShape(pos
, size
, col
)
410 wxLogMessage(wxT("DnDRectangularShape is being created"));
413 virtual ~DnDRectangularShape()
415 wxLogMessage(wxT("DnDRectangularShape is being deleted"));
418 virtual Kind
GetKind() const { return Rectangle
; }
419 virtual void Draw(wxDC
& dc
)
424 wxPoint
p2(p1
.x
+ m_size
.x
, p1
.y
);
425 wxPoint
p3(p2
.x
, p2
.y
+ m_size
.y
);
426 wxPoint
p4(p1
.x
, p3
.y
);
433 dc
.SetBrush(wxBrush(m_col
, wxSOLID
));
434 dc
.FloodFill(GetCentre(), m_col
, wxFLOOD_BORDER
);
438 class DnDEllipticShape
: public DnDShape
441 DnDEllipticShape(const wxPoint
& pos
,
444 : DnDShape(pos
, size
, col
)
446 wxLogMessage(wxT("DnDEllipticShape is being created"));
449 virtual ~DnDEllipticShape()
451 wxLogMessage(wxT("DnDEllipticShape is being deleted"));
454 virtual Kind
GetKind() const { return Ellipse
; }
455 virtual void Draw(wxDC
& dc
)
459 dc
.DrawEllipse(m_pos
, m_size
);
461 dc
.SetBrush(wxBrush(m_col
, wxSOLID
));
462 dc
.FloodFill(GetCentre(), m_col
, wxFLOOD_BORDER
);
466 // ----------------------------------------------------------------------------
467 // A wxDataObject specialisation for the application-specific data
468 // ----------------------------------------------------------------------------
470 static const wxChar
*shapeFormatId
= wxT("wxShape");
472 class DnDShapeDataObject
: public wxDataObject
475 // ctor doesn't copy the pointer, so it shouldn't go away while this object
477 DnDShapeDataObject(DnDShape
*shape
= (DnDShape
*)NULL
)
481 // we need to copy the shape because the one we're handled may be
482 // deleted while it's still on the clipboard (for example) - and we
483 // reuse the serialisation methods here to copy it
484 void *buf
= malloc(shape
->DnDShape::GetDataSize());
485 shape
->GetDataHere(buf
);
486 m_shape
= DnDShape::New(buf
);
496 // this string should uniquely identify our format, but is otherwise
498 m_formatShape
.SetId(shapeFormatId
);
500 // we don't draw the shape to a bitmap until it's really needed (i.e.
501 // we're asked to do so)
504 m_hasMetaFile
= false;
505 #endif // wxUSE_METAFILE
508 virtual ~DnDShapeDataObject() { delete m_shape
; }
510 // after a call to this function, the shape is owned by the caller and it
511 // is responsible for deleting it!
513 // NB: a better solution would be to make DnDShapes ref counted and this
514 // is what should probably be done in a real life program, otherwise
515 // the ownership problems become too complicated really fast
518 DnDShape
*shape
= m_shape
;
520 m_shape
= (DnDShape
*)NULL
;
523 m_hasMetaFile
= false;
524 #endif // wxUSE_METAFILE
529 // implement base class pure virtuals
530 // ----------------------------------
532 virtual wxDataFormat
GetPreferredFormat(Direction
WXUNUSED(dir
)) const
534 return m_formatShape
;
537 virtual size_t GetFormatCount(Direction dir
) const
539 // our custom format is supported by both GetData() and SetData()
543 // but the bitmap format(s) are only supported for output
544 nFormats
+= m_dobjBitmap
.GetFormatCount(dir
);
547 nFormats
+= m_dobjMetaFile
.GetFormatCount(dir
);
548 #endif // wxUSE_METAFILE
554 virtual void GetAllFormats(wxDataFormat
*formats
, Direction dir
) const
556 formats
[0] = m_formatShape
;
559 // in Get direction we additionally support bitmaps and metafiles
561 m_dobjBitmap
.GetAllFormats(&formats
[1], dir
);
564 // don't assume that m_dobjBitmap has only 1 format
565 m_dobjMetaFile
.GetAllFormats(&formats
[1 +
566 m_dobjBitmap
.GetFormatCount(dir
)], dir
);
567 #endif // wxUSE_METAFILE
571 virtual size_t GetDataSize(const wxDataFormat
& format
) const
573 if ( format
== m_formatShape
)
575 return m_shape
->GetDataSize();
578 else if ( m_dobjMetaFile
.IsSupported(format
) )
580 if ( !m_hasMetaFile
)
583 return m_dobjMetaFile
.GetDataSize(format
);
585 #endif // wxUSE_METAFILE
588 wxASSERT_MSG( m_dobjBitmap
.IsSupported(format
),
589 wxT("unexpected format") );
594 return m_dobjBitmap
.GetDataSize();
598 virtual bool GetDataHere(const wxDataFormat
& format
, void *pBuf
) const
600 if ( format
== m_formatShape
)
602 m_shape
->GetDataHere(pBuf
);
607 else if ( m_dobjMetaFile
.IsSupported(format
) )
609 if ( !m_hasMetaFile
)
612 return m_dobjMetaFile
.GetDataHere(format
, pBuf
);
614 #endif // wxUSE_METAFILE
617 wxASSERT_MSG( m_dobjBitmap
.IsSupported(format
),
618 wxT("unexpected format") );
623 return m_dobjBitmap
.GetDataHere(pBuf
);
627 virtual bool SetData(const wxDataFormat
& format
,
628 size_t WXUNUSED(len
), const void *buf
)
630 wxCHECK_MSG( format
== m_formatShape
, false,
631 wxT( "unsupported format") );
634 m_shape
= DnDShape::New(buf
);
636 // the shape has changed
640 m_hasMetaFile
= false;
641 #endif // wxUSE_METAFILE
647 // creates a bitmap and assigns it to m_dobjBitmap (also sets m_hasBitmap)
648 void CreateBitmap() const;
650 void CreateMetaFile() const;
651 #endif // wxUSE_METAFILE
653 wxDataFormat m_formatShape
; // our custom format
655 wxBitmapDataObject m_dobjBitmap
; // it handles bitmaps
656 bool m_hasBitmap
; // true if m_dobjBitmap has valid bitmap
659 wxMetaFileDataObject m_dobjMetaFile
;// handles metafiles
660 bool m_hasMetaFile
; // true if we have valid metafile
661 #endif // wxUSE_METAFILE
663 DnDShape
*m_shape
; // our data
666 // ----------------------------------------------------------------------------
667 // A dialog to edit shape properties
668 // ----------------------------------------------------------------------------
670 class DnDShapeDialog
: public wxDialog
673 DnDShapeDialog(wxFrame
*parent
, DnDShape
*shape
);
675 DnDShape
*GetShape() const;
677 virtual bool TransferDataToWindow();
678 virtual bool TransferDataFromWindow();
680 void OnColour(wxCommandEvent
& event
);
687 DnDShape::Kind m_shapeKind
;
699 DECLARE_EVENT_TABLE()
702 // ----------------------------------------------------------------------------
703 // A frame for the shapes which can be drag-and-dropped between frames
704 // ----------------------------------------------------------------------------
706 class DnDShapeFrame
: public wxFrame
709 DnDShapeFrame(wxFrame
*parent
);
712 void SetShape(DnDShape
*shape
);
713 virtual bool SetShape(const wxRegion
®ion
)
715 return wxFrame::SetShape( region
);
719 void OnNewShape(wxCommandEvent
& event
);
720 void OnEditShape(wxCommandEvent
& event
);
721 void OnClearShape(wxCommandEvent
& event
);
723 void OnCopyShape(wxCommandEvent
& event
);
724 void OnPasteShape(wxCommandEvent
& event
);
726 void OnUpdateUICopy(wxUpdateUIEvent
& event
);
727 void OnUpdateUIPaste(wxUpdateUIEvent
& event
);
729 void OnDrag(wxMouseEvent
& event
);
730 void OnPaint(wxPaintEvent
& event
);
731 void OnDrop(wxCoord x
, wxCoord y
, DnDShape
*shape
);
736 static DnDShapeFrame
*ms_lastDropTarget
;
738 DECLARE_EVENT_TABLE()
741 // ----------------------------------------------------------------------------
742 // wxDropTarget derivation for DnDShapes
743 // ----------------------------------------------------------------------------
745 class DnDShapeDropTarget
: public wxDropTarget
748 DnDShapeDropTarget(DnDShapeFrame
*frame
)
749 : wxDropTarget(new DnDShapeDataObject
)
754 // override base class (pure) virtuals
755 virtual wxDragResult
OnEnter(wxCoord x
, wxCoord y
, wxDragResult def
)
758 m_frame
->SetStatusText(wxT("Mouse entered the frame"));
759 #endif // wxUSE_STATUSBAR
760 return OnDragOver(x
, y
, def
);
762 virtual void OnLeave()
765 m_frame
->SetStatusText(wxT("Mouse left the frame"));
766 #endif // wxUSE_STATUSBAR
768 virtual wxDragResult
OnData(wxCoord x
, wxCoord y
, wxDragResult def
)
772 wxLogError(wxT("Failed to get drag and drop data"));
777 m_frame
->OnDrop(x
, y
,
778 ((DnDShapeDataObject
*)GetDataObject())->GetShape());
784 DnDShapeFrame
*m_frame
;
787 #endif // wxUSE_DRAG_AND_DROP
789 // ----------------------------------------------------------------------------
790 // functions prototypes
791 // ----------------------------------------------------------------------------
793 static void ShowBitmap(const wxBitmap
& bitmap
);
796 static void ShowMetaFile(const wxMetaFile
& metafile
);
797 #endif // wxUSE_METAFILE
799 // ----------------------------------------------------------------------------
800 // IDs for the menu commands
801 // ----------------------------------------------------------------------------
820 Menu_Shape_New
= 500,
823 Menu_ShapeClipboard_Copy
,
824 Menu_ShapeClipboard_Paste
,
828 BEGIN_EVENT_TABLE(DnDFrame
, wxFrame
)
829 EVT_MENU(Menu_Quit
, DnDFrame::OnQuit
)
830 EVT_MENU(Menu_About
, DnDFrame::OnAbout
)
831 EVT_MENU(Menu_Drag
, DnDFrame::OnDrag
)
832 EVT_MENU(Menu_DragMoveDef
, DnDFrame::OnDragMoveByDefault
)
833 EVT_MENU(Menu_DragMoveAllow
,DnDFrame::OnDragMoveAllow
)
834 EVT_MENU(Menu_NewFrame
, DnDFrame::OnNewFrame
)
835 EVT_MENU(Menu_Help
, DnDFrame::OnHelp
)
837 EVT_MENU(Menu_Clear
, DnDFrame::OnLogClear
)
839 EVT_MENU(Menu_Copy
, DnDFrame::OnCopy
)
840 EVT_MENU(Menu_Paste
, DnDFrame::OnPaste
)
841 EVT_MENU(Menu_CopyBitmap
, DnDFrame::OnCopyBitmap
)
842 EVT_MENU(Menu_PasteBitmap
,DnDFrame::OnPasteBitmap
)
844 EVT_MENU(Menu_PasteMFile
, DnDFrame::OnPasteMetafile
)
845 #endif // wxUSE_METAFILE
846 EVT_MENU(Menu_CopyFiles
, DnDFrame::OnCopyFiles
)
847 EVT_MENU(Menu_UsePrimary
, DnDFrame::OnUsePrimary
)
849 EVT_UPDATE_UI(Menu_DragMoveDef
, DnDFrame::OnUpdateUIMoveByDefault
)
851 EVT_UPDATE_UI(Menu_Paste
, DnDFrame::OnUpdateUIPasteText
)
852 EVT_UPDATE_UI(Menu_PasteBitmap
, DnDFrame::OnUpdateUIPasteBitmap
)
854 EVT_LEFT_DOWN( DnDFrame::OnLeftDown
)
855 EVT_RIGHT_DOWN( DnDFrame::OnRightDown
)
856 EVT_PAINT( DnDFrame::OnPaint
)
857 EVT_SIZE( DnDFrame::OnSize
)
860 #if wxUSE_DRAG_AND_DROP
862 BEGIN_EVENT_TABLE(DnDShapeFrame
, wxFrame
)
863 EVT_MENU(Menu_Shape_New
, DnDShapeFrame::OnNewShape
)
864 EVT_MENU(Menu_Shape_Edit
, DnDShapeFrame::OnEditShape
)
865 EVT_MENU(Menu_Shape_Clear
, DnDShapeFrame::OnClearShape
)
867 EVT_MENU(Menu_ShapeClipboard_Copy
, DnDShapeFrame::OnCopyShape
)
868 EVT_MENU(Menu_ShapeClipboard_Paste
, DnDShapeFrame::OnPasteShape
)
870 EVT_UPDATE_UI(Menu_ShapeClipboard_Copy
, DnDShapeFrame::OnUpdateUICopy
)
871 EVT_UPDATE_UI(Menu_ShapeClipboard_Paste
, DnDShapeFrame::OnUpdateUIPaste
)
873 EVT_LEFT_DOWN(DnDShapeFrame::OnDrag
)
875 EVT_PAINT(DnDShapeFrame::OnPaint
)
878 BEGIN_EVENT_TABLE(DnDShapeDialog
, wxDialog
)
879 EVT_BUTTON(Button_Colour
, DnDShapeDialog::OnColour
)
882 #endif // wxUSE_DRAG_AND_DROP
884 BEGIN_EVENT_TABLE(DnDCanvasBitmap
, wxScrolledWindow
)
885 EVT_PAINT(DnDCanvasBitmap::OnPaint
)
889 BEGIN_EVENT_TABLE(DnDCanvasMetafile
, wxScrolledWindow
)
890 EVT_PAINT(DnDCanvasMetafile::OnPaint
)
892 #endif // wxUSE_METAFILE
894 #endif // wxUSE_DRAG_AND_DROP
896 // ============================================================================
898 // ============================================================================
900 // `Main program' equivalent, creating windows and returning main app frame
901 bool DnDApp::OnInit()
903 if ( !wxApp::OnInit() )
906 #if wxUSE_DRAG_AND_DROP || wxUSE_CLIPBOARD
907 // switch on trace messages
909 #if defined(__WXGTK__)
910 wxLog::AddTraceMask(wxT("clipboard"));
911 #elif defined(__WXMSW__)
912 wxLog::AddTraceMask(wxTRACE_OleCalls
);
917 wxImage::AddHandler( new wxPNGHandler
);
920 // create the main frame window
925 wxMessageBox( wxT("This sample has to be compiled with wxUSE_DRAG_AND_DROP"), wxT("Building error"), wxOK
);
927 #endif // wxUSE_DRAG_AND_DROP
930 #if wxUSE_DRAG_AND_DROP || wxUSE_CLIPBOARD
933 : wxFrame(NULL
, wxID_ANY
, wxT("Drag-and-Drop/Clipboard wxWidgets Sample"),
935 m_strText(wxT("wxWidgets drag & drop works :-)"))
938 // frame icon and status bar
939 SetIcon(wxICON(sample
));
943 #endif // wxUSE_STATUSBAR
946 wxMenu
*file_menu
= new wxMenu
;
947 file_menu
->Append(Menu_Drag
, wxT("&Test drag..."));
948 file_menu
->AppendCheckItem(Menu_DragMoveDef
, wxT("&Move by default"));
949 file_menu
->AppendCheckItem(Menu_DragMoveAllow
, wxT("&Allow moving"));
950 file_menu
->AppendSeparator();
951 file_menu
->Append(Menu_NewFrame
, wxT("&New frame\tCtrl-N"));
952 file_menu
->AppendSeparator();
953 file_menu
->Append(Menu_Quit
, wxT("E&xit\tCtrl-Q"));
956 wxMenu
*log_menu
= new wxMenu
;
957 log_menu
->Append(Menu_Clear
, wxT("Clear\tCtrl-L"));
960 wxMenu
*help_menu
= new wxMenu
;
961 help_menu
->Append(Menu_Help
, wxT("&Help..."));
962 help_menu
->AppendSeparator();
963 help_menu
->Append(Menu_About
, wxT("&About"));
965 wxMenu
*clip_menu
= new wxMenu
;
966 clip_menu
->Append(Menu_Copy
, wxT("&Copy text\tCtrl-C"));
967 clip_menu
->Append(Menu_Paste
, wxT("&Paste text\tCtrl-V"));
968 clip_menu
->AppendSeparator();
969 clip_menu
->Append(Menu_CopyBitmap
, wxT("Copy &bitmap\tCtrl-Shift-C"));
970 clip_menu
->Append(Menu_PasteBitmap
, wxT("Paste b&itmap\tCtrl-Shift-V"));
972 clip_menu
->AppendSeparator();
973 clip_menu
->Append(Menu_PasteMFile
, wxT("Paste &metafile\tCtrl-M"));
974 #endif // wxUSE_METAFILE
975 clip_menu
->AppendSeparator();
976 clip_menu
->Append(Menu_CopyFiles
, wxT("Copy &files\tCtrl-F"));
977 clip_menu
->AppendSeparator();
978 clip_menu
->AppendCheckItem(Menu_UsePrimary
, wxT("Use &primary selection\tCtrl-P"));
980 wxMenuBar
*menu_bar
= new wxMenuBar
;
981 menu_bar
->Append(file_menu
, wxT("&File"));
983 menu_bar
->Append(log_menu
, wxT("&Log"));
985 menu_bar
->Append(clip_menu
, wxT("&Clipboard"));
986 menu_bar
->Append(help_menu
, wxT("&Help"));
988 SetMenuBar(menu_bar
);
990 // create the child controls
991 SetBackgroundColour(*wxWHITE
); // labels read better on this background
993 wxString
strFile(wxT("Drop files here!")), strText(wxT("Drop text on me"));
995 m_ctrlFile
= new wxListBox(this, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, 1, &strFile
,
996 wxLB_HSCROLL
| wxLB_ALWAYS_SB
);
997 m_ctrlText
= new wxListBox(this, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, 1, &strText
,
998 wxLB_HSCROLL
| wxLB_ALWAYS_SB
);
999 m_ctrlDir
= new wxGenericDirCtrl(this);
1002 m_ctrlLog
= new wxTextCtrl(this, wxID_ANY
, wxEmptyString
,
1003 wxDefaultPosition
, wxDefaultSize
,
1004 wxTE_MULTILINE
| wxTE_READONLY
|
1007 // redirect log messages to the text window
1008 m_pLog
= new wxLogTextCtrl(m_ctrlLog
);
1009 m_pLogPrev
= wxLog::SetActiveTarget(m_pLog
);
1012 #if wxUSE_DRAG_AND_DROP
1013 // associate drop targets with the controls
1014 m_ctrlFile
->SetDropTarget(new DnDFile(m_ctrlFile
));
1015 m_ctrlText
->SetDropTarget(new DnDText(m_ctrlText
));
1017 #if wxUSE_DRAG_AND_DROP
1021 wxEVT_COMMAND_TREE_BEGIN_DRAG
,
1022 wxTreeEventHandler(DnDFrame::OnBeginDrag
),
1026 #endif // wxUSE_DRAG_AND_DROP
1029 m_ctrlLog
->SetDropTarget(new URLDropTarget
);
1031 #endif // wxUSE_DRAG_AND_DROP
1033 wxBoxSizer
*sizer_top
= new wxBoxSizer( wxHORIZONTAL
);
1034 sizer_top
->Add(m_ctrlFile
, 1, wxEXPAND
);
1035 sizer_top
->Add(m_ctrlText
, 1, wxEXPAND
);
1037 wxBoxSizer
*sizerDirCtrl
= new wxBoxSizer(wxVERTICAL
);
1038 sizerDirCtrl
->Add(new wxStaticText(this, wxID_ANY
, "Drag files from here"),
1039 wxSizerFlags().Centre().Border());
1040 sizerDirCtrl
->Add(m_ctrlDir
, wxSizerFlags(1).Expand());
1041 sizer_top
->Add(sizerDirCtrl
, 1, wxEXPAND
);
1043 // make all columns of reasonable minimal size
1044 for ( unsigned n
= 0; n
< sizer_top
->GetChildren().size(); n
++ )
1045 sizer_top
->SetItemMinSize(n
, 200, 300);
1047 wxBoxSizer
*sizer
= new wxBoxSizer( wxVERTICAL
);
1048 sizer
->Add(sizer_top
, 1, wxEXPAND
);
1050 sizer
->Add(m_ctrlLog
, 2, wxEXPAND
);
1051 sizer
->SetItemMinSize(m_ctrlLog
, 450, 200);
1053 sizer
->AddSpacer(50);
1055 // copy data by default but allow moving it as well
1056 m_moveByDefault
= false;
1058 menu_bar
->Check(Menu_DragMoveAllow
, true);
1060 // set the correct size and show the frame
1061 SetSizerAndFit(sizer
);
1065 void DnDFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
1070 void DnDFrame::OnSize(wxSizeEvent
& event
)
1077 void DnDFrame::OnPaint(wxPaintEvent
& WXUNUSED(event
))
1081 GetClientSize( &w
, &h
);
1084 // dc.Clear(); -- this kills wxGTK
1085 dc
.SetFont( wxFont( 24, wxDECORATIVE
, wxNORMAL
, wxNORMAL
, false, wxT("charter") ) );
1086 dc
.DrawText( wxT("Drag text from here!"), 100, h
-50 );
1089 void DnDFrame::OnUpdateUIMoveByDefault(wxUpdateUIEvent
& event
)
1091 // only can move by default if moving is allowed at all
1092 event
.Enable(m_moveAllow
);
1095 void DnDFrame::OnUpdateUIPasteText(wxUpdateUIEvent
& event
)
1098 // too many trace messages if we don't do it - this function is called
1103 event
.Enable( wxTheClipboard
->IsSupported(wxDF_TEXT
) );
1106 void DnDFrame::OnUpdateUIPasteBitmap(wxUpdateUIEvent
& event
)
1109 // too many trace messages if we don't do it - this function is called
1114 event
.Enable( wxTheClipboard
->IsSupported(wxDF_BITMAP
) );
1117 void DnDFrame::OnNewFrame(wxCommandEvent
& WXUNUSED(event
))
1119 #if wxUSE_DRAG_AND_DROP
1120 (new DnDShapeFrame(this))->Show(true);
1122 wxLogStatus(this, wxT("Double click the new frame to select a shape for it"));
1123 #endif // wxUSE_DRAG_AND_DROP
1126 void DnDFrame::OnDrag(wxCommandEvent
& WXUNUSED(event
))
1128 #if wxUSE_DRAG_AND_DROP
1129 wxString strText
= wxGetTextFromUser
1131 wxT("After you enter text in this dialog, press any mouse\n")
1132 wxT("button in the bottom (empty) part of the frame and \n")
1133 wxT("drag it anywhere - you will be in fact dragging the\n")
1134 wxT("text object containing this text"),
1135 wxT("Please enter some text"), m_strText
, this
1138 m_strText
= strText
;
1139 #endif // wxUSE_DRAG_AND_DROP
1142 void DnDFrame::OnDragMoveByDefault(wxCommandEvent
& event
)
1144 m_moveByDefault
= event
.IsChecked();
1147 void DnDFrame::OnDragMoveAllow(wxCommandEvent
& event
)
1149 m_moveAllow
= event
.IsChecked();
1152 void DnDFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
1154 wxMessageBox(wxT("Drag-&-Drop Demo\n")
1155 wxT("Please see \"Help|Help...\" for details\n")
1156 wxT("Copyright (c) 1998 Vadim Zeitlin"),
1158 wxICON_INFORMATION
| wxOK
,
1162 void DnDFrame::OnHelp(wxCommandEvent
& /* event */)
1164 wxMessageDialog
dialog(this,
1165 wxT("This small program demonstrates drag & drop support in wxWidgets. The program window\n")
1166 wxT("consists of 3 parts: the bottom pane is for debug messages, so that you can see what's\n")
1167 wxT("going on inside. The top part is split into 2 listboxes, the left one accepts files\n")
1168 wxT("and the right one accepts text.\n")
1170 wxT("To test wxDropTarget: open wordpad (write.exe), select some text in it and drag it to\n")
1171 wxT("the right listbox (you'll notice the usual visual feedback, i.e. the cursor will change).\n")
1172 wxT("Also, try dragging some files (you can select several at once) from Windows Explorer (or \n")
1173 wxT("File Manager) to the left pane. Hold down Ctrl/Shift keys when you drop text (doesn't \n")
1174 wxT("work with files) and see what changes.\n")
1176 wxT("To test wxDropSource: just press any mouse button on the empty zone of the window and drag\n")
1177 wxT("it to wordpad or any other droptarget accepting text (and of course you can just drag it\n")
1178 wxT("to the right pane). Due to a lot of trace messages, the cursor might take some time to \n")
1179 wxT("change, don't release the mouse button until it does. You can change the string being\n")
1180 wxT("dragged in in \"File|Test drag...\" dialog.\n")
1183 wxT("Please send all questions/bug reports/suggestions &c to \n")
1184 wxT("Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>"),
1191 void DnDFrame::OnLogClear(wxCommandEvent
& /* event */ )
1194 m_ctrlText
->Clear();
1195 m_ctrlFile
->Clear();
1199 #if wxUSE_DRAG_AND_DROP
1201 void DnDFrame::LogDragResult(wxDragResult result
)
1207 case wxDragError
: pc
= wxT("Error!"); break;
1208 case wxDragNone
: pc
= wxT("Nothing"); break;
1209 case wxDragCopy
: pc
= wxT("Copied"); break;
1210 case wxDragMove
: pc
= wxT("Moved"); break;
1211 case wxDragCancel
: pc
= wxT("Cancelled"); break;
1212 default: pc
= wxT("Huh?"); break;
1215 SetStatusText(wxString(wxT("Drag result: ")) + pc
);
1217 wxUnusedVar(result
);
1218 #endif // wxUSE_STATUSBAR
1221 #endif // wxUSE_DRAG_AND_DROP
1223 void DnDFrame::OnLeftDown(wxMouseEvent
&WXUNUSED(event
) )
1225 #if wxUSE_DRAG_AND_DROP
1226 if ( !m_strText
.empty() )
1228 // start drag operation
1229 wxTextDataObject
textData(m_strText
);
1230 wxDropSource
source(textData
, this,
1231 wxDROP_ICON(dnd_copy
),
1232 wxDROP_ICON(dnd_move
),
1233 wxDROP_ICON(dnd_none
));
1236 if ( m_moveByDefault
)
1237 flags
|= wxDrag_DefaultMove
;
1238 else if ( m_moveAllow
)
1239 flags
|= wxDrag_AllowMove
;
1241 LogDragResult(source
.DoDragDrop(flags
));
1243 #endif // wxUSE_DRAG_AND_DROP
1246 void DnDFrame::OnRightDown(wxMouseEvent
&event
)
1248 wxMenu
menu(wxT("Dnd sample menu"));
1250 menu
.Append(Menu_Drag
, wxT("&Test drag..."));
1251 menu
.AppendSeparator();
1252 menu
.Append(Menu_About
, wxT("&About"));
1254 PopupMenu( &menu
, event
.GetX(), event
.GetY() );
1257 DnDFrame::~DnDFrame()
1260 if ( m_pLog
!= NULL
) {
1261 if ( wxLog::SetActiveTarget(m_pLogPrev
) == m_pLog
)
1267 void DnDFrame::OnUsePrimary(wxCommandEvent
& event
)
1269 const bool usePrimary
= event
.IsChecked();
1270 wxTheClipboard
->UsePrimarySelection(usePrimary
);
1272 wxLogStatus(wxT("Now using %s selection"), usePrimary
? wxT("primary")
1273 : wxT("clipboard"));
1276 #if wxUSE_DRAG_AND_DROP
1278 void DnDFrame::OnBeginDrag(wxTreeEvent
& WXUNUSED(event
))
1280 wxFileDataObject data
;
1281 data
.AddFile(m_ctrlDir
->GetPath());
1283 wxDropSource
dragSource(this);
1284 dragSource
.SetData(data
);
1286 LogDragResult(dragSource
.DoDragDrop());
1289 #endif // wxUSE_DRAG_AND_DROP
1291 // ---------------------------------------------------------------------------
1293 // ---------------------------------------------------------------------------
1295 void DnDFrame::OnCopyBitmap(wxCommandEvent
& WXUNUSED(event
))
1297 // PNG support is not always compiled in under Windows, so use BMP there
1299 wxFileDialog
dialog(this, wxT("Open a PNG file"), wxEmptyString
, wxEmptyString
, wxT("PNG files (*.png)|*.png"), 0);
1301 wxFileDialog
dialog(this, wxT("Open a BMP file"), wxEmptyString
, wxEmptyString
, wxT("BMP files (*.bmp)|*.bmp"), 0);
1304 if (dialog
.ShowModal() != wxID_OK
)
1306 wxLogMessage( wxT("Aborted file open") );
1310 if (dialog
.GetPath().empty())
1312 wxLogMessage( wxT("Returned empty string.") );
1316 if (!wxFileExists(dialog
.GetPath()))
1318 wxLogMessage( wxT("File doesn't exist.") );
1323 image
.LoadFile( dialog
.GetPath(),
1332 wxLogError( wxT("Invalid image file...") );
1336 wxLogStatus( wxT("Decoding image file...") );
1339 wxBitmap
bitmap( image
);
1341 if ( !wxTheClipboard
->Open() )
1343 wxLogError(wxT("Can't open clipboard."));
1348 wxLogMessage( wxT("Creating wxBitmapDataObject...") );
1351 if ( !wxTheClipboard
->AddData(new wxBitmapDataObject(bitmap
)) )
1353 wxLogError(wxT("Can't copy image to the clipboard."));
1357 wxLogMessage(wxT("Image has been put on the clipboard.") );
1358 wxLogMessage(wxT("You can paste it now and look at it.") );
1361 wxTheClipboard
->Close();
1364 void DnDFrame::OnPasteBitmap(wxCommandEvent
& WXUNUSED(event
))
1366 if ( !wxTheClipboard
->Open() )
1368 wxLogError(wxT("Can't open clipboard."));
1373 if ( !wxTheClipboard
->IsSupported(wxDF_BITMAP
) )
1375 wxLogWarning(wxT("No bitmap on clipboard"));
1377 wxTheClipboard
->Close();
1381 wxBitmapDataObject data
;
1382 if ( !wxTheClipboard
->GetData(data
) )
1384 wxLogError(wxT("Can't paste bitmap from the clipboard"));
1388 const wxBitmap
& bmp
= data
.GetBitmap();
1390 wxLogMessage(wxT("Bitmap %dx%d pasted from the clipboard"),
1391 bmp
.GetWidth(), bmp
.GetHeight());
1395 wxTheClipboard
->Close();
1400 void DnDFrame::OnPasteMetafile(wxCommandEvent
& WXUNUSED(event
))
1402 if ( !wxTheClipboard
->Open() )
1404 wxLogError(wxT("Can't open clipboard."));
1409 if ( !wxTheClipboard
->IsSupported(wxDF_METAFILE
) )
1411 wxLogWarning(wxT("No metafile on clipboard"));
1415 wxMetaFileDataObject data
;
1416 if ( !wxTheClipboard
->GetData(data
) )
1418 wxLogError(wxT("Can't paste metafile from the clipboard"));
1422 const wxMetaFile
& mf
= data
.GetMetafile();
1424 wxLogMessage(wxT("Metafile %dx%d pasted from the clipboard"),
1425 mf
.GetWidth(), mf
.GetHeight());
1431 wxTheClipboard
->Close();
1434 #endif // wxUSE_METAFILE
1436 // ----------------------------------------------------------------------------
1438 // ----------------------------------------------------------------------------
1440 void DnDFrame::OnCopyFiles(wxCommandEvent
& WXUNUSED(event
))
1443 wxFileDialog
dialog(this, wxT("Select a file to copy"), wxEmptyString
, wxEmptyString
,
1444 wxT("All files (*.*)|*.*"), 0);
1446 wxArrayString filenames
;
1447 while ( dialog
.ShowModal() == wxID_OK
)
1449 filenames
.Add(dialog
.GetPath());
1452 if ( !filenames
.IsEmpty() )
1454 wxFileDataObject
*dobj
= new wxFileDataObject
;
1455 size_t count
= filenames
.GetCount();
1456 for ( size_t n
= 0; n
< count
; n
++ )
1458 dobj
->AddFile(filenames
[n
]);
1461 wxClipboardLocker locker
;
1464 wxLogError(wxT("Can't open clipboard"));
1468 if ( !wxTheClipboard
->AddData(dobj
) )
1470 wxLogError(wxT("Can't copy file(s) to the clipboard"));
1474 wxLogStatus(this, wxT("%d file%s copied to the clipboard"),
1475 count
, count
== 1 ? wxEmptyString
: wxEmptyString
);
1481 wxLogStatus(this, wxT("Aborted"));
1484 wxLogError(wxT("Sorry, not implemented"));
1488 // ---------------------------------------------------------------------------
1490 // ---------------------------------------------------------------------------
1492 void DnDFrame::OnCopy(wxCommandEvent
& WXUNUSED(event
))
1494 if ( !wxTheClipboard
->Open() )
1496 wxLogError(wxT("Can't open clipboard."));
1501 if ( !wxTheClipboard
->AddData(new wxTextDataObject(m_strText
)) )
1503 wxLogError(wxT("Can't copy data to the clipboard"));
1507 wxLogMessage(wxT("Text '%s' put on the clipboard"), m_strText
.c_str());
1510 wxTheClipboard
->Close();
1513 void DnDFrame::OnPaste(wxCommandEvent
& WXUNUSED(event
))
1515 if ( !wxTheClipboard
->Open() )
1517 wxLogError(wxT("Can't open clipboard."));
1522 if ( !wxTheClipboard
->IsSupported(wxDF_TEXT
) )
1524 wxLogWarning(wxT("No text data on clipboard"));
1526 wxTheClipboard
->Close();
1530 wxTextDataObject text
;
1531 if ( !wxTheClipboard
->GetData(text
) )
1533 wxLogError(wxT("Can't paste data from the clipboard"));
1537 wxLogMessage(wxT("Text '%s' pasted from the clipboard"),
1538 text
.GetText().c_str());
1541 wxTheClipboard
->Close();
1544 #if wxUSE_DRAG_AND_DROP
1546 // ----------------------------------------------------------------------------
1547 // Notifications called by the base class
1548 // ----------------------------------------------------------------------------
1550 bool DnDText::OnDropText(wxCoord
, wxCoord
, const wxString
& text
)
1552 m_pOwner
->Append(text
);
1557 bool DnDFile::OnDropFiles(wxCoord
, wxCoord
, const wxArrayString
& filenames
)
1559 size_t nFiles
= filenames
.GetCount();
1561 str
.Printf( wxT("%d files dropped"), (int)nFiles
);
1563 if (m_pOwner
!= NULL
)
1565 m_pOwner
->Append(str
);
1566 for ( size_t n
= 0; n
< nFiles
; n
++ )
1567 m_pOwner
->Append(filenames
[n
]);
1573 // ----------------------------------------------------------------------------
1575 // ----------------------------------------------------------------------------
1577 DnDShapeDialog::DnDShapeDialog(wxFrame
*parent
, DnDShape
*shape
)
1578 :wxDialog( parent
, 6001, wxT("Choose Shape"), wxPoint( 10, 10 ),
1580 wxDEFAULT_DIALOG_STYLE
| wxRAISED_BORDER
| wxRESIZE_BORDER
)
1583 wxBoxSizer
* topSizer
= new wxBoxSizer( wxVERTICAL
);
1586 wxBoxSizer
* shapesSizer
= new wxBoxSizer( wxHORIZONTAL
);
1587 const wxString choices
[] = { wxT("None"), wxT("Triangle"),
1588 wxT("Rectangle"), wxT("Ellipse") };
1590 m_radio
= new wxRadioBox( this, wxID_ANY
, wxT("&Shape"),
1591 wxDefaultPosition
, wxDefaultSize
, 4, choices
, 4,
1592 wxRA_SPECIFY_COLS
);
1593 shapesSizer
->Add( m_radio
, 0, wxGROW
|wxALL
, 5 );
1594 topSizer
->Add( shapesSizer
, 0, wxALL
, 2 );
1597 wxStaticBox
* box
= new wxStaticBox( this, wxID_ANY
, wxT("&Attributes") );
1598 wxStaticBoxSizer
* attrSizer
= new wxStaticBoxSizer( box
, wxHORIZONTAL
);
1599 wxFlexGridSizer
* xywhSizer
= new wxFlexGridSizer( 2 );
1603 st
= new wxStaticText( this, wxID_ANY
, wxT("Position &X:") );
1604 m_textX
= new wxTextCtrl( this, wxID_ANY
, wxEmptyString
, wxDefaultPosition
,
1606 xywhSizer
->Add( st
, 1, wxGROW
|wxALL
, 2 );
1607 xywhSizer
->Add( m_textX
, 1, wxGROW
|wxALL
, 2 );
1609 st
= new wxStaticText( this, wxID_ANY
, wxT("Size &width:") );
1610 m_textW
= new wxTextCtrl( this, wxID_ANY
, wxEmptyString
, wxDefaultPosition
,
1612 xywhSizer
->Add( st
, 1, wxGROW
|wxALL
, 2 );
1613 xywhSizer
->Add( m_textW
, 1, wxGROW
|wxALL
, 2 );
1615 st
= new wxStaticText( this, wxID_ANY
, wxT("&Y:") );
1616 m_textY
= new wxTextCtrl( this, wxID_ANY
, wxEmptyString
, wxDefaultPosition
,
1618 xywhSizer
->Add( st
, 1, wxALL
|wxALIGN_RIGHT
, 2 );
1619 xywhSizer
->Add( m_textY
, 1, wxGROW
|wxALL
, 2 );
1621 st
= new wxStaticText( this, wxID_ANY
, wxT("&height:") );
1622 m_textH
= new wxTextCtrl( this, wxID_ANY
, wxEmptyString
, wxDefaultPosition
,
1624 xywhSizer
->Add( st
, 1, wxALL
|wxALIGN_RIGHT
, 2 );
1625 xywhSizer
->Add( m_textH
, 1, wxGROW
|wxALL
, 2 );
1627 wxButton
* col
= new wxButton( this, Button_Colour
, wxT("&Colour...") );
1628 attrSizer
->Add( xywhSizer
, 1, wxGROW
);
1629 attrSizer
->Add( col
, 0, wxALL
|wxALIGN_CENTRE_VERTICAL
, 2 );
1630 topSizer
->Add( attrSizer
, 0, wxGROW
|wxALL
, 5 );
1633 wxBoxSizer
* buttonSizer
= new wxBoxSizer( wxHORIZONTAL
);
1635 bt
= new wxButton( this, wxID_OK
, wxT("Ok") );
1636 buttonSizer
->Add( bt
, 0, wxALL
, 2 );
1637 bt
= new wxButton( this, wxID_CANCEL
, wxT("Cancel") );
1638 buttonSizer
->Add( bt
, 0, wxALL
, 2 );
1639 topSizer
->Add( buttonSizer
, 0, wxALL
|wxALIGN_RIGHT
, 2 );
1641 SetSizerAndFit( topSizer
);
1644 DnDShape
*DnDShapeDialog::GetShape() const
1646 switch ( m_shapeKind
)
1649 case DnDShape::None
: return NULL
;
1650 case DnDShape::Triangle
: return new DnDTriangularShape(m_pos
, m_size
, m_col
);
1651 case DnDShape::Rectangle
: return new DnDRectangularShape(m_pos
, m_size
, m_col
);
1652 case DnDShape::Ellipse
: return new DnDEllipticShape(m_pos
, m_size
, m_col
);
1656 bool DnDShapeDialog::TransferDataToWindow()
1661 m_radio
->SetSelection(m_shape
->GetKind());
1662 m_pos
= m_shape
->GetPosition();
1663 m_size
= m_shape
->GetSize();
1664 m_col
= m_shape
->GetColour();
1668 m_radio
->SetSelection(DnDShape::None
);
1669 m_pos
= wxPoint(1, 1);
1670 m_size
= wxSize(100, 100);
1673 m_textX
->SetValue(wxString() << m_pos
.x
);
1674 m_textY
->SetValue(wxString() << m_pos
.y
);
1675 m_textW
->SetValue(wxString() << m_size
.x
);
1676 m_textH
->SetValue(wxString() << m_size
.y
);
1681 bool DnDShapeDialog::TransferDataFromWindow()
1683 m_shapeKind
= (DnDShape::Kind
)m_radio
->GetSelection();
1685 m_pos
.x
= wxAtoi(m_textX
->GetValue());
1686 m_pos
.y
= wxAtoi(m_textY
->GetValue());
1687 m_size
.x
= wxAtoi(m_textW
->GetValue());
1688 m_size
.y
= wxAtoi(m_textH
->GetValue());
1690 if ( !m_pos
.x
|| !m_pos
.y
|| !m_size
.x
|| !m_size
.y
)
1692 wxMessageBox(wxT("All sizes and positions should be non null!"),
1693 wxT("Invalid shape"), wxICON_HAND
| wxOK
, this);
1701 void DnDShapeDialog::OnColour(wxCommandEvent
& WXUNUSED(event
))
1704 data
.SetChooseFull(true);
1705 for (int i
= 0; i
< 16; i
++)
1707 wxColour
colour((unsigned char)(i
*16), (unsigned char)(i
*16), (unsigned char)(i
*16));
1708 data
.SetCustomColour(i
, colour
);
1711 wxColourDialog
dialog(this, &data
);
1712 if ( dialog
.ShowModal() == wxID_OK
)
1714 m_col
= dialog
.GetColourData().GetColour();
1718 // ----------------------------------------------------------------------------
1720 // ----------------------------------------------------------------------------
1722 DnDShapeFrame
*DnDShapeFrame::ms_lastDropTarget
= NULL
;
1724 DnDShapeFrame::DnDShapeFrame(wxFrame
*parent
)
1725 : wxFrame(parent
, wxID_ANY
, wxT("Shape Frame"))
1729 #endif // wxUSE_STATUSBAR
1731 wxMenu
*menuShape
= new wxMenu
;
1732 menuShape
->Append(Menu_Shape_New
, wxT("&New default shape\tCtrl-S"));
1733 menuShape
->Append(Menu_Shape_Edit
, wxT("&Edit shape\tCtrl-E"));
1734 menuShape
->AppendSeparator();
1735 menuShape
->Append(Menu_Shape_Clear
, wxT("&Clear shape\tCtrl-L"));
1737 wxMenu
*menuClipboard
= new wxMenu
;
1738 menuClipboard
->Append(Menu_ShapeClipboard_Copy
, wxT("&Copy\tCtrl-C"));
1739 menuClipboard
->Append(Menu_ShapeClipboard_Paste
, wxT("&Paste\tCtrl-V"));
1741 wxMenuBar
*menubar
= new wxMenuBar
;
1742 menubar
->Append(menuShape
, wxT("&Shape"));
1743 menubar
->Append(menuClipboard
, wxT("&Clipboard"));
1745 SetMenuBar(menubar
);
1748 SetStatusText(wxT("Press Ctrl-S to create a new shape"));
1749 #endif // wxUSE_STATUSBAR
1751 SetDropTarget(new DnDShapeDropTarget(this));
1755 SetBackgroundColour(*wxWHITE
);
1758 DnDShapeFrame::~DnDShapeFrame()
1764 void DnDShapeFrame::SetShape(DnDShape
*shape
)
1773 void DnDShapeFrame::OnDrag(wxMouseEvent
& event
)
1782 // start drag operation
1783 DnDShapeDataObject
shapeData(m_shape
);
1784 wxDropSource
source(shapeData
, this);
1786 const wxChar
*pc
= NULL
;
1787 switch ( source
.DoDragDrop(true) )
1791 wxLogError(wxT("An error occurred during drag and drop operation"));
1796 SetStatusText(wxT("Nothing happened"));
1797 #endif // wxUSE_STATUSBAR
1806 if ( ms_lastDropTarget
!= this )
1808 // don't delete the shape if we dropped it on ourselves!
1815 SetStatusText(wxT("Drag and drop operation cancelled"));
1816 #endif // wxUSE_STATUSBAR
1823 SetStatusText(wxString(wxT("Shape successfully ")) + pc
);
1824 #endif // wxUSE_STATUSBAR
1826 //else: status text already set
1829 void DnDShapeFrame::OnDrop(wxCoord x
, wxCoord y
, DnDShape
*shape
)
1831 ms_lastDropTarget
= this;
1837 s
.Printf(wxT("Shape dropped at (%d, %d)"), pt
.x
, pt
.y
);
1839 #endif // wxUSE_STATUSBAR
1845 void DnDShapeFrame::OnEditShape(wxCommandEvent
& WXUNUSED(event
))
1847 DnDShapeDialog
dlg(this, m_shape
);
1848 if ( dlg
.ShowModal() == wxID_OK
)
1850 SetShape(dlg
.GetShape());
1855 SetStatusText(wxT("You can now drag the shape to another frame"));
1857 #endif // wxUSE_STATUSBAR
1861 void DnDShapeFrame::OnNewShape(wxCommandEvent
& WXUNUSED(event
))
1863 SetShape(new DnDEllipticShape(wxPoint(10, 10), wxSize(80, 60), *wxRED
));
1866 SetStatusText(wxT("You can now drag the shape to another frame"));
1867 #endif // wxUSE_STATUSBAR
1870 void DnDShapeFrame::OnClearShape(wxCommandEvent
& WXUNUSED(event
))
1875 void DnDShapeFrame::OnCopyShape(wxCommandEvent
& WXUNUSED(event
))
1879 wxClipboardLocker clipLocker
;
1882 wxLogError(wxT("Can't open the clipboard"));
1887 wxTheClipboard
->AddData(new DnDShapeDataObject(m_shape
));
1891 void DnDShapeFrame::OnPasteShape(wxCommandEvent
& WXUNUSED(event
))
1893 wxClipboardLocker clipLocker
;
1896 wxLogError(wxT("Can't open the clipboard"));
1901 DnDShapeDataObject
shapeDataObject(NULL
);
1902 if ( wxTheClipboard
->GetData(shapeDataObject
) )
1904 SetShape(shapeDataObject
.GetShape());
1908 wxLogStatus(wxT("No shape on the clipboard"));
1912 void DnDShapeFrame::OnUpdateUICopy(wxUpdateUIEvent
& event
)
1914 event
.Enable( m_shape
!= NULL
);
1917 void DnDShapeFrame::OnUpdateUIPaste(wxUpdateUIEvent
& event
)
1919 event
.Enable( wxTheClipboard
->IsSupported(wxDataFormat(shapeFormatId
)) );
1922 void DnDShapeFrame::OnPaint(wxPaintEvent
& event
)
1936 // ----------------------------------------------------------------------------
1938 // ----------------------------------------------------------------------------
1940 DnDShape
*DnDShape::New(const void *buf
)
1942 const ShapeDump
& dump
= *(const ShapeDump
*)buf
;
1946 return new DnDTriangularShape(wxPoint(dump
.x
, dump
.y
),
1947 wxSize(dump
.w
, dump
.h
),
1948 wxColour(dump
.r
, dump
.g
, dump
.b
));
1951 return new DnDRectangularShape(wxPoint(dump
.x
, dump
.y
),
1952 wxSize(dump
.w
, dump
.h
),
1953 wxColour(dump
.r
, dump
.g
, dump
.b
));
1956 return new DnDEllipticShape(wxPoint(dump
.x
, dump
.y
),
1957 wxSize(dump
.w
, dump
.h
),
1958 wxColour(dump
.r
, dump
.g
, dump
.b
));
1961 wxFAIL_MSG(wxT("invalid shape!"));
1966 // ----------------------------------------------------------------------------
1967 // DnDShapeDataObject
1968 // ----------------------------------------------------------------------------
1972 void DnDShapeDataObject::CreateMetaFile() const
1974 wxPoint pos
= m_shape
->GetPosition();
1975 wxSize size
= m_shape
->GetSize();
1977 wxMetaFileDC
dcMF(wxEmptyString
, pos
.x
+ size
.x
, pos
.y
+ size
.y
);
1979 m_shape
->Draw(dcMF
);
1981 wxMetafile
*mf
= dcMF
.Close();
1983 DnDShapeDataObject
*self
= (DnDShapeDataObject
*)this; // const_cast
1984 self
->m_dobjMetaFile
.SetMetafile(*mf
);
1985 self
->m_hasMetaFile
= true;
1990 #endif // wxUSE_METAFILE
1992 void DnDShapeDataObject::CreateBitmap() const
1994 wxPoint pos
= m_shape
->GetPosition();
1995 wxSize size
= m_shape
->GetSize();
1996 int x
= pos
.x
+ size
.x
,
1998 wxBitmap
bitmap(x
, y
);
2000 dc
.SelectObject(bitmap
);
2001 dc
.SetBrush(wxBrush(wxT("white"), wxSOLID
));
2004 dc
.SelectObject(wxNullBitmap
);
2006 DnDShapeDataObject
*self
= (DnDShapeDataObject
*)this; // const_cast
2007 self
->m_dobjBitmap
.SetBitmap(bitmap
);
2008 self
->m_hasBitmap
= true;
2011 #endif // wxUSE_DRAG_AND_DROP
2013 // ----------------------------------------------------------------------------
2015 // ----------------------------------------------------------------------------
2017 static void ShowBitmap(const wxBitmap
& bitmap
)
2019 wxFrame
*frame
= new wxFrame(NULL
, wxID_ANY
, wxT("Bitmap view"));
2021 frame
->CreateStatusBar();
2022 #endif // wxUSE_STATUSBAR
2023 DnDCanvasBitmap
*canvas
= new DnDCanvasBitmap(frame
);
2024 canvas
->SetBitmap(bitmap
);
2026 int w
= bitmap
.GetWidth(),
2027 h
= bitmap
.GetHeight();
2029 frame
->SetStatusText(wxString::Format(wxT("%dx%d"), w
, h
));
2030 #endif // wxUSE_STATUSBAR
2032 frame
->SetClientSize(w
> 100 ? 100 : w
, h
> 100 ? 100 : h
);
2038 static void ShowMetaFile(const wxMetaFile
& metafile
)
2040 wxFrame
*frame
= new wxFrame(NULL
, wxID_ANY
, wxT("Metafile view"));
2041 frame
->CreateStatusBar();
2042 DnDCanvasMetafile
*canvas
= new DnDCanvasMetafile(frame
);
2043 canvas
->SetMetafile(metafile
);
2045 wxSize size
= metafile
.GetSize();
2046 frame
->SetStatusText(wxString::Format(wxT("%dx%d"), size
.x
, size
.y
));
2048 frame
->SetClientSize(size
.x
> 100 ? 100 : size
.x
,
2049 size
.y
> 100 ? 100 : size
.y
);
2053 #endif // wxUSE_METAFILE
2055 #endif // wxUSE_DRAG_AND_DROP || wxUSE_CLIPBOARD