1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Drag and drop sample
4 // Author: Vadim Zeitlin
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #include "wx/wxprec.h"
22 #if !wxUSE_DRAG_AND_DROP
23 #error This sample requires drag and drop support in the library
26 // under Windows we also support data transfer of metafiles as an extra bonus,
27 // but they're not available under other platforms
32 #define USE_RESOURCES 0
35 #define USE_RESOURCES 0
42 #include "wx/dirdlg.h"
43 #include "wx/filedlg.h"
45 #include "wx/clipbrd.h"
46 #include "wx/colordlg.h"
48 #include "wx/resource.h"
54 #include "wx/metafile.h"
57 #if defined(__WXGTK__) || defined(__WXX11__) || defined(__WXMOTIF__) || defined(__WXMAC__)
58 #include "mondrian.xpm"
60 #include "dnd_copy.xpm"
61 #include "dnd_move.xpm"
62 #include "dnd_none.xpm"
65 // ----------------------------------------------------------------------------
66 // Derive two simple classes which just put in the listbox the strings (text or
67 // file names) we drop on them
68 // ----------------------------------------------------------------------------
70 class DnDText
: public wxTextDropTarget
73 DnDText(wxListBox
*pOwner
) { m_pOwner
= pOwner
; }
75 virtual bool OnDropText(wxCoord x
, wxCoord y
, const wxString
& text
);
77 // uncomment this if you want to always force Move to be the default
78 // action, even under wxGTK where it is normally Copy
80 wxDragResult
OnDragOver(wxCoord x
, wxCoord y
, wxDragResult def
)
82 wxDragResult res
= wxTextDropTarget::OnDragOver(x
, y
, def
);
83 return res
== wxDragNone
? wxDragNone
: wxDragMove
;
91 class DnDFile
: public wxFileDropTarget
94 DnDFile(wxListBox
*pOwner
) { m_pOwner
= pOwner
; }
96 virtual bool OnDropFiles(wxCoord x
, wxCoord y
,
97 const wxArrayString
& filenames
);
103 // ----------------------------------------------------------------------------
104 // Define a custom dtop target accepting URLs
105 // ----------------------------------------------------------------------------
107 class URLDropTarget
: public wxDropTarget
110 URLDropTarget() { SetDataObject(new wxURLDataObject
); }
112 void OnDropURL(wxCoord x
, wxCoord y
, const wxString
& text
)
114 // of course, a real program would do something more useful here...
115 wxMessageBox(text
, _T("wxDnD sample: got URL"),
116 wxICON_INFORMATION
| wxOK
);
119 // URLs can't be moved, only copied
120 virtual wxDragResult
OnDragOver(wxCoord
WXUNUSED(x
), wxCoord
WXUNUSED(y
),
123 return wxDragLink
; // At least IE 5.x needs wxDragLink, the
124 // other browsers on MSW seem okay with it too.
127 // translate this to calls to OnDropURL() just for convenience
128 virtual wxDragResult
OnData(wxCoord x
, wxCoord y
, wxDragResult def
)
133 OnDropURL(x
, y
, ((wxURLDataObject
*)m_dataObject
)->GetURL());
139 // ----------------------------------------------------------------------------
140 // Define a new application type
141 // ----------------------------------------------------------------------------
143 class DnDApp
: public wxApp
146 virtual bool OnInit();
149 IMPLEMENT_APP(DnDApp
);
151 // ----------------------------------------------------------------------------
152 // Define canvas class to show a bitmap
153 // ----------------------------------------------------------------------------
155 class DnDCanvasBitmap
: public wxScrolledWindow
158 DnDCanvasBitmap(wxWindow
*parent
) : wxScrolledWindow(parent
) { }
160 void SetBitmap(const wxBitmap
& bitmap
)
164 SetScrollbars(10, 10,
165 m_bitmap
.GetWidth() / 10, m_bitmap
.GetHeight() / 10);
170 void OnPaint(wxPaintEvent
& event
)
178 dc
.DrawBitmap(m_bitmap
, 0, 0);
185 DECLARE_EVENT_TABLE()
190 // and the same thing fo metafiles
191 class DnDCanvasMetafile
: public wxScrolledWindow
194 DnDCanvasMetafile(wxWindow
*parent
) : wxScrolledWindow(parent
) { }
196 void SetMetafile(const wxMetafile
& metafile
)
198 m_metafile
= metafile
;
200 SetScrollbars(10, 10,
201 m_metafile
.GetWidth() / 10, m_metafile
.GetHeight() / 10);
206 void OnPaint(wxPaintEvent
& event
)
210 if ( m_metafile
.Ok() )
214 m_metafile
.Play(&dc
);
219 wxMetafile m_metafile
;
221 DECLARE_EVENT_TABLE()
224 #endif // USE_METAFILES
226 // ----------------------------------------------------------------------------
227 // Define a new frame type for the main frame
228 // ----------------------------------------------------------------------------
230 class DnDFrame
: public wxFrame
233 DnDFrame(wxFrame
*frame
, char *title
, int x
, int y
, int w
, int h
);
236 void OnPaint(wxPaintEvent
& event
);
237 void OnSize(wxSizeEvent
& event
);
238 void OnQuit (wxCommandEvent
& event
);
239 void OnAbout(wxCommandEvent
& event
);
240 void OnDrag (wxCommandEvent
& event
);
241 void OnNewFrame(wxCommandEvent
& event
);
242 void OnHelp (wxCommandEvent
& event
);
243 void OnLogClear(wxCommandEvent
& event
);
245 void OnCopy(wxCommandEvent
& event
);
246 void OnPaste(wxCommandEvent
& event
);
248 void OnCopyBitmap(wxCommandEvent
& event
);
249 void OnPasteBitmap(wxCommandEvent
& event
);
252 void OnPasteMetafile(wxCommandEvent
& event
);
253 #endif // USE_METAFILES
255 void OnCopyFiles(wxCommandEvent
& event
);
257 void OnLeftDown(wxMouseEvent
& event
);
258 void OnRightDown(wxMouseEvent
& event
);
260 void OnUpdateUIPasteText(wxUpdateUIEvent
& event
);
261 void OnUpdateUIPasteBitmap(wxUpdateUIEvent
& event
);
263 DECLARE_EVENT_TABLE()
266 wxListBox
*m_ctrlFile
,
268 wxTextCtrl
*m_ctrlLog
;
276 // ----------------------------------------------------------------------------
277 // A shape is an example of application-specific data which may be transported
278 // via drag-and-drop or clipboard: in our case, we have different geometric
279 // shapes, each one with its own colour and position
280 // ----------------------------------------------------------------------------
293 DnDShape(const wxPoint
& pos
,
296 : m_pos(pos
), m_size(size
), m_col(col
)
300 // this is for debugging - lets us see when exactly an object is freed
301 // (this may be later than you think if it's on the clipboard, for example)
302 virtual ~DnDShape() { }
304 // the functions used for drag-and-drop: they dump and restore a shape into
305 // some bitwise-copiable data (might use streams too...)
306 // ------------------------------------------------------------------------
308 // restore from buffer
309 static DnDShape
*New(const void *buf
);
311 virtual size_t GetDataSize() const
313 return sizeof(ShapeDump
);
316 virtual void GetDataHere(void *buf
) const
318 ShapeDump
& dump
= *(ShapeDump
*)buf
;
323 dump
.r
= m_col
.Red();
324 dump
.g
= m_col
.Green();
325 dump
.b
= m_col
.Blue();
330 const wxPoint
& GetPosition() const { return m_pos
; }
331 const wxColour
& GetColour() const { return m_col
; }
332 const wxSize
& GetSize() const { return m_size
; }
334 void Move(const wxPoint
& pos
) { m_pos
= pos
; }
336 // to implement in derived classes
337 virtual Kind
GetKind() const = 0;
339 virtual void Draw(wxDC
& dc
)
341 dc
.SetPen(wxPen(m_col
, 1, wxSOLID
));
345 //get a point 1 up and 1 left, otherwise the mid-point of a triangle is on the line
346 wxPoint
GetCentre() const
347 { return wxPoint(m_pos
.x
+ m_size
.x
/ 2 - 1, m_pos
.y
+ m_size
.y
/ 2 - 1); }
351 int x
, y
, // position
362 class DnDTriangularShape
: public DnDShape
365 DnDTriangularShape(const wxPoint
& pos
,
368 : DnDShape(pos
, size
, col
)
370 wxLogMessage(wxT("DnDTriangularShape is being created"));
373 virtual ~DnDTriangularShape()
375 wxLogMessage(wxT("DnDTriangularShape is being deleted"));
378 virtual Kind
GetKind() const { return Triangle
; }
379 virtual void Draw(wxDC
& dc
)
383 // well, it's a bit difficult to describe a triangle by position and
384 // size, but we're not doing geometry here, do we? ;-)
386 wxPoint
p2(m_pos
.x
+ m_size
.x
, m_pos
.y
);
387 wxPoint
p3(m_pos
.x
, m_pos
.y
+ m_size
.y
);
393 //works in multicolor modes; on GTK (at least) will fail in 16-bit color
394 dc
.SetBrush(wxBrush(m_col
, wxSOLID
));
395 dc
.FloodFill(GetCentre(), m_col
, wxFLOOD_BORDER
);
399 class DnDRectangularShape
: public DnDShape
402 DnDRectangularShape(const wxPoint
& pos
,
405 : DnDShape(pos
, size
, col
)
407 wxLogMessage(wxT("DnDRectangularShape is being created"));
410 virtual ~DnDRectangularShape()
412 wxLogMessage(wxT("DnDRectangularShape is being deleted"));
415 virtual Kind
GetKind() const { return Rectangle
; }
416 virtual void Draw(wxDC
& dc
)
421 wxPoint
p2(p1
.x
+ m_size
.x
, p1
.y
);
422 wxPoint
p3(p2
.x
, p2
.y
+ m_size
.y
);
423 wxPoint
p4(p1
.x
, p3
.y
);
430 dc
.SetBrush(wxBrush(m_col
, wxSOLID
));
431 dc
.FloodFill(GetCentre(), m_col
, wxFLOOD_BORDER
);
435 class DnDEllipticShape
: public DnDShape
438 DnDEllipticShape(const wxPoint
& pos
,
441 : DnDShape(pos
, size
, col
)
443 wxLogMessage(wxT("DnDEllipticShape is being created"));
446 virtual ~DnDEllipticShape()
448 wxLogMessage(wxT("DnDEllipticShape is being deleted"));
451 virtual Kind
GetKind() const { return Ellipse
; }
452 virtual void Draw(wxDC
& dc
)
456 dc
.DrawEllipse(m_pos
, m_size
);
458 dc
.SetBrush(wxBrush(m_col
, wxSOLID
));
459 dc
.FloodFill(GetCentre(), m_col
, wxFLOOD_BORDER
);
463 // ----------------------------------------------------------------------------
464 // A wxDataObject specialisation for the application-specific data
465 // ----------------------------------------------------------------------------
467 static const wxChar
*shapeFormatId
= wxT("wxShape");
469 class DnDShapeDataObject
: public wxDataObject
472 // ctor doesn't copy the pointer, so it shouldn't go away while this object
474 DnDShapeDataObject(DnDShape
*shape
= (DnDShape
*)NULL
)
478 // we need to copy the shape because the one we're handled may be
479 // deleted while it's still on the clipboard (for example) - and we
480 // reuse the serialisation methods here to copy it
481 void *buf
= malloc(shape
->DnDShape::GetDataSize());
482 shape
->GetDataHere(buf
);
483 m_shape
= DnDShape::New(buf
);
493 // this string should uniquely identify our format, but is otherwise
495 m_formatShape
.SetId(shapeFormatId
);
497 // we don't draw the shape to a bitmap until it's really needed (i.e.
498 // we're asked to do so)
501 m_hasMetaFile
= FALSE
;
505 virtual ~DnDShapeDataObject() { delete m_shape
; }
507 // after a call to this function, the shape is owned by the caller and it
508 // is responsible for deleting it!
510 // NB: a better solution would be to make DnDShapes ref counted and this
511 // is what should probably be done in a real life program, otherwise
512 // the ownership problems become too complicated really fast
515 DnDShape
*shape
= m_shape
;
517 m_shape
= (DnDShape
*)NULL
;
520 m_hasMetaFile
= FALSE
;
526 // implement base class pure virtuals
527 // ----------------------------------
529 virtual wxDataFormat
GetPreferredFormat(Direction
WXUNUSED(dir
)) const
531 return m_formatShape
;
534 virtual size_t GetFormatCount(Direction dir
) const
536 // our custom format is supported by both GetData() and SetData()
540 // but the bitmap format(s) are only supported for output
541 nFormats
+= m_dobjBitmap
.GetFormatCount(dir
);
544 nFormats
+= m_dobjMetaFile
.GetFormatCount(dir
);
551 virtual void GetAllFormats(wxDataFormat
*formats
, Direction dir
) const
553 formats
[0] = m_formatShape
;
556 // in Get direction we additionally support bitmaps and metafiles
558 m_dobjBitmap
.GetAllFormats(&formats
[1], dir
);
561 // don't assume that m_dobjBitmap has only 1 format
562 m_dobjMetaFile
.GetAllFormats(&formats
[1 +
563 m_dobjBitmap
.GetFormatCount(dir
)], dir
);
568 virtual size_t GetDataSize(const wxDataFormat
& format
) const
570 if ( format
== m_formatShape
)
572 return m_shape
->GetDataSize();
575 else if ( m_dobjMetaFile
.IsSupported(format
) )
577 if ( !m_hasMetaFile
)
580 return m_dobjMetaFile
.GetDataSize(format
);
585 wxASSERT_MSG( m_dobjBitmap
.IsSupported(format
),
586 wxT("unexpected format") );
591 return m_dobjBitmap
.GetDataSize();
595 virtual bool GetDataHere(const wxDataFormat
& format
, void *pBuf
) const
597 if ( format
== m_formatShape
)
599 m_shape
->GetDataHere(pBuf
);
604 else if ( m_dobjMetaFile
.IsSupported(format
) )
606 if ( !m_hasMetaFile
)
609 return m_dobjMetaFile
.GetDataHere(format
, pBuf
);
614 wxASSERT_MSG( m_dobjBitmap
.IsSupported(format
),
615 wxT("unexpected format") );
620 return m_dobjBitmap
.GetDataHere(pBuf
);
624 virtual bool SetData(const wxDataFormat
& format
,
625 size_t len
, const void *buf
)
627 wxCHECK_MSG( format
== m_formatShape
, FALSE
,
628 wxT( "unsupported format") );
631 m_shape
= DnDShape::New(buf
);
633 // the shape has changed
637 m_hasMetaFile
= FALSE
;
644 // creates a bitmap and assigns it to m_dobjBitmap (also sets m_hasBitmap)
645 void CreateBitmap() const;
647 void CreateMetaFile() const;
650 wxDataFormat m_formatShape
; // our custom format
652 wxBitmapDataObject m_dobjBitmap
; // it handles bitmaps
653 bool m_hasBitmap
; // true if m_dobjBitmap has valid bitmap
656 wxMetaFileDataObject m_dobjMetaFile
;// handles metafiles
657 bool m_hasMetaFile
; // true if we have valid metafile
660 DnDShape
*m_shape
; // our data
663 // ----------------------------------------------------------------------------
664 // A dialog to edit shape properties
665 // ----------------------------------------------------------------------------
667 class DnDShapeDialog
: public wxDialog
670 DnDShapeDialog(wxFrame
*parent
, DnDShape
*shape
);
672 DnDShape
*GetShape() const;
674 virtual bool TransferDataToWindow();
675 virtual bool TransferDataFromWindow();
677 void OnColour(wxCommandEvent
& event
);
684 DnDShape::Kind m_shapeKind
;
696 DECLARE_EVENT_TABLE()
699 // ----------------------------------------------------------------------------
700 // A frame for the shapes which can be drag-and-dropped between frames
701 // ----------------------------------------------------------------------------
703 class DnDShapeFrame
: public wxFrame
706 DnDShapeFrame(wxFrame
*parent
);
709 void SetShape(DnDShape
*shape
);
712 void OnNewShape(wxCommandEvent
& event
);
713 void OnEditShape(wxCommandEvent
& event
);
714 void OnClearShape(wxCommandEvent
& event
);
716 void OnCopyShape(wxCommandEvent
& event
);
717 void OnPasteShape(wxCommandEvent
& event
);
719 void OnUpdateUICopy(wxUpdateUIEvent
& event
);
720 void OnUpdateUIPaste(wxUpdateUIEvent
& event
);
722 void OnDrag(wxMouseEvent
& event
);
723 void OnPaint(wxPaintEvent
& event
);
724 void OnDrop(wxCoord x
, wxCoord y
, DnDShape
*shape
);
729 static DnDShapeFrame
*ms_lastDropTarget
;
731 DECLARE_EVENT_TABLE()
734 // ----------------------------------------------------------------------------
735 // wxDropTarget derivation for DnDShapes
736 // ----------------------------------------------------------------------------
738 class DnDShapeDropTarget
: public wxDropTarget
741 DnDShapeDropTarget(DnDShapeFrame
*frame
)
742 : wxDropTarget(new DnDShapeDataObject
)
747 // override base class (pure) virtuals
748 virtual wxDragResult
OnEnter(wxCoord x
, wxCoord y
, wxDragResult def
)
749 { m_frame
->SetStatusText("Mouse entered the frame"); return OnDragOver(x
, y
, def
); }
750 virtual void OnLeave()
751 { m_frame
->SetStatusText("Mouse left the frame"); }
752 virtual wxDragResult
OnData(wxCoord x
, wxCoord y
, wxDragResult def
)
756 wxLogError(wxT("Failed to get drag and drop data"));
761 m_frame
->OnDrop(x
, y
,
762 ((DnDShapeDataObject
*)GetDataObject())->GetShape());
768 DnDShapeFrame
*m_frame
;
771 // ----------------------------------------------------------------------------
772 // functions prototypes
773 // ----------------------------------------------------------------------------
775 static void ShowBitmap(const wxBitmap
& bitmap
);
778 static void ShowMetaFile(const wxMetaFile
& metafile
);
779 #endif // USE_METAFILES
781 // ----------------------------------------------------------------------------
782 // IDs for the menu commands
783 // ----------------------------------------------------------------------------
799 Menu_Shape_New
= 500,
802 Menu_ShapeClipboard_Copy
,
803 Menu_ShapeClipboard_Paste
,
807 BEGIN_EVENT_TABLE(DnDFrame
, wxFrame
)
808 EVT_MENU(Menu_Quit
, DnDFrame::OnQuit
)
809 EVT_MENU(Menu_About
, DnDFrame::OnAbout
)
810 EVT_MENU(Menu_Drag
, DnDFrame::OnDrag
)
811 EVT_MENU(Menu_NewFrame
, DnDFrame::OnNewFrame
)
812 EVT_MENU(Menu_Help
, DnDFrame::OnHelp
)
813 EVT_MENU(Menu_Clear
, DnDFrame::OnLogClear
)
814 EVT_MENU(Menu_Copy
, DnDFrame::OnCopy
)
815 EVT_MENU(Menu_Paste
, DnDFrame::OnPaste
)
816 EVT_MENU(Menu_CopyBitmap
, DnDFrame::OnCopyBitmap
)
817 EVT_MENU(Menu_PasteBitmap
,DnDFrame::OnPasteBitmap
)
819 EVT_MENU(Menu_PasteMFile
, DnDFrame::OnPasteMetafile
)
820 #endif // USE_METAFILES
821 EVT_MENU(Menu_CopyFiles
, DnDFrame::OnCopyFiles
)
823 EVT_UPDATE_UI(Menu_Paste
, DnDFrame::OnUpdateUIPasteText
)
824 EVT_UPDATE_UI(Menu_PasteBitmap
, DnDFrame::OnUpdateUIPasteBitmap
)
826 EVT_LEFT_DOWN( DnDFrame::OnLeftDown
)
827 EVT_RIGHT_DOWN( DnDFrame::OnRightDown
)
828 EVT_PAINT( DnDFrame::OnPaint
)
829 EVT_SIZE( DnDFrame::OnSize
)
832 BEGIN_EVENT_TABLE(DnDShapeFrame
, wxFrame
)
833 EVT_MENU(Menu_Shape_New
, DnDShapeFrame::OnNewShape
)
834 EVT_MENU(Menu_Shape_Edit
, DnDShapeFrame::OnEditShape
)
835 EVT_MENU(Menu_Shape_Clear
, DnDShapeFrame::OnClearShape
)
837 EVT_MENU(Menu_ShapeClipboard_Copy
, DnDShapeFrame::OnCopyShape
)
838 EVT_MENU(Menu_ShapeClipboard_Paste
, DnDShapeFrame::OnPasteShape
)
840 EVT_UPDATE_UI(Menu_ShapeClipboard_Copy
, DnDShapeFrame::OnUpdateUICopy
)
841 EVT_UPDATE_UI(Menu_ShapeClipboard_Paste
, DnDShapeFrame::OnUpdateUIPaste
)
843 EVT_LEFT_DOWN(DnDShapeFrame::OnDrag
)
845 EVT_PAINT(DnDShapeFrame::OnPaint
)
848 BEGIN_EVENT_TABLE(DnDShapeDialog
, wxDialog
)
849 EVT_BUTTON(Button_Colour
, DnDShapeDialog::OnColour
)
852 BEGIN_EVENT_TABLE(DnDCanvasBitmap
, wxScrolledWindow
)
853 EVT_PAINT(DnDCanvasBitmap::OnPaint
)
857 BEGIN_EVENT_TABLE(DnDCanvasMetafile
, wxScrolledWindow
)
858 EVT_PAINT(DnDCanvasMetafile::OnPaint
)
860 #endif // USE_METAFILES
862 // ============================================================================
864 // ============================================================================
866 // `Main program' equivalent, creating windows and returning main app frame
867 bool DnDApp::OnInit()
870 // load our ressources
874 pathList
.Add("./Debug");
875 pathList
.Add("./Release");
878 wxString path
= pathList
.FindValidPath("dnd.wxr");
881 wxLogError(wxT("Can't find the resource file dnd.wxr in the current ")
882 wxT("directory, aborting."));
887 wxDefaultResourceTable
->ParseResourceFile(path
);
890 // switch on trace messages
891 #if defined(__WXGTK__)
892 wxLog::AddTraceMask(_T("clipboard"));
893 #elif defined(__WXMSW__)
894 wxLog::AddTraceMask(wxTRACE_OleCalls
);
898 wxImage::AddHandler( new wxPNGHandler
);
901 // under X we usually want to use the primary selection by default (which
902 // is shared with other apps)
903 wxTheClipboard
->UsePrimarySelection();
905 // create the main frame window
906 DnDFrame
*frame
= new DnDFrame((wxFrame
*) NULL
,
907 "Drag-and-Drop/Clipboard wxWindows Sample",
918 DnDFrame::DnDFrame(wxFrame
*frame
, char *title
, int x
, int y
, int w
, int h
)
919 : wxFrame(frame
, -1, title
, wxPoint(x
, y
), wxSize(w
, h
)),
920 m_strText("wxWindows drag & drop works :-)")
923 // frame icon and status bar
924 SetIcon(wxICON(mondrian
));
929 wxMenu
*file_menu
= new wxMenu
;
930 file_menu
->Append(Menu_Drag
, "&Test drag...");
931 file_menu
->AppendSeparator();
932 file_menu
->Append(Menu_NewFrame
, "&New frame\tCtrl-N");
933 file_menu
->AppendSeparator();
934 file_menu
->Append(Menu_Quit
, "E&xit\tCtrl-Q");
936 wxMenu
*log_menu
= new wxMenu
;
937 log_menu
->Append(Menu_Clear
, "Clear\tCtrl-L");
939 wxMenu
*help_menu
= new wxMenu
;
940 help_menu
->Append(Menu_Help
, "&Help...");
941 help_menu
->AppendSeparator();
942 help_menu
->Append(Menu_About
, "&About");
944 wxMenu
*clip_menu
= new wxMenu
;
945 clip_menu
->Append(Menu_Copy
, "&Copy text\tCtrl-C");
946 clip_menu
->Append(Menu_Paste
, "&Paste text\tCtrl-V");
947 clip_menu
->AppendSeparator();
948 clip_menu
->Append(Menu_CopyBitmap
, "Copy &bitmap\tCtrl-Shift-C");
949 clip_menu
->Append(Menu_PasteBitmap
, "Paste b&itmap\tCtrl-Shift-V");
951 clip_menu
->AppendSeparator();
952 clip_menu
->Append(Menu_PasteMFile
, "Paste &metafile\tCtrl-M");
953 #endif // USE_METAFILES
954 clip_menu
->AppendSeparator();
955 clip_menu
->Append(Menu_CopyFiles
, "Copy &files\tCtrl-F");
957 wxMenuBar
*menu_bar
= new wxMenuBar
;
958 menu_bar
->Append(file_menu
, "&File");
959 menu_bar
->Append(log_menu
, "&Log");
960 menu_bar
->Append(clip_menu
, "&Clipboard");
961 menu_bar
->Append(help_menu
, "&Help");
963 SetMenuBar(menu_bar
);
965 // make a panel with 3 subwindows
967 wxSize
size(400, 200);
969 wxString
strFile("Drop files here!"), strText("Drop text on me");
971 m_ctrlFile
= new wxListBox(this, -1, pos
, size
, 1, &strFile
,
972 wxLB_HSCROLL
| wxLB_ALWAYS_SB
);
973 m_ctrlText
= new wxListBox(this, -1, pos
, size
, 1, &strText
,
974 wxLB_HSCROLL
| wxLB_ALWAYS_SB
);
976 m_ctrlLog
= new wxTextCtrl(this, -1, "", pos
, size
,
977 wxTE_MULTILINE
| wxTE_READONLY
|
980 // redirect log messages to the text window
981 m_pLog
= new wxLogTextCtrl(m_ctrlLog
);
982 m_pLogPrev
= wxLog::SetActiveTarget(m_pLog
);
984 // associate drop targets with the controls
985 m_ctrlFile
->SetDropTarget(new DnDFile(m_ctrlFile
));
986 m_ctrlText
->SetDropTarget(new DnDText(m_ctrlText
));
987 m_ctrlLog
->SetDropTarget(new URLDropTarget
);
989 wxLayoutConstraints
*c
;
992 c
= new wxLayoutConstraints
;
993 c
->left
.SameAs(this, wxLeft
);
994 c
->top
.SameAs(this, wxTop
);
995 c
->right
.PercentOf(this, wxRight
, 50);
996 c
->height
.PercentOf(this, wxHeight
, 30);
997 m_ctrlFile
->SetConstraints(c
);
1000 c
= new wxLayoutConstraints
;
1001 c
->left
.SameAs (m_ctrlFile
, wxRight
);
1002 c
->top
.SameAs (this, wxTop
);
1003 c
->right
.SameAs (this, wxRight
);
1004 c
->height
.PercentOf(this, wxHeight
, 30);
1005 m_ctrlText
->SetConstraints(c
);
1007 // Lower text control
1008 c
= new wxLayoutConstraints
;
1009 c
->left
.SameAs (this, wxLeft
);
1010 c
->right
.SameAs (this, wxRight
);
1011 c
->height
.PercentOf(this, wxHeight
, 50);
1012 c
->top
.SameAs(m_ctrlText
, wxBottom
);
1013 m_ctrlLog
->SetConstraints(c
);
1015 SetAutoLayout(TRUE
);
1018 void DnDFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
1023 void DnDFrame::OnSize(wxSizeEvent
& event
)
1030 void DnDFrame::OnPaint(wxPaintEvent
& WXUNUSED(event
))
1034 GetClientSize( &w
, &h
);
1037 // dc.Clear(); -- this kills wxGTK
1038 dc
.SetFont( wxFont( 24, wxDECORATIVE
, wxNORMAL
, wxNORMAL
, FALSE
, "charter" ) );
1039 dc
.DrawText( "Drag text from here!", 100, h
-50 );
1042 void DnDFrame::OnUpdateUIPasteText(wxUpdateUIEvent
& event
)
1045 // too many trace messages if we don't do it - this function is called
1050 event
.Enable( wxTheClipboard
->IsSupported(wxDF_TEXT
) );
1053 void DnDFrame::OnUpdateUIPasteBitmap(wxUpdateUIEvent
& event
)
1056 // too many trace messages if we don't do it - this function is called
1061 event
.Enable( wxTheClipboard
->IsSupported(wxDF_BITMAP
) );
1064 void DnDFrame::OnNewFrame(wxCommandEvent
& WXUNUSED(event
))
1066 (new DnDShapeFrame(this))->Show(TRUE
);
1068 wxLogStatus(this, wxT("Double click the new frame to select a shape for it"));
1071 void DnDFrame::OnDrag(wxCommandEvent
& WXUNUSED(event
))
1073 wxString strText
= wxGetTextFromUser
1075 "After you enter text in this dialog, press any mouse\n"
1076 "button in the bottom (empty) part of the frame and \n"
1077 "drag it anywhere - you will be in fact dragging the\n"
1078 "text object containing this text",
1079 "Please enter some text", m_strText
, this
1082 m_strText
= strText
;
1085 void DnDFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
1087 wxMessageBox("Drag-&-Drop Demo\n"
1088 "Please see \"Help|Help...\" for details\n"
1089 "Copyright (c) 1998 Vadim Zeitlin",
1091 wxICON_INFORMATION
| wxOK
,
1095 void DnDFrame::OnHelp(wxCommandEvent
& /* event */)
1097 wxMessageDialog
dialog(this,
1098 "This small program demonstrates drag & drop support in wxWindows. The program window\n"
1099 "consists of 3 parts: the bottom pane is for debug messages, so that you can see what's\n"
1100 "going on inside. The top part is split into 2 listboxes, the left one accepts files\n"
1101 "and the right one accepts text.\n"
1103 "To test wxDropTarget: open wordpad (write.exe), select some text in it and drag it to\n"
1104 "the right listbox (you'll notice the usual visual feedback, i.e. the cursor will change).\n"
1105 "Also, try dragging some files (you can select several at once) from Windows Explorer (or \n"
1106 "File Manager) to the left pane. Hold down Ctrl/Shift keys when you drop text (doesn't \n"
1107 "work with files) and see what changes.\n"
1109 "To test wxDropSource: just press any mouse button on the empty zone of the window and drag\n"
1110 "it to wordpad or any other droptarget accepting text (and of course you can just drag it\n"
1111 "to the right pane). Due to a lot of trace messages, the cursor might take some time to \n"
1112 "change, don't release the mouse button until it does. You can change the string being\n"
1113 "dragged in in \"File|Test drag...\" dialog.\n"
1116 "Please send all questions/bug reports/suggestions &c to \n"
1117 "Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>",
1123 void DnDFrame::OnLogClear(wxCommandEvent
& /* event */ )
1126 m_ctrlText
->Clear();
1127 m_ctrlFile
->Clear();
1130 void DnDFrame::OnLeftDown(wxMouseEvent
&WXUNUSED(event
) )
1132 if ( !m_strText
.IsEmpty() )
1134 // start drag operation
1135 wxTextDataObject
textData(m_strText
);
1137 wxFileDataObject textData;
1138 textData.AddFile( "/file1.txt" );
1139 textData.AddFile( "/file2.txt" );
1141 wxDropSource
source(textData
, this,
1142 wxDROP_ICON(dnd_copy
),
1143 wxDROP_ICON(dnd_move
),
1144 wxDROP_ICON(dnd_none
));
1148 switch ( source
.DoDragDrop(TRUE
) )
1150 case wxDragError
: pc
= "Error!"; break;
1151 case wxDragNone
: pc
= "Nothing"; break;
1152 case wxDragCopy
: pc
= "Copied"; break;
1153 case wxDragMove
: pc
= "Moved"; break;
1154 case wxDragCancel
: pc
= "Cancelled"; break;
1155 default: pc
= "Huh?"; break;
1158 SetStatusText(wxString("Drag result: ") + pc
);
1162 void DnDFrame::OnRightDown(wxMouseEvent
&event
)
1164 wxMenu
menu("Dnd sample menu");
1166 menu
.Append(Menu_Drag
, "&Test drag...");
1167 menu
.AppendSeparator();
1168 menu
.Append(Menu_About
, "&About");
1170 PopupMenu( &menu
, event
.GetX(), event
.GetY() );
1173 DnDFrame::~DnDFrame()
1175 if ( m_pLog
!= NULL
) {
1176 if ( wxLog::SetActiveTarget(m_pLogPrev
) == m_pLog
)
1181 // ---------------------------------------------------------------------------
1183 // ---------------------------------------------------------------------------
1185 void DnDFrame::OnCopyBitmap(wxCommandEvent
& WXUNUSED(event
))
1187 // PNG support is not always compiled in under Windows, so use BMP there
1189 wxFileDialog
dialog(this, "Open a BMP file", "", "", "BMP files (*.bmp)|*.bmp", 0);
1191 wxFileDialog
dialog(this, "Open a PNG file", "", "", "PNG files (*.png)|*.png", 0);
1194 if (dialog
.ShowModal() != wxID_OK
)
1196 wxLogMessage( _T("Aborted file open") );
1200 if (dialog
.GetPath().IsEmpty())
1202 wxLogMessage( _T("Returned empty string.") );
1206 if (!wxFileExists(dialog
.GetPath()))
1208 wxLogMessage( _T("File doesn't exist.") );
1213 image
.LoadFile( dialog
.GetPath(),
1222 wxLogError( _T("Invalid image file...") );
1226 wxLogStatus( _T("Decoding image file...") );
1229 wxBitmap
bitmap( image
);
1231 if ( !wxTheClipboard
->Open() )
1233 wxLogError(_T("Can't open clipboard."));
1238 wxLogMessage( _T("Creating wxBitmapDataObject...") );
1241 if ( !wxTheClipboard
->AddData(new wxBitmapDataObject(bitmap
)) )
1243 wxLogError(_T("Can't copy image to the clipboard."));
1247 wxLogMessage(_T("Image has been put on the clipboard.") );
1248 wxLogMessage(_T("You can paste it now and look at it.") );
1251 wxTheClipboard
->Close();
1254 void DnDFrame::OnPasteBitmap(wxCommandEvent
& WXUNUSED(event
))
1256 if ( !wxTheClipboard
->Open() )
1258 wxLogError(_T("Can't open clipboard."));
1263 if ( !wxTheClipboard
->IsSupported(wxDF_BITMAP
) )
1265 wxLogWarning(_T("No bitmap on clipboard"));
1267 wxTheClipboard
->Close();
1271 wxBitmapDataObject data
;
1272 if ( !wxTheClipboard
->GetData(data
) )
1274 wxLogError(_T("Can't paste bitmap from the clipboard"));
1278 const wxBitmap
& bmp
= data
.GetBitmap();
1280 wxLogMessage(_T("Bitmap %dx%d pasted from the clipboard"),
1281 bmp
.GetWidth(), bmp
.GetHeight());
1285 wxTheClipboard
->Close();
1288 #ifdef USE_METAFILES
1290 void DnDFrame::OnPasteMetafile(wxCommandEvent
& WXUNUSED(event
))
1292 if ( !wxTheClipboard
->Open() )
1294 wxLogError(_T("Can't open clipboard."));
1299 if ( !wxTheClipboard
->IsSupported(wxDF_METAFILE
) )
1301 wxLogWarning(_T("No metafile on clipboard"));
1305 wxMetaFileDataObject data
;
1306 if ( !wxTheClipboard
->GetData(data
) )
1308 wxLogError(_T("Can't paste metafile from the clipboard"));
1312 const wxMetaFile
& mf
= data
.GetMetafile();
1314 wxLogMessage(_T("Metafile %dx%d pasted from the clipboard"),
1315 mf
.GetWidth(), mf
.GetHeight());
1321 wxTheClipboard
->Close();
1324 #endif // USE_METAFILES
1326 // ----------------------------------------------------------------------------
1328 // ----------------------------------------------------------------------------
1330 void DnDFrame::OnCopyFiles(wxCommandEvent
& WXUNUSED(event
))
1333 wxFileDialog
dialog(this, "Select a file to copy", "", "",
1334 "All files (*.*)|*.*", 0);
1336 wxArrayString filenames
;
1337 while ( dialog
.ShowModal() == wxID_OK
)
1339 filenames
.Add(dialog
.GetPath());
1342 if ( !filenames
.IsEmpty() )
1344 wxFileDataObject
*dobj
= new wxFileDataObject
;
1345 size_t count
= filenames
.GetCount();
1346 for ( size_t n
= 0; n
< count
; n
++ )
1348 dobj
->AddFile(filenames
[n
]);
1351 wxClipboardLocker locker
;
1354 wxLogError(wxT("Can't open clipboard"));
1358 if ( !wxTheClipboard
->AddData(dobj
) )
1360 wxLogError(wxT("Can't copy file(s) to the clipboard"));
1364 wxLogStatus(this, wxT("%d file%s copied to the clipboard"),
1365 count
, count
== 1 ? wxT("") : wxT("s"));
1371 wxLogStatus(this, wxT("Aborted"));
1374 wxLogError(wxT("Sorry, not implemented"));
1378 // ---------------------------------------------------------------------------
1380 // ---------------------------------------------------------------------------
1382 void DnDFrame::OnCopy(wxCommandEvent
& WXUNUSED(event
))
1384 if ( !wxTheClipboard
->Open() )
1386 wxLogError(_T("Can't open clipboard."));
1391 if ( !wxTheClipboard
->AddData(new wxTextDataObject(m_strText
)) )
1393 wxLogError(_T("Can't copy data to the clipboard"));
1397 wxLogMessage(_T("Text '%s' put on the clipboard"), m_strText
.c_str());
1400 wxTheClipboard
->Close();
1403 void DnDFrame::OnPaste(wxCommandEvent
& WXUNUSED(event
))
1405 if ( !wxTheClipboard
->Open() )
1407 wxLogError(_T("Can't open clipboard."));
1412 if ( !wxTheClipboard
->IsSupported(wxDF_TEXT
) )
1414 wxLogWarning(_T("No text data on clipboard"));
1416 wxTheClipboard
->Close();
1420 wxTextDataObject text
;
1421 if ( !wxTheClipboard
->GetData(text
) )
1423 wxLogError(_T("Can't paste data from the clipboard"));
1427 wxLogMessage(_T("Text '%s' pasted from the clipboard"),
1428 text
.GetText().c_str());
1431 wxTheClipboard
->Close();
1434 // ----------------------------------------------------------------------------
1435 // Notifications called by the base class
1436 // ----------------------------------------------------------------------------
1438 bool DnDText::OnDropText(wxCoord
, wxCoord
, const wxString
& text
)
1440 m_pOwner
->Append(text
);
1445 bool DnDFile::OnDropFiles(wxCoord
, wxCoord
, const wxArrayString
& filenames
)
1447 size_t nFiles
= filenames
.GetCount();
1449 str
.Printf( _T("%d files dropped"), nFiles
);
1450 m_pOwner
->Append(str
);
1451 for ( size_t n
= 0; n
< nFiles
; n
++ ) {
1452 m_pOwner
->Append(filenames
[n
]);
1458 // ----------------------------------------------------------------------------
1460 // ----------------------------------------------------------------------------
1462 DnDShapeDialog::DnDShapeDialog(wxFrame
*parent
, DnDShape
*shape
)
1464 :wxDialog( parent
, 6001, wxT("Choose Shape"), wxPoint( 10, 10 ),
1466 wxRAISED_BORDER
|wxCAPTION
|wxTHICK_FRAME
|wxSYSTEM_MENU
)
1471 LoadFromResource(parent
, "dialogShape");
1473 m_textX
= (wxTextCtrl
*)wxFindWindowByName("textX", this);
1474 m_textY
= (wxTextCtrl
*)wxFindWindowByName("textY", this);
1475 m_textW
= (wxTextCtrl
*)wxFindWindowByName("textW", this);
1476 m_textH
= (wxTextCtrl
*)wxFindWindowByName("textH", this);
1478 m_radio
= (wxRadioBox
*)wxFindWindowByName("radio", this);
1480 wxBoxSizer
* topSizer
= new wxBoxSizer( wxVERTICAL
);
1483 wxBoxSizer
* shapesSizer
= new wxBoxSizer( wxHORIZONTAL
);
1484 const wxString choices
[] = { wxT("None"), wxT("Triangle"),
1485 wxT("Rectangle"), wxT("Ellipse") };
1487 m_radio
= new wxRadioBox( this, -1, wxT("&Shape"),
1488 wxDefaultPosition
, wxDefaultSize
, 4, choices
, 4,
1489 wxRA_SPECIFY_COLS
);
1490 shapesSizer
->Add( m_radio
, 0, wxGROW
|wxALL
, 5 );
1491 topSizer
->Add( shapesSizer
, 0, wxALL
, 2 );
1494 wxStaticBox
* box
= new wxStaticBox( this, -1, wxT("&Attributes") );
1495 wxStaticBoxSizer
* attrSizer
= new wxStaticBoxSizer( box
, wxHORIZONTAL
);
1496 wxFlexGridSizer
* xywhSizer
= new wxFlexGridSizer( 4, 2 );
1500 st
= new wxStaticText( this, -1, wxT("Position &X:") );
1501 m_textX
= new wxTextCtrl( this, -1, wxEmptyString
, wxDefaultPosition
,
1503 xywhSizer
->Add( st
, 1, wxGROW
|wxALL
, 2 );
1504 xywhSizer
->Add( m_textX
, 1, wxGROW
|wxALL
, 2 );
1506 st
= new wxStaticText( this, -1, wxT("Size &width:") );
1507 m_textW
= new wxTextCtrl( this, -1, wxEmptyString
, wxDefaultPosition
,
1509 xywhSizer
->Add( st
, 1, wxGROW
|wxALL
, 2 );
1510 xywhSizer
->Add( m_textW
, 1, wxGROW
|wxALL
, 2 );
1512 st
= new wxStaticText( this, -1, wxT("&Y:") );
1513 m_textY
= new wxTextCtrl( this, -1, wxEmptyString
, wxDefaultPosition
,
1515 xywhSizer
->Add( st
, 1, wxALL
|wxALIGN_RIGHT
, 2 );
1516 xywhSizer
->Add( m_textY
, 1, wxGROW
|wxALL
, 2 );
1518 st
= new wxStaticText( this, -1, wxT("&height:") );
1519 m_textH
= new wxTextCtrl( this, -1, wxEmptyString
, wxDefaultPosition
,
1521 xywhSizer
->Add( st
, 1, wxALL
|wxALIGN_RIGHT
, 2 );
1522 xywhSizer
->Add( m_textH
, 1, wxGROW
|wxALL
, 2 );
1524 wxButton
* col
= new wxButton( this, Button_Colour
, wxT("&Colour...") );
1525 attrSizer
->Add( xywhSizer
, 1, wxGROW
);
1526 attrSizer
->Add( col
, 0, wxALL
|wxALIGN_CENTRE_VERTICAL
, 2 );
1527 topSizer
->Add( attrSizer
, 0, wxGROW
|wxALL
, 5 );
1530 wxBoxSizer
* buttonSizer
= new wxBoxSizer( wxHORIZONTAL
);
1532 bt
= new wxButton( this, wxID_OK
, wxT("Ok") );
1533 buttonSizer
->Add( bt
, 0, wxALL
, 2 );
1534 bt
= new wxButton( this, wxID_CANCEL
, wxT("Cancel") );
1535 buttonSizer
->Add( bt
, 0, wxALL
, 2 );
1536 topSizer
->Add( buttonSizer
, 0, wxALL
|wxALIGN_RIGHT
, 2 );
1538 SetAutoLayout( TRUE
);
1539 SetSizer( topSizer
);
1540 topSizer
->Fit( this );
1544 DnDShape
*DnDShapeDialog::GetShape() const
1546 switch ( m_shapeKind
)
1549 case DnDShape::None
: return NULL
;
1550 case DnDShape::Triangle
: return new DnDTriangularShape(m_pos
, m_size
, m_col
);
1551 case DnDShape::Rectangle
: return new DnDRectangularShape(m_pos
, m_size
, m_col
);
1552 case DnDShape::Ellipse
: return new DnDEllipticShape(m_pos
, m_size
, m_col
);
1556 bool DnDShapeDialog::TransferDataToWindow()
1561 m_radio
->SetSelection(m_shape
->GetKind());
1562 m_pos
= m_shape
->GetPosition();
1563 m_size
= m_shape
->GetSize();
1564 m_col
= m_shape
->GetColour();
1568 m_radio
->SetSelection(DnDShape::None
);
1569 m_pos
= wxPoint(1, 1);
1570 m_size
= wxSize(100, 100);
1573 m_textX
->SetValue(wxString() << m_pos
.x
);
1574 m_textY
->SetValue(wxString() << m_pos
.y
);
1575 m_textW
->SetValue(wxString() << m_size
.x
);
1576 m_textH
->SetValue(wxString() << m_size
.y
);
1581 bool DnDShapeDialog::TransferDataFromWindow()
1583 m_shapeKind
= (DnDShape::Kind
)m_radio
->GetSelection();
1585 m_pos
.x
= wxAtoi(m_textX
->GetValue());
1586 m_pos
.y
= wxAtoi(m_textY
->GetValue());
1587 m_size
.x
= wxAtoi(m_textW
->GetValue());
1588 m_size
.y
= wxAtoi(m_textH
->GetValue());
1590 if ( !m_pos
.x
|| !m_pos
.y
|| !m_size
.x
|| !m_size
.y
)
1592 wxMessageBox("All sizes and positions should be non null!",
1593 "Invalid shape", wxICON_HAND
| wxOK
, this);
1601 void DnDShapeDialog::OnColour(wxCommandEvent
& WXUNUSED(event
))
1604 data
.SetChooseFull(TRUE
);
1605 for (int i
= 0; i
< 16; i
++)
1607 wxColour
colour(i
*16, i
*16, i
*16);
1608 data
.SetCustomColour(i
, colour
);
1611 wxColourDialog
dialog(this, &data
);
1612 if ( dialog
.ShowModal() == wxID_OK
)
1614 m_col
= dialog
.GetColourData().GetColour();
1618 // ----------------------------------------------------------------------------
1620 // ----------------------------------------------------------------------------
1622 DnDShapeFrame
*DnDShapeFrame::ms_lastDropTarget
= NULL
;
1624 DnDShapeFrame::DnDShapeFrame(wxFrame
*parent
)
1625 : wxFrame(parent
, -1, "Shape Frame",
1626 wxDefaultPosition
, wxSize(250, 150))
1630 wxMenu
*menuShape
= new wxMenu
;
1631 menuShape
->Append(Menu_Shape_New
, "&New default shape\tCtrl-S");
1632 menuShape
->Append(Menu_Shape_Edit
, "&Edit shape\tCtrl-E");
1633 menuShape
->AppendSeparator();
1634 menuShape
->Append(Menu_Shape_Clear
, "&Clear shape\tCtrl-L");
1636 wxMenu
*menuClipboard
= new wxMenu
;
1637 menuClipboard
->Append(Menu_ShapeClipboard_Copy
, "&Copy\tCtrl-C");
1638 menuClipboard
->Append(Menu_ShapeClipboard_Paste
, "&Paste\tCtrl-V");
1640 wxMenuBar
*menubar
= new wxMenuBar
;
1641 menubar
->Append(menuShape
, "&Shape");
1642 menubar
->Append(menuClipboard
, "&Clipboard");
1644 SetMenuBar(menubar
);
1646 SetStatusText("Press Ctrl-S to create a new shape");
1648 SetDropTarget(new DnDShapeDropTarget(this));
1652 SetBackgroundColour(*wxWHITE
);
1655 DnDShapeFrame::~DnDShapeFrame()
1661 void DnDShapeFrame::SetShape(DnDShape
*shape
)
1670 void DnDShapeFrame::OnDrag(wxMouseEvent
& event
)
1679 // start drag operation
1680 DnDShapeDataObject
shapeData(m_shape
);
1681 wxDropSource
source(shapeData
, this);
1683 const char *pc
= NULL
;
1684 switch ( source
.DoDragDrop(TRUE
) )
1688 wxLogError(wxT("An error occured during drag and drop operation"));
1692 SetStatusText("Nothing happened");
1701 if ( ms_lastDropTarget
!= this )
1703 // don't delete the shape if we dropped it on ourselves!
1709 SetStatusText("Drag and drop operation cancelled");
1715 SetStatusText(wxString("Shape successfully ") + pc
);
1717 //else: status text already set
1720 void DnDShapeFrame::OnDrop(wxCoord x
, wxCoord y
, DnDShape
*shape
)
1722 ms_lastDropTarget
= this;
1727 s
.Printf(wxT("Shape dropped at (%ld, %ld)"), pt
.x
, pt
.y
);
1734 void DnDShapeFrame::OnEditShape(wxCommandEvent
& event
)
1736 DnDShapeDialog
dlg(this, m_shape
);
1737 if ( dlg
.ShowModal() == wxID_OK
)
1739 SetShape(dlg
.GetShape());
1743 SetStatusText("You can now drag the shape to another frame");
1748 void DnDShapeFrame::OnNewShape(wxCommandEvent
& event
)
1750 SetShape(new DnDEllipticShape(wxPoint(10, 10), wxSize(80, 60), *wxRED
));
1752 SetStatusText("You can now drag the shape to another frame");
1755 void DnDShapeFrame::OnClearShape(wxCommandEvent
& event
)
1760 void DnDShapeFrame::OnCopyShape(wxCommandEvent
& event
)
1764 wxClipboardLocker clipLocker
;
1767 wxLogError(wxT("Can't open the clipboard"));
1772 wxTheClipboard
->AddData(new DnDShapeDataObject(m_shape
));
1776 void DnDShapeFrame::OnPasteShape(wxCommandEvent
& event
)
1778 wxClipboardLocker clipLocker
;
1781 wxLogError(wxT("Can't open the clipboard"));
1786 DnDShapeDataObject
shapeDataObject(NULL
);
1787 if ( wxTheClipboard
->GetData(shapeDataObject
) )
1789 SetShape(shapeDataObject
.GetShape());
1793 wxLogStatus(wxT("No shape on the clipboard"));
1797 void DnDShapeFrame::OnUpdateUICopy(wxUpdateUIEvent
& event
)
1799 event
.Enable( m_shape
!= NULL
);
1802 void DnDShapeFrame::OnUpdateUIPaste(wxUpdateUIEvent
& event
)
1804 event
.Enable( wxTheClipboard
->IsSupported(wxDataFormat(shapeFormatId
)) );
1807 void DnDShapeFrame::OnPaint(wxPaintEvent
& event
)
1821 // ----------------------------------------------------------------------------
1823 // ----------------------------------------------------------------------------
1825 DnDShape
*DnDShape::New(const void *buf
)
1827 const ShapeDump
& dump
= *(const ShapeDump
*)buf
;
1831 return new DnDTriangularShape(wxPoint(dump
.x
, dump
.y
),
1832 wxSize(dump
.w
, dump
.h
),
1833 wxColour(dump
.r
, dump
.g
, dump
.b
));
1836 return new DnDRectangularShape(wxPoint(dump
.x
, dump
.y
),
1837 wxSize(dump
.w
, dump
.h
),
1838 wxColour(dump
.r
, dump
.g
, dump
.b
));
1841 return new DnDEllipticShape(wxPoint(dump
.x
, dump
.y
),
1842 wxSize(dump
.w
, dump
.h
),
1843 wxColour(dump
.r
, dump
.g
, dump
.b
));
1846 wxFAIL_MSG(wxT("invalid shape!"));
1851 // ----------------------------------------------------------------------------
1852 // DnDShapeDataObject
1853 // ----------------------------------------------------------------------------
1855 #ifdef USE_METAFILES
1857 void DnDShapeDataObject::CreateMetaFile() const
1859 wxPoint pos
= m_shape
->GetPosition();
1860 wxSize size
= m_shape
->GetSize();
1862 wxMetaFileDC
dcMF(wxEmptyString
, pos
.x
+ size
.x
, pos
.y
+ size
.y
);
1864 m_shape
->Draw(dcMF
);
1866 wxMetafile
*mf
= dcMF
.Close();
1868 DnDShapeDataObject
*self
= (DnDShapeDataObject
*)this; // const_cast
1869 self
->m_dobjMetaFile
.SetMetafile(*mf
);
1870 self
->m_hasMetaFile
= TRUE
;
1877 void DnDShapeDataObject::CreateBitmap() const
1879 wxPoint pos
= m_shape
->GetPosition();
1880 wxSize size
= m_shape
->GetSize();
1881 int x
= pos
.x
+ size
.x
,
1883 wxBitmap
bitmap(x
, y
);
1885 dc
.SelectObject(bitmap
);
1886 dc
.SetBrush(wxBrush(wxT("white"), wxSOLID
));
1889 dc
.SelectObject(wxNullBitmap
);
1891 DnDShapeDataObject
*self
= (DnDShapeDataObject
*)this; // const_cast
1892 self
->m_dobjBitmap
.SetBitmap(bitmap
);
1893 self
->m_hasBitmap
= TRUE
;
1896 // ----------------------------------------------------------------------------
1898 // ----------------------------------------------------------------------------
1900 static void ShowBitmap(const wxBitmap
& bitmap
)
1902 wxFrame
*frame
= new wxFrame(NULL
, -1, _T("Bitmap view"));
1903 frame
->CreateStatusBar();
1904 DnDCanvasBitmap
*canvas
= new DnDCanvasBitmap(frame
);
1905 canvas
->SetBitmap(bitmap
);
1907 int w
= bitmap
.GetWidth(),
1908 h
= bitmap
.GetHeight();
1909 frame
->SetStatusText(wxString::Format(_T("%dx%d"), w
, h
));
1911 frame
->SetClientSize(w
> 100 ? 100 : w
, h
> 100 ? 100 : h
);
1915 #ifdef USE_METAFILES
1917 static void ShowMetaFile(const wxMetaFile
& metafile
)
1919 wxFrame
*frame
= new wxFrame(NULL
, -1, _T("Metafile view"));
1920 frame
->CreateStatusBar();
1921 DnDCanvasMetafile
*canvas
= new DnDCanvasMetafile(frame
);
1922 canvas
->SetMetafile(metafile
);
1924 wxSize size
= metafile
.GetSize();
1925 frame
->SetStatusText(wxString::Format(_T("%dx%d"), size
.x
, size
.y
));
1927 frame
->SetClientSize(size
.x
> 100 ? 100 : size
.x
,
1928 size
.y
> 100 ? 100 : size
.y
);
1932 #endif // USE_METAFILES