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
30 #include "wx/dirdlg.h"
31 #include "wx/filedlg.h"
33 #include "wx/clipbrd.h"
34 #include "wx/colordlg.h"
35 #include "wx/resource.h"
37 #if defined(__WXGTK__) || defined(__WXMOTIF__)
38 #include "mondrian.xpm"
41 // ----------------------------------------------------------------------------
42 // Derive two simple classes which just put in the listbox the strings (text or
43 // file names) we drop on them
44 // ----------------------------------------------------------------------------
46 typedef long wxDropPointCoord
;
48 class DnDText
: public wxTextDropTarget
51 DnDText(wxListBox
*pOwner
) { m_pOwner
= pOwner
; }
53 virtual bool OnDropText(wxDropPointCoord x
, wxDropPointCoord y
,
60 class DnDFile
: public wxFileDropTarget
63 DnDFile(wxListBox
*pOwner
) { m_pOwner
= pOwner
; }
65 virtual bool OnDropFiles(wxDropPointCoord x
, wxDropPointCoord y
,
66 size_t nFiles
, const wxChar
* const aszFiles
[] );
72 // ----------------------------------------------------------------------------
73 // Define a new application type
74 // ----------------------------------------------------------------------------
76 class DnDApp
: public wxApp
79 virtual bool OnInit();
82 IMPLEMENT_APP(DnDApp
);
84 // ----------------------------------------------------------------------------
85 // Define a new frame type for the main frame
86 // ----------------------------------------------------------------------------
88 class DnDFrame
: public wxFrame
91 DnDFrame(wxFrame
*frame
, char *title
, int x
, int y
, int w
, int h
);
94 void OnPaint(wxPaintEvent
& event
);
95 void OnQuit (wxCommandEvent
& event
);
96 void OnAbout(wxCommandEvent
& event
);
97 void OnDrag (wxCommandEvent
& event
);
98 void OnNewFrame(wxCommandEvent
& event
);
99 void OnHelp (wxCommandEvent
& event
);
100 void OnLogClear(wxCommandEvent
& event
);
101 void OnCopy(wxCommandEvent
& event
);
102 void OnPaste(wxCommandEvent
& event
);
103 void OnCopyBitmap(wxCommandEvent
& event
);
104 void OnPasteBitmap(wxCommandEvent
& event
);
105 void OnClipboardHasText(wxCommandEvent
& event
);
106 void OnClipboardHasBitmap(wxCommandEvent
& event
);
108 void OnLeftDown(wxMouseEvent
& event
);
109 void OnRightDown(wxMouseEvent
& event
);
111 DECLARE_EVENT_TABLE()
114 wxListBox
*m_ctrlFile
,
116 wxTextCtrl
*m_ctrlLog
;
118 wxLog
*m_pLog
, *m_pLogPrev
;
124 // ----------------------------------------------------------------------------
125 // A shape is an example of application-specific data which may be transported
126 // via drag-and-drop or clipboard: in our case, we have different geometric
127 // shapes, each one with its own colour and position
128 // ----------------------------------------------------------------------------
141 DnDShape(const wxPoint
& pos
,
144 : m_pos(pos
), m_size(size
), m_col(col
)
148 // the functions used for drag-and-drop: they dump and restore a shape into
149 // some bitwise-copiable data
151 // NB: here we profit from the fact that wxPoint, wxSize and wxColour are
152 // POD (plain old data) and so can be copied directly - but it wouldn't
153 // work for other types!
154 // ------------------------------------------------------------------------
156 // restore from buffer
157 static DnDShape
*New(const void *buf
);
159 virtual size_t GetDataSize() const
161 return sizeof(ShapeDump
);
164 virtual void GetDataHere(void *buf
) const
166 ShapeDump
& dump
= *(ShapeDump
*)buf
;
171 dump
.r
= m_col
.Red();
172 dump
.g
= m_col
.Green();
173 dump
.b
= m_col
.Blue();
178 const wxPoint
& GetPosition() const { return m_pos
; }
179 const wxColour
& GetColour() const { return m_col
; }
180 const wxSize
& GetSize() const { return m_size
; }
182 // to implement in derived classes
183 virtual Kind
GetKind() const = 0;
185 virtual void Draw(wxDC
& dc
) = 0
187 dc
.SetPen(wxPen(m_col
, 1, wxSOLID
));
191 wxPoint
GetCentre() const
192 { return wxPoint(m_pos
.x
+ m_size
.x
/ 2, m_pos
.y
+ m_size
.y
/ 2); }
196 int x
, y
, // position
207 class DnDTriangularShape
: public DnDShape
210 DnDTriangularShape(const wxPoint
& pos
,
213 : DnDShape(pos
, size
, col
)
217 virtual Kind
GetKind() const { return Triangle
; }
218 virtual void Draw(wxDC
& dc
)
222 // well, it's a bit difficult to describe a triangle by position and
223 // size, but we're not doing geometry here, do we? ;-)
225 wxPoint
p2(m_pos
.x
+ m_size
.x
, m_pos
.y
);
226 wxPoint
p3(m_pos
.x
, m_pos
.y
+ m_size
.y
);
232 dc
.FloodFill(GetCentre(), m_col
, wxFLOOD_BORDER
);
236 class DnDRectangularShape
: public DnDShape
239 DnDRectangularShape(const wxPoint
& pos
,
242 : DnDShape(pos
, size
, col
)
246 virtual Kind
GetKind() const { return Rectangle
; }
247 virtual void Draw(wxDC
& dc
)
252 wxPoint
p2(p1
.x
+ m_size
.x
, p1
.y
);
253 wxPoint
p3(p2
.x
, p2
.y
+ m_size
.y
);
254 wxPoint
p4(p1
.x
, p3
.y
);
261 dc
.FloodFill(GetCentre(), m_col
, wxFLOOD_BORDER
);
265 class DnDEllipticShape
: public DnDShape
268 DnDEllipticShape(const wxPoint
& pos
,
271 : DnDShape(pos
, size
, col
)
275 virtual Kind
GetKind() const { return Ellipse
; }
276 virtual void Draw(wxDC
& dc
)
280 dc
.DrawEllipse(m_pos
, m_size
);
282 dc
.FloodFill(GetCentre(), m_col
, wxFLOOD_BORDER
);
286 // ----------------------------------------------------------------------------
287 // A wxDataObject specialisation for the application-specific data
288 // ----------------------------------------------------------------------------
290 static const char *shapeFormatId
= "wxShape";
292 class DnDShapeDataObject
: public wxDataObject
295 // ctor doesn't copy the pointer, so it shouldn't go away while this object
297 DnDShapeDataObject(DnDShape
*shape
)
301 // this string should uniquely identify our format, but is otherwise
303 m_formatShape
.SetId(shapeFormatId
);
305 // we don't draw the shape to a bitmap until it's really needed (i.e.
306 // we're asked to do so)
310 // implement base class pure virtuals
311 // ----------------------------------
313 virtual wxDataFormat
GetPreferredFormat() const
315 return m_formatShape
;
318 virtual size_t GetFormatCount() const
320 // +1 for our custom format
321 return m_dataobj
.GetFormatCount() + 1;
324 virtual void GetAllFormats(wxDataFormat
*formats
) const
326 formats
[0] = m_formatShape
;
327 m_dataobj
.GetAllFormats(&formats
[1]);
330 virtual size_t GetDataSize(const wxDataFormat
& format
) const
332 if ( format
== m_formatShape
)
334 return m_shape
->GetDataSize();
338 wxASSERT_MSG( format
== wxDF_BITMAP
, "unsupported format" );
343 return m_dataobj
.GetDataSize(format
);
347 virtual void GetDataHere(const wxDataFormat
& format
, void *pBuf
) const
349 if ( format
== m_formatShape
)
351 m_shape
->GetDataHere(pBuf
);
355 wxASSERT_MSG( format
== wxDF_BITMAP
, "unsupported format" );
360 m_dataobj
.GetDataHere(format
, pBuf
);
365 // creates a bitmap and assigns it to m_dataobj (also sets m_hasBitmap)
366 void CreateBitmap() const;
368 wxDataFormat m_formatShape
; // our custom format
370 wxBitmapDataObject m_dataobj
; // it handles bitmaps
371 bool m_hasBitmap
; // true if m_dataobj has valid bitmap
373 DnDShape
*m_shape
; // our data
376 // ----------------------------------------------------------------------------
377 // A dialog to edit shape properties
378 // ----------------------------------------------------------------------------
380 class DnDShapeDialog
: public wxDialog
383 DnDShapeDialog(wxFrame
*parent
, DnDShape
*shape
);
385 DnDShape
*GetShape() const;
387 virtual bool TransferDataToWindow();
388 virtual bool TransferDataFromWindow();
390 void OnColour(wxCommandEvent
& event
);
397 DnDShape::Kind m_shapeKind
;
409 DECLARE_EVENT_TABLE()
412 // ----------------------------------------------------------------------------
413 // A frame for the shapes which can be drag-and-dropped between frames
414 // ----------------------------------------------------------------------------
416 class DnDShapeFrame
: public wxFrame
419 DnDShapeFrame(wxFrame
*parent
);
422 void SetShape(DnDShape
*shape
);
425 void OnDrag(wxMouseEvent
& event
);
426 void OnEdit(wxMouseEvent
& event
);
427 void OnPaint(wxPaintEvent
& event
);
428 void OnDrop(long x
, long y
, DnDShape
*shape
);
433 DECLARE_EVENT_TABLE()
436 // ----------------------------------------------------------------------------
437 // wxDropTarget derivation for DnDShapes
438 // ----------------------------------------------------------------------------
440 class DnDShapeDropTarget
: public wxDropTarget
443 DnDShapeDropTarget(DnDShapeFrame
*frame
)
447 // the same as used by DnDShapeDataObject
448 m_formatShape
.SetId(shapeFormatId
);
451 // override base class (pure) virtuals
452 virtual void OnEnter()
453 { m_frame
->SetStatusText("Mouse entered the frame"); }
454 virtual void OnLeave()
455 { m_frame
->SetStatusText("Mouse left the frame"); }
456 virtual bool OnDrop(long x
, long y
, const void *pData
)
458 m_frame
->OnDrop(x
, y
, DnDShape::New(pData
));
464 virtual size_t GetFormatCount() const { return 1; }
465 virtual wxDataFormat
GetFormat(size_t WXUNUSED(n
)) const
466 { return m_formatShape
; }
469 DnDShapeFrame
*m_frame
;
470 wxDataFormat m_formatShape
;
473 // ----------------------------------------------------------------------------
474 // IDs for the menu commands
475 // ----------------------------------------------------------------------------
491 Menu_ToBeGreyed
, /* for testing */
492 Menu_ToBeDeleted
, /* for testing */
496 BEGIN_EVENT_TABLE(DnDFrame
, wxFrame
)
497 EVT_MENU(Menu_Quit
, DnDFrame::OnQuit
)
498 EVT_MENU(Menu_About
, DnDFrame::OnAbout
)
499 EVT_MENU(Menu_Drag
, DnDFrame::OnDrag
)
500 EVT_MENU(Menu_NewFrame
, DnDFrame::OnNewFrame
)
501 EVT_MENU(Menu_Help
, DnDFrame::OnHelp
)
502 EVT_MENU(Menu_Clear
, DnDFrame::OnLogClear
)
503 EVT_MENU(Menu_Copy
, DnDFrame::OnCopy
)
504 EVT_MENU(Menu_Paste
, DnDFrame::OnPaste
)
505 EVT_MENU(Menu_CopyBitmap
, DnDFrame::OnCopyBitmap
)
506 EVT_MENU(Menu_PasteBitmap
,DnDFrame::OnPasteBitmap
)
507 EVT_MENU(Menu_HasText
, DnDFrame::OnClipboardHasText
)
508 EVT_MENU(Menu_HasBitmap
, DnDFrame::OnClipboardHasBitmap
)
510 EVT_LEFT_DOWN( DnDFrame::OnLeftDown
)
511 EVT_RIGHT_DOWN( DnDFrame::OnRightDown
)
512 EVT_PAINT( DnDFrame::OnPaint
)
515 BEGIN_EVENT_TABLE(DnDShapeFrame
, wxFrame
)
516 EVT_RIGHT_DOWN(DnDShapeFrame::OnDrag
)
517 EVT_LEFT_DCLICK(DnDShapeFrame::OnEdit
)
518 EVT_PAINT(DnDShapeFrame::OnPaint
)
521 BEGIN_EVENT_TABLE(DnDShapeDialog
, wxDialog
)
522 EVT_BUTTON(Button_Colour
, OnColour
)
525 // ============================================================================
527 // ============================================================================
529 // `Main program' equivalent, creating windows and returning main app frame
530 bool DnDApp::OnInit()
533 wxImage::AddHandler( new wxPNGHandler
);
536 // create the main frame window
537 DnDFrame
*frame
= new DnDFrame((wxFrame
*) NULL
,
538 "Drag-and-Drop/Clipboard wxWindows Sample",
546 wxDefaultResourceTable
->ParseResourceFile("dnd.wxr");
551 DnDFrame::DnDFrame(wxFrame
*frame
, char *title
, int x
, int y
, int w
, int h
)
552 : wxFrame(frame
, -1, title
, wxPoint(x
, y
), wxSize(w
, h
)),
553 m_strText("wxWindows drag & drop works :-)")
556 // frame icon and status bar
557 SetIcon(wxICON(mondrian
));
562 wxMenu
*file_menu
= new wxMenu
;
563 file_menu
->Append(Menu_Drag
, "&Test drag...");
564 file_menu
->AppendSeparator();
565 file_menu
->Append(Menu_NewFrame
, "&New frame\tCtrl-N");
566 file_menu
->AppendSeparator();
567 file_menu
->Append(Menu_Quit
, "E&xit");
569 wxMenu
*log_menu
= new wxMenu
;
570 log_menu
->Append(Menu_Clear
, "Clear");
572 wxMenu
*help_menu
= new wxMenu
;
573 help_menu
->Append(Menu_Help
, "&Help...");
574 help_menu
->AppendSeparator();
575 help_menu
->Append(Menu_About
, "&About");
577 wxMenu
*clip_menu
= new wxMenu
;
578 clip_menu
->Append(Menu_Copy
, "&Copy text\tCtrl+C");
579 clip_menu
->Append(Menu_Paste
, "&Paste text\tCtrl+V");
580 clip_menu
->AppendSeparator();
581 clip_menu
->Append(Menu_CopyBitmap
, "&Copy bitmap");
582 clip_menu
->Append(Menu_PasteBitmap
, "&Paste bitmap");
583 clip_menu
->AppendSeparator();
584 clip_menu
->Append(Menu_HasText
, "Clipboard has &text\tCtrl+T");
585 clip_menu
->Append(Menu_HasBitmap
, "Clipboard has a &bitmap\tCtrl+B");
587 wxMenuBar
*menu_bar
= new wxMenuBar
;
588 menu_bar
->Append(file_menu
, "&File");
589 menu_bar
->Append(log_menu
, "&Log");
590 menu_bar
->Append(clip_menu
, "&Clipboard");
591 menu_bar
->Append(help_menu
, "&Help");
593 SetMenuBar(menu_bar
);
595 // make a panel with 3 subwindows
597 wxSize
size(400, 200);
599 wxString
strFile("Drop files here!"), strText("Drop text on me");
601 m_ctrlFile
= new wxListBox(this, -1, pos
, size
, 1, &strFile
, wxLB_HSCROLL
| wxLB_ALWAYS_SB
);
602 m_ctrlText
= new wxListBox(this, -1, pos
, size
, 1, &strText
, wxLB_HSCROLL
| wxLB_ALWAYS_SB
);
604 m_ctrlLog
= new wxTextCtrl(this, -1, "", pos
, size
,
605 wxTE_MULTILINE
| wxTE_READONLY
|
608 // redirect log messages to the text window and switch on OLE messages
610 wxLog::AddTraceMask(wxTRACE_OleCalls
);
611 m_pLog
= new wxLogTextCtrl(m_ctrlLog
);
612 m_pLogPrev
= wxLog::SetActiveTarget(m_pLog
);
614 // associate drop targets with 2 text controls
615 m_ctrlFile
->SetDropTarget(new DnDFile(m_ctrlFile
));
616 m_ctrlText
->SetDropTarget(new DnDText(m_ctrlText
));
618 wxLayoutConstraints
*c
;
621 c
= new wxLayoutConstraints
;
622 c
->left
.SameAs(this, wxLeft
);
623 c
->top
.SameAs(this, wxTop
);
624 c
->right
.PercentOf(this, wxRight
, 50);
625 c
->height
.PercentOf(this, wxHeight
, 30);
626 m_ctrlFile
->SetConstraints(c
);
629 c
= new wxLayoutConstraints
;
630 c
->left
.SameAs (m_ctrlFile
, wxRight
);
631 c
->top
.SameAs (this, wxTop
);
632 c
->right
.SameAs (this, wxRight
);
633 c
->height
.PercentOf(this, wxHeight
, 30);
634 m_ctrlText
->SetConstraints(c
);
636 // Lower text control
637 c
= new wxLayoutConstraints
;
638 c
->left
.SameAs (this, wxLeft
);
639 c
->right
.SameAs (this, wxRight
);
640 c
->height
.PercentOf(this, wxHeight
, 30);
641 c
->top
.SameAs(m_ctrlText
, wxBottom
);
642 m_ctrlLog
->SetConstraints(c
);
647 void DnDFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
652 void DnDFrame::OnPaint(wxPaintEvent
& WXUNUSED(event
))
656 GetClientSize( &w
, &h
);
659 dc
.SetFont( wxFont( 24, wxDECORATIVE
, wxNORMAL
, wxNORMAL
, FALSE
, "charter" ) );
660 dc
.DrawText( "Drag text from here!", 20, h
-50 );
663 dc
.DrawBitmap( m_bitmap
, 280, h
-120, TRUE
);
666 void DnDFrame::OnClipboardHasText(wxCommandEvent
& WXUNUSED(event
))
668 if ( !wxTheClipboard
->Open() )
670 wxLogError( _T("Can't open clipboard.") );
675 if ( !wxTheClipboard
->IsSupported( wxDF_TEXT
) )
677 wxLogMessage( _T("No text on the clipboard") );
681 wxLogMessage( _T("There is text on the clipboard") );
684 wxTheClipboard
->Close();
687 void DnDFrame::OnClipboardHasBitmap(wxCommandEvent
& WXUNUSED(event
))
689 if ( !wxTheClipboard
->Open() )
691 wxLogError( _T("Can't open clipboard.") );
696 if ( !wxTheClipboard
->IsSupported( wxDF_BITMAP
) )
698 wxLogMessage( _T("No bitmap on the clipboard") );
702 wxLogMessage( _T("There is a bitmap on the clipboard") );
705 wxTheClipboard
->Close();
708 void DnDFrame::OnNewFrame(wxCommandEvent
& WXUNUSED(event
))
710 (new DnDShapeFrame(this))->Show(TRUE
);
712 wxLogStatus(this, "Double click the new frame to select a shape for it");
715 void DnDFrame::OnDrag(wxCommandEvent
& WXUNUSED(event
))
717 wxString strText
= wxGetTextFromUser
719 "After you enter text in this dialog, press any mouse\n"
720 "button in the bottom (empty) part of the frame and \n"
721 "drag it anywhere - you will be in fact dragging the\n"
722 "text object containing this text",
723 "Please enter some text", m_strText
, this
729 void DnDFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
731 wxMessageBox("Drag-&-Drop Demo\n"
732 "Please see \"Help|Help...\" for details\n"
733 "Copyright (c) 1998 Vadim Zeitlin",
735 wxICON_INFORMATION
| wxOK
,
739 void DnDFrame::OnHelp(wxCommandEvent
& /* event */)
741 wxMessageDialog
dialog(this,
742 "This small program demonstrates drag & drop support in wxWindows. The program window\n"
743 "consists of 3 parts: the bottom pane is for debug messages, so that you can see what's\n"
744 "going on inside. The top part is split into 2 listboxes, the left one accepts files\n"
745 "and the right one accepts text.\n"
747 "To test wxDropTarget: open wordpad (write.exe), select some text in it and drag it to\n"
748 "the right listbox (you'll notice the usual visual feedback, i.e. the cursor will change).\n"
749 "Also, try dragging some files (you can select several at once) from Windows Explorer (or \n"
750 "File Manager) to the left pane. Hold down Ctrl/Shift keys when you drop text (doesn't \n"
751 "work with files) and see what changes.\n"
753 "To test wxDropSource: just press any mouse button on the empty zone of the window and drag\n"
754 "it to wordpad or any other droptarget accepting text (and of course you can just drag it\n"
755 "to the right pane). Due to a lot of trace messages, the cursor might take some time to \n"
756 "change, don't release the mouse button until it does. You can change the string being\n"
757 "dragged in in \"File|Test drag...\" dialog.\n"
760 "Please send all questions/bug reports/suggestions &c to \n"
761 "Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>",
767 void DnDFrame::OnLogClear(wxCommandEvent
& /* event */ )
772 void DnDFrame::OnLeftDown(wxMouseEvent
&WXUNUSED(event
) )
774 if ( !m_strText
.IsEmpty() )
776 // start drag operation
777 wxTextDataObject
textData(m_strText
);
778 wxDropSource
source(textData
, this, wxICON(mondrian
));
782 switch ( source
.DoDragDrop(TRUE
) )
784 case wxDragError
: pc
= "Error!"; break;
785 case wxDragNone
: pc
= "Nothing"; break;
786 case wxDragCopy
: pc
= "Copied"; break;
787 case wxDragMove
: pc
= "Moved"; break;
788 case wxDragCancel
: pc
= "Cancelled"; break;
789 default: pc
= "Huh?"; break;
792 SetStatusText(wxString("Drag result: ") + pc
);
796 void DnDFrame::OnRightDown(wxMouseEvent
&event
)
798 wxMenu
*menu
= new wxMenu
;
800 menu
->Append(Menu_Drag
, "&Test drag...");
801 menu
->Append(Menu_About
, "&About");
802 menu
->Append(Menu_Quit
, "E&xit");
803 menu
->Append(Menu_ToBeDeleted
, "To be deleted");
804 menu
->Append(Menu_ToBeGreyed
, "To be greyed");
806 menu
->Delete( Menu_ToBeDeleted
);
807 menu
->Enable( Menu_ToBeGreyed
, FALSE
);
809 PopupMenu( menu
, event
.GetX(), event
.GetY() );
812 DnDFrame::~DnDFrame()
814 if ( m_pLog
!= NULL
) {
815 if ( wxLog::SetActiveTarget(m_pLogPrev
) == m_pLog
)
820 // ---------------------------------------------------------------------------
822 // ---------------------------------------------------------------------------
824 void DnDFrame::OnCopyBitmap(wxCommandEvent
& WXUNUSED(event
))
826 // PNG support is not always compiled in under Windows, so use BMP there
828 wxFileDialog
dialog(this, "Open a BMP file", "", "", "BMP files (*.bmp)|*.bmp", 0);
830 wxFileDialog
dialog(this, "Open a PNG file", "", "", "PNG files (*.png)|*.png", 0);
833 if (dialog
.ShowModal() != wxID_OK
)
835 wxLogMessage( _T("Aborted file open") );
839 if (dialog
.GetPath().IsEmpty())
841 wxLogMessage( _T("Returned empty string.") );
845 if (!wxFileExists(dialog
.GetPath()))
847 wxLogMessage( _T("File doesn't exist.") );
852 image
.LoadFile( dialog
.GetPath(),
861 wxLogError( _T("Invalid image file...") );
865 wxLogStatus( _T("Decoding image file...") );
868 wxBitmap
bitmap( image
.ConvertToBitmap() );
870 if ( !wxTheClipboard
->Open() )
872 wxLogError(_T("Can't open clipboard."));
877 wxLogMessage( _T("Creating wxBitmapDataObject...") );
880 if ( !wxTheClipboard
->AddData(new wxBitmapDataObject(bitmap
)) )
882 wxLogError(_T("Can't copy image to the clipboard."));
886 wxLogMessage(_T("Image has been put on the clipboard.") );
887 wxLogMessage(_T("You can paste it now and look at it.") );
890 wxTheClipboard
->Close();
893 void DnDFrame::OnPasteBitmap(wxCommandEvent
& WXUNUSED(event
))
895 if ( !wxTheClipboard
->Open() )
897 wxLogError(_T("Can't open clipboard."));
902 if ( !wxTheClipboard
->IsSupported(wxDF_BITMAP
) )
904 wxLogWarning(_T("No bitmap on clipboard"));
906 wxTheClipboard
->Close();
910 wxBitmapDataObject data
;
911 if ( !wxTheClipboard
->GetData(&data
) )
913 wxLogError(_T("Can't paste bitmap from the clipboard"));
917 wxLogMessage(_T("Bitmap pasted from the clipboard") );
918 m_bitmap
= data
.GetBitmap();
922 wxTheClipboard
->Close();
925 // ---------------------------------------------------------------------------
927 // ---------------------------------------------------------------------------
929 void DnDFrame::OnCopy(wxCommandEvent
& WXUNUSED(event
))
931 if ( !wxTheClipboard
->Open() )
933 wxLogError(_T("Can't open clipboard."));
938 if ( !wxTheClipboard
->AddData(new wxTextDataObject(m_strText
)) )
940 wxLogError(_T("Can't copy data to the clipboard"));
944 wxLogMessage(_T("Text '%s' put on the clipboard"), m_strText
.c_str());
947 wxTheClipboard
->Close();
950 void DnDFrame::OnPaste(wxCommandEvent
& WXUNUSED(event
))
952 if ( !wxTheClipboard
->Open() )
954 wxLogError(_T("Can't open clipboard."));
959 if ( !wxTheClipboard
->IsSupported(wxDF_TEXT
) )
961 wxLogWarning(_T("No text data on clipboard"));
963 wxTheClipboard
->Close();
967 wxTextDataObject text
;
968 if ( !wxTheClipboard
->GetData(&text
) )
970 wxLogError(_T("Can't paste data from the clipboard"));
974 wxLogMessage(_T("Text '%s' pasted from the clipboard"),
975 text
.GetText().c_str());
978 wxTheClipboard
->Close();
981 // ----------------------------------------------------------------------------
982 // Notifications called by the base class
983 // ----------------------------------------------------------------------------
985 bool DnDText::OnDropText( wxDropPointCoord
, wxDropPointCoord
, const wxChar
*psz
)
987 m_pOwner
->Append(psz
);
992 bool DnDFile::OnDropFiles( wxDropPointCoord
, wxDropPointCoord
, size_t nFiles
,
993 const wxChar
* const aszFiles
[])
996 str
.Printf( _T("%d files dropped"), nFiles
);
997 m_pOwner
->Append(str
);
998 for ( size_t n
= 0; n
< nFiles
; n
++ ) {
999 m_pOwner
->Append(aszFiles
[n
]);
1005 // ----------------------------------------------------------------------------
1007 // ----------------------------------------------------------------------------
1009 DnDShapeDialog::DnDShapeDialog(wxFrame
*parent
, DnDShape
*shape
)
1013 LoadFromResource(parent
, "dialogShape");
1015 m_textX
= (wxTextCtrl
*)wxFindWindowByName("textX", this);
1016 m_textY
= (wxTextCtrl
*)wxFindWindowByName("textY", this);
1017 m_textW
= (wxTextCtrl
*)wxFindWindowByName("textW", this);
1018 m_textH
= (wxTextCtrl
*)wxFindWindowByName("textH", this);
1020 m_radio
= (wxRadioBox
*)wxFindWindowByName("radio", this);
1023 DnDShape
*DnDShapeDialog::GetShape() const
1025 switch ( m_shapeKind
)
1028 case DnDShape::None
: return NULL
;
1029 case DnDShape::Triangle
: return new DnDTriangularShape(m_pos
, m_size
, m_col
);
1030 case DnDShape::Rectangle
: return new DnDRectangularShape(m_pos
, m_size
, m_col
);
1031 case DnDShape::Ellipse
: return new DnDEllipticShape(m_pos
, m_size
, m_col
);
1035 bool DnDShapeDialog::TransferDataToWindow()
1039 m_radio
->SetSelection(m_shape
->GetKind());
1040 m_pos
= m_shape
->GetPosition();
1041 m_size
= m_shape
->GetSize();
1042 m_col
= m_shape
->GetColour();
1046 m_radio
->SetSelection(DnDShape::None
);
1047 m_pos
= wxPoint(1, 1);
1048 m_size
= wxSize(100, 100);
1051 m_textX
->SetValue(wxString() << m_pos
.x
);
1052 m_textY
->SetValue(wxString() << m_pos
.y
);
1053 m_textW
->SetValue(wxString() << m_size
.x
);
1054 m_textH
->SetValue(wxString() << m_size
.y
);
1059 bool DnDShapeDialog::TransferDataFromWindow()
1061 m_shapeKind
= (DnDShape::Kind
)m_radio
->GetSelection();
1063 m_pos
.x
= atoi(m_textX
->GetValue());
1064 m_pos
.y
= atoi(m_textY
->GetValue());
1065 m_size
.x
= atoi(m_textW
->GetValue());
1066 m_size
.y
= atoi(m_textH
->GetValue());
1068 if ( !m_pos
.x
|| !m_pos
.y
|| !m_size
.x
|| !m_size
.y
)
1070 wxMessageBox("All sizes and positions should be non null!",
1071 "Invalid shape", wxICON_HAND
| wxOK
, this);
1079 void DnDShapeDialog::OnColour(wxCommandEvent
& WXUNUSED(event
))
1082 data
.SetChooseFull(TRUE
);
1083 for (int i
= 0; i
< 16; i
++)
1085 wxColour
colour(i
*16, i
*16, i
*16);
1086 data
.SetCustomColour(i
, colour
);
1089 wxColourDialog
dialog(this, &data
);
1090 if ( dialog
.ShowModal() == wxID_OK
)
1092 m_col
= dialog
.GetColourData().GetColour();
1096 // ----------------------------------------------------------------------------
1098 // ----------------------------------------------------------------------------
1100 DnDShapeFrame::DnDShapeFrame(wxFrame
*parent
)
1101 : wxFrame(parent
, -1, "Shape Frame",
1102 wxDefaultPosition
, wxSize(250, 150))
1104 SetBackgroundColour(*wxWHITE
);
1108 SetStatusText("Double click the frame to create a shape");
1110 SetDropTarget(new DnDShapeDropTarget(this));
1115 DnDShapeFrame::~DnDShapeFrame()
1120 void DnDShapeFrame::SetShape(DnDShape
*shape
)
1128 void DnDShapeFrame::OnDrag(wxMouseEvent
& event
)
1137 // start drag operation
1138 DnDShapeDataObject
shapeData(m_shape
);
1139 wxDropSource
source(shapeData
, this, wxICON(mondrian
));
1141 const char *pc
= NULL
;
1142 switch ( source
.DoDragDrop(TRUE
) )
1146 wxLogError("An error occured during drag and drop operation");
1150 SetStatusText("Nothing happened");
1163 SetStatusText("Drag and drop operation cancelled");
1169 SetStatusText(wxString("Shape successfully ") + pc
);
1171 //else: status text already set
1174 void DnDShapeFrame::OnEdit(wxMouseEvent
& event
)
1176 DnDShapeDialog
dlg(this, m_shape
);
1177 if ( dlg
.ShowModal() == wxID_OK
)
1179 SetShape(dlg
.GetShape());
1183 SetStatusText("Right click now drag the shape to another frame");
1188 void DnDShapeFrame::OnPaint(wxPaintEvent
& event
)
1191 m_shape
->Draw(wxPaintDC(this));
1196 void DnDShapeFrame::OnDrop(long x
, long y
, DnDShape
*shape
)
1199 s
.Printf("Drop occured at (%ld, %ld)", x
, y
);
1205 // ----------------------------------------------------------------------------
1207 // ----------------------------------------------------------------------------
1209 DnDShape
*DnDShape::New(const void *buf
)
1211 const ShapeDump
& dump
= *(const ShapeDump
*)buf
;
1215 return new DnDTriangularShape(wxPoint(dump
.x
, dump
.y
),
1216 wxSize(dump
.w
, dump
.h
),
1217 wxColour(dump
.r
, dump
.g
, dump
.b
));
1220 return new DnDRectangularShape(wxPoint(dump
.x
, dump
.y
),
1221 wxSize(dump
.w
, dump
.h
),
1222 wxColour(dump
.r
, dump
.g
, dump
.b
));
1225 return new DnDEllipticShape(wxPoint(dump
.x
, dump
.y
),
1226 wxSize(dump
.w
, dump
.h
),
1227 wxColour(dump
.r
, dump
.g
, dump
.b
));
1230 wxFAIL_MSG("invalid shape!");
1235 // ----------------------------------------------------------------------------
1236 // DnDShapeDataObject
1237 // ----------------------------------------------------------------------------
1239 void DnDShapeDataObject::CreateBitmap() const
1243 dc
.SelectObject(bitmap
);
1245 dc
.SelectObject(wxNullBitmap
);
1247 DnDShapeDataObject
*self
= (DnDShapeDataObject
*)this; // const_cast
1248 self
->m_dataobj
.SetBitmap(bitmap
);
1249 self
->m_hasBitmap
= TRUE
;