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 #ifndef wxHAS_IMAGES_IN_RESOURCES
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
))
144 if ( m_bitmap
.IsOk() )
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
.IsOk() )
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
);
230 void OnCopyURL(wxCommandEvent
& event
);
232 void OnUsePrimary(wxCommandEvent
& event
);
234 void OnLeftDown(wxMouseEvent
& event
);
235 void OnRightDown(wxMouseEvent
& event
);
237 #if wxUSE_DRAG_AND_DROP
238 void OnBeginDrag(wxTreeEvent
& event
);
239 #endif // wxUSE_DRAG_AND_DROP
241 void OnUpdateUIMoveByDefault(wxUpdateUIEvent
& event
);
243 void OnUpdateUIPasteText(wxUpdateUIEvent
& event
);
244 void OnUpdateUIPasteBitmap(wxUpdateUIEvent
& event
);
247 #if wxUSE_DRAG_AND_DROP
248 // show the result of a dnd operation in the status bar
249 void LogDragResult(wxDragResult result
);
250 #endif // wxUSE_DRAG_AND_DROP
254 wxListBox
*m_ctrlFile
,
256 wxGenericDirCtrl
*m_ctrlDir
;
259 wxTextCtrl
*m_ctrlLog
;
265 // move the text by default (or copy)?
266 bool m_moveByDefault
;
268 // allow moving the text at all?
275 DECLARE_EVENT_TABLE()
278 // ----------------------------------------------------------------------------
279 // A shape is an example of application-specific data which may be transported
280 // via drag-and-drop or clipboard: in our case, we have different geometric
281 // shapes, each one with its own colour and position
282 // ----------------------------------------------------------------------------
284 #if wxUSE_DRAG_AND_DROP
297 DnDShape(const wxPoint
& pos
,
300 : m_pos(pos
), m_size(size
), m_col(col
)
304 // this is for debugging - lets us see when exactly an object is freed
305 // (this may be later than you think if it's on the clipboard, for example)
306 virtual ~DnDShape() { }
308 // the functions used for drag-and-drop: they dump and restore a shape into
309 // some bitwise-copiable data (might use streams too...)
310 // ------------------------------------------------------------------------
312 // restore from buffer
313 static DnDShape
*New(const void *buf
);
315 virtual size_t GetDataSize() const
317 return sizeof(ShapeDump
);
320 virtual void GetDataHere(void *buf
) const
322 ShapeDump
& dump
= *(ShapeDump
*)buf
;
327 dump
.r
= m_col
.Red();
328 dump
.g
= m_col
.Green();
329 dump
.b
= m_col
.Blue();
334 const wxPoint
& GetPosition() const { return m_pos
; }
335 const wxColour
& GetColour() const { return m_col
; }
336 const wxSize
& GetSize() const { return m_size
; }
338 void Move(const wxPoint
& pos
) { m_pos
= pos
; }
340 // to implement in derived classes
341 virtual Kind
GetKind() const = 0;
343 virtual void Draw(wxDC
& dc
)
345 dc
.SetPen(wxPen(m_col
));
349 //get a point 1 up and 1 left, otherwise the mid-point of a triangle is on the line
350 wxPoint
GetCentre() const
351 { return wxPoint(m_pos
.x
+ m_size
.x
/ 2 - 1, m_pos
.y
+ m_size
.y
/ 2 - 1); }
355 wxCoord x
, y
, // position
358 unsigned char r
, g
, b
; // colour
366 class DnDTriangularShape
: public DnDShape
369 DnDTriangularShape(const wxPoint
& pos
,
372 : DnDShape(pos
, size
, col
)
374 wxLogMessage(wxT("DnDTriangularShape is being created"));
377 virtual ~DnDTriangularShape()
379 wxLogMessage(wxT("DnDTriangularShape is being deleted"));
382 virtual Kind
GetKind() const { return Triangle
; }
383 virtual void Draw(wxDC
& dc
)
387 // well, it's a bit difficult to describe a triangle by position and
388 // size, but we're not doing geometry here, do we? ;-)
390 wxPoint
p2(m_pos
.x
+ m_size
.x
, m_pos
.y
);
391 wxPoint
p3(m_pos
.x
, m_pos
.y
+ m_size
.y
);
397 //works in multicolor modes; on GTK (at least) will fail in 16-bit color
398 dc
.SetBrush(wxBrush(m_col
));
399 dc
.FloodFill(GetCentre(), m_col
, wxFLOOD_BORDER
);
403 class DnDRectangularShape
: public DnDShape
406 DnDRectangularShape(const wxPoint
& pos
,
409 : DnDShape(pos
, size
, col
)
411 wxLogMessage(wxT("DnDRectangularShape is being created"));
414 virtual ~DnDRectangularShape()
416 wxLogMessage(wxT("DnDRectangularShape is being deleted"));
419 virtual Kind
GetKind() const { return Rectangle
; }
420 virtual void Draw(wxDC
& dc
)
425 wxPoint
p2(p1
.x
+ m_size
.x
, p1
.y
);
426 wxPoint
p3(p2
.x
, p2
.y
+ m_size
.y
);
427 wxPoint
p4(p1
.x
, p3
.y
);
434 dc
.SetBrush(wxBrush(m_col
));
435 dc
.FloodFill(GetCentre(), m_col
, wxFLOOD_BORDER
);
439 class DnDEllipticShape
: public DnDShape
442 DnDEllipticShape(const wxPoint
& pos
,
445 : DnDShape(pos
, size
, col
)
447 wxLogMessage(wxT("DnDEllipticShape is being created"));
450 virtual ~DnDEllipticShape()
452 wxLogMessage(wxT("DnDEllipticShape is being deleted"));
455 virtual Kind
GetKind() const { return Ellipse
; }
456 virtual void Draw(wxDC
& dc
)
460 dc
.DrawEllipse(m_pos
, m_size
);
462 dc
.SetBrush(wxBrush(m_col
));
463 dc
.FloodFill(GetCentre(), m_col
, wxFLOOD_BORDER
);
467 // ----------------------------------------------------------------------------
468 // A wxDataObject specialisation for the application-specific data
469 // ----------------------------------------------------------------------------
471 static const wxChar
*shapeFormatId
= wxT("wxShape");
473 class DnDShapeDataObject
: public wxDataObject
476 // ctor doesn't copy the pointer, so it shouldn't go away while this object
478 DnDShapeDataObject(DnDShape
*shape
= (DnDShape
*)NULL
)
482 // we need to copy the shape because the one we're handled may be
483 // deleted while it's still on the clipboard (for example) - and we
484 // reuse the serialisation methods here to copy it
485 void *buf
= malloc(shape
->DnDShape::GetDataSize());
486 shape
->GetDataHere(buf
);
487 m_shape
= DnDShape::New(buf
);
497 // this string should uniquely identify our format, but is otherwise
499 m_formatShape
.SetId(shapeFormatId
);
501 // we don't draw the shape to a bitmap until it's really needed (i.e.
502 // we're asked to do so)
505 m_hasMetaFile
= false;
506 #endif // wxUSE_METAFILE
509 virtual ~DnDShapeDataObject() { delete m_shape
; }
511 // after a call to this function, the shape is owned by the caller and it
512 // is responsible for deleting it!
514 // NB: a better solution would be to make DnDShapes ref counted and this
515 // is what should probably be done in a real life program, otherwise
516 // the ownership problems become too complicated really fast
519 DnDShape
*shape
= m_shape
;
521 m_shape
= (DnDShape
*)NULL
;
524 m_hasMetaFile
= false;
525 #endif // wxUSE_METAFILE
530 // implement base class pure virtuals
531 // ----------------------------------
533 virtual wxDataFormat
GetPreferredFormat(Direction
WXUNUSED(dir
)) const
535 return m_formatShape
;
538 virtual size_t GetFormatCount(Direction dir
) const
540 // our custom format is supported by both GetData() and SetData()
544 // but the bitmap format(s) are only supported for output
545 nFormats
+= m_dobjBitmap
.GetFormatCount(dir
);
548 nFormats
+= m_dobjMetaFile
.GetFormatCount(dir
);
549 #endif // wxUSE_METAFILE
555 virtual void GetAllFormats(wxDataFormat
*formats
, Direction dir
) const
557 formats
[0] = m_formatShape
;
560 // in Get direction we additionally support bitmaps and metafiles
562 m_dobjBitmap
.GetAllFormats(&formats
[1], dir
);
565 // don't assume that m_dobjBitmap has only 1 format
566 m_dobjMetaFile
.GetAllFormats(&formats
[1 +
567 m_dobjBitmap
.GetFormatCount(dir
)], dir
);
568 #endif // wxUSE_METAFILE
572 virtual size_t GetDataSize(const wxDataFormat
& format
) const
574 if ( format
== m_formatShape
)
576 return m_shape
->GetDataSize();
579 else if ( m_dobjMetaFile
.IsSupported(format
) )
581 if ( !m_hasMetaFile
)
584 return m_dobjMetaFile
.GetDataSize(format
);
586 #endif // wxUSE_METAFILE
589 wxASSERT_MSG( m_dobjBitmap
.IsSupported(format
),
590 wxT("unexpected format") );
595 return m_dobjBitmap
.GetDataSize();
599 virtual bool GetDataHere(const wxDataFormat
& format
, void *pBuf
) const
601 if ( format
== m_formatShape
)
603 m_shape
->GetDataHere(pBuf
);
608 else if ( m_dobjMetaFile
.IsSupported(format
) )
610 if ( !m_hasMetaFile
)
613 return m_dobjMetaFile
.GetDataHere(format
, pBuf
);
615 #endif // wxUSE_METAFILE
618 wxASSERT_MSG( m_dobjBitmap
.IsSupported(format
),
619 wxT("unexpected format") );
624 return m_dobjBitmap
.GetDataHere(pBuf
);
628 virtual bool SetData(const wxDataFormat
& format
,
629 size_t WXUNUSED(len
), const void *buf
)
631 wxCHECK_MSG( format
== m_formatShape
, false,
632 wxT( "unsupported format") );
635 m_shape
= DnDShape::New(buf
);
637 // the shape has changed
641 m_hasMetaFile
= false;
642 #endif // wxUSE_METAFILE
648 // creates a bitmap and assigns it to m_dobjBitmap (also sets m_hasBitmap)
649 void CreateBitmap() const;
651 void CreateMetaFile() const;
652 #endif // wxUSE_METAFILE
654 wxDataFormat m_formatShape
; // our custom format
656 wxBitmapDataObject m_dobjBitmap
; // it handles bitmaps
657 bool m_hasBitmap
; // true if m_dobjBitmap has valid bitmap
660 wxMetaFileDataObject m_dobjMetaFile
;// handles metafiles
661 bool m_hasMetaFile
; // true if we have valid metafile
662 #endif // wxUSE_METAFILE
664 DnDShape
*m_shape
; // our data
667 // ----------------------------------------------------------------------------
668 // A dialog to edit shape properties
669 // ----------------------------------------------------------------------------
671 class DnDShapeDialog
: public wxDialog
674 DnDShapeDialog(wxFrame
*parent
, DnDShape
*shape
);
676 DnDShape
*GetShape() const;
678 virtual bool TransferDataToWindow();
679 virtual bool TransferDataFromWindow();
681 void OnColour(wxCommandEvent
& event
);
688 DnDShape::Kind m_shapeKind
;
700 DECLARE_EVENT_TABLE()
703 // ----------------------------------------------------------------------------
704 // A frame for the shapes which can be drag-and-dropped between frames
705 // ----------------------------------------------------------------------------
707 class DnDShapeFrame
: public wxFrame
710 DnDShapeFrame(wxFrame
*parent
);
713 void SetShape(DnDShape
*shape
);
714 virtual bool SetShape(const wxRegion
®ion
)
716 return wxFrame::SetShape( region
);
720 void OnNewShape(wxCommandEvent
& event
);
721 void OnEditShape(wxCommandEvent
& event
);
722 void OnClearShape(wxCommandEvent
& event
);
724 void OnCopyShape(wxCommandEvent
& event
);
725 void OnPasteShape(wxCommandEvent
& event
);
727 void OnUpdateUICopy(wxUpdateUIEvent
& event
);
728 void OnUpdateUIPaste(wxUpdateUIEvent
& event
);
730 void OnDrag(wxMouseEvent
& event
);
731 void OnPaint(wxPaintEvent
& event
);
732 void OnDrop(wxCoord x
, wxCoord y
, DnDShape
*shape
);
737 static DnDShapeFrame
*ms_lastDropTarget
;
739 DECLARE_EVENT_TABLE()
742 // ----------------------------------------------------------------------------
743 // wxDropTarget derivation for DnDShapes
744 // ----------------------------------------------------------------------------
746 class DnDShapeDropTarget
: public wxDropTarget
749 DnDShapeDropTarget(DnDShapeFrame
*frame
)
750 : wxDropTarget(new DnDShapeDataObject
)
755 // override base class (pure) virtuals
756 virtual wxDragResult
OnEnter(wxCoord x
, wxCoord y
, wxDragResult def
)
759 m_frame
->SetStatusText(wxT("Mouse entered the frame"));
760 #endif // wxUSE_STATUSBAR
761 return OnDragOver(x
, y
, def
);
763 virtual void OnLeave()
766 m_frame
->SetStatusText(wxT("Mouse left the frame"));
767 #endif // wxUSE_STATUSBAR
769 virtual wxDragResult
OnData(wxCoord x
, wxCoord y
, wxDragResult def
)
773 wxLogError(wxT("Failed to get drag and drop data"));
778 m_frame
->OnDrop(x
, y
,
779 ((DnDShapeDataObject
*)GetDataObject())->GetShape());
785 DnDShapeFrame
*m_frame
;
788 #endif // wxUSE_DRAG_AND_DROP
790 // ----------------------------------------------------------------------------
791 // functions prototypes
792 // ----------------------------------------------------------------------------
794 static void ShowBitmap(const wxBitmap
& bitmap
);
797 static void ShowMetaFile(const wxMetaFile
& metafile
);
798 #endif // wxUSE_METAFILE
800 // ----------------------------------------------------------------------------
801 // IDs for the menu commands
802 // ----------------------------------------------------------------------------
822 Menu_Shape_New
= 500,
825 Menu_ShapeClipboard_Copy
,
826 Menu_ShapeClipboard_Paste
,
830 BEGIN_EVENT_TABLE(DnDFrame
, wxFrame
)
831 EVT_MENU(Menu_Quit
, DnDFrame::OnQuit
)
832 EVT_MENU(Menu_About
, DnDFrame::OnAbout
)
833 EVT_MENU(Menu_Drag
, DnDFrame::OnDrag
)
834 EVT_MENU(Menu_DragMoveDef
, DnDFrame::OnDragMoveByDefault
)
835 EVT_MENU(Menu_DragMoveAllow
,DnDFrame::OnDragMoveAllow
)
836 EVT_MENU(Menu_NewFrame
, DnDFrame::OnNewFrame
)
837 EVT_MENU(Menu_Help
, DnDFrame::OnHelp
)
839 EVT_MENU(Menu_Clear
, DnDFrame::OnLogClear
)
841 EVT_MENU(Menu_Copy
, DnDFrame::OnCopy
)
842 EVT_MENU(Menu_Paste
, DnDFrame::OnPaste
)
843 EVT_MENU(Menu_CopyBitmap
, DnDFrame::OnCopyBitmap
)
844 EVT_MENU(Menu_PasteBitmap
,DnDFrame::OnPasteBitmap
)
846 EVT_MENU(Menu_PasteMFile
, DnDFrame::OnPasteMetafile
)
847 #endif // wxUSE_METAFILE
848 EVT_MENU(Menu_CopyFiles
, DnDFrame::OnCopyFiles
)
849 EVT_MENU(Menu_CopyURL
, DnDFrame::OnCopyURL
)
850 EVT_MENU(Menu_UsePrimary
, DnDFrame::OnUsePrimary
)
852 EVT_UPDATE_UI(Menu_DragMoveDef
, DnDFrame::OnUpdateUIMoveByDefault
)
854 EVT_UPDATE_UI(Menu_Paste
, DnDFrame::OnUpdateUIPasteText
)
855 EVT_UPDATE_UI(Menu_PasteBitmap
, DnDFrame::OnUpdateUIPasteBitmap
)
857 EVT_LEFT_DOWN( DnDFrame::OnLeftDown
)
858 EVT_RIGHT_DOWN( DnDFrame::OnRightDown
)
859 EVT_PAINT( DnDFrame::OnPaint
)
860 EVT_SIZE( DnDFrame::OnSize
)
863 #if wxUSE_DRAG_AND_DROP
865 BEGIN_EVENT_TABLE(DnDShapeFrame
, wxFrame
)
866 EVT_MENU(Menu_Shape_New
, DnDShapeFrame::OnNewShape
)
867 EVT_MENU(Menu_Shape_Edit
, DnDShapeFrame::OnEditShape
)
868 EVT_MENU(Menu_Shape_Clear
, DnDShapeFrame::OnClearShape
)
870 EVT_MENU(Menu_ShapeClipboard_Copy
, DnDShapeFrame::OnCopyShape
)
871 EVT_MENU(Menu_ShapeClipboard_Paste
, DnDShapeFrame::OnPasteShape
)
873 EVT_UPDATE_UI(Menu_ShapeClipboard_Copy
, DnDShapeFrame::OnUpdateUICopy
)
874 EVT_UPDATE_UI(Menu_ShapeClipboard_Paste
, DnDShapeFrame::OnUpdateUIPaste
)
876 EVT_LEFT_DOWN(DnDShapeFrame::OnDrag
)
878 EVT_PAINT(DnDShapeFrame::OnPaint
)
881 BEGIN_EVENT_TABLE(DnDShapeDialog
, wxDialog
)
882 EVT_BUTTON(Button_Colour
, DnDShapeDialog::OnColour
)
885 #endif // wxUSE_DRAG_AND_DROP
887 BEGIN_EVENT_TABLE(DnDCanvasBitmap
, wxScrolledWindow
)
888 EVT_PAINT(DnDCanvasBitmap::OnPaint
)
892 BEGIN_EVENT_TABLE(DnDCanvasMetafile
, wxScrolledWindow
)
893 EVT_PAINT(DnDCanvasMetafile::OnPaint
)
895 #endif // wxUSE_METAFILE
897 #endif // wxUSE_DRAG_AND_DROP
899 // ============================================================================
901 // ============================================================================
903 // `Main program' equivalent, creating windows and returning main app frame
904 bool DnDApp::OnInit()
906 if ( !wxApp::OnInit() )
909 #if wxUSE_DRAG_AND_DROP || wxUSE_CLIPBOARD
910 // switch on trace messages
912 #if defined(__WXGTK__)
913 wxLog::AddTraceMask(wxT("clipboard"));
914 #elif defined(__WXMSW__)
915 wxLog::AddTraceMask(wxTRACE_OleCalls
);
920 wxImage::AddHandler( new wxPNGHandler
);
923 // create the main frame window
928 wxMessageBox( wxT("This sample has to be compiled with wxUSE_DRAG_AND_DROP"), wxT("Building error"), wxOK
);
930 #endif // wxUSE_DRAG_AND_DROP
933 #if wxUSE_DRAG_AND_DROP || wxUSE_CLIPBOARD
936 : wxFrame(NULL
, wxID_ANY
, wxT("Drag-and-Drop/Clipboard wxWidgets Sample"),
938 m_strText(wxT("wxWidgets drag & drop works :-)"))
941 // frame icon and status bar
942 SetIcon(wxICON(sample
));
946 #endif // wxUSE_STATUSBAR
949 wxMenu
*file_menu
= new wxMenu
;
950 file_menu
->Append(Menu_Drag
, wxT("&Test drag..."));
951 file_menu
->AppendCheckItem(Menu_DragMoveDef
, wxT("&Move by default"));
952 file_menu
->AppendCheckItem(Menu_DragMoveAllow
, wxT("&Allow moving"));
953 file_menu
->AppendSeparator();
954 file_menu
->Append(Menu_NewFrame
, wxT("&New frame\tCtrl-N"));
955 file_menu
->AppendSeparator();
956 file_menu
->Append(Menu_Quit
, wxT("E&xit\tCtrl-Q"));
959 wxMenu
*log_menu
= new wxMenu
;
960 log_menu
->Append(Menu_Clear
, wxT("Clear\tCtrl-L"));
963 wxMenu
*help_menu
= new wxMenu
;
964 help_menu
->Append(Menu_Help
, wxT("&Help..."));
965 help_menu
->AppendSeparator();
966 help_menu
->Append(Menu_About
, wxT("&About"));
968 wxMenu
*clip_menu
= new wxMenu
;
969 clip_menu
->Append(Menu_Copy
, wxT("&Copy text\tCtrl-C"));
970 clip_menu
->Append(Menu_Paste
, wxT("&Paste text\tCtrl-V"));
971 clip_menu
->AppendSeparator();
972 clip_menu
->Append(Menu_CopyBitmap
, wxT("Copy &bitmap\tCtrl-Shift-C"));
973 clip_menu
->Append(Menu_PasteBitmap
, wxT("Paste b&itmap\tCtrl-Shift-V"));
975 clip_menu
->AppendSeparator();
976 clip_menu
->Append(Menu_PasteMFile
, wxT("Paste &metafile\tCtrl-M"));
977 #endif // wxUSE_METAFILE
978 clip_menu
->AppendSeparator();
979 clip_menu
->Append(Menu_CopyFiles
, wxT("Copy &files\tCtrl-F"));
980 clip_menu
->Append(Menu_CopyURL
, wxT("Copy &URL\tCtrl-U"));
981 clip_menu
->AppendSeparator();
982 clip_menu
->AppendCheckItem(Menu_UsePrimary
, wxT("Use &primary selection\tCtrl-P"));
984 wxMenuBar
*menu_bar
= new wxMenuBar
;
985 menu_bar
->Append(file_menu
, wxT("&File"));
987 menu_bar
->Append(log_menu
, wxT("&Log"));
989 menu_bar
->Append(clip_menu
, wxT("&Clipboard"));
990 menu_bar
->Append(help_menu
, wxT("&Help"));
992 SetMenuBar(menu_bar
);
994 // create the child controls
995 SetBackgroundColour(*wxWHITE
); // labels read better on this background
997 wxString
strFile(wxT("Drop files here!")), strText(wxT("Drop text on me"));
999 m_ctrlFile
= new wxListBox(this, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, 1, &strFile
,
1000 wxLB_HSCROLL
| wxLB_ALWAYS_SB
);
1001 m_ctrlText
= new wxListBox(this, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
, 1, &strText
,
1002 wxLB_HSCROLL
| wxLB_ALWAYS_SB
);
1003 m_ctrlDir
= new wxGenericDirCtrl(this);
1006 m_ctrlLog
= new wxTextCtrl(this, wxID_ANY
, wxEmptyString
,
1007 wxDefaultPosition
, wxDefaultSize
,
1008 wxTE_MULTILINE
| wxTE_READONLY
|
1011 // redirect log messages to the text window
1012 m_pLog
= new wxLogTextCtrl(m_ctrlLog
);
1013 m_pLogPrev
= wxLog::SetActiveTarget(m_pLog
);
1016 #if wxUSE_DRAG_AND_DROP
1017 // associate drop targets with the controls
1018 m_ctrlFile
->SetDropTarget(new DnDFile(m_ctrlFile
));
1019 m_ctrlText
->SetDropTarget(new DnDText(m_ctrlText
));
1021 #if wxUSE_DRAG_AND_DROP
1025 wxEVT_COMMAND_TREE_BEGIN_DRAG
,
1026 wxTreeEventHandler(DnDFrame::OnBeginDrag
),
1030 #endif // wxUSE_DRAG_AND_DROP
1033 m_ctrlLog
->SetDropTarget(new URLDropTarget
);
1035 #endif // wxUSE_DRAG_AND_DROP
1037 wxBoxSizer
*sizer_top
= new wxBoxSizer( wxHORIZONTAL
);
1038 sizer_top
->Add(m_ctrlFile
, 1, wxEXPAND
);
1039 sizer_top
->Add(m_ctrlText
, 1, wxEXPAND
);
1041 wxBoxSizer
*sizerDirCtrl
= new wxBoxSizer(wxVERTICAL
);
1042 sizerDirCtrl
->Add(new wxStaticText(this, wxID_ANY
, "Drag files from here"),
1043 wxSizerFlags().Centre().Border());
1044 sizerDirCtrl
->Add(m_ctrlDir
, wxSizerFlags(1).Expand());
1045 sizer_top
->Add(sizerDirCtrl
, 1, wxEXPAND
);
1047 // make all columns of reasonable minimal size
1048 for ( unsigned n
= 0; n
< sizer_top
->GetChildren().size(); n
++ )
1049 sizer_top
->SetItemMinSize(n
, 200, 300);
1051 wxBoxSizer
*sizer
= new wxBoxSizer( wxVERTICAL
);
1052 sizer
->Add(sizer_top
, 1, wxEXPAND
);
1054 sizer
->Add(m_ctrlLog
, 2, wxEXPAND
);
1055 sizer
->SetItemMinSize(m_ctrlLog
, 450, 200);
1057 sizer
->AddSpacer(50);
1059 // copy data by default but allow moving it as well
1060 m_moveByDefault
= false;
1062 menu_bar
->Check(Menu_DragMoveAllow
, true);
1064 // set the correct size and show the frame
1065 SetSizerAndFit(sizer
);
1069 void DnDFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
1074 void DnDFrame::OnSize(wxSizeEvent
& event
)
1081 void DnDFrame::OnPaint(wxPaintEvent
& WXUNUSED(event
))
1085 GetClientSize( &w
, &h
);
1088 // dc.Clear(); -- this kills wxGTK
1089 dc
.SetFont( wxFont( 24, wxDECORATIVE
, wxNORMAL
, wxNORMAL
, false, wxT("charter") ) );
1090 dc
.DrawText( wxT("Drag text from here!"), 100, h
-50 );
1093 void DnDFrame::OnUpdateUIMoveByDefault(wxUpdateUIEvent
& event
)
1095 // only can move by default if moving is allowed at all
1096 event
.Enable(m_moveAllow
);
1099 void DnDFrame::OnUpdateUIPasteText(wxUpdateUIEvent
& event
)
1102 // too many trace messages if we don't do it - this function is called
1107 event
.Enable( wxTheClipboard
->IsSupported(wxDF_TEXT
) );
1110 void DnDFrame::OnUpdateUIPasteBitmap(wxUpdateUIEvent
& event
)
1113 // too many trace messages if we don't do it - this function is called
1118 event
.Enable( wxTheClipboard
->IsSupported(wxDF_BITMAP
) );
1121 void DnDFrame::OnNewFrame(wxCommandEvent
& WXUNUSED(event
))
1123 #if wxUSE_DRAG_AND_DROP
1124 (new DnDShapeFrame(this))->Show(true);
1126 wxLogStatus(this, wxT("Double click the new frame to select a shape for it"));
1127 #endif // wxUSE_DRAG_AND_DROP
1130 void DnDFrame::OnDrag(wxCommandEvent
& WXUNUSED(event
))
1132 #if wxUSE_DRAG_AND_DROP
1133 wxString strText
= wxGetTextFromUser
1135 wxT("After you enter text in this dialog, press any mouse\n")
1136 wxT("button in the bottom (empty) part of the frame and \n")
1137 wxT("drag it anywhere - you will be in fact dragging the\n")
1138 wxT("text object containing this text"),
1139 wxT("Please enter some text"), m_strText
, this
1142 m_strText
= strText
;
1143 #endif // wxUSE_DRAG_AND_DROP
1146 void DnDFrame::OnDragMoveByDefault(wxCommandEvent
& event
)
1148 m_moveByDefault
= event
.IsChecked();
1151 void DnDFrame::OnDragMoveAllow(wxCommandEvent
& event
)
1153 m_moveAllow
= event
.IsChecked();
1156 void DnDFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
1158 wxMessageBox(wxT("Drag-&-Drop Demo\n")
1159 wxT("Please see \"Help|Help...\" for details\n")
1160 wxT("Copyright (c) 1998 Vadim Zeitlin"),
1162 wxICON_INFORMATION
| wxOK
,
1166 void DnDFrame::OnHelp(wxCommandEvent
& /* event */)
1168 wxMessageDialog
dialog(this,
1169 wxT("This small program demonstrates drag & drop support in wxWidgets. The program window\n")
1170 wxT("consists of 3 parts: the bottom pane is for debug messages, so that you can see what's\n")
1171 wxT("going on inside. The top part is split into 2 listboxes, the left one accepts files\n")
1172 wxT("and the right one accepts text.\n")
1174 wxT("To test wxDropTarget: open wordpad (write.exe), select some text in it and drag it to\n")
1175 wxT("the right listbox (you'll notice the usual visual feedback, i.e. the cursor will change).\n")
1176 wxT("Also, try dragging some files (you can select several at once) from Windows Explorer (or \n")
1177 wxT("File Manager) to the left pane. Hold down Ctrl/Shift keys when you drop text (doesn't \n")
1178 wxT("work with files) and see what changes.\n")
1180 wxT("To test wxDropSource: just press any mouse button on the empty zone of the window and drag\n")
1181 wxT("it to wordpad or any other droptarget accepting text (and of course you can just drag it\n")
1182 wxT("to the right pane). Due to a lot of trace messages, the cursor might take some time to \n")
1183 wxT("change, don't release the mouse button until it does. You can change the string being\n")
1184 wxT("dragged in \"File|Test drag...\" dialog.\n")
1187 wxT("Please send all questions/bug reports/suggestions &c to \n")
1188 wxT("Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>"),
1195 void DnDFrame::OnLogClear(wxCommandEvent
& /* event */ )
1198 m_ctrlText
->Clear();
1199 m_ctrlFile
->Clear();
1203 #if wxUSE_DRAG_AND_DROP
1205 void DnDFrame::LogDragResult(wxDragResult result
)
1211 case wxDragError
: pc
= wxT("Error!"); break;
1212 case wxDragNone
: pc
= wxT("Nothing"); break;
1213 case wxDragCopy
: pc
= wxT("Copied"); break;
1214 case wxDragMove
: pc
= wxT("Moved"); break;
1215 case wxDragCancel
: pc
= wxT("Cancelled"); break;
1216 default: pc
= wxT("Huh?"); break;
1219 SetStatusText(wxString(wxT("Drag result: ")) + pc
);
1221 wxUnusedVar(result
);
1222 #endif // wxUSE_STATUSBAR
1225 #endif // wxUSE_DRAG_AND_DROP
1227 void DnDFrame::OnLeftDown(wxMouseEvent
&WXUNUSED(event
) )
1229 #if wxUSE_DRAG_AND_DROP
1230 if ( !m_strText
.empty() )
1232 // start drag operation
1233 wxTextDataObject
textData(m_strText
);
1234 wxDropSource
source(textData
, this,
1235 wxDROP_ICON(dnd_copy
),
1236 wxDROP_ICON(dnd_move
),
1237 wxDROP_ICON(dnd_none
));
1240 if ( m_moveByDefault
)
1241 flags
|= wxDrag_DefaultMove
;
1242 else if ( m_moveAllow
)
1243 flags
|= wxDrag_AllowMove
;
1245 LogDragResult(source
.DoDragDrop(flags
));
1247 #endif // wxUSE_DRAG_AND_DROP
1250 void DnDFrame::OnRightDown(wxMouseEvent
&event
)
1252 wxMenu
menu(wxT("Dnd sample menu"));
1254 menu
.Append(Menu_Drag
, wxT("&Test drag..."));
1255 menu
.AppendSeparator();
1256 menu
.Append(Menu_About
, wxT("&About"));
1258 PopupMenu( &menu
, event
.GetX(), event
.GetY() );
1261 DnDFrame::~DnDFrame()
1264 if ( m_pLog
!= NULL
) {
1265 if ( wxLog::SetActiveTarget(m_pLogPrev
) == m_pLog
)
1271 void DnDFrame::OnUsePrimary(wxCommandEvent
& event
)
1273 const bool usePrimary
= event
.IsChecked();
1274 wxTheClipboard
->UsePrimarySelection(usePrimary
);
1276 wxLogStatus(wxT("Now using %s selection"), usePrimary
? wxT("primary")
1277 : wxT("clipboard"));
1280 #if wxUSE_DRAG_AND_DROP
1282 void DnDFrame::OnBeginDrag(wxTreeEvent
& WXUNUSED(event
))
1284 wxFileDataObject data
;
1285 data
.AddFile(m_ctrlDir
->GetPath());
1287 wxDropSource
dragSource(this);
1288 dragSource
.SetData(data
);
1290 LogDragResult(dragSource
.DoDragDrop());
1293 #endif // wxUSE_DRAG_AND_DROP
1295 // ---------------------------------------------------------------------------
1297 // ---------------------------------------------------------------------------
1299 void DnDFrame::OnCopyBitmap(wxCommandEvent
& WXUNUSED(event
))
1301 // PNG support is not always compiled in under Windows, so use BMP there
1303 wxFileDialog
dialog(this, wxT("Open a PNG file"), wxEmptyString
, wxEmptyString
, wxT("PNG files (*.png)|*.png"), 0);
1305 wxFileDialog
dialog(this, wxT("Open a BMP file"), wxEmptyString
, wxEmptyString
, wxT("BMP files (*.bmp)|*.bmp"), 0);
1308 if (dialog
.ShowModal() != wxID_OK
)
1310 wxLogMessage( wxT("Aborted file open") );
1314 if (dialog
.GetPath().empty())
1316 wxLogMessage( wxT("Returned empty string.") );
1320 if (!wxFileExists(dialog
.GetPath()))
1322 wxLogMessage( wxT("File doesn't exist.") );
1327 image
.LoadFile( dialog
.GetPath(),
1336 wxLogError( wxT("Invalid image file...") );
1340 wxLogStatus( wxT("Decoding image file...") );
1343 wxBitmap
bitmap( image
);
1345 if ( !wxTheClipboard
->Open() )
1347 wxLogError(wxT("Can't open clipboard."));
1352 wxLogMessage( wxT("Creating wxBitmapDataObject...") );
1355 if ( !wxTheClipboard
->AddData(new wxBitmapDataObject(bitmap
)) )
1357 wxLogError(wxT("Can't copy image to the clipboard."));
1361 wxLogMessage(wxT("Image has been put on the clipboard.") );
1362 wxLogMessage(wxT("You can paste it now and look at it.") );
1365 wxTheClipboard
->Close();
1368 void DnDFrame::OnPasteBitmap(wxCommandEvent
& WXUNUSED(event
))
1370 if ( !wxTheClipboard
->Open() )
1372 wxLogError(wxT("Can't open clipboard."));
1377 if ( !wxTheClipboard
->IsSupported(wxDF_BITMAP
) )
1379 wxLogWarning(wxT("No bitmap on clipboard"));
1381 wxTheClipboard
->Close();
1385 wxBitmapDataObject data
;
1386 if ( !wxTheClipboard
->GetData(data
) )
1388 wxLogError(wxT("Can't paste bitmap from the clipboard"));
1392 const wxBitmap
& bmp
= data
.GetBitmap();
1394 wxLogMessage(wxT("Bitmap %dx%d pasted from the clipboard"),
1395 bmp
.GetWidth(), bmp
.GetHeight());
1399 wxTheClipboard
->Close();
1404 void DnDFrame::OnPasteMetafile(wxCommandEvent
& WXUNUSED(event
))
1406 if ( !wxTheClipboard
->Open() )
1408 wxLogError(wxT("Can't open clipboard."));
1413 if ( !wxTheClipboard
->IsSupported(wxDF_METAFILE
) )
1415 wxLogWarning(wxT("No metafile on clipboard"));
1419 wxMetaFileDataObject data
;
1420 if ( !wxTheClipboard
->GetData(data
) )
1422 wxLogError(wxT("Can't paste metafile from the clipboard"));
1426 const wxMetaFile
& mf
= data
.GetMetafile();
1428 wxLogMessage(wxT("Metafile %dx%d pasted from the clipboard"),
1429 mf
.GetWidth(), mf
.GetHeight());
1435 wxTheClipboard
->Close();
1438 #endif // wxUSE_METAFILE
1440 // ----------------------------------------------------------------------------
1442 // ----------------------------------------------------------------------------
1444 void DnDFrame::OnCopyFiles(wxCommandEvent
& WXUNUSED(event
))
1447 wxFileDialog
dialog(this, wxT("Select a file to copy"), wxEmptyString
, wxEmptyString
,
1448 wxT("All files (*.*)|*.*"), 0);
1450 wxArrayString filenames
;
1451 while ( dialog
.ShowModal() == wxID_OK
)
1453 filenames
.Add(dialog
.GetPath());
1456 if ( !filenames
.IsEmpty() )
1458 wxFileDataObject
*dobj
= new wxFileDataObject
;
1459 size_t count
= filenames
.GetCount();
1460 for ( size_t n
= 0; n
< count
; n
++ )
1462 dobj
->AddFile(filenames
[n
]);
1465 wxClipboardLocker locker
;
1468 wxLogError(wxT("Can't open clipboard"));
1472 if ( !wxTheClipboard
->AddData(dobj
) )
1474 wxLogError(wxT("Can't copy file(s) to the clipboard"));
1478 wxLogStatus(this, wxT("%d file%s copied to the clipboard"),
1479 count
, count
== 1 ? wxEmptyString
: wxEmptyString
);
1485 wxLogStatus(this, wxT("Aborted"));
1488 wxLogError(wxT("Sorry, not implemented"));
1492 void DnDFrame::OnCopyURL(wxCommandEvent
& WXUNUSED(event
))
1494 // Just hard code it for now, we could ask the user but the point here is
1495 // to test copying URLs, it doesn't really matter what it is.
1496 const wxString
url("http://www.wxwidgets.org/");
1498 wxClipboardLocker locker
;
1499 if ( !!locker
&& wxTheClipboard
->AddData(new wxURLDataObject(url
)) )
1501 wxLogStatus(this, "Copied URL \"%s\" to %s.",
1503 GetMenuBar()->IsChecked(Menu_UsePrimary
)
1504 ? "primary selection"
1509 wxLogError("Failed to copy URL.");
1513 // ---------------------------------------------------------------------------
1515 // ---------------------------------------------------------------------------
1517 void DnDFrame::OnCopy(wxCommandEvent
& WXUNUSED(event
))
1519 if ( !wxTheClipboard
->Open() )
1521 wxLogError(wxT("Can't open clipboard."));
1526 if ( !wxTheClipboard
->AddData(new wxTextDataObject(m_strText
)) )
1528 wxLogError(wxT("Can't copy data to the clipboard"));
1532 wxLogMessage(wxT("Text '%s' put on the clipboard"), m_strText
.c_str());
1535 wxTheClipboard
->Close();
1538 void DnDFrame::OnPaste(wxCommandEvent
& WXUNUSED(event
))
1540 if ( !wxTheClipboard
->Open() )
1542 wxLogError(wxT("Can't open clipboard."));
1547 if ( !wxTheClipboard
->IsSupported(wxDF_TEXT
) )
1549 wxLogWarning(wxT("No text data on clipboard"));
1551 wxTheClipboard
->Close();
1555 wxTextDataObject text
;
1556 if ( !wxTheClipboard
->GetData(text
) )
1558 wxLogError(wxT("Can't paste data from the clipboard"));
1562 wxLogMessage(wxT("Text '%s' pasted from the clipboard"),
1563 text
.GetText().c_str());
1566 wxTheClipboard
->Close();
1569 #if wxUSE_DRAG_AND_DROP
1571 // ----------------------------------------------------------------------------
1572 // Notifications called by the base class
1573 // ----------------------------------------------------------------------------
1575 bool DnDText::OnDropText(wxCoord
, wxCoord
, const wxString
& text
)
1577 m_pOwner
->Append(text
);
1582 bool DnDFile::OnDropFiles(wxCoord
, wxCoord
, const wxArrayString
& filenames
)
1584 size_t nFiles
= filenames
.GetCount();
1586 str
.Printf( wxT("%d files dropped"), (int)nFiles
);
1588 if (m_pOwner
!= NULL
)
1590 m_pOwner
->Append(str
);
1591 for ( size_t n
= 0; n
< nFiles
; n
++ )
1592 m_pOwner
->Append(filenames
[n
]);
1598 // ----------------------------------------------------------------------------
1600 // ----------------------------------------------------------------------------
1602 DnDShapeDialog::DnDShapeDialog(wxFrame
*parent
, DnDShape
*shape
)
1603 :wxDialog( parent
, 6001, wxT("Choose Shape"), wxPoint( 10, 10 ),
1605 wxDEFAULT_DIALOG_STYLE
| wxRAISED_BORDER
| wxRESIZE_BORDER
)
1608 wxBoxSizer
* topSizer
= new wxBoxSizer( wxVERTICAL
);
1611 wxBoxSizer
* shapesSizer
= new wxBoxSizer( wxHORIZONTAL
);
1612 const wxString choices
[] = { wxT("None"), wxT("Triangle"),
1613 wxT("Rectangle"), wxT("Ellipse") };
1615 m_radio
= new wxRadioBox( this, wxID_ANY
, wxT("&Shape"),
1616 wxDefaultPosition
, wxDefaultSize
, 4, choices
, 4,
1617 wxRA_SPECIFY_COLS
);
1618 shapesSizer
->Add( m_radio
, 0, wxGROW
|wxALL
, 5 );
1619 topSizer
->Add( shapesSizer
, 0, wxALL
, 2 );
1622 wxStaticBox
* box
= new wxStaticBox( this, wxID_ANY
, wxT("&Attributes") );
1623 wxStaticBoxSizer
* attrSizer
= new wxStaticBoxSizer( box
, wxHORIZONTAL
);
1624 wxFlexGridSizer
* xywhSizer
= new wxFlexGridSizer( 2 );
1628 st
= new wxStaticText( this, wxID_ANY
, wxT("Position &X:") );
1629 m_textX
= new wxTextCtrl( this, wxID_ANY
, wxEmptyString
, wxDefaultPosition
,
1631 xywhSizer
->Add( st
, 1, wxGROW
|wxALL
, 2 );
1632 xywhSizer
->Add( m_textX
, 1, wxGROW
|wxALL
, 2 );
1634 st
= new wxStaticText( this, wxID_ANY
, wxT("Size &width:") );
1635 m_textW
= new wxTextCtrl( this, wxID_ANY
, wxEmptyString
, wxDefaultPosition
,
1637 xywhSizer
->Add( st
, 1, wxGROW
|wxALL
, 2 );
1638 xywhSizer
->Add( m_textW
, 1, wxGROW
|wxALL
, 2 );
1640 st
= new wxStaticText( this, wxID_ANY
, wxT("&Y:") );
1641 m_textY
= new wxTextCtrl( this, wxID_ANY
, wxEmptyString
, wxDefaultPosition
,
1643 xywhSizer
->Add( st
, 1, wxALL
|wxALIGN_RIGHT
, 2 );
1644 xywhSizer
->Add( m_textY
, 1, wxGROW
|wxALL
, 2 );
1646 st
= new wxStaticText( this, wxID_ANY
, wxT("&height:") );
1647 m_textH
= new wxTextCtrl( this, wxID_ANY
, wxEmptyString
, wxDefaultPosition
,
1649 xywhSizer
->Add( st
, 1, wxALL
|wxALIGN_RIGHT
, 2 );
1650 xywhSizer
->Add( m_textH
, 1, wxGROW
|wxALL
, 2 );
1652 wxButton
* col
= new wxButton( this, Button_Colour
, wxT("&Colour...") );
1653 attrSizer
->Add( xywhSizer
, 1, wxGROW
);
1654 attrSizer
->Add( col
, 0, wxALL
|wxALIGN_CENTRE_VERTICAL
, 2 );
1655 topSizer
->Add( attrSizer
, 0, wxGROW
|wxALL
, 5 );
1658 wxBoxSizer
* buttonSizer
= new wxBoxSizer( wxHORIZONTAL
);
1660 bt
= new wxButton( this, wxID_OK
, wxT("Ok") );
1661 buttonSizer
->Add( bt
, 0, wxALL
, 2 );
1662 bt
= new wxButton( this, wxID_CANCEL
, wxT("Cancel") );
1663 buttonSizer
->Add( bt
, 0, wxALL
, 2 );
1664 topSizer
->Add( buttonSizer
, 0, wxALL
|wxALIGN_RIGHT
, 2 );
1666 SetSizerAndFit( topSizer
);
1669 DnDShape
*DnDShapeDialog::GetShape() const
1671 switch ( m_shapeKind
)
1674 case DnDShape::None
: return NULL
;
1675 case DnDShape::Triangle
: return new DnDTriangularShape(m_pos
, m_size
, m_col
);
1676 case DnDShape::Rectangle
: return new DnDRectangularShape(m_pos
, m_size
, m_col
);
1677 case DnDShape::Ellipse
: return new DnDEllipticShape(m_pos
, m_size
, m_col
);
1681 bool DnDShapeDialog::TransferDataToWindow()
1686 m_radio
->SetSelection(m_shape
->GetKind());
1687 m_pos
= m_shape
->GetPosition();
1688 m_size
= m_shape
->GetSize();
1689 m_col
= m_shape
->GetColour();
1693 m_radio
->SetSelection(DnDShape::None
);
1694 m_pos
= wxPoint(1, 1);
1695 m_size
= wxSize(100, 100);
1698 m_textX
->SetValue(wxString() << m_pos
.x
);
1699 m_textY
->SetValue(wxString() << m_pos
.y
);
1700 m_textW
->SetValue(wxString() << m_size
.x
);
1701 m_textH
->SetValue(wxString() << m_size
.y
);
1706 bool DnDShapeDialog::TransferDataFromWindow()
1708 m_shapeKind
= (DnDShape::Kind
)m_radio
->GetSelection();
1710 m_pos
.x
= wxAtoi(m_textX
->GetValue());
1711 m_pos
.y
= wxAtoi(m_textY
->GetValue());
1712 m_size
.x
= wxAtoi(m_textW
->GetValue());
1713 m_size
.y
= wxAtoi(m_textH
->GetValue());
1715 if ( !m_pos
.x
|| !m_pos
.y
|| !m_size
.x
|| !m_size
.y
)
1717 wxMessageBox(wxT("All sizes and positions should be non null!"),
1718 wxT("Invalid shape"), wxICON_HAND
| wxOK
, this);
1726 void DnDShapeDialog::OnColour(wxCommandEvent
& WXUNUSED(event
))
1729 data
.SetChooseFull(true);
1730 for (int i
= 0; i
< 16; i
++)
1732 wxColour
colour((unsigned char)(i
*16), (unsigned char)(i
*16), (unsigned char)(i
*16));
1733 data
.SetCustomColour(i
, colour
);
1736 wxColourDialog
dialog(this, &data
);
1737 if ( dialog
.ShowModal() == wxID_OK
)
1739 m_col
= dialog
.GetColourData().GetColour();
1743 // ----------------------------------------------------------------------------
1745 // ----------------------------------------------------------------------------
1747 DnDShapeFrame
*DnDShapeFrame::ms_lastDropTarget
= NULL
;
1749 DnDShapeFrame::DnDShapeFrame(wxFrame
*parent
)
1750 : wxFrame(parent
, wxID_ANY
, wxT("Shape Frame"))
1754 #endif // wxUSE_STATUSBAR
1756 wxMenu
*menuShape
= new wxMenu
;
1757 menuShape
->Append(Menu_Shape_New
, wxT("&New default shape\tCtrl-S"));
1758 menuShape
->Append(Menu_Shape_Edit
, wxT("&Edit shape\tCtrl-E"));
1759 menuShape
->AppendSeparator();
1760 menuShape
->Append(Menu_Shape_Clear
, wxT("&Clear shape\tCtrl-L"));
1762 wxMenu
*menuClipboard
= new wxMenu
;
1763 menuClipboard
->Append(Menu_ShapeClipboard_Copy
, wxT("&Copy\tCtrl-C"));
1764 menuClipboard
->Append(Menu_ShapeClipboard_Paste
, wxT("&Paste\tCtrl-V"));
1766 wxMenuBar
*menubar
= new wxMenuBar
;
1767 menubar
->Append(menuShape
, wxT("&Shape"));
1768 menubar
->Append(menuClipboard
, wxT("&Clipboard"));
1770 SetMenuBar(menubar
);
1773 SetStatusText(wxT("Press Ctrl-S to create a new shape"));
1774 #endif // wxUSE_STATUSBAR
1776 SetDropTarget(new DnDShapeDropTarget(this));
1780 SetBackgroundColour(*wxWHITE
);
1783 DnDShapeFrame::~DnDShapeFrame()
1789 void DnDShapeFrame::SetShape(DnDShape
*shape
)
1798 void DnDShapeFrame::OnDrag(wxMouseEvent
& event
)
1807 // start drag operation
1808 DnDShapeDataObject
shapeData(m_shape
);
1809 wxDropSource
source(shapeData
, this);
1811 const wxChar
*pc
= NULL
;
1812 switch ( source
.DoDragDrop(true) )
1816 wxLogError(wxT("An error occurred during drag and drop operation"));
1821 SetStatusText(wxT("Nothing happened"));
1822 #endif // wxUSE_STATUSBAR
1831 if ( ms_lastDropTarget
!= this )
1833 // don't delete the shape if we dropped it on ourselves!
1840 SetStatusText(wxT("Drag and drop operation cancelled"));
1841 #endif // wxUSE_STATUSBAR
1848 SetStatusText(wxString(wxT("Shape successfully ")) + pc
);
1849 #endif // wxUSE_STATUSBAR
1851 //else: status text already set
1854 void DnDShapeFrame::OnDrop(wxCoord x
, wxCoord y
, DnDShape
*shape
)
1856 ms_lastDropTarget
= this;
1862 s
.Printf(wxT("Shape dropped at (%d, %d)"), pt
.x
, pt
.y
);
1864 #endif // wxUSE_STATUSBAR
1870 void DnDShapeFrame::OnEditShape(wxCommandEvent
& WXUNUSED(event
))
1872 DnDShapeDialog
dlg(this, m_shape
);
1873 if ( dlg
.ShowModal() == wxID_OK
)
1875 SetShape(dlg
.GetShape());
1880 SetStatusText(wxT("You can now drag the shape to another frame"));
1882 #endif // wxUSE_STATUSBAR
1886 void DnDShapeFrame::OnNewShape(wxCommandEvent
& WXUNUSED(event
))
1888 SetShape(new DnDEllipticShape(wxPoint(10, 10), wxSize(80, 60), *wxRED
));
1891 SetStatusText(wxT("You can now drag the shape to another frame"));
1892 #endif // wxUSE_STATUSBAR
1895 void DnDShapeFrame::OnClearShape(wxCommandEvent
& WXUNUSED(event
))
1900 void DnDShapeFrame::OnCopyShape(wxCommandEvent
& WXUNUSED(event
))
1904 wxClipboardLocker clipLocker
;
1907 wxLogError(wxT("Can't open the clipboard"));
1912 wxTheClipboard
->AddData(new DnDShapeDataObject(m_shape
));
1916 void DnDShapeFrame::OnPasteShape(wxCommandEvent
& WXUNUSED(event
))
1918 wxClipboardLocker clipLocker
;
1921 wxLogError(wxT("Can't open the clipboard"));
1926 DnDShapeDataObject
shapeDataObject(NULL
);
1927 if ( wxTheClipboard
->GetData(shapeDataObject
) )
1929 SetShape(shapeDataObject
.GetShape());
1933 wxLogStatus(wxT("No shape on the clipboard"));
1937 void DnDShapeFrame::OnUpdateUICopy(wxUpdateUIEvent
& event
)
1939 event
.Enable( m_shape
!= NULL
);
1942 void DnDShapeFrame::OnUpdateUIPaste(wxUpdateUIEvent
& event
)
1944 event
.Enable( wxTheClipboard
->IsSupported(wxDataFormat(shapeFormatId
)) );
1947 void DnDShapeFrame::OnPaint(wxPaintEvent
& event
)
1961 // ----------------------------------------------------------------------------
1963 // ----------------------------------------------------------------------------
1965 DnDShape
*DnDShape::New(const void *buf
)
1967 const ShapeDump
& dump
= *(const ShapeDump
*)buf
;
1971 return new DnDTriangularShape(wxPoint(dump
.x
, dump
.y
),
1972 wxSize(dump
.w
, dump
.h
),
1973 wxColour(dump
.r
, dump
.g
, dump
.b
));
1976 return new DnDRectangularShape(wxPoint(dump
.x
, dump
.y
),
1977 wxSize(dump
.w
, dump
.h
),
1978 wxColour(dump
.r
, dump
.g
, dump
.b
));
1981 return new DnDEllipticShape(wxPoint(dump
.x
, dump
.y
),
1982 wxSize(dump
.w
, dump
.h
),
1983 wxColour(dump
.r
, dump
.g
, dump
.b
));
1986 wxFAIL_MSG(wxT("invalid shape!"));
1991 // ----------------------------------------------------------------------------
1992 // DnDShapeDataObject
1993 // ----------------------------------------------------------------------------
1997 void DnDShapeDataObject::CreateMetaFile() const
1999 wxPoint pos
= m_shape
->GetPosition();
2000 wxSize size
= m_shape
->GetSize();
2002 wxMetaFileDC
dcMF(wxEmptyString
, pos
.x
+ size
.x
, pos
.y
+ size
.y
);
2004 m_shape
->Draw(dcMF
);
2006 wxMetafile
*mf
= dcMF
.Close();
2008 DnDShapeDataObject
*self
= (DnDShapeDataObject
*)this; // const_cast
2009 self
->m_dobjMetaFile
.SetMetafile(*mf
);
2010 self
->m_hasMetaFile
= true;
2015 #endif // wxUSE_METAFILE
2017 void DnDShapeDataObject::CreateBitmap() const
2019 wxPoint pos
= m_shape
->GetPosition();
2020 wxSize size
= m_shape
->GetSize();
2021 int x
= pos
.x
+ size
.x
,
2023 wxBitmap
bitmap(x
, y
);
2025 dc
.SelectObject(bitmap
);
2026 dc
.SetBrush(*wxWHITE_BRUSH
);
2029 dc
.SelectObject(wxNullBitmap
);
2031 DnDShapeDataObject
*self
= (DnDShapeDataObject
*)this; // const_cast
2032 self
->m_dobjBitmap
.SetBitmap(bitmap
);
2033 self
->m_hasBitmap
= true;
2036 #endif // wxUSE_DRAG_AND_DROP
2038 // ----------------------------------------------------------------------------
2040 // ----------------------------------------------------------------------------
2042 static void ShowBitmap(const wxBitmap
& bitmap
)
2044 wxFrame
*frame
= new wxFrame(NULL
, wxID_ANY
, wxT("Bitmap view"));
2046 frame
->CreateStatusBar();
2047 #endif // wxUSE_STATUSBAR
2048 DnDCanvasBitmap
*canvas
= new DnDCanvasBitmap(frame
);
2049 canvas
->SetBitmap(bitmap
);
2051 int w
= bitmap
.GetWidth(),
2052 h
= bitmap
.GetHeight();
2054 frame
->SetStatusText(wxString::Format(wxT("%dx%d"), w
, h
));
2055 #endif // wxUSE_STATUSBAR
2057 frame
->SetClientSize(w
> 100 ? 100 : w
, h
> 100 ? 100 : h
);
2063 static void ShowMetaFile(const wxMetaFile
& metafile
)
2065 wxFrame
*frame
= new wxFrame(NULL
, wxID_ANY
, wxT("Metafile view"));
2066 frame
->CreateStatusBar();
2067 DnDCanvasMetafile
*canvas
= new DnDCanvasMetafile(frame
);
2068 canvas
->SetMetafile(metafile
);
2070 wxSize size
= metafile
.GetSize();
2071 frame
->SetStatusText(wxString::Format(wxT("%dx%d"), size
.x
, size
.y
));
2073 frame
->SetClientSize(size
.x
> 100 ? 100 : size
.x
,
2074 size
.y
> 100 ? 100 : size
.y
);
2078 #endif // wxUSE_METAFILE
2080 #endif // wxUSE_DRAG_AND_DROP || wxUSE_CLIPBOARD