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(__WXMOTIF__)
58 #include "mondrian.xpm"
60 #include "dnd_copy.xpm"
61 #include "dnd_move.xpm"
62 #include "dnd_none.xpm"
65 // ----------------------------------------------------------------------------
66 // Derive two simple classes which just put in the listbox the strings (text or
67 // file names) we drop on them
68 // ----------------------------------------------------------------------------
70 class DnDText
: public wxTextDropTarget
73 DnDText(wxListBox
*pOwner
) { m_pOwner
= pOwner
; }
75 virtual bool OnDropText(wxCoord x
, wxCoord y
, const wxString
& text
);
81 class DnDFile
: public wxFileDropTarget
84 DnDFile(wxListBox
*pOwner
) { m_pOwner
= pOwner
; }
86 virtual bool OnDropFiles(wxCoord x
, wxCoord y
,
87 const wxArrayString
& filenames
);
93 // ----------------------------------------------------------------------------
94 // Define a custom dtop target accepting URLs
95 // ----------------------------------------------------------------------------
97 class URLDropTarget
: public wxDropTarget
100 URLDropTarget() { SetDataObject(new wxURLDataObject
); }
102 void OnDropURL(wxCoord x
, wxCoord y
, const wxString
& text
)
104 // of course, a real program would do something more useful here...
105 wxMessageBox(text
, _T("wxDnD sample: got URL"),
106 wxICON_INFORMATION
| wxOK
);
109 // URLs can't be moved, only copied
110 virtual wxDragResult
OnDragOver(wxCoord
WXUNUSED(x
), wxCoord
WXUNUSED(y
),
112 { return def
== wxDragMove
? wxDragCopy
: def
; }
114 // translate this to calls to OnDropURL() just for convenience
115 virtual wxDragResult
OnData(wxCoord x
, wxCoord y
, wxDragResult def
)
120 OnDropURL(x
, y
, ((wxURLDataObject
*)m_dataObject
)->GetURL());
126 // ----------------------------------------------------------------------------
127 // Define a new application type
128 // ----------------------------------------------------------------------------
130 class DnDApp
: public wxApp
133 virtual bool OnInit();
136 IMPLEMENT_APP(DnDApp
);
138 // ----------------------------------------------------------------------------
139 // Define canvas class to show a bitmap
140 // ----------------------------------------------------------------------------
142 class DnDCanvasBitmap
: public wxScrolledWindow
145 DnDCanvasBitmap(wxWindow
*parent
) : wxScrolledWindow(parent
) { }
147 void SetBitmap(const wxBitmap
& bitmap
)
151 SetScrollbars(10, 10,
152 m_bitmap
.GetWidth() / 10, m_bitmap
.GetHeight() / 10);
157 void OnPaint(wxPaintEvent
& event
)
165 dc
.DrawBitmap(m_bitmap
, 0, 0);
172 DECLARE_EVENT_TABLE()
177 // and the same thing fo metafiles
178 class DnDCanvasMetafile
: public wxScrolledWindow
181 DnDCanvasMetafile(wxWindow
*parent
) : wxScrolledWindow(parent
) { }
183 void SetMetafile(const wxMetafile
& metafile
)
185 m_metafile
= metafile
;
187 SetScrollbars(10, 10,
188 m_metafile
.GetWidth() / 10, m_metafile
.GetHeight() / 10);
193 void OnPaint(wxPaintEvent
& event
)
197 if ( m_metafile
.Ok() )
201 m_metafile
.Play(&dc
);
206 wxMetafile m_metafile
;
208 DECLARE_EVENT_TABLE()
211 #endif // USE_METAFILES
213 // ----------------------------------------------------------------------------
214 // Define a new frame type for the main frame
215 // ----------------------------------------------------------------------------
217 class DnDFrame
: public wxFrame
220 DnDFrame(wxFrame
*frame
, char *title
, int x
, int y
, int w
, int h
);
223 void OnPaint(wxPaintEvent
& event
);
224 void OnQuit (wxCommandEvent
& event
);
225 void OnAbout(wxCommandEvent
& event
);
226 void OnDrag (wxCommandEvent
& event
);
227 void OnNewFrame(wxCommandEvent
& event
);
228 void OnHelp (wxCommandEvent
& event
);
229 void OnLogClear(wxCommandEvent
& event
);
231 void OnCopy(wxCommandEvent
& event
);
232 void OnPaste(wxCommandEvent
& event
);
234 void OnCopyBitmap(wxCommandEvent
& event
);
235 void OnPasteBitmap(wxCommandEvent
& event
);
238 void OnPasteMetafile(wxCommandEvent
& event
);
239 #endif // USE_METAFILES
241 void OnCopyFiles(wxCommandEvent
& event
);
243 void OnLeftDown(wxMouseEvent
& event
);
244 void OnRightDown(wxMouseEvent
& event
);
246 void OnUpdateUIPasteText(wxUpdateUIEvent
& event
);
247 void OnUpdateUIPasteBitmap(wxUpdateUIEvent
& event
);
249 DECLARE_EVENT_TABLE()
252 wxListBox
*m_ctrlFile
,
254 wxTextCtrl
*m_ctrlLog
;
262 // ----------------------------------------------------------------------------
263 // A shape is an example of application-specific data which may be transported
264 // via drag-and-drop or clipboard: in our case, we have different geometric
265 // shapes, each one with its own colour and position
266 // ----------------------------------------------------------------------------
279 DnDShape(const wxPoint
& pos
,
282 : m_pos(pos
), m_size(size
), m_col(col
)
286 // this is for debugging - lets us see when exactly an object is freed
287 // (this may be later than you think if it's on the clipboard, for example)
288 virtual ~DnDShape() { }
290 // the functions used for drag-and-drop: they dump and restore a shape into
291 // some bitwise-copiable data (might use streams too...)
292 // ------------------------------------------------------------------------
294 // restore from buffer
295 static DnDShape
*New(const void *buf
);
297 virtual size_t GetDataSize() const
299 return sizeof(ShapeDump
);
302 virtual void GetDataHere(void *buf
) const
304 ShapeDump
& dump
= *(ShapeDump
*)buf
;
309 dump
.r
= m_col
.Red();
310 dump
.g
= m_col
.Green();
311 dump
.b
= m_col
.Blue();
316 const wxPoint
& GetPosition() const { return m_pos
; }
317 const wxColour
& GetColour() const { return m_col
; }
318 const wxSize
& GetSize() const { return m_size
; }
320 void Move(const wxPoint
& pos
) { m_pos
= pos
; }
322 // to implement in derived classes
323 virtual Kind
GetKind() const = 0;
325 virtual void Draw(wxDC
& dc
)
327 dc
.SetPen(wxPen(m_col
, 1, wxSOLID
));
331 wxPoint
GetCentre() const
332 { return wxPoint(m_pos
.x
+ m_size
.x
/ 2, m_pos
.y
+ m_size
.y
/ 2); }
336 int x
, y
, // position
347 class DnDTriangularShape
: public DnDShape
350 DnDTriangularShape(const wxPoint
& pos
,
353 : DnDShape(pos
, size
, col
)
355 wxLogMessage(wxT("DnDTriangularShape is being created"));
358 virtual ~DnDTriangularShape()
360 wxLogMessage(wxT("DnDTriangularShape is being deleted"));
363 virtual Kind
GetKind() const { return Triangle
; }
364 virtual void Draw(wxDC
& dc
)
368 // well, it's a bit difficult to describe a triangle by position and
369 // size, but we're not doing geometry here, do we? ;-)
371 wxPoint
p2(m_pos
.x
+ m_size
.x
, m_pos
.y
);
372 wxPoint
p3(m_pos
.x
, m_pos
.y
+ m_size
.y
);
379 dc
.FloodFill(GetCentre(), m_col
, wxFLOOD_BORDER
);
384 class DnDRectangularShape
: public DnDShape
387 DnDRectangularShape(const wxPoint
& pos
,
390 : DnDShape(pos
, size
, col
)
392 wxLogMessage(wxT("DnDRectangularShape is being created"));
395 virtual ~DnDRectangularShape()
397 wxLogMessage(wxT("DnDRectangularShape is being deleted"));
400 virtual Kind
GetKind() const { return Rectangle
; }
401 virtual void Draw(wxDC
& dc
)
406 wxPoint
p2(p1
.x
+ m_size
.x
, p1
.y
);
407 wxPoint
p3(p2
.x
, p2
.y
+ m_size
.y
);
408 wxPoint
p4(p1
.x
, p3
.y
);
416 dc
.FloodFill(GetCentre(), m_col
, wxFLOOD_BORDER
);
421 class DnDEllipticShape
: public DnDShape
424 DnDEllipticShape(const wxPoint
& pos
,
427 : DnDShape(pos
, size
, col
)
429 wxLogMessage(wxT("DnDEllipticShape is being created"));
432 virtual ~DnDEllipticShape()
434 wxLogMessage(wxT("DnDEllipticShape is being deleted"));
437 virtual Kind
GetKind() const { return Ellipse
; }
438 virtual void Draw(wxDC
& dc
)
442 dc
.DrawEllipse(m_pos
, m_size
);
445 dc
.FloodFill(GetCentre(), m_col
, wxFLOOD_BORDER
);
450 // ----------------------------------------------------------------------------
451 // A wxDataObject specialisation for the application-specific data
452 // ----------------------------------------------------------------------------
454 static const wxChar
*shapeFormatId
= wxT("wxShape");
456 class DnDShapeDataObject
: public wxDataObject
459 // ctor doesn't copy the pointer, so it shouldn't go away while this object
461 DnDShapeDataObject(DnDShape
*shape
= (DnDShape
*)NULL
)
465 // we need to copy the shape because the one we're handled may be
466 // deleted while it's still on the clipboard (for example) - and we
467 // reuse the serialisation methods here to copy it
468 void *buf
= malloc(shape
->DnDShape::GetDataSize());
469 shape
->GetDataHere(buf
);
470 m_shape
= DnDShape::New(buf
);
480 // this string should uniquely identify our format, but is otherwise
482 m_formatShape
.SetId(shapeFormatId
);
484 // we don't draw the shape to a bitmap until it's really needed (i.e.
485 // we're asked to do so)
488 m_hasMetaFile
= FALSE
;
492 virtual ~DnDShapeDataObject() { delete m_shape
; }
494 // after a call to this function, the shape is owned by the caller and it
495 // is responsible for deleting it!
497 // NB: a better solution would be to make DnDShapes ref counted and this
498 // is what should probably be done in a real life program, otherwise
499 // the ownership problems become too complicated really fast
502 DnDShape
*shape
= m_shape
;
504 m_shape
= (DnDShape
*)NULL
;
507 m_hasMetaFile
= FALSE
;
513 // implement base class pure virtuals
514 // ----------------------------------
516 virtual wxDataFormat
GetPreferredFormat(Direction
WXUNUSED(dir
)) const
518 return m_formatShape
;
521 virtual size_t GetFormatCount(Direction dir
) const
523 // our custom format is supported by both GetData() and SetData()
527 // but the bitmap format(s) are only supported for output
528 nFormats
+= m_dobjBitmap
.GetFormatCount(dir
);
531 nFormats
+= m_dobjMetaFile
.GetFormatCount(dir
);
538 virtual void GetAllFormats(wxDataFormat
*formats
, Direction dir
) const
540 formats
[0] = m_formatShape
;
543 // in Get direction we additionally support bitmaps and metafiles
545 m_dobjBitmap
.GetAllFormats(&formats
[1], dir
);
548 // don't assume that m_dobjBitmap has only 1 format
549 m_dobjMetaFile
.GetAllFormats(&formats
[1 +
550 m_dobjBitmap
.GetFormatCount(dir
)], dir
);
555 virtual size_t GetDataSize(const wxDataFormat
& format
) const
557 if ( format
== m_formatShape
)
559 return m_shape
->GetDataSize();
562 else if ( m_dobjMetaFile
.IsSupported(format
) )
564 if ( !m_hasMetaFile
)
567 return m_dobjMetaFile
.GetDataSize(format
);
572 wxASSERT_MSG( m_dobjBitmap
.IsSupported(format
),
573 wxT("unexpected format") );
578 return m_dobjBitmap
.GetDataSize();
582 virtual bool GetDataHere(const wxDataFormat
& format
, void *pBuf
) const
584 if ( format
== m_formatShape
)
586 m_shape
->GetDataHere(pBuf
);
591 else if ( m_dobjMetaFile
.IsSupported(format
) )
593 if ( !m_hasMetaFile
)
596 return m_dobjMetaFile
.GetDataHere(format
, pBuf
);
601 wxASSERT_MSG( m_dobjBitmap
.IsSupported(format
),
602 wxT("unexpected format") );
607 return m_dobjBitmap
.GetDataHere(pBuf
);
611 virtual bool SetData(const wxDataFormat
& format
,
612 size_t len
, const void *buf
)
614 wxCHECK_MSG( format
== m_formatShape
, FALSE
,
615 wxT( "unsupported format") );
618 m_shape
= DnDShape::New(buf
);
620 // the shape has changed
624 m_hasMetaFile
= FALSE
;
631 // creates a bitmap and assigns it to m_dobjBitmap (also sets m_hasBitmap)
632 void CreateBitmap() const;
634 void CreateMetaFile() const;
637 wxDataFormat m_formatShape
; // our custom format
639 wxBitmapDataObject m_dobjBitmap
; // it handles bitmaps
640 bool m_hasBitmap
; // true if m_dobjBitmap has valid bitmap
643 wxMetaFileDataObject m_dobjMetaFile
;// handles metafiles
644 bool m_hasMetaFile
; // true if we have valid metafile
647 DnDShape
*m_shape
; // our data
650 // ----------------------------------------------------------------------------
651 // A dialog to edit shape properties
652 // ----------------------------------------------------------------------------
654 class DnDShapeDialog
: public wxDialog
657 DnDShapeDialog(wxFrame
*parent
, DnDShape
*shape
);
659 DnDShape
*GetShape() const;
661 virtual bool TransferDataToWindow();
662 virtual bool TransferDataFromWindow();
664 void OnColour(wxCommandEvent
& event
);
671 DnDShape::Kind m_shapeKind
;
683 DECLARE_EVENT_TABLE()
686 // ----------------------------------------------------------------------------
687 // A frame for the shapes which can be drag-and-dropped between frames
688 // ----------------------------------------------------------------------------
690 class DnDShapeFrame
: public wxFrame
693 DnDShapeFrame(wxFrame
*parent
);
696 void SetShape(DnDShape
*shape
);
699 void OnNewShape(wxCommandEvent
& event
);
700 void OnEditShape(wxCommandEvent
& event
);
701 void OnClearShape(wxCommandEvent
& event
);
703 void OnCopyShape(wxCommandEvent
& event
);
704 void OnPasteShape(wxCommandEvent
& event
);
706 void OnUpdateUICopy(wxUpdateUIEvent
& event
);
707 void OnUpdateUIPaste(wxUpdateUIEvent
& event
);
709 void OnDrag(wxMouseEvent
& event
);
710 void OnPaint(wxPaintEvent
& event
);
711 void OnDrop(wxCoord x
, wxCoord y
, DnDShape
*shape
);
716 static DnDShapeFrame
*ms_lastDropTarget
;
718 DECLARE_EVENT_TABLE()
721 // ----------------------------------------------------------------------------
722 // wxDropTarget derivation for DnDShapes
723 // ----------------------------------------------------------------------------
725 class DnDShapeDropTarget
: public wxDropTarget
728 DnDShapeDropTarget(DnDShapeFrame
*frame
)
729 : wxDropTarget(new DnDShapeDataObject
)
734 // override base class (pure) virtuals
735 virtual wxDragResult
OnEnter(wxCoord x
, wxCoord y
, wxDragResult def
)
736 { m_frame
->SetStatusText("Mouse entered the frame"); return OnDragOver(x
, y
, def
); }
737 virtual void OnLeave()
738 { m_frame
->SetStatusText("Mouse left the frame"); }
739 virtual wxDragResult
OnData(wxCoord x
, wxCoord y
, wxDragResult def
)
743 wxLogError(wxT("Failed to get drag and drop data"));
748 m_frame
->OnDrop(x
, y
,
749 ((DnDShapeDataObject
*)GetDataObject())->GetShape());
755 DnDShapeFrame
*m_frame
;
758 // ----------------------------------------------------------------------------
759 // functions prototypes
760 // ----------------------------------------------------------------------------
762 static void ShowBitmap(const wxBitmap
& bitmap
);
765 static void ShowMetaFile(const wxMetaFile
& metafile
);
766 #endif // USE_METAFILES
768 // ----------------------------------------------------------------------------
769 // IDs for the menu commands
770 // ----------------------------------------------------------------------------
786 Menu_Shape_New
= 500,
789 Menu_ShapeClipboard_Copy
,
790 Menu_ShapeClipboard_Paste
,
794 BEGIN_EVENT_TABLE(DnDFrame
, wxFrame
)
795 EVT_MENU(Menu_Quit
, DnDFrame::OnQuit
)
796 EVT_MENU(Menu_About
, DnDFrame::OnAbout
)
797 EVT_MENU(Menu_Drag
, DnDFrame::OnDrag
)
798 EVT_MENU(Menu_NewFrame
, DnDFrame::OnNewFrame
)
799 EVT_MENU(Menu_Help
, DnDFrame::OnHelp
)
800 EVT_MENU(Menu_Clear
, DnDFrame::OnLogClear
)
801 EVT_MENU(Menu_Copy
, DnDFrame::OnCopy
)
802 EVT_MENU(Menu_Paste
, DnDFrame::OnPaste
)
803 EVT_MENU(Menu_CopyBitmap
, DnDFrame::OnCopyBitmap
)
804 EVT_MENU(Menu_PasteBitmap
,DnDFrame::OnPasteBitmap
)
806 EVT_MENU(Menu_PasteMFile
, DnDFrame::OnPasteMetafile
)
807 #endif // USE_METAFILES
808 EVT_MENU(Menu_CopyFiles
, DnDFrame::OnCopyFiles
)
810 EVT_UPDATE_UI(Menu_Paste
, DnDFrame::OnUpdateUIPasteText
)
811 EVT_UPDATE_UI(Menu_PasteBitmap
, DnDFrame::OnUpdateUIPasteBitmap
)
813 EVT_LEFT_DOWN( DnDFrame::OnLeftDown
)
814 EVT_RIGHT_DOWN( DnDFrame::OnRightDown
)
815 EVT_PAINT( DnDFrame::OnPaint
)
818 BEGIN_EVENT_TABLE(DnDShapeFrame
, wxFrame
)
819 EVT_MENU(Menu_Shape_New
, DnDShapeFrame::OnNewShape
)
820 EVT_MENU(Menu_Shape_Edit
, DnDShapeFrame::OnEditShape
)
821 EVT_MENU(Menu_Shape_Clear
, DnDShapeFrame::OnClearShape
)
823 EVT_MENU(Menu_ShapeClipboard_Copy
, DnDShapeFrame::OnCopyShape
)
824 EVT_MENU(Menu_ShapeClipboard_Paste
, DnDShapeFrame::OnPasteShape
)
826 EVT_UPDATE_UI(Menu_ShapeClipboard_Copy
, DnDShapeFrame::OnUpdateUICopy
)
827 EVT_UPDATE_UI(Menu_ShapeClipboard_Paste
, DnDShapeFrame::OnUpdateUIPaste
)
829 EVT_LEFT_DOWN(DnDShapeFrame::OnDrag
)
831 EVT_PAINT(DnDShapeFrame::OnPaint
)
834 BEGIN_EVENT_TABLE(DnDShapeDialog
, wxDialog
)
835 EVT_BUTTON(Button_Colour
, DnDShapeDialog::OnColour
)
838 BEGIN_EVENT_TABLE(DnDCanvasBitmap
, wxScrolledWindow
)
839 EVT_PAINT(DnDCanvasBitmap::OnPaint
)
843 BEGIN_EVENT_TABLE(DnDCanvasMetafile
, wxScrolledWindow
)
844 EVT_PAINT(DnDCanvasMetafile::OnPaint
)
846 #endif // USE_METAFILES
848 // ============================================================================
850 // ============================================================================
852 // `Main program' equivalent, creating windows and returning main app frame
853 bool DnDApp::OnInit()
856 // load our ressources
860 pathList
.Add("./Debug");
861 pathList
.Add("./Release");
864 wxString path
= pathList
.FindValidPath("dnd.wxr");
867 wxLogError(wxT("Can't find the resource file dnd.wxr in the current ")
868 wxT("directory, aborting."));
873 wxDefaultResourceTable
->ParseResourceFile(path
);
876 // switch on trace messages
877 #if defined(__WXGTK__)
878 wxLog::AddTraceMask(_T("clipboard"));
879 #elif defined(__WXMSW__)
880 wxLog::AddTraceMask(wxTRACE_OleCalls
);
884 wxImage::AddHandler( new wxPNGHandler
);
887 // under X we usually want to use the primary selection by default (which
888 // is shared with other apps)
889 wxTheClipboard
->UsePrimarySelection();
891 // create the main frame window
892 DnDFrame
*frame
= new DnDFrame((wxFrame
*) NULL
,
893 "Drag-and-Drop/Clipboard wxWindows Sample",
904 DnDFrame::DnDFrame(wxFrame
*frame
, char *title
, int x
, int y
, int w
, int h
)
905 : wxFrame(frame
, -1, title
, wxPoint(x
, y
), wxSize(w
, h
)),
906 m_strText("wxWindows drag & drop works :-)")
909 // frame icon and status bar
910 SetIcon(wxICON(mondrian
));
915 wxMenu
*file_menu
= new wxMenu
;
916 file_menu
->Append(Menu_Drag
, "&Test drag...");
917 file_menu
->AppendSeparator();
918 file_menu
->Append(Menu_NewFrame
, "&New frame\tCtrl-N");
919 file_menu
->AppendSeparator();
920 file_menu
->Append(Menu_Quit
, "E&xit");
922 wxMenu
*log_menu
= new wxMenu
;
923 log_menu
->Append(Menu_Clear
, "Clear\tCtrl-L");
925 wxMenu
*help_menu
= new wxMenu
;
926 help_menu
->Append(Menu_Help
, "&Help...");
927 help_menu
->AppendSeparator();
928 help_menu
->Append(Menu_About
, "&About");
930 wxMenu
*clip_menu
= new wxMenu
;
931 clip_menu
->Append(Menu_Copy
, "&Copy text\tCtrl+C");
932 clip_menu
->Append(Menu_Paste
, "&Paste text\tCtrl+V");
933 clip_menu
->AppendSeparator();
934 clip_menu
->Append(Menu_CopyBitmap
, "Copy &bitmap\tAlt+C");
935 clip_menu
->Append(Menu_PasteBitmap
, "Paste b&itmap\tAlt+V");
937 clip_menu
->AppendSeparator();
938 clip_menu
->Append(Menu_PasteMFile
, "Paste &metafile\tCtrl-M");
939 #endif // USE_METAFILES
940 clip_menu
->AppendSeparator();
941 clip_menu
->Append(Menu_CopyFiles
, "Copy &files\tCtrl+F");
943 wxMenuBar
*menu_bar
= new wxMenuBar
;
944 menu_bar
->Append(file_menu
, "&File");
945 menu_bar
->Append(log_menu
, "&Log");
946 menu_bar
->Append(clip_menu
, "&Clipboard");
947 menu_bar
->Append(help_menu
, "&Help");
949 SetMenuBar(menu_bar
);
951 // make a panel with 3 subwindows
953 wxSize
size(400, 200);
955 wxString
strFile("Drop files here!"), strText("Drop text on me");
957 m_ctrlFile
= new wxListBox(this, -1, pos
, size
, 1, &strFile
,
958 wxLB_HSCROLL
| wxLB_ALWAYS_SB
);
959 m_ctrlText
= new wxListBox(this, -1, pos
, size
, 1, &strText
,
960 wxLB_HSCROLL
| wxLB_ALWAYS_SB
);
962 m_ctrlLog
= new wxTextCtrl(this, -1, "", pos
, size
,
963 wxTE_MULTILINE
| wxTE_READONLY
|
966 // redirect log messages to the text window
967 m_pLog
= new wxLogTextCtrl(m_ctrlLog
);
968 m_pLogPrev
= wxLog::SetActiveTarget(m_pLog
);
970 // associate drop targets with the controls
971 m_ctrlFile
->SetDropTarget(new DnDFile(m_ctrlFile
));
972 m_ctrlText
->SetDropTarget(new DnDText(m_ctrlText
));
973 m_ctrlLog
->SetDropTarget(new URLDropTarget
);
975 wxLayoutConstraints
*c
;
978 c
= new wxLayoutConstraints
;
979 c
->left
.SameAs(this, wxLeft
);
980 c
->top
.SameAs(this, wxTop
);
981 c
->right
.PercentOf(this, wxRight
, 50);
982 c
->height
.PercentOf(this, wxHeight
, 30);
983 m_ctrlFile
->SetConstraints(c
);
986 c
= new wxLayoutConstraints
;
987 c
->left
.SameAs (m_ctrlFile
, wxRight
);
988 c
->top
.SameAs (this, wxTop
);
989 c
->right
.SameAs (this, wxRight
);
990 c
->height
.PercentOf(this, wxHeight
, 30);
991 m_ctrlText
->SetConstraints(c
);
993 // Lower text control
994 c
= new wxLayoutConstraints
;
995 c
->left
.SameAs (this, wxLeft
);
996 c
->right
.SameAs (this, wxRight
);
997 c
->height
.PercentOf(this, wxHeight
, 50);
998 c
->top
.SameAs(m_ctrlText
, wxBottom
);
999 m_ctrlLog
->SetConstraints(c
);
1001 SetAutoLayout(TRUE
);
1004 void DnDFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
1009 void DnDFrame::OnPaint(wxPaintEvent
& WXUNUSED(event
))
1013 GetClientSize( &w
, &h
);
1016 dc
.SetFont( wxFont( 24, wxDECORATIVE
, wxNORMAL
, wxNORMAL
, FALSE
, "charter" ) );
1017 dc
.DrawText( "Drag text from here!", 100, h
-50 );
1020 void DnDFrame::OnUpdateUIPasteText(wxUpdateUIEvent
& event
)
1023 // too many trace messages if we don't do it - this function is called
1028 event
.Enable( wxTheClipboard
->IsSupported(wxDF_TEXT
) );
1031 void DnDFrame::OnUpdateUIPasteBitmap(wxUpdateUIEvent
& event
)
1034 // too many trace messages if we don't do it - this function is called
1039 event
.Enable( wxTheClipboard
->IsSupported(wxDF_BITMAP
) );
1042 void DnDFrame::OnNewFrame(wxCommandEvent
& WXUNUSED(event
))
1044 (new DnDShapeFrame(this))->Show(TRUE
);
1046 wxLogStatus(this, wxT("Double click the new frame to select a shape for it"));
1049 void DnDFrame::OnDrag(wxCommandEvent
& WXUNUSED(event
))
1051 wxString strText
= wxGetTextFromUser
1053 "After you enter text in this dialog, press any mouse\n"
1054 "button in the bottom (empty) part of the frame and \n"
1055 "drag it anywhere - you will be in fact dragging the\n"
1056 "text object containing this text",
1057 "Please enter some text", m_strText
, this
1060 m_strText
= strText
;
1063 void DnDFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
1065 wxMessageBox("Drag-&-Drop Demo\n"
1066 "Please see \"Help|Help...\" for details\n"
1067 "Copyright (c) 1998 Vadim Zeitlin",
1069 wxICON_INFORMATION
| wxOK
,
1073 void DnDFrame::OnHelp(wxCommandEvent
& /* event */)
1075 wxMessageDialog
dialog(this,
1076 "This small program demonstrates drag & drop support in wxWindows. The program window\n"
1077 "consists of 3 parts: the bottom pane is for debug messages, so that you can see what's\n"
1078 "going on inside. The top part is split into 2 listboxes, the left one accepts files\n"
1079 "and the right one accepts text.\n"
1081 "To test wxDropTarget: open wordpad (write.exe), select some text in it and drag it to\n"
1082 "the right listbox (you'll notice the usual visual feedback, i.e. the cursor will change).\n"
1083 "Also, try dragging some files (you can select several at once) from Windows Explorer (or \n"
1084 "File Manager) to the left pane. Hold down Ctrl/Shift keys when you drop text (doesn't \n"
1085 "work with files) and see what changes.\n"
1087 "To test wxDropSource: just press any mouse button on the empty zone of the window and drag\n"
1088 "it to wordpad or any other droptarget accepting text (and of course you can just drag it\n"
1089 "to the right pane). Due to a lot of trace messages, the cursor might take some time to \n"
1090 "change, don't release the mouse button until it does. You can change the string being\n"
1091 "dragged in in \"File|Test drag...\" dialog.\n"
1094 "Please send all questions/bug reports/suggestions &c to \n"
1095 "Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>",
1101 void DnDFrame::OnLogClear(wxCommandEvent
& /* event */ )
1104 m_ctrlText
->Clear();
1105 m_ctrlFile
->Clear();
1108 void DnDFrame::OnLeftDown(wxMouseEvent
&WXUNUSED(event
) )
1110 if ( !m_strText
.IsEmpty() )
1112 // start drag operation
1113 wxTextDataObject
textData(m_strText
);
1115 wxFileDataObject textData;
1116 textData.AddFile( "/file1.txt" );
1117 textData.AddFile( "/file2.txt" );
1119 wxDropSource
source(textData
, this,
1120 wxDROP_ICON(dnd_copy
),
1121 wxDROP_ICON(dnd_move
),
1122 wxDROP_ICON(dnd_none
));
1126 switch ( source
.DoDragDrop(TRUE
) )
1128 case wxDragError
: pc
= "Error!"; break;
1129 case wxDragNone
: pc
= "Nothing"; break;
1130 case wxDragCopy
: pc
= "Copied"; break;
1131 case wxDragMove
: pc
= "Moved"; break;
1132 case wxDragCancel
: pc
= "Cancelled"; break;
1133 default: pc
= "Huh?"; break;
1136 SetStatusText(wxString("Drag result: ") + pc
);
1140 void DnDFrame::OnRightDown(wxMouseEvent
&event
)
1142 wxMenu
menu("Dnd sample menu");
1144 menu
.Append(Menu_Drag
, "&Test drag...");
1145 menu
.AppendSeparator();
1146 menu
.Append(Menu_About
, "&About");
1148 PopupMenu( &menu
, event
.GetX(), event
.GetY() );
1151 DnDFrame::~DnDFrame()
1153 if ( m_pLog
!= NULL
) {
1154 if ( wxLog::SetActiveTarget(m_pLogPrev
) == m_pLog
)
1159 // ---------------------------------------------------------------------------
1161 // ---------------------------------------------------------------------------
1163 void DnDFrame::OnCopyBitmap(wxCommandEvent
& WXUNUSED(event
))
1165 // PNG support is not always compiled in under Windows, so use BMP there
1167 wxFileDialog
dialog(this, "Open a BMP file", "", "", "BMP files (*.bmp)|*.bmp", 0);
1169 wxFileDialog
dialog(this, "Open a PNG file", "", "", "PNG files (*.png)|*.png", 0);
1172 if (dialog
.ShowModal() != wxID_OK
)
1174 wxLogMessage( _T("Aborted file open") );
1178 if (dialog
.GetPath().IsEmpty())
1180 wxLogMessage( _T("Returned empty string.") );
1184 if (!wxFileExists(dialog
.GetPath()))
1186 wxLogMessage( _T("File doesn't exist.") );
1191 image
.LoadFile( dialog
.GetPath(),
1200 wxLogError( _T("Invalid image file...") );
1204 wxLogStatus( _T("Decoding image file...") );
1207 wxBitmap
bitmap( image
.ConvertToBitmap() );
1209 if ( !wxTheClipboard
->Open() )
1211 wxLogError(_T("Can't open clipboard."));
1216 wxLogMessage( _T("Creating wxBitmapDataObject...") );
1219 if ( !wxTheClipboard
->AddData(new wxBitmapDataObject(bitmap
)) )
1221 wxLogError(_T("Can't copy image to the clipboard."));
1225 wxLogMessage(_T("Image has been put on the clipboard.") );
1226 wxLogMessage(_T("You can paste it now and look at it.") );
1229 wxTheClipboard
->Close();
1232 void DnDFrame::OnPasteBitmap(wxCommandEvent
& WXUNUSED(event
))
1234 if ( !wxTheClipboard
->Open() )
1236 wxLogError(_T("Can't open clipboard."));
1241 if ( !wxTheClipboard
->IsSupported(wxDF_BITMAP
) )
1243 wxLogWarning(_T("No bitmap on clipboard"));
1245 wxTheClipboard
->Close();
1249 wxBitmapDataObject data
;
1250 if ( !wxTheClipboard
->GetData(data
) )
1252 wxLogError(_T("Can't paste bitmap from the clipboard"));
1256 const wxBitmap
& bmp
= data
.GetBitmap();
1258 wxLogMessage(_T("Bitmap %dx%d pasted from the clipboard"),
1259 bmp
.GetWidth(), bmp
.GetHeight());
1263 wxTheClipboard
->Close();
1266 #ifdef USE_METAFILES
1268 void DnDFrame::OnPasteMetafile(wxCommandEvent
& WXUNUSED(event
))
1270 if ( !wxTheClipboard
->Open() )
1272 wxLogError(_T("Can't open clipboard."));
1277 if ( !wxTheClipboard
->IsSupported(wxDF_METAFILE
) )
1279 wxLogWarning(_T("No metafile on clipboard"));
1283 wxMetaFileDataObject data
;
1284 if ( !wxTheClipboard
->GetData(data
) )
1286 wxLogError(_T("Can't paste metafile from the clipboard"));
1290 const wxMetaFile
& mf
= data
.GetMetafile();
1292 wxLogMessage(_T("Metafile %dx%d pasted from the clipboard"),
1293 mf
.GetWidth(), mf
.GetHeight());
1299 wxTheClipboard
->Close();
1302 #endif // USE_METAFILES
1304 // ----------------------------------------------------------------------------
1306 // ----------------------------------------------------------------------------
1308 void DnDFrame::OnCopyFiles(wxCommandEvent
& WXUNUSED(event
))
1311 wxFileDialog
dialog(this, "Select a file to copy", "", "",
1312 "All files (*.*)|*.*", 0);
1314 wxArrayString filenames
;
1315 while ( dialog
.ShowModal() == wxID_OK
)
1317 filenames
.Add(dialog
.GetPath());
1320 if ( !filenames
.IsEmpty() )
1322 wxFileDataObject
*dobj
= new wxFileDataObject
;
1323 size_t count
= filenames
.GetCount();
1324 for ( size_t n
= 0; n
< count
; n
++ )
1326 dobj
->AddFile(filenames
[n
]);
1329 wxClipboardLocker locker
;
1332 wxLogError(wxT("Can't open clipboard"));
1336 if ( !wxTheClipboard
->AddData(dobj
) )
1338 wxLogError(wxT("Can't copy file(s) to the clipboard"));
1342 wxLogStatus(this, wxT("%d file%s copied to the clipboard"),
1343 count
, count
== 1 ? wxT("") : wxT("s"));
1349 wxLogStatus(this, wxT("Aborted"));
1352 wxLogError(wxT("Sorry, not implemented"));
1356 // ---------------------------------------------------------------------------
1358 // ---------------------------------------------------------------------------
1360 void DnDFrame::OnCopy(wxCommandEvent
& WXUNUSED(event
))
1362 if ( !wxTheClipboard
->Open() )
1364 wxLogError(_T("Can't open clipboard."));
1369 if ( !wxTheClipboard
->AddData(new wxTextDataObject(m_strText
)) )
1371 wxLogError(_T("Can't copy data to the clipboard"));
1375 wxLogMessage(_T("Text '%s' put on the clipboard"), m_strText
.c_str());
1378 wxTheClipboard
->Close();
1381 void DnDFrame::OnPaste(wxCommandEvent
& WXUNUSED(event
))
1383 if ( !wxTheClipboard
->Open() )
1385 wxLogError(_T("Can't open clipboard."));
1390 if ( !wxTheClipboard
->IsSupported(wxDF_TEXT
) )
1392 wxLogWarning(_T("No text data on clipboard"));
1394 wxTheClipboard
->Close();
1398 wxTextDataObject text
;
1399 if ( !wxTheClipboard
->GetData(text
) )
1401 wxLogError(_T("Can't paste data from the clipboard"));
1405 wxLogMessage(_T("Text '%s' pasted from the clipboard"),
1406 text
.GetText().c_str());
1409 wxTheClipboard
->Close();
1412 // ----------------------------------------------------------------------------
1413 // Notifications called by the base class
1414 // ----------------------------------------------------------------------------
1416 bool DnDText::OnDropText(wxCoord
, wxCoord
, const wxString
& text
)
1418 m_pOwner
->Append(text
);
1423 bool DnDFile::OnDropFiles(wxCoord
, wxCoord
, const wxArrayString
& filenames
)
1425 size_t nFiles
= filenames
.GetCount();
1427 str
.Printf( _T("%d files dropped"), nFiles
);
1428 m_pOwner
->Append(str
);
1429 for ( size_t n
= 0; n
< nFiles
; n
++ ) {
1430 m_pOwner
->Append(filenames
[n
]);
1436 // ----------------------------------------------------------------------------
1438 // ----------------------------------------------------------------------------
1440 DnDShapeDialog::DnDShapeDialog(wxFrame
*parent
, DnDShape
*shape
)
1442 :wxDialog( parent
, 6001, wxT("Choose Shape"), wxPoint( 10, 10 ),
1444 wxRAISED_BORDER
|wxCAPTION
|wxTHICK_FRAME
|wxSYSTEM_MENU
)
1449 LoadFromResource(parent
, "dialogShape");
1451 m_textX
= (wxTextCtrl
*)wxFindWindowByName("textX", this);
1452 m_textY
= (wxTextCtrl
*)wxFindWindowByName("textY", this);
1453 m_textW
= (wxTextCtrl
*)wxFindWindowByName("textW", this);
1454 m_textH
= (wxTextCtrl
*)wxFindWindowByName("textH", this);
1456 m_radio
= (wxRadioBox
*)wxFindWindowByName("radio", this);
1458 wxBoxSizer
* topSizer
= new wxBoxSizer( wxVERTICAL
);
1461 wxBoxSizer
* shapesSizer
= new wxBoxSizer( wxHORIZONTAL
);
1462 const wxString choices
[] = { wxT("None"), wxT("Triangle"),
1463 wxT("Rectangle"), wxT("Ellipse") };
1465 m_radio
= new wxRadioBox( this, -1, wxT("&Shape"),
1466 wxDefaultPosition
, wxDefaultSize
, 4, choices
, 4,
1467 wxRA_SPECIFY_COLS
);
1468 shapesSizer
->Add( m_radio
, 0, wxGROW
|wxALL
, 5 );
1469 topSizer
->Add( shapesSizer
, 0, wxALL
, 2 );
1472 wxStaticBox
* box
= new wxStaticBox( this, -1, wxT("&Attributes") );
1473 wxStaticBoxSizer
* attrSizer
= new wxStaticBoxSizer( box
, wxHORIZONTAL
);
1474 wxFlexGridSizer
* xywhSizer
= new wxFlexGridSizer( 4, 2 );
1478 st
= new wxStaticText( this, -1, wxT("Position &X:") );
1479 m_textX
= new wxTextCtrl( this, -1, wxEmptyString
, wxDefaultPosition
,
1481 xywhSizer
->Add( st
, 1, wxGROW
|wxALL
, 2 );
1482 xywhSizer
->Add( m_textX
, 1, wxGROW
|wxALL
, 2 );
1484 st
= new wxStaticText( this, -1, wxT("Size &width:") );
1485 m_textW
= new wxTextCtrl( this, -1, wxEmptyString
, wxDefaultPosition
,
1487 xywhSizer
->Add( st
, 1, wxGROW
|wxALL
, 2 );
1488 xywhSizer
->Add( m_textW
, 1, wxGROW
|wxALL
, 2 );
1490 st
= new wxStaticText( this, -1, wxT("&Y:") );
1491 m_textY
= new wxTextCtrl( this, -1, wxEmptyString
, wxDefaultPosition
,
1493 xywhSizer
->Add( st
, 1, wxALL
|wxALIGN_RIGHT
, 2 );
1494 xywhSizer
->Add( m_textY
, 1, wxGROW
|wxALL
, 2 );
1496 st
= new wxStaticText( this, -1, wxT("&height:") );
1497 m_textH
= new wxTextCtrl( this, -1, wxEmptyString
, wxDefaultPosition
,
1499 xywhSizer
->Add( st
, 1, wxALL
|wxALIGN_RIGHT
, 2 );
1500 xywhSizer
->Add( m_textH
, 1, wxGROW
|wxALL
, 2 );
1502 wxButton
* col
= new wxButton( this, Button_Colour
, wxT("&Colour...") );
1503 attrSizer
->Add( xywhSizer
, 1, wxGROW
);
1504 attrSizer
->Add( col
, 0, wxALL
|wxALIGN_CENTRE_VERTICAL
, 2 );
1505 topSizer
->Add( attrSizer
, 0, wxGROW
|wxALL
, 5 );
1508 wxBoxSizer
* buttonSizer
= new wxBoxSizer( wxHORIZONTAL
);
1510 bt
= new wxButton( this, wxID_OK
, wxT("Ok") );
1511 buttonSizer
->Add( bt
, 0, wxALL
, 2 );
1512 bt
= new wxButton( this, wxID_CANCEL
, wxT("Cancel") );
1513 buttonSizer
->Add( bt
, 0, wxALL
, 2 );
1514 topSizer
->Add( buttonSizer
, 0, wxALL
|wxALIGN_RIGHT
, 2 );
1516 SetAutoLayout( TRUE
);
1517 SetSizer( topSizer
);
1518 topSizer
->Fit( this );
1522 DnDShape
*DnDShapeDialog::GetShape() const
1524 switch ( m_shapeKind
)
1527 case DnDShape::None
: return NULL
;
1528 case DnDShape::Triangle
: return new DnDTriangularShape(m_pos
, m_size
, m_col
);
1529 case DnDShape::Rectangle
: return new DnDRectangularShape(m_pos
, m_size
, m_col
);
1530 case DnDShape::Ellipse
: return new DnDEllipticShape(m_pos
, m_size
, m_col
);
1534 bool DnDShapeDialog::TransferDataToWindow()
1539 m_radio
->SetSelection(m_shape
->GetKind());
1540 m_pos
= m_shape
->GetPosition();
1541 m_size
= m_shape
->GetSize();
1542 m_col
= m_shape
->GetColour();
1546 m_radio
->SetSelection(DnDShape::None
);
1547 m_pos
= wxPoint(1, 1);
1548 m_size
= wxSize(100, 100);
1551 m_textX
->SetValue(wxString() << m_pos
.x
);
1552 m_textY
->SetValue(wxString() << m_pos
.y
);
1553 m_textW
->SetValue(wxString() << m_size
.x
);
1554 m_textH
->SetValue(wxString() << m_size
.y
);
1559 bool DnDShapeDialog::TransferDataFromWindow()
1561 m_shapeKind
= (DnDShape::Kind
)m_radio
->GetSelection();
1563 m_pos
.x
= wxAtoi(m_textX
->GetValue());
1564 m_pos
.y
= wxAtoi(m_textY
->GetValue());
1565 m_size
.x
= wxAtoi(m_textW
->GetValue());
1566 m_size
.y
= wxAtoi(m_textH
->GetValue());
1568 if ( !m_pos
.x
|| !m_pos
.y
|| !m_size
.x
|| !m_size
.y
)
1570 wxMessageBox("All sizes and positions should be non null!",
1571 "Invalid shape", wxICON_HAND
| wxOK
, this);
1579 void DnDShapeDialog::OnColour(wxCommandEvent
& WXUNUSED(event
))
1582 data
.SetChooseFull(TRUE
);
1583 for (int i
= 0; i
< 16; i
++)
1585 wxColour
colour(i
*16, i
*16, i
*16);
1586 data
.SetCustomColour(i
, colour
);
1589 wxColourDialog
dialog(this, &data
);
1590 if ( dialog
.ShowModal() == wxID_OK
)
1592 m_col
= dialog
.GetColourData().GetColour();
1596 // ----------------------------------------------------------------------------
1598 // ----------------------------------------------------------------------------
1600 DnDShapeFrame
*DnDShapeFrame::ms_lastDropTarget
= NULL
;
1602 DnDShapeFrame::DnDShapeFrame(wxFrame
*parent
)
1603 : wxFrame(parent
, -1, "Shape Frame",
1604 wxDefaultPosition
, wxSize(250, 150))
1608 wxMenu
*menuShape
= new wxMenu
;
1609 menuShape
->Append(Menu_Shape_New
, "&New default shape\tCtrl-S");
1610 menuShape
->Append(Menu_Shape_Edit
, "&Edit shape\tCtrl-E");
1611 menuShape
->AppendSeparator();
1612 menuShape
->Append(Menu_Shape_Clear
, "&Clear shape\tCtrl-L");
1614 wxMenu
*menuClipboard
= new wxMenu
;
1615 menuClipboard
->Append(Menu_ShapeClipboard_Copy
, "&Copy\tCtrl-C");
1616 menuClipboard
->Append(Menu_ShapeClipboard_Paste
, "&Paste\tCtrl-V");
1618 wxMenuBar
*menubar
= new wxMenuBar
;
1619 menubar
->Append(menuShape
, "&Shape");
1620 menubar
->Append(menuClipboard
, "&Clipboard");
1622 SetMenuBar(menubar
);
1624 SetStatusText("Press Ctrl-S to create a new shape");
1626 SetDropTarget(new DnDShapeDropTarget(this));
1630 SetBackgroundColour(*wxWHITE
);
1633 DnDShapeFrame::~DnDShapeFrame()
1639 void DnDShapeFrame::SetShape(DnDShape
*shape
)
1648 void DnDShapeFrame::OnDrag(wxMouseEvent
& event
)
1657 // start drag operation
1658 DnDShapeDataObject
shapeData(m_shape
);
1659 wxDropSource
source(shapeData
, this);
1661 const char *pc
= NULL
;
1662 switch ( source
.DoDragDrop(TRUE
) )
1666 wxLogError(wxT("An error occured during drag and drop operation"));
1670 SetStatusText("Nothing happened");
1679 if ( ms_lastDropTarget
!= this )
1681 // don't delete the shape if we dropped it on ourselves!
1687 SetStatusText("Drag and drop operation cancelled");
1693 SetStatusText(wxString("Shape successfully ") + pc
);
1695 //else: status text already set
1698 void DnDShapeFrame::OnDrop(wxCoord x
, wxCoord y
, DnDShape
*shape
)
1700 ms_lastDropTarget
= this;
1705 s
.Printf(wxT("Shape dropped at (%ld, %ld)"), pt
.x
, pt
.y
);
1712 void DnDShapeFrame::OnEditShape(wxCommandEvent
& event
)
1714 DnDShapeDialog
dlg(this, m_shape
);
1715 if ( dlg
.ShowModal() == wxID_OK
)
1717 SetShape(dlg
.GetShape());
1721 SetStatusText("You can now drag the shape to another frame");
1726 void DnDShapeFrame::OnNewShape(wxCommandEvent
& event
)
1728 SetShape(new DnDEllipticShape(wxPoint(10, 10), wxSize(80, 60), *wxRED
));
1730 SetStatusText("You can now drag the shape to another frame");
1733 void DnDShapeFrame::OnClearShape(wxCommandEvent
& event
)
1738 void DnDShapeFrame::OnCopyShape(wxCommandEvent
& event
)
1742 wxClipboardLocker clipLocker
;
1745 wxLogError(wxT("Can't open the clipboard"));
1750 wxTheClipboard
->AddData(new DnDShapeDataObject(m_shape
));
1754 void DnDShapeFrame::OnPasteShape(wxCommandEvent
& event
)
1756 wxClipboardLocker clipLocker
;
1759 wxLogError(wxT("Can't open the clipboard"));
1764 DnDShapeDataObject
shapeDataObject(NULL
);
1765 if ( wxTheClipboard
->GetData(shapeDataObject
) )
1767 SetShape(shapeDataObject
.GetShape());
1771 wxLogStatus(wxT("No shape on the clipboard"));
1775 void DnDShapeFrame::OnUpdateUICopy(wxUpdateUIEvent
& event
)
1777 event
.Enable( m_shape
!= NULL
);
1780 void DnDShapeFrame::OnUpdateUIPaste(wxUpdateUIEvent
& event
)
1782 event
.Enable( wxTheClipboard
->IsSupported(wxDataFormat(shapeFormatId
)) );
1785 void DnDShapeFrame::OnPaint(wxPaintEvent
& event
)
1799 // ----------------------------------------------------------------------------
1801 // ----------------------------------------------------------------------------
1803 DnDShape
*DnDShape::New(const void *buf
)
1805 const ShapeDump
& dump
= *(const ShapeDump
*)buf
;
1809 return new DnDTriangularShape(wxPoint(dump
.x
, dump
.y
),
1810 wxSize(dump
.w
, dump
.h
),
1811 wxColour(dump
.r
, dump
.g
, dump
.b
));
1814 return new DnDRectangularShape(wxPoint(dump
.x
, dump
.y
),
1815 wxSize(dump
.w
, dump
.h
),
1816 wxColour(dump
.r
, dump
.g
, dump
.b
));
1819 return new DnDEllipticShape(wxPoint(dump
.x
, dump
.y
),
1820 wxSize(dump
.w
, dump
.h
),
1821 wxColour(dump
.r
, dump
.g
, dump
.b
));
1824 wxFAIL_MSG(wxT("invalid shape!"));
1829 // ----------------------------------------------------------------------------
1830 // DnDShapeDataObject
1831 // ----------------------------------------------------------------------------
1833 #ifdef USE_METAFILES
1835 void DnDShapeDataObject::CreateMetaFile() const
1837 wxPoint pos
= m_shape
->GetPosition();
1838 wxSize size
= m_shape
->GetSize();
1840 wxMetaFileDC
dcMF(wxEmptyString
, pos
.x
+ size
.x
, pos
.y
+ size
.y
);
1842 m_shape
->Draw(dcMF
);
1844 wxMetafile
*mf
= dcMF
.Close();
1846 DnDShapeDataObject
*self
= (DnDShapeDataObject
*)this; // const_cast
1847 self
->m_dobjMetaFile
.SetMetafile(*mf
);
1848 self
->m_hasMetaFile
= TRUE
;
1855 void DnDShapeDataObject::CreateBitmap() const
1857 wxPoint pos
= m_shape
->GetPosition();
1858 wxSize size
= m_shape
->GetSize();
1859 int x
= pos
.x
+ size
.x
,
1861 wxBitmap
bitmap(x
, y
);
1863 dc
.SelectObject(bitmap
);
1864 dc
.SetBrush(wxBrush("white", wxSOLID
));
1867 dc
.SelectObject(wxNullBitmap
);
1869 DnDShapeDataObject
*self
= (DnDShapeDataObject
*)this; // const_cast
1870 self
->m_dobjBitmap
.SetBitmap(bitmap
);
1871 self
->m_hasBitmap
= TRUE
;
1874 // ----------------------------------------------------------------------------
1876 // ----------------------------------------------------------------------------
1878 static void ShowBitmap(const wxBitmap
& bitmap
)
1880 wxFrame
*frame
= new wxFrame(NULL
, -1, _T("Bitmap view"));
1881 frame
->CreateStatusBar();
1882 DnDCanvasBitmap
*canvas
= new DnDCanvasBitmap(frame
);
1883 canvas
->SetBitmap(bitmap
);
1885 int w
= bitmap
.GetWidth(),
1886 h
= bitmap
.GetHeight();
1887 frame
->SetStatusText(wxString::Format(_T("%dx%d"), w
, h
));
1889 frame
->SetClientSize(w
> 100 ? 100 : w
, h
> 100 ? 100 : h
);
1893 #ifdef USE_METAFILES
1895 static void ShowMetaFile(const wxMetaFile
& metafile
)
1897 wxFrame
*frame
= new wxFrame(NULL
, -1, _T("Metafile view"));
1898 frame
->CreateStatusBar();
1899 DnDCanvasMetafile
*canvas
= new DnDCanvasMetafile(frame
);
1900 canvas
->SetMetafile(metafile
);
1902 wxSize size
= metafile
.GetSize();
1903 frame
->SetStatusText(wxString::Format(_T("%dx%d"), size
.x
, size
.y
));
1905 frame
->SetClientSize(size
.x
> 100 ? 100 : size
.x
,
1906 size
.y
> 100 ? 100 : size
.y
);
1910 #endif // USE_METAFILES