1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Drag and drop sample
4 // Author: Vadim Zeitlin
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 #include "wx/wxprec.h"
22 #include "wx/dataobj.h"
24 #include "wx/clipbrd.h"
25 #include "wx/colordlg.h"
26 #include "wx/metafile.h"
27 #include "wx/dirctrl.h"
29 #ifndef wxHAS_IMAGES_IN_RESOURCES
30 #include "../sample.xpm"
31 #if wxUSE_DRAG_AND_DROP
32 #include "dnd_copy.xpm"
33 #include "dnd_move.xpm"
34 #include "dnd_none.xpm"
38 #if wxUSE_DRAG_AND_DROP
40 // ----------------------------------------------------------------------------
41 // Derive two simple classes which just put in the listbox the strings (text or
42 // file names) we drop on them
43 // ----------------------------------------------------------------------------
45 class DnDText
: public wxTextDropTarget
48 DnDText(wxListBox
*pOwner
) { m_pOwner
= pOwner
; }
50 virtual bool OnDropText(wxCoord x
, wxCoord y
, const wxString
& text
);
56 class DnDFile
: public wxFileDropTarget
59 DnDFile(wxListBox
*pOwner
= NULL
) { m_pOwner
= pOwner
; }
61 virtual bool OnDropFiles(wxCoord x
, wxCoord y
,
62 const wxArrayString
& filenames
);
68 // ----------------------------------------------------------------------------
69 // Define a custom dtop target accepting URLs
70 // ----------------------------------------------------------------------------
72 class URLDropTarget
: public wxDropTarget
75 URLDropTarget() { SetDataObject(new wxURLDataObject
); }
77 void OnDropURL(wxCoord
WXUNUSED(x
), wxCoord
WXUNUSED(y
), const wxString
& text
)
79 // of course, a real program would do something more useful here...
80 wxMessageBox(text
, wxT("wxDnD sample: got URL"),
81 wxICON_INFORMATION
| wxOK
);
84 // URLs can't be moved, only copied
85 virtual wxDragResult
OnDragOver(wxCoord
WXUNUSED(x
), wxCoord
WXUNUSED(y
),
86 wxDragResult
WXUNUSED(def
))
88 return wxDragLink
; // At least IE 5.x needs wxDragLink, the
89 // other browsers on MSW seem okay with it too.
92 // translate this to calls to OnDropURL() just for convenience
93 virtual wxDragResult
OnData(wxCoord x
, wxCoord y
, wxDragResult def
)
98 OnDropURL(x
, y
, ((wxURLDataObject
*)m_dataObject
)->GetURL());
104 #endif // wxUSE_DRAG_AND_DROP
106 // ----------------------------------------------------------------------------
107 // Define a new application type
108 // ----------------------------------------------------------------------------
110 class DnDApp
: public wxApp
113 virtual bool OnInit();
116 IMPLEMENT_APP(DnDApp
)
118 #if wxUSE_DRAG_AND_DROP || wxUSE_CLIPBOARD
120 // ----------------------------------------------------------------------------
121 // Define canvas class to show a bitmap
122 // ----------------------------------------------------------------------------
124 class DnDCanvasBitmap
: public wxScrolledWindow
127 DnDCanvasBitmap(wxWindow
*parent
) : wxScrolledWindow(parent
) { }
129 void SetBitmap(const wxBitmap
& bitmap
)
133 SetScrollbars(10, 10,
134 m_bitmap
.GetWidth() / 10, m_bitmap
.GetHeight() / 10);
139 void OnPaint(wxPaintEvent
& WXUNUSED(event
))
143 if ( m_bitmap
.IsOk() )
147 dc
.DrawBitmap(m_bitmap
, 0, 0);
154 DECLARE_EVENT_TABLE()
159 // and the same thing fo metafiles
160 class DnDCanvasMetafile
: public wxScrolledWindow
163 DnDCanvasMetafile(wxWindow
*parent
) : wxScrolledWindow(parent
) { }
165 void SetMetafile(const wxMetafile
& metafile
)
167 m_metafile
= metafile
;
169 SetScrollbars(10, 10,
170 m_metafile
.GetWidth() / 10, m_metafile
.GetHeight() / 10);
175 void OnPaint(wxPaintEvent
&)
179 if ( m_metafile
.IsOk() )
183 m_metafile
.Play(&dc
);
188 wxMetafile m_metafile
;
190 DECLARE_EVENT_TABLE()
193 #endif // wxUSE_METAFILE
195 // ----------------------------------------------------------------------------
196 // Define a new frame type for the main frame
197 // ----------------------------------------------------------------------------
199 class DnDFrame
: public wxFrame
205 void OnPaint(wxPaintEvent
& event
);
206 void OnSize(wxSizeEvent
& event
);
207 void OnQuit(wxCommandEvent
& event
);
208 void OnAbout(wxCommandEvent
& event
);
209 void OnDrag(wxCommandEvent
& event
);
210 void OnDragMoveByDefault(wxCommandEvent
& event
);
211 void OnDragMoveAllow(wxCommandEvent
& event
);
212 void OnNewFrame(wxCommandEvent
& event
);
213 void OnHelp (wxCommandEvent
& event
);
215 void OnLogClear(wxCommandEvent
& event
);
218 void OnCopy(wxCommandEvent
& event
);
219 void OnPaste(wxCommandEvent
& event
);
221 void OnCopyBitmap(wxCommandEvent
& event
);
222 void OnPasteBitmap(wxCommandEvent
& event
);
225 void OnPasteMetafile(wxCommandEvent
& event
);
226 #endif // wxUSE_METAFILE
228 void OnCopyFiles(wxCommandEvent
& event
);
229 void OnCopyURL(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
));
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
));
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
));
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
));
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 // ----------------------------------------------------------------------------
821 Menu_Shape_New
= 500,
824 Menu_ShapeClipboard_Copy
,
825 Menu_ShapeClipboard_Paste
,
829 BEGIN_EVENT_TABLE(DnDFrame
, wxFrame
)
830 EVT_MENU(Menu_Quit
, DnDFrame::OnQuit
)
831 EVT_MENU(Menu_About
, DnDFrame::OnAbout
)
832 EVT_MENU(Menu_Drag
, DnDFrame::OnDrag
)
833 EVT_MENU(Menu_DragMoveDef
, DnDFrame::OnDragMoveByDefault
)
834 EVT_MENU(Menu_DragMoveAllow
,DnDFrame::OnDragMoveAllow
)
835 EVT_MENU(Menu_NewFrame
, DnDFrame::OnNewFrame
)
836 EVT_MENU(Menu_Help
, DnDFrame::OnHelp
)
838 EVT_MENU(Menu_Clear
, DnDFrame::OnLogClear
)
840 EVT_MENU(Menu_Copy
, DnDFrame::OnCopy
)
841 EVT_MENU(Menu_Paste
, DnDFrame::OnPaste
)
842 EVT_MENU(Menu_CopyBitmap
, DnDFrame::OnCopyBitmap
)
843 EVT_MENU(Menu_PasteBitmap
,DnDFrame::OnPasteBitmap
)
845 EVT_MENU(Menu_PasteMFile
, DnDFrame::OnPasteMetafile
)
846 #endif // wxUSE_METAFILE
847 EVT_MENU(Menu_CopyFiles
, DnDFrame::OnCopyFiles
)
848 EVT_MENU(Menu_CopyURL
, DnDFrame::OnCopyURL
)
849 EVT_MENU(Menu_UsePrimary
, DnDFrame::OnUsePrimary
)
851 EVT_UPDATE_UI(Menu_DragMoveDef
, DnDFrame::OnUpdateUIMoveByDefault
)
853 EVT_UPDATE_UI(Menu_Paste
, DnDFrame::OnUpdateUIPasteText
)
854 EVT_UPDATE_UI(Menu_PasteBitmap
, DnDFrame::OnUpdateUIPasteBitmap
)
856 EVT_LEFT_DOWN( DnDFrame::OnLeftDown
)
857 EVT_RIGHT_DOWN( DnDFrame::OnRightDown
)
858 EVT_PAINT( DnDFrame::OnPaint
)
859 EVT_SIZE( DnDFrame::OnSize
)
862 #if wxUSE_DRAG_AND_DROP
864 BEGIN_EVENT_TABLE(DnDShapeFrame
, wxFrame
)
865 EVT_MENU(Menu_Shape_New
, DnDShapeFrame::OnNewShape
)
866 EVT_MENU(Menu_Shape_Edit
, DnDShapeFrame::OnEditShape
)
867 EVT_MENU(Menu_Shape_Clear
, DnDShapeFrame::OnClearShape
)
869 EVT_MENU(Menu_ShapeClipboard_Copy
, DnDShapeFrame::OnCopyShape
)
870 EVT_MENU(Menu_ShapeClipboard_Paste
, DnDShapeFrame::OnPasteShape
)
872 EVT_UPDATE_UI(Menu_ShapeClipboard_Copy
, DnDShapeFrame::OnUpdateUICopy
)
873 EVT_UPDATE_UI(Menu_ShapeClipboard_Paste
, DnDShapeFrame::OnUpdateUIPaste
)
875 EVT_LEFT_DOWN(DnDShapeFrame::OnDrag
)
877 EVT_PAINT(DnDShapeFrame::OnPaint
)
880 BEGIN_EVENT_TABLE(DnDShapeDialog
, wxDialog
)
881 EVT_BUTTON(Button_Colour
, DnDShapeDialog::OnColour
)
884 #endif // wxUSE_DRAG_AND_DROP
886 BEGIN_EVENT_TABLE(DnDCanvasBitmap
, wxScrolledWindow
)
887 EVT_PAINT(DnDCanvasBitmap::OnPaint
)
891 BEGIN_EVENT_TABLE(DnDCanvasMetafile
, wxScrolledWindow
)
892 EVT_PAINT(DnDCanvasMetafile::OnPaint
)
894 #endif // wxUSE_METAFILE
896 #endif // wxUSE_DRAG_AND_DROP
898 // ============================================================================
900 // ============================================================================
902 // `Main program' equivalent, creating windows and returning main app frame
903 bool DnDApp::OnInit()
905 if ( !wxApp::OnInit() )
908 #if wxUSE_DRAG_AND_DROP || wxUSE_CLIPBOARD
909 // switch on trace messages
911 #if defined(__WXGTK__)
912 wxLog::AddTraceMask(wxT("clipboard"));
913 #elif defined(__WXMSW__)
914 wxLog::AddTraceMask(wxTRACE_OleCalls
);
919 wxImage::AddHandler( new wxPNGHandler
);
922 // create the main frame window
927 wxMessageBox( wxT("This sample has to be compiled with wxUSE_DRAG_AND_DROP"), wxT("Building error"), wxOK
);
929 #endif // wxUSE_DRAG_AND_DROP
932 #if wxUSE_DRAG_AND_DROP || wxUSE_CLIPBOARD
935 : wxFrame(NULL
, wxID_ANY
, wxT("Drag-and-Drop/Clipboard wxWidgets Sample"),
937 m_strText(wxT("wxWidgets drag & drop works :-)"))
940 // frame icon and status bar
941 SetIcon(wxICON(sample
));
945 #endif // wxUSE_STATUSBAR
948 wxMenu
*file_menu
= new wxMenu
;
949 file_menu
->Append(Menu_Drag
, wxT("&Test drag..."));
950 file_menu
->AppendCheckItem(Menu_DragMoveDef
, wxT("&Move by default"));
951 file_menu
->AppendCheckItem(Menu_DragMoveAllow
, wxT("&Allow moving"));
952 file_menu
->AppendSeparator();
953 file_menu
->Append(Menu_NewFrame
, wxT("&New frame\tCtrl-N"));
954 file_menu
->AppendSeparator();
955 file_menu
->Append(Menu_Quit
, wxT("E&xit\tCtrl-Q"));
958 wxMenu
*log_menu
= new wxMenu
;
959 log_menu
->Append(Menu_Clear
, wxT("Clear\tCtrl-L"));
962 wxMenu
*help_menu
= new wxMenu
;
963 help_menu
->Append(Menu_Help
, wxT("&Help..."));
964 help_menu
->AppendSeparator();
965 help_menu
->Append(Menu_About
, wxT("&About"));
967 wxMenu
*clip_menu
= new wxMenu
;
968 clip_menu
->Append(Menu_Copy
, wxT("&Copy text\tCtrl-C"));
969 clip_menu
->Append(Menu_Paste
, wxT("&Paste text\tCtrl-V"));
970 clip_menu
->AppendSeparator();
971 clip_menu
->Append(Menu_CopyBitmap
, wxT("Copy &bitmap\tCtrl-Shift-C"));
972 clip_menu
->Append(Menu_PasteBitmap
, wxT("Paste b&itmap\tCtrl-Shift-V"));
974 clip_menu
->AppendSeparator();
975 clip_menu
->Append(Menu_PasteMFile
, wxT("Paste &metafile\tCtrl-M"));
976 #endif // wxUSE_METAFILE
977 clip_menu
->AppendSeparator();
978 clip_menu
->Append(Menu_CopyFiles
, wxT("Copy &files\tCtrl-F"));
979 clip_menu
->Append(Menu_CopyURL
, wxT("Copy &URL\tCtrl-U"));
980 clip_menu
->AppendSeparator();
981 clip_menu
->AppendCheckItem(Menu_UsePrimary
, wxT("Use &primary selection\tCtrl-P"));
983 wxMenuBar
*menu_bar
= new wxMenuBar
;
984 menu_bar
->Append(file_menu
, wxT("&File"));
986 menu_bar
->Append(log_menu
, wxT("&Log"));
988 menu_bar
->Append(clip_menu
, wxT("&Clipboard"));
989 menu_bar
->Append(help_menu
, wxT("&Help"));
991 SetMenuBar(menu_bar
);
993 // create the child controls
994 SetBackgroundColour(*wxWHITE
); // labels read better on this background
996 wxString
strFile(wxT("Drop files here!")), strText(wxT("Drop text on me"));
998 m_ctrlFile
= new wxListBox(this, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, 1, &strFile
,
999 wxLB_HSCROLL
| wxLB_ALWAYS_SB
);
1000 m_ctrlText
= new wxListBox(this, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, 1, &strText
,
1001 wxLB_HSCROLL
| wxLB_ALWAYS_SB
);
1002 m_ctrlDir
= new wxGenericDirCtrl(this);
1005 m_ctrlLog
= new wxTextCtrl(this, wxID_ANY
, wxEmptyString
,
1006 wxDefaultPosition
, wxDefaultSize
,
1007 wxTE_MULTILINE
| wxTE_READONLY
|
1010 // redirect log messages to the text window
1011 m_pLog
= new wxLogTextCtrl(m_ctrlLog
);
1012 m_pLogPrev
= wxLog::SetActiveTarget(m_pLog
);
1015 #if wxUSE_DRAG_AND_DROP
1016 // associate drop targets with the controls
1017 m_ctrlFile
->SetDropTarget(new DnDFile(m_ctrlFile
));
1018 m_ctrlText
->SetDropTarget(new DnDText(m_ctrlText
));
1020 #if wxUSE_DRAG_AND_DROP
1024 wxEVT_TREE_BEGIN_DRAG
,
1025 wxTreeEventHandler(DnDFrame::OnBeginDrag
),
1029 #endif // wxUSE_DRAG_AND_DROP
1032 m_ctrlLog
->SetDropTarget(new URLDropTarget
);
1034 #endif // wxUSE_DRAG_AND_DROP
1036 wxBoxSizer
*sizer_top
= new wxBoxSizer( wxHORIZONTAL
);
1037 sizer_top
->Add(m_ctrlFile
, 1, wxEXPAND
);
1038 sizer_top
->Add(m_ctrlText
, 1, wxEXPAND
);
1040 wxBoxSizer
*sizerDirCtrl
= new wxBoxSizer(wxVERTICAL
);
1041 sizerDirCtrl
->Add(new wxStaticText(this, wxID_ANY
, "Drag files from here"),
1042 wxSizerFlags().Centre().Border());
1043 sizerDirCtrl
->Add(m_ctrlDir
, wxSizerFlags(1).Expand());
1044 sizer_top
->Add(sizerDirCtrl
, 1, wxEXPAND
);
1046 // make all columns of reasonable minimal size
1047 for ( unsigned n
= 0; n
< sizer_top
->GetChildren().size(); n
++ )
1048 sizer_top
->SetItemMinSize(n
, 200, 300);
1050 wxBoxSizer
*sizer
= new wxBoxSizer( wxVERTICAL
);
1051 sizer
->Add(sizer_top
, 1, wxEXPAND
);
1053 sizer
->Add(m_ctrlLog
, 2, wxEXPAND
);
1054 sizer
->SetItemMinSize(m_ctrlLog
, 450, 200);
1056 sizer
->AddSpacer(50);
1058 // copy data by default but allow moving it as well
1059 m_moveByDefault
= false;
1061 menu_bar
->Check(Menu_DragMoveAllow
, true);
1063 // set the correct size and show the frame
1064 SetSizerAndFit(sizer
);
1068 void DnDFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
1073 void DnDFrame::OnSize(wxSizeEvent
& event
)
1080 void DnDFrame::OnPaint(wxPaintEvent
& WXUNUSED(event
))
1084 GetClientSize( &w
, &h
);
1087 // dc.Clear(); -- this kills wxGTK
1088 dc
.SetFont( wxFont( 24, wxDECORATIVE
, wxNORMAL
, wxNORMAL
, false, wxT("charter") ) );
1089 dc
.DrawText( wxT("Drag text from here!"), 100, h
-50 );
1092 void DnDFrame::OnUpdateUIMoveByDefault(wxUpdateUIEvent
& event
)
1094 // only can move by default if moving is allowed at all
1095 event
.Enable(m_moveAllow
);
1098 void DnDFrame::OnUpdateUIPasteText(wxUpdateUIEvent
& event
)
1101 // too many trace messages if we don't do it - this function is called
1106 event
.Enable( wxTheClipboard
->IsSupported(wxDF_TEXT
) );
1109 void DnDFrame::OnUpdateUIPasteBitmap(wxUpdateUIEvent
& event
)
1112 // too many trace messages if we don't do it - this function is called
1117 event
.Enable( wxTheClipboard
->IsSupported(wxDF_BITMAP
) );
1120 void DnDFrame::OnNewFrame(wxCommandEvent
& WXUNUSED(event
))
1122 #if wxUSE_DRAG_AND_DROP
1123 (new DnDShapeFrame(this))->Show(true);
1125 wxLogStatus(this, wxT("Double click the new frame to select a shape for it"));
1126 #endif // wxUSE_DRAG_AND_DROP
1129 void DnDFrame::OnDrag(wxCommandEvent
& WXUNUSED(event
))
1131 #if wxUSE_DRAG_AND_DROP
1132 wxString strText
= wxGetTextFromUser
1134 wxT("After you enter text in this dialog, press any mouse\n")
1135 wxT("button in the bottom (empty) part of the frame and \n")
1136 wxT("drag it anywhere - you will be in fact dragging the\n")
1137 wxT("text object containing this text"),
1138 wxT("Please enter some text"), m_strText
, this
1141 m_strText
= strText
;
1142 #endif // wxUSE_DRAG_AND_DROP
1145 void DnDFrame::OnDragMoveByDefault(wxCommandEvent
& event
)
1147 m_moveByDefault
= event
.IsChecked();
1150 void DnDFrame::OnDragMoveAllow(wxCommandEvent
& event
)
1152 m_moveAllow
= event
.IsChecked();
1155 void DnDFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
1157 wxMessageBox(wxT("Drag-&-Drop Demo\n")
1158 wxT("Please see \"Help|Help...\" for details\n")
1159 wxT("Copyright (c) 1998 Vadim Zeitlin"),
1161 wxICON_INFORMATION
| wxOK
,
1165 void DnDFrame::OnHelp(wxCommandEvent
& /* event */)
1167 wxMessageDialog
dialog(this,
1168 wxT("This small program demonstrates drag & drop support in wxWidgets. The program window\n")
1169 wxT("consists of 3 parts: the bottom pane is for debug messages, so that you can see what's\n")
1170 wxT("going on inside. The top part is split into 2 listboxes, the left one accepts files\n")
1171 wxT("and the right one accepts text.\n")
1173 wxT("To test wxDropTarget: open wordpad (write.exe), select some text in it and drag it to\n")
1174 wxT("the right listbox (you'll notice the usual visual feedback, i.e. the cursor will change).\n")
1175 wxT("Also, try dragging some files (you can select several at once) from Windows Explorer (or \n")
1176 wxT("File Manager) to the left pane. Hold down Ctrl/Shift keys when you drop text (doesn't \n")
1177 wxT("work with files) and see what changes.\n")
1179 wxT("To test wxDropSource: just press any mouse button on the empty zone of the window and drag\n")
1180 wxT("it to wordpad or any other droptarget accepting text (and of course you can just drag it\n")
1181 wxT("to the right pane). Due to a lot of trace messages, the cursor might take some time to \n")
1182 wxT("change, don't release the mouse button until it does. You can change the string being\n")
1183 wxT("dragged in \"File|Test drag...\" dialog.\n")
1186 wxT("Please send all questions/bug reports/suggestions &c to \n")
1187 wxT("Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>"),
1194 void DnDFrame::OnLogClear(wxCommandEvent
& /* event */ )
1197 m_ctrlText
->Clear();
1198 m_ctrlFile
->Clear();
1202 #if wxUSE_DRAG_AND_DROP
1204 void DnDFrame::LogDragResult(wxDragResult result
)
1210 case wxDragError
: pc
= wxT("Error!"); break;
1211 case wxDragNone
: pc
= wxT("Nothing"); break;
1212 case wxDragCopy
: pc
= wxT("Copied"); break;
1213 case wxDragMove
: pc
= wxT("Moved"); break;
1214 case wxDragCancel
: pc
= wxT("Cancelled"); break;
1215 default: pc
= wxT("Huh?"); break;
1218 SetStatusText(wxString(wxT("Drag result: ")) + pc
);
1220 wxUnusedVar(result
);
1221 #endif // wxUSE_STATUSBAR
1224 #endif // wxUSE_DRAG_AND_DROP
1226 void DnDFrame::OnLeftDown(wxMouseEvent
&WXUNUSED(event
) )
1228 #if wxUSE_DRAG_AND_DROP
1229 if ( !m_strText
.empty() )
1231 // start drag operation
1232 wxTextDataObject
textData(m_strText
);
1233 wxDropSource
source(textData
, this,
1234 wxDROP_ICON(dnd_copy
),
1235 wxDROP_ICON(dnd_move
),
1236 wxDROP_ICON(dnd_none
));
1239 if ( m_moveByDefault
)
1240 flags
|= wxDrag_DefaultMove
;
1241 else if ( m_moveAllow
)
1242 flags
|= wxDrag_AllowMove
;
1244 LogDragResult(source
.DoDragDrop(flags
));
1246 #endif // wxUSE_DRAG_AND_DROP
1249 void DnDFrame::OnRightDown(wxMouseEvent
&event
)
1251 wxMenu
menu(wxT("Dnd sample menu"));
1253 menu
.Append(Menu_Drag
, wxT("&Test drag..."));
1254 menu
.AppendSeparator();
1255 menu
.Append(Menu_About
, wxT("&About"));
1257 PopupMenu( &menu
, event
.GetX(), event
.GetY() );
1260 DnDFrame::~DnDFrame()
1263 if ( m_pLog
!= NULL
) {
1264 if ( wxLog::SetActiveTarget(m_pLogPrev
) == m_pLog
)
1270 void DnDFrame::OnUsePrimary(wxCommandEvent
& event
)
1272 const bool usePrimary
= event
.IsChecked();
1273 wxTheClipboard
->UsePrimarySelection(usePrimary
);
1275 wxLogStatus(wxT("Now using %s selection"), usePrimary
? wxT("primary")
1276 : wxT("clipboard"));
1279 #if wxUSE_DRAG_AND_DROP
1281 void DnDFrame::OnBeginDrag(wxTreeEvent
& WXUNUSED(event
))
1283 wxFileDataObject data
;
1284 data
.AddFile(m_ctrlDir
->GetPath());
1286 wxDropSource
dragSource(this);
1287 dragSource
.SetData(data
);
1289 LogDragResult(dragSource
.DoDragDrop());
1292 #endif // wxUSE_DRAG_AND_DROP
1294 // ---------------------------------------------------------------------------
1296 // ---------------------------------------------------------------------------
1298 void DnDFrame::OnCopyBitmap(wxCommandEvent
& WXUNUSED(event
))
1300 // PNG support is not always compiled in under Windows, so use BMP there
1302 wxFileDialog
dialog(this, wxT("Open a PNG file"), wxEmptyString
, wxEmptyString
, wxT("PNG files (*.png)|*.png"), 0);
1304 wxFileDialog
dialog(this, wxT("Open a BMP file"), wxEmptyString
, wxEmptyString
, wxT("BMP files (*.bmp)|*.bmp"), 0);
1307 if (dialog
.ShowModal() != wxID_OK
)
1309 wxLogMessage( wxT("Aborted file open") );
1313 if (dialog
.GetPath().empty())
1315 wxLogMessage( wxT("Returned empty string.") );
1319 if (!wxFileExists(dialog
.GetPath()))
1321 wxLogMessage( wxT("File doesn't exist.") );
1326 image
.LoadFile( dialog
.GetPath(),
1335 wxLogError( wxT("Invalid image file...") );
1339 wxLogStatus( wxT("Decoding image file...") );
1342 wxBitmap
bitmap( image
);
1344 if ( !wxTheClipboard
->Open() )
1346 wxLogError(wxT("Can't open clipboard."));
1351 wxLogMessage( wxT("Creating wxBitmapDataObject...") );
1354 if ( !wxTheClipboard
->AddData(new wxBitmapDataObject(bitmap
)) )
1356 wxLogError(wxT("Can't copy image to the clipboard."));
1360 wxLogMessage(wxT("Image has been put on the clipboard.") );
1361 wxLogMessage(wxT("You can paste it now and look at it.") );
1364 wxTheClipboard
->Close();
1367 void DnDFrame::OnPasteBitmap(wxCommandEvent
& WXUNUSED(event
))
1369 if ( !wxTheClipboard
->Open() )
1371 wxLogError(wxT("Can't open clipboard."));
1376 if ( !wxTheClipboard
->IsSupported(wxDF_BITMAP
) )
1378 wxLogWarning(wxT("No bitmap on clipboard"));
1380 wxTheClipboard
->Close();
1384 wxBitmapDataObject data
;
1385 if ( !wxTheClipboard
->GetData(data
) )
1387 wxLogError(wxT("Can't paste bitmap from the clipboard"));
1391 const wxBitmap
& bmp
= data
.GetBitmap();
1393 wxLogMessage(wxT("Bitmap %dx%d pasted from the clipboard"),
1394 bmp
.GetWidth(), bmp
.GetHeight());
1398 wxTheClipboard
->Close();
1403 void DnDFrame::OnPasteMetafile(wxCommandEvent
& WXUNUSED(event
))
1405 if ( !wxTheClipboard
->Open() )
1407 wxLogError(wxT("Can't open clipboard."));
1412 if ( !wxTheClipboard
->IsSupported(wxDF_METAFILE
) )
1414 wxLogWarning(wxT("No metafile on clipboard"));
1418 wxMetaFileDataObject data
;
1419 if ( !wxTheClipboard
->GetData(data
) )
1421 wxLogError(wxT("Can't paste metafile from the clipboard"));
1425 const wxMetaFile
& mf
= data
.GetMetafile();
1427 wxLogMessage(wxT("Metafile %dx%d pasted from the clipboard"),
1428 mf
.GetWidth(), mf
.GetHeight());
1434 wxTheClipboard
->Close();
1437 #endif // wxUSE_METAFILE
1439 // ----------------------------------------------------------------------------
1441 // ----------------------------------------------------------------------------
1443 void DnDFrame::OnCopyFiles(wxCommandEvent
& WXUNUSED(event
))
1446 wxFileDialog
dialog(this, wxT("Select a file to copy"), wxEmptyString
, wxEmptyString
,
1447 wxT("All files (*.*)|*.*"), 0);
1449 wxArrayString filenames
;
1450 while ( dialog
.ShowModal() == wxID_OK
)
1452 filenames
.Add(dialog
.GetPath());
1455 if ( !filenames
.IsEmpty() )
1457 wxFileDataObject
*dobj
= new wxFileDataObject
;
1458 size_t count
= filenames
.GetCount();
1459 for ( size_t n
= 0; n
< count
; n
++ )
1461 dobj
->AddFile(filenames
[n
]);
1464 wxClipboardLocker locker
;
1467 wxLogError(wxT("Can't open clipboard"));
1471 if ( !wxTheClipboard
->AddData(dobj
) )
1473 wxLogError(wxT("Can't copy file(s) to the clipboard"));
1477 wxLogStatus(this, wxT("%d file%s copied to the clipboard"),
1478 count
, count
== 1 ? wxEmptyString
: wxEmptyString
);
1484 wxLogStatus(this, wxT("Aborted"));
1487 wxLogError(wxT("Sorry, not implemented"));
1491 void DnDFrame::OnCopyURL(wxCommandEvent
& WXUNUSED(event
))
1493 // Just hard code it for now, we could ask the user but the point here is
1494 // to test copying URLs, it doesn't really matter what it is.
1495 const wxString
url("http://www.wxwidgets.org/");
1497 wxClipboardLocker locker
;
1498 if ( !!locker
&& wxTheClipboard
->AddData(new wxURLDataObject(url
)) )
1500 wxLogStatus(this, "Copied URL \"%s\" to %s.",
1502 GetMenuBar()->IsChecked(Menu_UsePrimary
)
1503 ? "primary selection"
1508 wxLogError("Failed to copy URL.");
1512 // ---------------------------------------------------------------------------
1514 // ---------------------------------------------------------------------------
1516 void DnDFrame::OnCopy(wxCommandEvent
& WXUNUSED(event
))
1518 if ( !wxTheClipboard
->Open() )
1520 wxLogError(wxT("Can't open clipboard."));
1525 if ( !wxTheClipboard
->AddData(new wxTextDataObject(m_strText
)) )
1527 wxLogError(wxT("Can't copy data to the clipboard"));
1531 wxLogMessage(wxT("Text '%s' put on the clipboard"), m_strText
.c_str());
1534 wxTheClipboard
->Close();
1537 void DnDFrame::OnPaste(wxCommandEvent
& WXUNUSED(event
))
1539 if ( !wxTheClipboard
->Open() )
1541 wxLogError(wxT("Can't open clipboard."));
1546 if ( !wxTheClipboard
->IsSupported(wxDF_TEXT
) )
1548 wxLogWarning(wxT("No text data on clipboard"));
1550 wxTheClipboard
->Close();
1554 wxTextDataObject text
;
1555 if ( !wxTheClipboard
->GetData(text
) )
1557 wxLogError(wxT("Can't paste data from the clipboard"));
1561 wxLogMessage(wxT("Text '%s' pasted from the clipboard"),
1562 text
.GetText().c_str());
1565 wxTheClipboard
->Close();
1568 #if wxUSE_DRAG_AND_DROP
1570 // ----------------------------------------------------------------------------
1571 // Notifications called by the base class
1572 // ----------------------------------------------------------------------------
1574 bool DnDText::OnDropText(wxCoord
, wxCoord
, const wxString
& text
)
1576 m_pOwner
->Append(text
);
1581 bool DnDFile::OnDropFiles(wxCoord
, wxCoord
, const wxArrayString
& filenames
)
1583 size_t nFiles
= filenames
.GetCount();
1585 str
.Printf( wxT("%d files dropped"), (int)nFiles
);
1587 if (m_pOwner
!= NULL
)
1589 m_pOwner
->Append(str
);
1590 for ( size_t n
= 0; n
< nFiles
; n
++ )
1591 m_pOwner
->Append(filenames
[n
]);
1597 // ----------------------------------------------------------------------------
1599 // ----------------------------------------------------------------------------
1601 DnDShapeDialog::DnDShapeDialog(wxFrame
*parent
, DnDShape
*shape
)
1602 :wxDialog( parent
, 6001, wxT("Choose Shape"), wxPoint( 10, 10 ),
1604 wxDEFAULT_DIALOG_STYLE
| wxRAISED_BORDER
| wxRESIZE_BORDER
)
1607 wxBoxSizer
* topSizer
= new wxBoxSizer( wxVERTICAL
);
1610 wxBoxSizer
* shapesSizer
= new wxBoxSizer( wxHORIZONTAL
);
1611 const wxString choices
[] = { wxT("None"), wxT("Triangle"),
1612 wxT("Rectangle"), wxT("Ellipse") };
1614 m_radio
= new wxRadioBox( this, wxID_ANY
, wxT("&Shape"),
1615 wxDefaultPosition
, wxDefaultSize
, 4, choices
, 4,
1616 wxRA_SPECIFY_COLS
);
1617 shapesSizer
->Add( m_radio
, 0, wxGROW
|wxALL
, 5 );
1618 topSizer
->Add( shapesSizer
, 0, wxALL
, 2 );
1621 wxStaticBox
* box
= new wxStaticBox( this, wxID_ANY
, wxT("&Attributes") );
1622 wxStaticBoxSizer
* attrSizer
= new wxStaticBoxSizer( box
, wxHORIZONTAL
);
1623 wxFlexGridSizer
* xywhSizer
= new wxFlexGridSizer( 2 );
1627 st
= new wxStaticText( this, wxID_ANY
, wxT("Position &X:") );
1628 m_textX
= new wxTextCtrl( this, wxID_ANY
, wxEmptyString
, wxDefaultPosition
,
1630 xywhSizer
->Add( st
, 1, wxGROW
|wxALL
, 2 );
1631 xywhSizer
->Add( m_textX
, 1, wxGROW
|wxALL
, 2 );
1633 st
= new wxStaticText( this, wxID_ANY
, wxT("Size &width:") );
1634 m_textW
= new wxTextCtrl( this, wxID_ANY
, wxEmptyString
, wxDefaultPosition
,
1636 xywhSizer
->Add( st
, 1, wxGROW
|wxALL
, 2 );
1637 xywhSizer
->Add( m_textW
, 1, wxGROW
|wxALL
, 2 );
1639 st
= new wxStaticText( this, wxID_ANY
, wxT("&Y:") );
1640 m_textY
= new wxTextCtrl( this, wxID_ANY
, wxEmptyString
, wxDefaultPosition
,
1642 xywhSizer
->Add( st
, 1, wxALL
|wxALIGN_RIGHT
, 2 );
1643 xywhSizer
->Add( m_textY
, 1, wxGROW
|wxALL
, 2 );
1645 st
= new wxStaticText( this, wxID_ANY
, wxT("&height:") );
1646 m_textH
= new wxTextCtrl( this, wxID_ANY
, wxEmptyString
, wxDefaultPosition
,
1648 xywhSizer
->Add( st
, 1, wxALL
|wxALIGN_RIGHT
, 2 );
1649 xywhSizer
->Add( m_textH
, 1, wxGROW
|wxALL
, 2 );
1651 wxButton
* col
= new wxButton( this, Button_Colour
, wxT("&Colour...") );
1652 attrSizer
->Add( xywhSizer
, 1, wxGROW
);
1653 attrSizer
->Add( col
, 0, wxALL
|wxALIGN_CENTRE_VERTICAL
, 2 );
1654 topSizer
->Add( attrSizer
, 0, wxGROW
|wxALL
, 5 );
1657 wxBoxSizer
* buttonSizer
= new wxBoxSizer( wxHORIZONTAL
);
1659 bt
= new wxButton( this, wxID_OK
, wxT("Ok") );
1660 buttonSizer
->Add( bt
, 0, wxALL
, 2 );
1661 bt
= new wxButton( this, wxID_CANCEL
, wxT("Cancel") );
1662 buttonSizer
->Add( bt
, 0, wxALL
, 2 );
1663 topSizer
->Add( buttonSizer
, 0, wxALL
|wxALIGN_RIGHT
, 2 );
1665 SetSizerAndFit( topSizer
);
1668 DnDShape
*DnDShapeDialog::GetShape() const
1670 switch ( m_shapeKind
)
1673 case DnDShape::None
: return NULL
;
1674 case DnDShape::Triangle
: return new DnDTriangularShape(m_pos
, m_size
, m_col
);
1675 case DnDShape::Rectangle
: return new DnDRectangularShape(m_pos
, m_size
, m_col
);
1676 case DnDShape::Ellipse
: return new DnDEllipticShape(m_pos
, m_size
, m_col
);
1680 bool DnDShapeDialog::TransferDataToWindow()
1685 m_radio
->SetSelection(m_shape
->GetKind());
1686 m_pos
= m_shape
->GetPosition();
1687 m_size
= m_shape
->GetSize();
1688 m_col
= m_shape
->GetColour();
1692 m_radio
->SetSelection(DnDShape::None
);
1693 m_pos
= wxPoint(1, 1);
1694 m_size
= wxSize(100, 100);
1697 m_textX
->SetValue(wxString() << m_pos
.x
);
1698 m_textY
->SetValue(wxString() << m_pos
.y
);
1699 m_textW
->SetValue(wxString() << m_size
.x
);
1700 m_textH
->SetValue(wxString() << m_size
.y
);
1705 bool DnDShapeDialog::TransferDataFromWindow()
1707 m_shapeKind
= (DnDShape::Kind
)m_radio
->GetSelection();
1709 m_pos
.x
= wxAtoi(m_textX
->GetValue());
1710 m_pos
.y
= wxAtoi(m_textY
->GetValue());
1711 m_size
.x
= wxAtoi(m_textW
->GetValue());
1712 m_size
.y
= wxAtoi(m_textH
->GetValue());
1714 if ( !m_pos
.x
|| !m_pos
.y
|| !m_size
.x
|| !m_size
.y
)
1716 wxMessageBox(wxT("All sizes and positions should be non null!"),
1717 wxT("Invalid shape"), wxICON_HAND
| wxOK
, this);
1725 void DnDShapeDialog::OnColour(wxCommandEvent
& WXUNUSED(event
))
1728 data
.SetChooseFull(true);
1729 for (int i
= 0; i
< 16; i
++)
1731 wxColour
colour((unsigned char)(i
*16), (unsigned char)(i
*16), (unsigned char)(i
*16));
1732 data
.SetCustomColour(i
, colour
);
1735 wxColourDialog
dialog(this, &data
);
1736 if ( dialog
.ShowModal() == wxID_OK
)
1738 m_col
= dialog
.GetColourData().GetColour();
1742 // ----------------------------------------------------------------------------
1744 // ----------------------------------------------------------------------------
1746 DnDShapeFrame
*DnDShapeFrame::ms_lastDropTarget
= NULL
;
1748 DnDShapeFrame::DnDShapeFrame(wxFrame
*parent
)
1749 : wxFrame(parent
, wxID_ANY
, wxT("Shape Frame"))
1753 #endif // wxUSE_STATUSBAR
1755 wxMenu
*menuShape
= new wxMenu
;
1756 menuShape
->Append(Menu_Shape_New
, wxT("&New default shape\tCtrl-S"));
1757 menuShape
->Append(Menu_Shape_Edit
, wxT("&Edit shape\tCtrl-E"));
1758 menuShape
->AppendSeparator();
1759 menuShape
->Append(Menu_Shape_Clear
, wxT("&Clear shape\tCtrl-L"));
1761 wxMenu
*menuClipboard
= new wxMenu
;
1762 menuClipboard
->Append(Menu_ShapeClipboard_Copy
, wxT("&Copy\tCtrl-C"));
1763 menuClipboard
->Append(Menu_ShapeClipboard_Paste
, wxT("&Paste\tCtrl-V"));
1765 wxMenuBar
*menubar
= new wxMenuBar
;
1766 menubar
->Append(menuShape
, wxT("&Shape"));
1767 menubar
->Append(menuClipboard
, wxT("&Clipboard"));
1769 SetMenuBar(menubar
);
1772 SetStatusText(wxT("Press Ctrl-S to create a new shape"));
1773 #endif // wxUSE_STATUSBAR
1775 SetDropTarget(new DnDShapeDropTarget(this));
1779 SetBackgroundColour(*wxWHITE
);
1782 DnDShapeFrame::~DnDShapeFrame()
1788 void DnDShapeFrame::SetShape(DnDShape
*shape
)
1797 void DnDShapeFrame::OnDrag(wxMouseEvent
& event
)
1806 // start drag operation
1807 DnDShapeDataObject
shapeData(m_shape
);
1808 wxDropSource
source(shapeData
, this);
1810 const wxChar
*pc
= NULL
;
1811 switch ( source
.DoDragDrop(true) )
1815 wxLogError(wxT("An error occurred during drag and drop operation"));
1820 SetStatusText(wxT("Nothing happened"));
1821 #endif // wxUSE_STATUSBAR
1830 if ( ms_lastDropTarget
!= this )
1832 // don't delete the shape if we dropped it on ourselves!
1839 SetStatusText(wxT("Drag and drop operation cancelled"));
1840 #endif // wxUSE_STATUSBAR
1847 SetStatusText(wxString(wxT("Shape successfully ")) + pc
);
1848 #endif // wxUSE_STATUSBAR
1850 //else: status text already set
1853 void DnDShapeFrame::OnDrop(wxCoord x
, wxCoord y
, DnDShape
*shape
)
1855 ms_lastDropTarget
= this;
1861 s
.Printf(wxT("Shape dropped at (%d, %d)"), pt
.x
, pt
.y
);
1863 #endif // wxUSE_STATUSBAR
1869 void DnDShapeFrame::OnEditShape(wxCommandEvent
& WXUNUSED(event
))
1871 DnDShapeDialog
dlg(this, m_shape
);
1872 if ( dlg
.ShowModal() == wxID_OK
)
1874 SetShape(dlg
.GetShape());
1879 SetStatusText(wxT("You can now drag the shape to another frame"));
1881 #endif // wxUSE_STATUSBAR
1885 void DnDShapeFrame::OnNewShape(wxCommandEvent
& WXUNUSED(event
))
1887 SetShape(new DnDEllipticShape(wxPoint(10, 10), wxSize(80, 60), *wxRED
));
1890 SetStatusText(wxT("You can now drag the shape to another frame"));
1891 #endif // wxUSE_STATUSBAR
1894 void DnDShapeFrame::OnClearShape(wxCommandEvent
& WXUNUSED(event
))
1899 void DnDShapeFrame::OnCopyShape(wxCommandEvent
& WXUNUSED(event
))
1903 wxClipboardLocker clipLocker
;
1906 wxLogError(wxT("Can't open the clipboard"));
1911 wxTheClipboard
->AddData(new DnDShapeDataObject(m_shape
));
1915 void DnDShapeFrame::OnPasteShape(wxCommandEvent
& WXUNUSED(event
))
1917 wxClipboardLocker clipLocker
;
1920 wxLogError(wxT("Can't open the clipboard"));
1925 DnDShapeDataObject
shapeDataObject(NULL
);
1926 if ( wxTheClipboard
->GetData(shapeDataObject
) )
1928 SetShape(shapeDataObject
.GetShape());
1932 wxLogStatus(wxT("No shape on the clipboard"));
1936 void DnDShapeFrame::OnUpdateUICopy(wxUpdateUIEvent
& event
)
1938 event
.Enable( m_shape
!= NULL
);
1941 void DnDShapeFrame::OnUpdateUIPaste(wxUpdateUIEvent
& event
)
1943 event
.Enable( wxTheClipboard
->IsSupported(wxDataFormat(shapeFormatId
)) );
1946 void DnDShapeFrame::OnPaint(wxPaintEvent
& event
)
1960 // ----------------------------------------------------------------------------
1962 // ----------------------------------------------------------------------------
1964 DnDShape
*DnDShape::New(const void *buf
)
1966 const ShapeDump
& dump
= *(const ShapeDump
*)buf
;
1970 return new DnDTriangularShape(wxPoint(dump
.x
, dump
.y
),
1971 wxSize(dump
.w
, dump
.h
),
1972 wxColour(dump
.r
, dump
.g
, dump
.b
));
1975 return new DnDRectangularShape(wxPoint(dump
.x
, dump
.y
),
1976 wxSize(dump
.w
, dump
.h
),
1977 wxColour(dump
.r
, dump
.g
, dump
.b
));
1980 return new DnDEllipticShape(wxPoint(dump
.x
, dump
.y
),
1981 wxSize(dump
.w
, dump
.h
),
1982 wxColour(dump
.r
, dump
.g
, dump
.b
));
1985 wxFAIL_MSG(wxT("invalid shape!"));
1990 // ----------------------------------------------------------------------------
1991 // DnDShapeDataObject
1992 // ----------------------------------------------------------------------------
1996 void DnDShapeDataObject::CreateMetaFile() const
1998 wxPoint pos
= m_shape
->GetPosition();
1999 wxSize size
= m_shape
->GetSize();
2001 wxMetaFileDC
dcMF(wxEmptyString
, pos
.x
+ size
.x
, pos
.y
+ size
.y
);
2003 m_shape
->Draw(dcMF
);
2005 wxMetafile
*mf
= dcMF
.Close();
2007 DnDShapeDataObject
*self
= (DnDShapeDataObject
*)this; // const_cast
2008 self
->m_dobjMetaFile
.SetMetafile(*mf
);
2009 self
->m_hasMetaFile
= true;
2014 #endif // wxUSE_METAFILE
2016 void DnDShapeDataObject::CreateBitmap() const
2018 wxPoint pos
= m_shape
->GetPosition();
2019 wxSize size
= m_shape
->GetSize();
2020 int x
= pos
.x
+ size
.x
,
2022 wxBitmap
bitmap(x
, y
);
2024 dc
.SelectObject(bitmap
);
2025 dc
.SetBrush(*wxWHITE_BRUSH
);
2028 dc
.SelectObject(wxNullBitmap
);
2030 DnDShapeDataObject
*self
= (DnDShapeDataObject
*)this; // const_cast
2031 self
->m_dobjBitmap
.SetBitmap(bitmap
);
2032 self
->m_hasBitmap
= true;
2035 #endif // wxUSE_DRAG_AND_DROP
2037 // ----------------------------------------------------------------------------
2039 // ----------------------------------------------------------------------------
2041 static void ShowBitmap(const wxBitmap
& bitmap
)
2043 wxFrame
*frame
= new wxFrame(NULL
, wxID_ANY
, wxT("Bitmap view"));
2045 frame
->CreateStatusBar();
2046 #endif // wxUSE_STATUSBAR
2047 DnDCanvasBitmap
*canvas
= new DnDCanvasBitmap(frame
);
2048 canvas
->SetBitmap(bitmap
);
2050 int w
= bitmap
.GetWidth(),
2051 h
= bitmap
.GetHeight();
2053 frame
->SetStatusText(wxString::Format(wxT("%dx%d"), w
, h
));
2054 #endif // wxUSE_STATUSBAR
2056 frame
->SetClientSize(w
> 100 ? 100 : w
, h
> 100 ? 100 : h
);
2062 static void ShowMetaFile(const wxMetaFile
& metafile
)
2064 wxFrame
*frame
= new wxFrame(NULL
, wxID_ANY
, wxT("Metafile view"));
2065 frame
->CreateStatusBar();
2066 DnDCanvasMetafile
*canvas
= new DnDCanvasMetafile(frame
);
2067 canvas
->SetMetafile(metafile
);
2069 wxSize size
= metafile
.GetSize();
2070 frame
->SetStatusText(wxString::Format(wxT("%dx%d"), size
.x
, size
.y
));
2072 frame
->SetClientSize(size
.x
> 100 ? 100 : size
.x
,
2073 size
.y
> 100 ? 100 : size
.y
);
2077 #endif // wxUSE_METAFILE
2079 #endif // wxUSE_DRAG_AND_DROP || wxUSE_CLIPBOARD