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
);
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
),
113 return wxDragLink
; // At least IE 5.x needs wxDragLink, the
114 // other browsers on MSW seem okay with it too.
117 // translate this to calls to OnDropURL() just for convenience
118 virtual wxDragResult
OnData(wxCoord x
, wxCoord y
, wxDragResult def
)
123 OnDropURL(x
, y
, ((wxURLDataObject
*)m_dataObject
)->GetURL());
129 // ----------------------------------------------------------------------------
130 // Define a new application type
131 // ----------------------------------------------------------------------------
133 class DnDApp
: public wxApp
136 virtual bool OnInit();
139 IMPLEMENT_APP(DnDApp
);
141 // ----------------------------------------------------------------------------
142 // Define canvas class to show a bitmap
143 // ----------------------------------------------------------------------------
145 class DnDCanvasBitmap
: public wxScrolledWindow
148 DnDCanvasBitmap(wxWindow
*parent
) : wxScrolledWindow(parent
) { }
150 void SetBitmap(const wxBitmap
& bitmap
)
154 SetScrollbars(10, 10,
155 m_bitmap
.GetWidth() / 10, m_bitmap
.GetHeight() / 10);
160 void OnPaint(wxPaintEvent
& event
)
168 dc
.DrawBitmap(m_bitmap
, 0, 0);
175 DECLARE_EVENT_TABLE()
180 // and the same thing fo metafiles
181 class DnDCanvasMetafile
: public wxScrolledWindow
184 DnDCanvasMetafile(wxWindow
*parent
) : wxScrolledWindow(parent
) { }
186 void SetMetafile(const wxMetafile
& metafile
)
188 m_metafile
= metafile
;
190 SetScrollbars(10, 10,
191 m_metafile
.GetWidth() / 10, m_metafile
.GetHeight() / 10);
196 void OnPaint(wxPaintEvent
& event
)
200 if ( m_metafile
.Ok() )
204 m_metafile
.Play(&dc
);
209 wxMetafile m_metafile
;
211 DECLARE_EVENT_TABLE()
214 #endif // USE_METAFILES
216 // ----------------------------------------------------------------------------
217 // Define a new frame type for the main frame
218 // ----------------------------------------------------------------------------
220 class DnDFrame
: public wxFrame
223 DnDFrame(wxFrame
*frame
, char *title
, int x
, int y
, int w
, int h
);
226 void OnPaint(wxPaintEvent
& event
);
227 void OnSize(wxSizeEvent
& event
);
228 void OnQuit (wxCommandEvent
& event
);
229 void OnAbout(wxCommandEvent
& event
);
230 void OnDrag (wxCommandEvent
& event
);
231 void OnNewFrame(wxCommandEvent
& event
);
232 void OnHelp (wxCommandEvent
& event
);
233 void OnLogClear(wxCommandEvent
& event
);
235 void OnCopy(wxCommandEvent
& event
);
236 void OnPaste(wxCommandEvent
& event
);
238 void OnCopyBitmap(wxCommandEvent
& event
);
239 void OnPasteBitmap(wxCommandEvent
& event
);
242 void OnPasteMetafile(wxCommandEvent
& event
);
243 #endif // USE_METAFILES
245 void OnCopyFiles(wxCommandEvent
& event
);
247 void OnLeftDown(wxMouseEvent
& event
);
248 void OnRightDown(wxMouseEvent
& event
);
250 void OnUpdateUIPasteText(wxUpdateUIEvent
& event
);
251 void OnUpdateUIPasteBitmap(wxUpdateUIEvent
& event
);
253 DECLARE_EVENT_TABLE()
256 wxListBox
*m_ctrlFile
,
258 wxTextCtrl
*m_ctrlLog
;
266 // ----------------------------------------------------------------------------
267 // A shape is an example of application-specific data which may be transported
268 // via drag-and-drop or clipboard: in our case, we have different geometric
269 // shapes, each one with its own colour and position
270 // ----------------------------------------------------------------------------
283 DnDShape(const wxPoint
& pos
,
286 : m_pos(pos
), m_size(size
), m_col(col
)
290 // this is for debugging - lets us see when exactly an object is freed
291 // (this may be later than you think if it's on the clipboard, for example)
292 virtual ~DnDShape() { }
294 // the functions used for drag-and-drop: they dump and restore a shape into
295 // some bitwise-copiable data (might use streams too...)
296 // ------------------------------------------------------------------------
298 // restore from buffer
299 static DnDShape
*New(const void *buf
);
301 virtual size_t GetDataSize() const
303 return sizeof(ShapeDump
);
306 virtual void GetDataHere(void *buf
) const
308 ShapeDump
& dump
= *(ShapeDump
*)buf
;
313 dump
.r
= m_col
.Red();
314 dump
.g
= m_col
.Green();
315 dump
.b
= m_col
.Blue();
320 const wxPoint
& GetPosition() const { return m_pos
; }
321 const wxColour
& GetColour() const { return m_col
; }
322 const wxSize
& GetSize() const { return m_size
; }
324 void Move(const wxPoint
& pos
) { m_pos
= pos
; }
326 // to implement in derived classes
327 virtual Kind
GetKind() const = 0;
329 virtual void Draw(wxDC
& dc
)
331 dc
.SetPen(wxPen(m_col
, 1, wxSOLID
));
335 wxPoint
GetCentre() const
336 { return wxPoint(m_pos
.x
+ m_size
.x
/ 2, m_pos
.y
+ m_size
.y
/ 2); }
340 int x
, y
, // position
351 class DnDTriangularShape
: public DnDShape
354 DnDTriangularShape(const wxPoint
& pos
,
357 : DnDShape(pos
, size
, col
)
359 wxLogMessage(wxT("DnDTriangularShape is being created"));
362 virtual ~DnDTriangularShape()
364 wxLogMessage(wxT("DnDTriangularShape is being deleted"));
367 virtual Kind
GetKind() const { return Triangle
; }
368 virtual void Draw(wxDC
& dc
)
372 // well, it's a bit difficult to describe a triangle by position and
373 // size, but we're not doing geometry here, do we? ;-)
375 wxPoint
p2(m_pos
.x
+ m_size
.x
, m_pos
.y
);
376 wxPoint
p3(m_pos
.x
, m_pos
.y
+ m_size
.y
);
383 dc
.FloodFill(GetCentre(), m_col
, wxFLOOD_BORDER
);
388 class DnDRectangularShape
: public DnDShape
391 DnDRectangularShape(const wxPoint
& pos
,
394 : DnDShape(pos
, size
, col
)
396 wxLogMessage(wxT("DnDRectangularShape is being created"));
399 virtual ~DnDRectangularShape()
401 wxLogMessage(wxT("DnDRectangularShape is being deleted"));
404 virtual Kind
GetKind() const { return Rectangle
; }
405 virtual void Draw(wxDC
& dc
)
410 wxPoint
p2(p1
.x
+ m_size
.x
, p1
.y
);
411 wxPoint
p3(p2
.x
, p2
.y
+ m_size
.y
);
412 wxPoint
p4(p1
.x
, p3
.y
);
420 dc
.FloodFill(GetCentre(), m_col
, wxFLOOD_BORDER
);
425 class DnDEllipticShape
: public DnDShape
428 DnDEllipticShape(const wxPoint
& pos
,
431 : DnDShape(pos
, size
, col
)
433 wxLogMessage(wxT("DnDEllipticShape is being created"));
436 virtual ~DnDEllipticShape()
438 wxLogMessage(wxT("DnDEllipticShape is being deleted"));
441 virtual Kind
GetKind() const { return Ellipse
; }
442 virtual void Draw(wxDC
& dc
)
446 dc
.DrawEllipse(m_pos
, m_size
);
449 dc
.FloodFill(GetCentre(), m_col
, wxFLOOD_BORDER
);
454 // ----------------------------------------------------------------------------
455 // A wxDataObject specialisation for the application-specific data
456 // ----------------------------------------------------------------------------
458 static const wxChar
*shapeFormatId
= wxT("wxShape");
460 class DnDShapeDataObject
: public wxDataObject
463 // ctor doesn't copy the pointer, so it shouldn't go away while this object
465 DnDShapeDataObject(DnDShape
*shape
= (DnDShape
*)NULL
)
469 // we need to copy the shape because the one we're handled may be
470 // deleted while it's still on the clipboard (for example) - and we
471 // reuse the serialisation methods here to copy it
472 void *buf
= malloc(shape
->DnDShape::GetDataSize());
473 shape
->GetDataHere(buf
);
474 m_shape
= DnDShape::New(buf
);
484 // this string should uniquely identify our format, but is otherwise
486 m_formatShape
.SetId(shapeFormatId
);
488 // we don't draw the shape to a bitmap until it's really needed (i.e.
489 // we're asked to do so)
492 m_hasMetaFile
= FALSE
;
496 virtual ~DnDShapeDataObject() { delete m_shape
; }
498 // after a call to this function, the shape is owned by the caller and it
499 // is responsible for deleting it!
501 // NB: a better solution would be to make DnDShapes ref counted and this
502 // is what should probably be done in a real life program, otherwise
503 // the ownership problems become too complicated really fast
506 DnDShape
*shape
= m_shape
;
508 m_shape
= (DnDShape
*)NULL
;
511 m_hasMetaFile
= FALSE
;
517 // implement base class pure virtuals
518 // ----------------------------------
520 virtual wxDataFormat
GetPreferredFormat(Direction
WXUNUSED(dir
)) const
522 return m_formatShape
;
525 virtual size_t GetFormatCount(Direction dir
) const
527 // our custom format is supported by both GetData() and SetData()
531 // but the bitmap format(s) are only supported for output
532 nFormats
+= m_dobjBitmap
.GetFormatCount(dir
);
535 nFormats
+= m_dobjMetaFile
.GetFormatCount(dir
);
542 virtual void GetAllFormats(wxDataFormat
*formats
, Direction dir
) const
544 formats
[0] = m_formatShape
;
547 // in Get direction we additionally support bitmaps and metafiles
549 m_dobjBitmap
.GetAllFormats(&formats
[1], dir
);
552 // don't assume that m_dobjBitmap has only 1 format
553 m_dobjMetaFile
.GetAllFormats(&formats
[1 +
554 m_dobjBitmap
.GetFormatCount(dir
)], dir
);
559 virtual size_t GetDataSize(const wxDataFormat
& format
) const
561 if ( format
== m_formatShape
)
563 return m_shape
->GetDataSize();
566 else if ( m_dobjMetaFile
.IsSupported(format
) )
568 if ( !m_hasMetaFile
)
571 return m_dobjMetaFile
.GetDataSize(format
);
576 wxASSERT_MSG( m_dobjBitmap
.IsSupported(format
),
577 wxT("unexpected format") );
582 return m_dobjBitmap
.GetDataSize();
586 virtual bool GetDataHere(const wxDataFormat
& format
, void *pBuf
) const
588 if ( format
== m_formatShape
)
590 m_shape
->GetDataHere(pBuf
);
595 else if ( m_dobjMetaFile
.IsSupported(format
) )
597 if ( !m_hasMetaFile
)
600 return m_dobjMetaFile
.GetDataHere(format
, pBuf
);
605 wxASSERT_MSG( m_dobjBitmap
.IsSupported(format
),
606 wxT("unexpected format") );
611 return m_dobjBitmap
.GetDataHere(pBuf
);
615 virtual bool SetData(const wxDataFormat
& format
,
616 size_t len
, const void *buf
)
618 wxCHECK_MSG( format
== m_formatShape
, FALSE
,
619 wxT( "unsupported format") );
622 m_shape
= DnDShape::New(buf
);
624 // the shape has changed
628 m_hasMetaFile
= FALSE
;
635 // creates a bitmap and assigns it to m_dobjBitmap (also sets m_hasBitmap)
636 void CreateBitmap() const;
638 void CreateMetaFile() const;
641 wxDataFormat m_formatShape
; // our custom format
643 wxBitmapDataObject m_dobjBitmap
; // it handles bitmaps
644 bool m_hasBitmap
; // true if m_dobjBitmap has valid bitmap
647 wxMetaFileDataObject m_dobjMetaFile
;// handles metafiles
648 bool m_hasMetaFile
; // true if we have valid metafile
651 DnDShape
*m_shape
; // our data
654 // ----------------------------------------------------------------------------
655 // A dialog to edit shape properties
656 // ----------------------------------------------------------------------------
658 class DnDShapeDialog
: public wxDialog
661 DnDShapeDialog(wxFrame
*parent
, DnDShape
*shape
);
663 DnDShape
*GetShape() const;
665 virtual bool TransferDataToWindow();
666 virtual bool TransferDataFromWindow();
668 void OnColour(wxCommandEvent
& event
);
675 DnDShape::Kind m_shapeKind
;
687 DECLARE_EVENT_TABLE()
690 // ----------------------------------------------------------------------------
691 // A frame for the shapes which can be drag-and-dropped between frames
692 // ----------------------------------------------------------------------------
694 class DnDShapeFrame
: public wxFrame
697 DnDShapeFrame(wxFrame
*parent
);
700 void SetShape(DnDShape
*shape
);
703 void OnNewShape(wxCommandEvent
& event
);
704 void OnEditShape(wxCommandEvent
& event
);
705 void OnClearShape(wxCommandEvent
& event
);
707 void OnCopyShape(wxCommandEvent
& event
);
708 void OnPasteShape(wxCommandEvent
& event
);
710 void OnUpdateUICopy(wxUpdateUIEvent
& event
);
711 void OnUpdateUIPaste(wxUpdateUIEvent
& event
);
713 void OnDrag(wxMouseEvent
& event
);
714 void OnPaint(wxPaintEvent
& event
);
715 void OnDrop(wxCoord x
, wxCoord y
, DnDShape
*shape
);
720 static DnDShapeFrame
*ms_lastDropTarget
;
722 DECLARE_EVENT_TABLE()
725 // ----------------------------------------------------------------------------
726 // wxDropTarget derivation for DnDShapes
727 // ----------------------------------------------------------------------------
729 class DnDShapeDropTarget
: public wxDropTarget
732 DnDShapeDropTarget(DnDShapeFrame
*frame
)
733 : wxDropTarget(new DnDShapeDataObject
)
738 // override base class (pure) virtuals
739 virtual wxDragResult
OnEnter(wxCoord x
, wxCoord y
, wxDragResult def
)
740 { m_frame
->SetStatusText("Mouse entered the frame"); return OnDragOver(x
, y
, def
); }
741 virtual void OnLeave()
742 { m_frame
->SetStatusText("Mouse left the frame"); }
743 virtual wxDragResult
OnData(wxCoord x
, wxCoord y
, wxDragResult def
)
747 wxLogError(wxT("Failed to get drag and drop data"));
752 m_frame
->OnDrop(x
, y
,
753 ((DnDShapeDataObject
*)GetDataObject())->GetShape());
759 DnDShapeFrame
*m_frame
;
762 // ----------------------------------------------------------------------------
763 // functions prototypes
764 // ----------------------------------------------------------------------------
766 static void ShowBitmap(const wxBitmap
& bitmap
);
769 static void ShowMetaFile(const wxMetaFile
& metafile
);
770 #endif // USE_METAFILES
772 // ----------------------------------------------------------------------------
773 // IDs for the menu commands
774 // ----------------------------------------------------------------------------
790 Menu_Shape_New
= 500,
793 Menu_ShapeClipboard_Copy
,
794 Menu_ShapeClipboard_Paste
,
798 BEGIN_EVENT_TABLE(DnDFrame
, wxFrame
)
799 EVT_MENU(Menu_Quit
, DnDFrame::OnQuit
)
800 EVT_MENU(Menu_About
, DnDFrame::OnAbout
)
801 EVT_MENU(Menu_Drag
, DnDFrame::OnDrag
)
802 EVT_MENU(Menu_NewFrame
, DnDFrame::OnNewFrame
)
803 EVT_MENU(Menu_Help
, DnDFrame::OnHelp
)
804 EVT_MENU(Menu_Clear
, DnDFrame::OnLogClear
)
805 EVT_MENU(Menu_Copy
, DnDFrame::OnCopy
)
806 EVT_MENU(Menu_Paste
, DnDFrame::OnPaste
)
807 EVT_MENU(Menu_CopyBitmap
, DnDFrame::OnCopyBitmap
)
808 EVT_MENU(Menu_PasteBitmap
,DnDFrame::OnPasteBitmap
)
810 EVT_MENU(Menu_PasteMFile
, DnDFrame::OnPasteMetafile
)
811 #endif // USE_METAFILES
812 EVT_MENU(Menu_CopyFiles
, DnDFrame::OnCopyFiles
)
814 EVT_UPDATE_UI(Menu_Paste
, DnDFrame::OnUpdateUIPasteText
)
815 EVT_UPDATE_UI(Menu_PasteBitmap
, DnDFrame::OnUpdateUIPasteBitmap
)
817 EVT_LEFT_DOWN( DnDFrame::OnLeftDown
)
818 EVT_RIGHT_DOWN( DnDFrame::OnRightDown
)
819 EVT_PAINT( DnDFrame::OnPaint
)
820 EVT_SIZE( DnDFrame::OnSize
)
823 BEGIN_EVENT_TABLE(DnDShapeFrame
, wxFrame
)
824 EVT_MENU(Menu_Shape_New
, DnDShapeFrame::OnNewShape
)
825 EVT_MENU(Menu_Shape_Edit
, DnDShapeFrame::OnEditShape
)
826 EVT_MENU(Menu_Shape_Clear
, DnDShapeFrame::OnClearShape
)
828 EVT_MENU(Menu_ShapeClipboard_Copy
, DnDShapeFrame::OnCopyShape
)
829 EVT_MENU(Menu_ShapeClipboard_Paste
, DnDShapeFrame::OnPasteShape
)
831 EVT_UPDATE_UI(Menu_ShapeClipboard_Copy
, DnDShapeFrame::OnUpdateUICopy
)
832 EVT_UPDATE_UI(Menu_ShapeClipboard_Paste
, DnDShapeFrame::OnUpdateUIPaste
)
834 EVT_LEFT_DOWN(DnDShapeFrame::OnDrag
)
836 EVT_PAINT(DnDShapeFrame::OnPaint
)
839 BEGIN_EVENT_TABLE(DnDShapeDialog
, wxDialog
)
840 EVT_BUTTON(Button_Colour
, DnDShapeDialog::OnColour
)
843 BEGIN_EVENT_TABLE(DnDCanvasBitmap
, wxScrolledWindow
)
844 EVT_PAINT(DnDCanvasBitmap::OnPaint
)
848 BEGIN_EVENT_TABLE(DnDCanvasMetafile
, wxScrolledWindow
)
849 EVT_PAINT(DnDCanvasMetafile::OnPaint
)
851 #endif // USE_METAFILES
853 // ============================================================================
855 // ============================================================================
857 // `Main program' equivalent, creating windows and returning main app frame
858 bool DnDApp::OnInit()
861 // load our ressources
865 pathList
.Add("./Debug");
866 pathList
.Add("./Release");
869 wxString path
= pathList
.FindValidPath("dnd.wxr");
872 wxLogError(wxT("Can't find the resource file dnd.wxr in the current ")
873 wxT("directory, aborting."));
878 wxDefaultResourceTable
->ParseResourceFile(path
);
881 // switch on trace messages
882 #if defined(__WXGTK__)
883 wxLog::AddTraceMask(_T("clipboard"));
884 #elif defined(__WXMSW__)
885 wxLog::AddTraceMask(wxTRACE_OleCalls
);
889 wxImage::AddHandler( new wxPNGHandler
);
892 // under X we usually want to use the primary selection by default (which
893 // is shared with other apps)
894 wxTheClipboard
->UsePrimarySelection();
896 // create the main frame window
897 DnDFrame
*frame
= new DnDFrame((wxFrame
*) NULL
,
898 "Drag-and-Drop/Clipboard wxWindows Sample",
909 DnDFrame::DnDFrame(wxFrame
*frame
, char *title
, int x
, int y
, int w
, int h
)
910 : wxFrame(frame
, -1, title
, wxPoint(x
, y
), wxSize(w
, h
)),
911 m_strText("wxWindows drag & drop works :-)")
914 // frame icon and status bar
915 SetIcon(wxICON(mondrian
));
920 wxMenu
*file_menu
= new wxMenu
;
921 file_menu
->Append(Menu_Drag
, "&Test drag...");
922 file_menu
->AppendSeparator();
923 file_menu
->Append(Menu_NewFrame
, "&New frame\tCtrl-N");
924 file_menu
->AppendSeparator();
925 file_menu
->Append(Menu_Quit
, "E&xit");
927 wxMenu
*log_menu
= new wxMenu
;
928 log_menu
->Append(Menu_Clear
, "Clear\tCtrl-L");
930 wxMenu
*help_menu
= new wxMenu
;
931 help_menu
->Append(Menu_Help
, "&Help...");
932 help_menu
->AppendSeparator();
933 help_menu
->Append(Menu_About
, "&About");
935 wxMenu
*clip_menu
= new wxMenu
;
936 clip_menu
->Append(Menu_Copy
, "&Copy text\tCtrl-C");
937 clip_menu
->Append(Menu_Paste
, "&Paste text\tCtrl-V");
938 clip_menu
->AppendSeparator();
939 clip_menu
->Append(Menu_CopyBitmap
, "Copy &bitmap\tCtrl-Shift-C");
940 clip_menu
->Append(Menu_PasteBitmap
, "Paste b&itmap\tCtrl-Shift-V");
942 clip_menu
->AppendSeparator();
943 clip_menu
->Append(Menu_PasteMFile
, "Paste &metafile\tCtrl-M");
944 #endif // USE_METAFILES
945 clip_menu
->AppendSeparator();
946 clip_menu
->Append(Menu_CopyFiles
, "Copy &files\tCtrl-F");
948 wxMenuBar
*menu_bar
= new wxMenuBar
;
949 menu_bar
->Append(file_menu
, "&File");
950 menu_bar
->Append(log_menu
, "&Log");
951 menu_bar
->Append(clip_menu
, "&Clipboard");
952 menu_bar
->Append(help_menu
, "&Help");
954 SetMenuBar(menu_bar
);
956 // make a panel with 3 subwindows
958 wxSize
size(400, 200);
960 wxString
strFile("Drop files here!"), strText("Drop text on me");
962 m_ctrlFile
= new wxListBox(this, -1, pos
, size
, 1, &strFile
,
963 wxLB_HSCROLL
| wxLB_ALWAYS_SB
);
964 m_ctrlText
= new wxListBox(this, -1, pos
, size
, 1, &strText
,
965 wxLB_HSCROLL
| wxLB_ALWAYS_SB
);
967 m_ctrlLog
= new wxTextCtrl(this, -1, "", pos
, size
,
968 wxTE_MULTILINE
| wxTE_READONLY
|
971 // redirect log messages to the text window
972 m_pLog
= new wxLogTextCtrl(m_ctrlLog
);
973 m_pLogPrev
= wxLog::SetActiveTarget(m_pLog
);
975 // associate drop targets with the controls
976 m_ctrlFile
->SetDropTarget(new DnDFile(m_ctrlFile
));
977 m_ctrlText
->SetDropTarget(new DnDText(m_ctrlText
));
978 m_ctrlLog
->SetDropTarget(new URLDropTarget
);
980 wxLayoutConstraints
*c
;
983 c
= new wxLayoutConstraints
;
984 c
->left
.SameAs(this, wxLeft
);
985 c
->top
.SameAs(this, wxTop
);
986 c
->right
.PercentOf(this, wxRight
, 50);
987 c
->height
.PercentOf(this, wxHeight
, 30);
988 m_ctrlFile
->SetConstraints(c
);
991 c
= new wxLayoutConstraints
;
992 c
->left
.SameAs (m_ctrlFile
, wxRight
);
993 c
->top
.SameAs (this, wxTop
);
994 c
->right
.SameAs (this, wxRight
);
995 c
->height
.PercentOf(this, wxHeight
, 30);
996 m_ctrlText
->SetConstraints(c
);
998 // Lower text control
999 c
= new wxLayoutConstraints
;
1000 c
->left
.SameAs (this, wxLeft
);
1001 c
->right
.SameAs (this, wxRight
);
1002 c
->height
.PercentOf(this, wxHeight
, 50);
1003 c
->top
.SameAs(m_ctrlText
, wxBottom
);
1004 m_ctrlLog
->SetConstraints(c
);
1006 SetAutoLayout(TRUE
);
1009 void DnDFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
1014 void DnDFrame::OnSize(wxSizeEvent
& event
)
1021 void DnDFrame::OnPaint(wxPaintEvent
& WXUNUSED(event
))
1025 GetClientSize( &w
, &h
);
1029 dc
.SetFont( wxFont( 24, wxDECORATIVE
, wxNORMAL
, wxNORMAL
, FALSE
, "charter" ) );
1030 dc
.DrawText( "Drag text from here!", 100, h
-50 );
1033 void DnDFrame::OnUpdateUIPasteText(wxUpdateUIEvent
& event
)
1036 // too many trace messages if we don't do it - this function is called
1041 event
.Enable( wxTheClipboard
->IsSupported(wxDF_TEXT
) );
1044 void DnDFrame::OnUpdateUIPasteBitmap(wxUpdateUIEvent
& event
)
1047 // too many trace messages if we don't do it - this function is called
1052 event
.Enable( wxTheClipboard
->IsSupported(wxDF_BITMAP
) );
1055 void DnDFrame::OnNewFrame(wxCommandEvent
& WXUNUSED(event
))
1057 (new DnDShapeFrame(this))->Show(TRUE
);
1059 wxLogStatus(this, wxT("Double click the new frame to select a shape for it"));
1062 void DnDFrame::OnDrag(wxCommandEvent
& WXUNUSED(event
))
1064 wxString strText
= wxGetTextFromUser
1066 "After you enter text in this dialog, press any mouse\n"
1067 "button in the bottom (empty) part of the frame and \n"
1068 "drag it anywhere - you will be in fact dragging the\n"
1069 "text object containing this text",
1070 "Please enter some text", m_strText
, this
1073 m_strText
= strText
;
1076 void DnDFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
1078 wxMessageBox("Drag-&-Drop Demo\n"
1079 "Please see \"Help|Help...\" for details\n"
1080 "Copyright (c) 1998 Vadim Zeitlin",
1082 wxICON_INFORMATION
| wxOK
,
1086 void DnDFrame::OnHelp(wxCommandEvent
& /* event */)
1088 wxMessageDialog
dialog(this,
1089 "This small program demonstrates drag & drop support in wxWindows. The program window\n"
1090 "consists of 3 parts: the bottom pane is for debug messages, so that you can see what's\n"
1091 "going on inside. The top part is split into 2 listboxes, the left one accepts files\n"
1092 "and the right one accepts text.\n"
1094 "To test wxDropTarget: open wordpad (write.exe), select some text in it and drag it to\n"
1095 "the right listbox (you'll notice the usual visual feedback, i.e. the cursor will change).\n"
1096 "Also, try dragging some files (you can select several at once) from Windows Explorer (or \n"
1097 "File Manager) to the left pane. Hold down Ctrl/Shift keys when you drop text (doesn't \n"
1098 "work with files) and see what changes.\n"
1100 "To test wxDropSource: just press any mouse button on the empty zone of the window and drag\n"
1101 "it to wordpad or any other droptarget accepting text (and of course you can just drag it\n"
1102 "to the right pane). Due to a lot of trace messages, the cursor might take some time to \n"
1103 "change, don't release the mouse button until it does. You can change the string being\n"
1104 "dragged in in \"File|Test drag...\" dialog.\n"
1107 "Please send all questions/bug reports/suggestions &c to \n"
1108 "Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>",
1114 void DnDFrame::OnLogClear(wxCommandEvent
& /* event */ )
1117 m_ctrlText
->Clear();
1118 m_ctrlFile
->Clear();
1121 void DnDFrame::OnLeftDown(wxMouseEvent
&WXUNUSED(event
) )
1123 if ( !m_strText
.IsEmpty() )
1125 // start drag operation
1126 wxTextDataObject
textData(m_strText
);
1128 wxFileDataObject textData;
1129 textData.AddFile( "/file1.txt" );
1130 textData.AddFile( "/file2.txt" );
1132 wxDropSource
source(textData
, this,
1133 wxDROP_ICON(dnd_copy
),
1134 wxDROP_ICON(dnd_move
),
1135 wxDROP_ICON(dnd_none
));
1139 switch ( source
.DoDragDrop(TRUE
) )
1141 case wxDragError
: pc
= "Error!"; break;
1142 case wxDragNone
: pc
= "Nothing"; break;
1143 case wxDragCopy
: pc
= "Copied"; break;
1144 case wxDragMove
: pc
= "Moved"; break;
1145 case wxDragCancel
: pc
= "Cancelled"; break;
1146 default: pc
= "Huh?"; break;
1149 SetStatusText(wxString("Drag result: ") + pc
);
1153 void DnDFrame::OnRightDown(wxMouseEvent
&event
)
1155 wxMenu
menu("Dnd sample menu");
1157 menu
.Append(Menu_Drag
, "&Test drag...");
1158 menu
.AppendSeparator();
1159 menu
.Append(Menu_About
, "&About");
1161 PopupMenu( &menu
, event
.GetX(), event
.GetY() );
1164 DnDFrame::~DnDFrame()
1166 if ( m_pLog
!= NULL
) {
1167 if ( wxLog::SetActiveTarget(m_pLogPrev
) == m_pLog
)
1172 // ---------------------------------------------------------------------------
1174 // ---------------------------------------------------------------------------
1176 void DnDFrame::OnCopyBitmap(wxCommandEvent
& WXUNUSED(event
))
1178 // PNG support is not always compiled in under Windows, so use BMP there
1180 wxFileDialog
dialog(this, "Open a BMP file", "", "", "BMP files (*.bmp)|*.bmp", 0);
1182 wxFileDialog
dialog(this, "Open a PNG file", "", "", "PNG files (*.png)|*.png", 0);
1185 if (dialog
.ShowModal() != wxID_OK
)
1187 wxLogMessage( _T("Aborted file open") );
1191 if (dialog
.GetPath().IsEmpty())
1193 wxLogMessage( _T("Returned empty string.") );
1197 if (!wxFileExists(dialog
.GetPath()))
1199 wxLogMessage( _T("File doesn't exist.") );
1204 image
.LoadFile( dialog
.GetPath(),
1213 wxLogError( _T("Invalid image file...") );
1217 wxLogStatus( _T("Decoding image file...") );
1220 wxBitmap
bitmap( image
);
1222 if ( !wxTheClipboard
->Open() )
1224 wxLogError(_T("Can't open clipboard."));
1229 wxLogMessage( _T("Creating wxBitmapDataObject...") );
1232 if ( !wxTheClipboard
->AddData(new wxBitmapDataObject(bitmap
)) )
1234 wxLogError(_T("Can't copy image to the clipboard."));
1238 wxLogMessage(_T("Image has been put on the clipboard.") );
1239 wxLogMessage(_T("You can paste it now and look at it.") );
1242 wxTheClipboard
->Close();
1245 void DnDFrame::OnPasteBitmap(wxCommandEvent
& WXUNUSED(event
))
1247 if ( !wxTheClipboard
->Open() )
1249 wxLogError(_T("Can't open clipboard."));
1254 if ( !wxTheClipboard
->IsSupported(wxDF_BITMAP
) )
1256 wxLogWarning(_T("No bitmap on clipboard"));
1258 wxTheClipboard
->Close();
1262 wxBitmapDataObject data
;
1263 if ( !wxTheClipboard
->GetData(data
) )
1265 wxLogError(_T("Can't paste bitmap from the clipboard"));
1269 const wxBitmap
& bmp
= data
.GetBitmap();
1271 wxLogMessage(_T("Bitmap %dx%d pasted from the clipboard"),
1272 bmp
.GetWidth(), bmp
.GetHeight());
1276 wxTheClipboard
->Close();
1279 #ifdef USE_METAFILES
1281 void DnDFrame::OnPasteMetafile(wxCommandEvent
& WXUNUSED(event
))
1283 if ( !wxTheClipboard
->Open() )
1285 wxLogError(_T("Can't open clipboard."));
1290 if ( !wxTheClipboard
->IsSupported(wxDF_METAFILE
) )
1292 wxLogWarning(_T("No metafile on clipboard"));
1296 wxMetaFileDataObject data
;
1297 if ( !wxTheClipboard
->GetData(data
) )
1299 wxLogError(_T("Can't paste metafile from the clipboard"));
1303 const wxMetaFile
& mf
= data
.GetMetafile();
1305 wxLogMessage(_T("Metafile %dx%d pasted from the clipboard"),
1306 mf
.GetWidth(), mf
.GetHeight());
1312 wxTheClipboard
->Close();
1315 #endif // USE_METAFILES
1317 // ----------------------------------------------------------------------------
1319 // ----------------------------------------------------------------------------
1321 void DnDFrame::OnCopyFiles(wxCommandEvent
& WXUNUSED(event
))
1324 wxFileDialog
dialog(this, "Select a file to copy", "", "",
1325 "All files (*.*)|*.*", 0);
1327 wxArrayString filenames
;
1328 while ( dialog
.ShowModal() == wxID_OK
)
1330 filenames
.Add(dialog
.GetPath());
1333 if ( !filenames
.IsEmpty() )
1335 wxFileDataObject
*dobj
= new wxFileDataObject
;
1336 size_t count
= filenames
.GetCount();
1337 for ( size_t n
= 0; n
< count
; n
++ )
1339 dobj
->AddFile(filenames
[n
]);
1342 wxClipboardLocker locker
;
1345 wxLogError(wxT("Can't open clipboard"));
1349 if ( !wxTheClipboard
->AddData(dobj
) )
1351 wxLogError(wxT("Can't copy file(s) to the clipboard"));
1355 wxLogStatus(this, wxT("%d file%s copied to the clipboard"),
1356 count
, count
== 1 ? wxT("") : wxT("s"));
1362 wxLogStatus(this, wxT("Aborted"));
1365 wxLogError(wxT("Sorry, not implemented"));
1369 // ---------------------------------------------------------------------------
1371 // ---------------------------------------------------------------------------
1373 void DnDFrame::OnCopy(wxCommandEvent
& WXUNUSED(event
))
1375 if ( !wxTheClipboard
->Open() )
1377 wxLogError(_T("Can't open clipboard."));
1382 if ( !wxTheClipboard
->AddData(new wxTextDataObject(m_strText
)) )
1384 wxLogError(_T("Can't copy data to the clipboard"));
1388 wxLogMessage(_T("Text '%s' put on the clipboard"), m_strText
.c_str());
1391 wxTheClipboard
->Close();
1394 void DnDFrame::OnPaste(wxCommandEvent
& WXUNUSED(event
))
1396 if ( !wxTheClipboard
->Open() )
1398 wxLogError(_T("Can't open clipboard."));
1403 if ( !wxTheClipboard
->IsSupported(wxDF_TEXT
) )
1405 wxLogWarning(_T("No text data on clipboard"));
1407 wxTheClipboard
->Close();
1411 wxTextDataObject text
;
1412 if ( !wxTheClipboard
->GetData(text
) )
1414 wxLogError(_T("Can't paste data from the clipboard"));
1418 wxLogMessage(_T("Text '%s' pasted from the clipboard"),
1419 text
.GetText().c_str());
1422 wxTheClipboard
->Close();
1425 // ----------------------------------------------------------------------------
1426 // Notifications called by the base class
1427 // ----------------------------------------------------------------------------
1429 bool DnDText::OnDropText(wxCoord
, wxCoord
, const wxString
& text
)
1431 m_pOwner
->Append(text
);
1436 bool DnDFile::OnDropFiles(wxCoord
, wxCoord
, const wxArrayString
& filenames
)
1438 size_t nFiles
= filenames
.GetCount();
1440 str
.Printf( _T("%d files dropped"), nFiles
);
1441 m_pOwner
->Append(str
);
1442 for ( size_t n
= 0; n
< nFiles
; n
++ ) {
1443 m_pOwner
->Append(filenames
[n
]);
1449 // ----------------------------------------------------------------------------
1451 // ----------------------------------------------------------------------------
1453 DnDShapeDialog::DnDShapeDialog(wxFrame
*parent
, DnDShape
*shape
)
1455 :wxDialog( parent
, 6001, wxT("Choose Shape"), wxPoint( 10, 10 ),
1457 wxRAISED_BORDER
|wxCAPTION
|wxTHICK_FRAME
|wxSYSTEM_MENU
)
1462 LoadFromResource(parent
, "dialogShape");
1464 m_textX
= (wxTextCtrl
*)wxFindWindowByName("textX", this);
1465 m_textY
= (wxTextCtrl
*)wxFindWindowByName("textY", this);
1466 m_textW
= (wxTextCtrl
*)wxFindWindowByName("textW", this);
1467 m_textH
= (wxTextCtrl
*)wxFindWindowByName("textH", this);
1469 m_radio
= (wxRadioBox
*)wxFindWindowByName("radio", this);
1471 wxBoxSizer
* topSizer
= new wxBoxSizer( wxVERTICAL
);
1474 wxBoxSizer
* shapesSizer
= new wxBoxSizer( wxHORIZONTAL
);
1475 const wxString choices
[] = { wxT("None"), wxT("Triangle"),
1476 wxT("Rectangle"), wxT("Ellipse") };
1478 m_radio
= new wxRadioBox( this, -1, wxT("&Shape"),
1479 wxDefaultPosition
, wxDefaultSize
, 4, choices
, 4,
1480 wxRA_SPECIFY_COLS
);
1481 shapesSizer
->Add( m_radio
, 0, wxGROW
|wxALL
, 5 );
1482 topSizer
->Add( shapesSizer
, 0, wxALL
, 2 );
1485 wxStaticBox
* box
= new wxStaticBox( this, -1, wxT("&Attributes") );
1486 wxStaticBoxSizer
* attrSizer
= new wxStaticBoxSizer( box
, wxHORIZONTAL
);
1487 wxFlexGridSizer
* xywhSizer
= new wxFlexGridSizer( 4, 2 );
1491 st
= new wxStaticText( this, -1, wxT("Position &X:") );
1492 m_textX
= new wxTextCtrl( this, -1, wxEmptyString
, wxDefaultPosition
,
1494 xywhSizer
->Add( st
, 1, wxGROW
|wxALL
, 2 );
1495 xywhSizer
->Add( m_textX
, 1, wxGROW
|wxALL
, 2 );
1497 st
= new wxStaticText( this, -1, wxT("Size &width:") );
1498 m_textW
= new wxTextCtrl( this, -1, wxEmptyString
, wxDefaultPosition
,
1500 xywhSizer
->Add( st
, 1, wxGROW
|wxALL
, 2 );
1501 xywhSizer
->Add( m_textW
, 1, wxGROW
|wxALL
, 2 );
1503 st
= new wxStaticText( this, -1, wxT("&Y:") );
1504 m_textY
= new wxTextCtrl( this, -1, wxEmptyString
, wxDefaultPosition
,
1506 xywhSizer
->Add( st
, 1, wxALL
|wxALIGN_RIGHT
, 2 );
1507 xywhSizer
->Add( m_textY
, 1, wxGROW
|wxALL
, 2 );
1509 st
= new wxStaticText( this, -1, wxT("&height:") );
1510 m_textH
= new wxTextCtrl( this, -1, wxEmptyString
, wxDefaultPosition
,
1512 xywhSizer
->Add( st
, 1, wxALL
|wxALIGN_RIGHT
, 2 );
1513 xywhSizer
->Add( m_textH
, 1, wxGROW
|wxALL
, 2 );
1515 wxButton
* col
= new wxButton( this, Button_Colour
, wxT("&Colour...") );
1516 attrSizer
->Add( xywhSizer
, 1, wxGROW
);
1517 attrSizer
->Add( col
, 0, wxALL
|wxALIGN_CENTRE_VERTICAL
, 2 );
1518 topSizer
->Add( attrSizer
, 0, wxGROW
|wxALL
, 5 );
1521 wxBoxSizer
* buttonSizer
= new wxBoxSizer( wxHORIZONTAL
);
1523 bt
= new wxButton( this, wxID_OK
, wxT("Ok") );
1524 buttonSizer
->Add( bt
, 0, wxALL
, 2 );
1525 bt
= new wxButton( this, wxID_CANCEL
, wxT("Cancel") );
1526 buttonSizer
->Add( bt
, 0, wxALL
, 2 );
1527 topSizer
->Add( buttonSizer
, 0, wxALL
|wxALIGN_RIGHT
, 2 );
1529 SetAutoLayout( TRUE
);
1530 SetSizer( topSizer
);
1531 topSizer
->Fit( this );
1535 DnDShape
*DnDShapeDialog::GetShape() const
1537 switch ( m_shapeKind
)
1540 case DnDShape::None
: return NULL
;
1541 case DnDShape::Triangle
: return new DnDTriangularShape(m_pos
, m_size
, m_col
);
1542 case DnDShape::Rectangle
: return new DnDRectangularShape(m_pos
, m_size
, m_col
);
1543 case DnDShape::Ellipse
: return new DnDEllipticShape(m_pos
, m_size
, m_col
);
1547 bool DnDShapeDialog::TransferDataToWindow()
1552 m_radio
->SetSelection(m_shape
->GetKind());
1553 m_pos
= m_shape
->GetPosition();
1554 m_size
= m_shape
->GetSize();
1555 m_col
= m_shape
->GetColour();
1559 m_radio
->SetSelection(DnDShape::None
);
1560 m_pos
= wxPoint(1, 1);
1561 m_size
= wxSize(100, 100);
1564 m_textX
->SetValue(wxString() << m_pos
.x
);
1565 m_textY
->SetValue(wxString() << m_pos
.y
);
1566 m_textW
->SetValue(wxString() << m_size
.x
);
1567 m_textH
->SetValue(wxString() << m_size
.y
);
1572 bool DnDShapeDialog::TransferDataFromWindow()
1574 m_shapeKind
= (DnDShape::Kind
)m_radio
->GetSelection();
1576 m_pos
.x
= wxAtoi(m_textX
->GetValue());
1577 m_pos
.y
= wxAtoi(m_textY
->GetValue());
1578 m_size
.x
= wxAtoi(m_textW
->GetValue());
1579 m_size
.y
= wxAtoi(m_textH
->GetValue());
1581 if ( !m_pos
.x
|| !m_pos
.y
|| !m_size
.x
|| !m_size
.y
)
1583 wxMessageBox("All sizes and positions should be non null!",
1584 "Invalid shape", wxICON_HAND
| wxOK
, this);
1592 void DnDShapeDialog::OnColour(wxCommandEvent
& WXUNUSED(event
))
1595 data
.SetChooseFull(TRUE
);
1596 for (int i
= 0; i
< 16; i
++)
1598 wxColour
colour(i
*16, i
*16, i
*16);
1599 data
.SetCustomColour(i
, colour
);
1602 wxColourDialog
dialog(this, &data
);
1603 if ( dialog
.ShowModal() == wxID_OK
)
1605 m_col
= dialog
.GetColourData().GetColour();
1609 // ----------------------------------------------------------------------------
1611 // ----------------------------------------------------------------------------
1613 DnDShapeFrame
*DnDShapeFrame::ms_lastDropTarget
= NULL
;
1615 DnDShapeFrame::DnDShapeFrame(wxFrame
*parent
)
1616 : wxFrame(parent
, -1, "Shape Frame",
1617 wxDefaultPosition
, wxSize(250, 150))
1621 wxMenu
*menuShape
= new wxMenu
;
1622 menuShape
->Append(Menu_Shape_New
, "&New default shape\tCtrl-S");
1623 menuShape
->Append(Menu_Shape_Edit
, "&Edit shape\tCtrl-E");
1624 menuShape
->AppendSeparator();
1625 menuShape
->Append(Menu_Shape_Clear
, "&Clear shape\tCtrl-L");
1627 wxMenu
*menuClipboard
= new wxMenu
;
1628 menuClipboard
->Append(Menu_ShapeClipboard_Copy
, "&Copy\tCtrl-C");
1629 menuClipboard
->Append(Menu_ShapeClipboard_Paste
, "&Paste\tCtrl-V");
1631 wxMenuBar
*menubar
= new wxMenuBar
;
1632 menubar
->Append(menuShape
, "&Shape");
1633 menubar
->Append(menuClipboard
, "&Clipboard");
1635 SetMenuBar(menubar
);
1637 SetStatusText("Press Ctrl-S to create a new shape");
1639 SetDropTarget(new DnDShapeDropTarget(this));
1643 SetBackgroundColour(*wxWHITE
);
1646 DnDShapeFrame::~DnDShapeFrame()
1652 void DnDShapeFrame::SetShape(DnDShape
*shape
)
1661 void DnDShapeFrame::OnDrag(wxMouseEvent
& event
)
1670 // start drag operation
1671 DnDShapeDataObject
shapeData(m_shape
);
1672 wxDropSource
source(shapeData
, this);
1674 const char *pc
= NULL
;
1675 switch ( source
.DoDragDrop(TRUE
) )
1679 wxLogError(wxT("An error occured during drag and drop operation"));
1683 SetStatusText("Nothing happened");
1692 if ( ms_lastDropTarget
!= this )
1694 // don't delete the shape if we dropped it on ourselves!
1700 SetStatusText("Drag and drop operation cancelled");
1706 SetStatusText(wxString("Shape successfully ") + pc
);
1708 //else: status text already set
1711 void DnDShapeFrame::OnDrop(wxCoord x
, wxCoord y
, DnDShape
*shape
)
1713 ms_lastDropTarget
= this;
1718 s
.Printf(wxT("Shape dropped at (%ld, %ld)"), pt
.x
, pt
.y
);
1725 void DnDShapeFrame::OnEditShape(wxCommandEvent
& event
)
1727 DnDShapeDialog
dlg(this, m_shape
);
1728 if ( dlg
.ShowModal() == wxID_OK
)
1730 SetShape(dlg
.GetShape());
1734 SetStatusText("You can now drag the shape to another frame");
1739 void DnDShapeFrame::OnNewShape(wxCommandEvent
& event
)
1741 SetShape(new DnDEllipticShape(wxPoint(10, 10), wxSize(80, 60), *wxRED
));
1743 SetStatusText("You can now drag the shape to another frame");
1746 void DnDShapeFrame::OnClearShape(wxCommandEvent
& event
)
1751 void DnDShapeFrame::OnCopyShape(wxCommandEvent
& event
)
1755 wxClipboardLocker clipLocker
;
1758 wxLogError(wxT("Can't open the clipboard"));
1763 wxTheClipboard
->AddData(new DnDShapeDataObject(m_shape
));
1767 void DnDShapeFrame::OnPasteShape(wxCommandEvent
& event
)
1769 wxClipboardLocker clipLocker
;
1772 wxLogError(wxT("Can't open the clipboard"));
1777 DnDShapeDataObject
shapeDataObject(NULL
);
1778 if ( wxTheClipboard
->GetData(shapeDataObject
) )
1780 SetShape(shapeDataObject
.GetShape());
1784 wxLogStatus(wxT("No shape on the clipboard"));
1788 void DnDShapeFrame::OnUpdateUICopy(wxUpdateUIEvent
& event
)
1790 event
.Enable( m_shape
!= NULL
);
1793 void DnDShapeFrame::OnUpdateUIPaste(wxUpdateUIEvent
& event
)
1795 event
.Enable( wxTheClipboard
->IsSupported(wxDataFormat(shapeFormatId
)) );
1798 void DnDShapeFrame::OnPaint(wxPaintEvent
& event
)
1812 // ----------------------------------------------------------------------------
1814 // ----------------------------------------------------------------------------
1816 DnDShape
*DnDShape::New(const void *buf
)
1818 const ShapeDump
& dump
= *(const ShapeDump
*)buf
;
1822 return new DnDTriangularShape(wxPoint(dump
.x
, dump
.y
),
1823 wxSize(dump
.w
, dump
.h
),
1824 wxColour(dump
.r
, dump
.g
, dump
.b
));
1827 return new DnDRectangularShape(wxPoint(dump
.x
, dump
.y
),
1828 wxSize(dump
.w
, dump
.h
),
1829 wxColour(dump
.r
, dump
.g
, dump
.b
));
1832 return new DnDEllipticShape(wxPoint(dump
.x
, dump
.y
),
1833 wxSize(dump
.w
, dump
.h
),
1834 wxColour(dump
.r
, dump
.g
, dump
.b
));
1837 wxFAIL_MSG(wxT("invalid shape!"));
1842 // ----------------------------------------------------------------------------
1843 // DnDShapeDataObject
1844 // ----------------------------------------------------------------------------
1846 #ifdef USE_METAFILES
1848 void DnDShapeDataObject::CreateMetaFile() const
1850 wxPoint pos
= m_shape
->GetPosition();
1851 wxSize size
= m_shape
->GetSize();
1853 wxMetaFileDC
dcMF(wxEmptyString
, pos
.x
+ size
.x
, pos
.y
+ size
.y
);
1855 m_shape
->Draw(dcMF
);
1857 wxMetafile
*mf
= dcMF
.Close();
1859 DnDShapeDataObject
*self
= (DnDShapeDataObject
*)this; // const_cast
1860 self
->m_dobjMetaFile
.SetMetafile(*mf
);
1861 self
->m_hasMetaFile
= TRUE
;
1868 void DnDShapeDataObject::CreateBitmap() const
1870 wxPoint pos
= m_shape
->GetPosition();
1871 wxSize size
= m_shape
->GetSize();
1872 int x
= pos
.x
+ size
.x
,
1874 wxBitmap
bitmap(x
, y
);
1876 dc
.SelectObject(bitmap
);
1877 dc
.SetBrush(wxBrush(wxT("white"), wxSOLID
));
1880 dc
.SelectObject(wxNullBitmap
);
1882 DnDShapeDataObject
*self
= (DnDShapeDataObject
*)this; // const_cast
1883 self
->m_dobjBitmap
.SetBitmap(bitmap
);
1884 self
->m_hasBitmap
= TRUE
;
1887 // ----------------------------------------------------------------------------
1889 // ----------------------------------------------------------------------------
1891 static void ShowBitmap(const wxBitmap
& bitmap
)
1893 wxFrame
*frame
= new wxFrame(NULL
, -1, _T("Bitmap view"));
1894 frame
->CreateStatusBar();
1895 DnDCanvasBitmap
*canvas
= new DnDCanvasBitmap(frame
);
1896 canvas
->SetBitmap(bitmap
);
1898 int w
= bitmap
.GetWidth(),
1899 h
= bitmap
.GetHeight();
1900 frame
->SetStatusText(wxString::Format(_T("%dx%d"), w
, h
));
1902 frame
->SetClientSize(w
> 100 ? 100 : w
, h
> 100 ? 100 : h
);
1906 #ifdef USE_METAFILES
1908 static void ShowMetaFile(const wxMetaFile
& metafile
)
1910 wxFrame
*frame
= new wxFrame(NULL
, -1, _T("Metafile view"));
1911 frame
->CreateStatusBar();
1912 DnDCanvasMetafile
*canvas
= new DnDCanvasMetafile(frame
);
1913 canvas
->SetMetafile(metafile
);
1915 wxSize size
= metafile
.GetSize();
1916 frame
->SetStatusText(wxString::Format(_T("%dx%d"), size
.x
, size
.y
));
1918 frame
->SetClientSize(size
.x
> 100 ? 100 : size
.x
,
1919 size
.y
> 100 ? 100 : size
.y
);
1923 #endif // USE_METAFILES