1 /////////////////////////////////////////////////////////////////////////////
2 // Name: dnd.cpp
3 // Purpose: Drag and drop sample
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 04/01/98
7 // Copyright:
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 #include "wx/wxprec.h"
12
13
14 #ifndef WX_PRECOMP
15 #include "wx/wx.h"
16 #endif
17
18 #include "wx/dnd.h"
19 #include "wx/dataobj.h"
20 #include "wx/image.h"
21 #include "wx/clipbrd.h"
22 #include "wx/colordlg.h"
23 #include "wx/metafile.h"
24 #include "wx/dirctrl.h"
25
26 #ifndef wxHAS_IMAGES_IN_RESOURCES
27 #include "../sample.xpm"
28 #if wxUSE_DRAG_AND_DROP
29 #include "dnd_copy.xpm"
30 #include "dnd_move.xpm"
31 #include "dnd_none.xpm"
32 #endif
33 #endif
34
35 #if wxUSE_DRAG_AND_DROP
36
37 // ----------------------------------------------------------------------------
38 // Derive two simple classes which just put in the listbox the strings (text or
39 // file names) we drop on them
40 // ----------------------------------------------------------------------------
41
42 class DnDText : public wxTextDropTarget
43 {
44 public:
DnDText(wxListBox * pOwner)45 DnDText(wxListBox *pOwner) { m_pOwner = pOwner; }
46
47 virtual bool OnDropText(wxCoord x, wxCoord y, const wxString& text) wxOVERRIDE;
48
49 private:
50 wxListBox *m_pOwner;
51 };
52
53 class DnDFile : public wxFileDropTarget
54 {
55 public:
DnDFile(wxListBox * pOwner=NULL)56 DnDFile(wxListBox *pOwner = NULL) { m_pOwner = pOwner; }
57
58 virtual bool OnDropFiles(wxCoord x, wxCoord y,
59 const wxArrayString& filenames) wxOVERRIDE;
60
61 private:
62 wxListBox *m_pOwner;
63 };
64
65 // ----------------------------------------------------------------------------
66 // Define a custom dtop target accepting URLs
67 // ----------------------------------------------------------------------------
68
69 class URLDropTarget : public wxDropTarget
70 {
71 public:
URLDropTarget()72 URLDropTarget() { SetDataObject(new wxURLDataObject); }
73
OnDropURL(wxCoord WXUNUSED (x),wxCoord WXUNUSED (y),const wxString & text)74 void OnDropURL(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), const wxString& text)
75 {
76 // of course, a real program would do something more useful here...
77 wxMessageBox(text, "wxDnD sample: got URL",
78 wxICON_INFORMATION | wxOK);
79 }
80
81 // URLs can't be moved, only copied
OnDragOver(wxCoord WXUNUSED (x),wxCoord WXUNUSED (y),wxDragResult WXUNUSED (def))82 virtual wxDragResult OnDragOver(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y),
83 wxDragResult WXUNUSED(def)) wxOVERRIDE
84 {
85 return wxDragLink; // At least IE 5.x needs wxDragLink, the
86 // other browsers on MSW seem okay with it too.
87 }
88
89 // translate this to calls to OnDropURL() just for convenience
OnData(wxCoord x,wxCoord y,wxDragResult def)90 virtual wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult def) wxOVERRIDE
91 {
92 if ( !GetData() )
93 return wxDragNone;
94
95 OnDropURL(x, y, ((wxURLDataObject *)m_dataObject)->GetURL());
96
97 return def;
98 }
99 };
100
101 #endif // wxUSE_DRAG_AND_DROP
102
103 // ----------------------------------------------------------------------------
104 // Define a new application type
105 // ----------------------------------------------------------------------------
106
107 class DnDApp : public wxApp
108 {
109 public:
110 virtual bool OnInit() wxOVERRIDE;
111 };
112
113 wxIMPLEMENT_APP(DnDApp);
114
115 #if wxUSE_DRAG_AND_DROP || wxUSE_CLIPBOARD
116
117 // ----------------------------------------------------------------------------
118 // Define canvas class to show a bitmap
119 // ----------------------------------------------------------------------------
120
121 class DnDCanvasBitmap : public wxScrolledWindow
122 {
123 public:
DnDCanvasBitmap(wxWindow * parent)124 DnDCanvasBitmap(wxWindow *parent) : wxScrolledWindow(parent) { }
125
SetBitmap(const wxBitmap & bitmap)126 void SetBitmap(const wxBitmap& bitmap)
127 {
128 m_bitmap = bitmap;
129
130 SetScrollbars(10, 10,
131 m_bitmap.GetWidth() / 10, m_bitmap.GetHeight() / 10);
132
133 Refresh();
134 }
135
OnPaint(wxPaintEvent & WXUNUSED (event))136 void OnPaint(wxPaintEvent& WXUNUSED(event))
137 {
138 wxPaintDC dc(this);
139
140 if ( m_bitmap.IsOk() )
141 {
142 PrepareDC(dc);
143
144 dc.DrawBitmap(m_bitmap, 0, 0);
145 }
146 }
147
148 private:
149 wxBitmap m_bitmap;
150
151 wxDECLARE_EVENT_TABLE();
152 };
153
154 #if wxUSE_METAFILE
155
156 // and the same thing fo metafiles
157 class DnDCanvasMetafile : public wxScrolledWindow
158 {
159 public:
DnDCanvasMetafile(wxWindow * parent)160 DnDCanvasMetafile(wxWindow *parent) : wxScrolledWindow(parent) { }
161
SetMetafile(const wxMetafile & metafile)162 void SetMetafile(const wxMetafile& metafile)
163 {
164 m_metafile = metafile;
165
166 SetScrollbars(10, 10,
167 m_metafile.GetWidth() / 10, m_metafile.GetHeight() / 10);
168
169 Refresh();
170 }
171
OnPaint(wxPaintEvent &)172 void OnPaint(wxPaintEvent&)
173 {
174 wxPaintDC dc(this);
175
176 if ( m_metafile.IsOk() )
177 {
178 PrepareDC(dc);
179
180 m_metafile.Play(&dc);
181 }
182 }
183
184 private:
185 wxMetafile m_metafile;
186
187 wxDECLARE_EVENT_TABLE();
188 };
189
190 #endif // wxUSE_METAFILE
191
192 // ----------------------------------------------------------------------------
193 // Define a new frame type for the main frame
194 // ----------------------------------------------------------------------------
195
196 class DnDFrame : public wxFrame
197 {
198 public:
199 DnDFrame();
200 virtual ~DnDFrame();
201
202 void OnPaint(wxPaintEvent& event);
203 void OnSize(wxSizeEvent& event);
204 void OnQuit(wxCommandEvent& event);
205 void OnAbout(wxCommandEvent& event);
206 void OnDrag(wxCommandEvent& event);
207 void OnDragMoveByDefault(wxCommandEvent& event);
208 void OnDragMoveAllow(wxCommandEvent& event);
209 void OnNewFrame(wxCommandEvent& event);
210 void OnHelp (wxCommandEvent& event);
211 #if wxUSE_LOG
212 void OnLogClear(wxCommandEvent& event);
213 #endif // wxUSE_LOG
214
215 void OnCopy(wxCommandEvent& event);
216 void OnPaste(wxCommandEvent& event);
217
218 void OnCopyBitmap(wxCommandEvent& event);
219 void OnPasteBitmap(wxCommandEvent& event);
220
221 #if wxUSE_METAFILE
222 void OnPasteMetafile(wxCommandEvent& event);
223 #endif // wxUSE_METAFILE
224
225 void OnCopyFiles(wxCommandEvent& event);
226 void OnCopyURL(wxCommandEvent& event);
227
228 void OnUsePrimary(wxCommandEvent& event);
229
230 void OnLeftDown(wxMouseEvent& event);
231 void OnRightDown(wxMouseEvent& event);
232
233 #if wxUSE_DRAG_AND_DROP
234 void OnBeginDrag(wxTreeEvent& event);
235 #endif // wxUSE_DRAG_AND_DROP
236
237 void OnUpdateUIMoveByDefault(wxUpdateUIEvent& event);
238
239 void OnUpdateUIPasteText(wxUpdateUIEvent& event);
240 void OnUpdateUIPasteBitmap(wxUpdateUIEvent& event);
241
242 private:
243 #if wxUSE_DRAG_AND_DROP
244 // show the result of a dnd operation in the status bar
245 void LogDragResult(wxDragResult result);
246 #endif // wxUSE_DRAG_AND_DROP
247
248
249 // GUI controls
250 wxListBox *m_ctrlFile,
251 *m_ctrlText;
252 wxGenericDirCtrl *m_ctrlDir;
253
254 #if wxUSE_LOG
255 wxTextCtrl *m_ctrlLog;
256
257 wxLog *m_pLog,
258 *m_pLogPrev;
259 #endif // wxUSE_LOG
260
261 // move the text by default (or copy)?
262 bool m_moveByDefault;
263
264 // allow moving the text at all?
265 bool m_moveAllow;
266
267 // the text we drag
268 wxString m_strText;
269
270
271 wxDECLARE_EVENT_TABLE();
272 };
273
274 // ----------------------------------------------------------------------------
275 // A shape is an example of application-specific data which may be transported
276 // via drag-and-drop or clipboard: in our case, we have different geometric
277 // shapes, each one with its own colour and position
278 // ----------------------------------------------------------------------------
279
280 #if wxUSE_DRAG_AND_DROP
281
282 class DnDShape
283 {
284 public:
285 enum Kind
286 {
287 None,
288 Triangle,
289 Rectangle,
290 Ellipse
291 };
292
DnDShape(const wxPoint & pos,const wxSize & size,const wxColour & col)293 DnDShape(const wxPoint& pos,
294 const wxSize& size,
295 const wxColour& col)
296 : m_pos(pos), m_size(size), m_col(col)
297 {
298 }
299
300 // this is for debugging - lets us see when exactly an object is freed
301 // (this may be later than you think if it's on the clipboard, for example)
~DnDShape()302 virtual ~DnDShape() { }
303
304 // the functions used for drag-and-drop: they dump and restore a shape into
305 // some bitwise-copiable data (might use streams too...)
306 // ------------------------------------------------------------------------
307
308 // restore from buffer
309 static DnDShape *New(const void *buf);
310
GetDataSize() const311 virtual size_t GetDataSize() const
312 {
313 return sizeof(ShapeDump);
314 }
315
GetDataHere(void * buf) const316 virtual void GetDataHere(void *buf) const
317 {
318 ShapeDump& dump = *(ShapeDump *)buf;
319 dump.x = m_pos.x;
320 dump.y = m_pos.y;
321 dump.w = m_size.x;
322 dump.h = m_size.y;
323 dump.r = m_col.Red();
324 dump.g = m_col.Green();
325 dump.b = m_col.Blue();
326 dump.k = GetKind();
327 }
328
329 // accessors
GetPosition() const330 const wxPoint& GetPosition() const { return m_pos; }
GetColour() const331 const wxColour& GetColour() const { return m_col; }
GetSize() const332 const wxSize& GetSize() const { return m_size; }
333
Move(const wxPoint & pos)334 void Move(const wxPoint& pos) { m_pos = pos; }
335
336 // to implement in derived classes
337 virtual Kind GetKind() const = 0;
338
Draw(wxDC & dc)339 virtual void Draw(wxDC& dc)
340 {
341 dc.SetPen(wxPen(m_col));
342 }
343
344 protected:
345 //get a point 1 up and 1 left, otherwise the mid-point of a triangle is on the line
GetCentre() const346 wxPoint GetCentre() const
347 { return wxPoint(m_pos.x + m_size.x / 2 - 1, m_pos.y + m_size.y / 2 - 1); }
348
349 struct ShapeDump
350 {
351 wxCoord x, y, // position
352 w, h; // size
353 int k; // kind
354 unsigned char r, g, b; // colour
355 };
356
357 wxPoint m_pos;
358 wxSize m_size;
359 wxColour m_col;
360 };
361
362 class DnDTriangularShape : public DnDShape
363 {
364 public:
DnDTriangularShape(const wxPoint & pos,const wxSize & size,const wxColour & col)365 DnDTriangularShape(const wxPoint& pos,
366 const wxSize& size,
367 const wxColour& col)
368 : DnDShape(pos, size, col)
369 {
370 wxLogMessage("DnDTriangularShape is being created");
371 }
372
~DnDTriangularShape()373 virtual ~DnDTriangularShape()
374 {
375 wxLogMessage("DnDTriangularShape is being deleted");
376 }
377
GetKind() const378 virtual Kind GetKind() const wxOVERRIDE { return Triangle; }
Draw(wxDC & dc)379 virtual void Draw(wxDC& dc) wxOVERRIDE
380 {
381 DnDShape::Draw(dc);
382
383 // well, it's a bit difficult to describe a triangle by position and
384 // size, but we're not doing geometry here, do we? ;-)
385 wxPoint p1(m_pos);
386 wxPoint p2(m_pos.x + m_size.x, m_pos.y);
387 wxPoint p3(m_pos.x, m_pos.y + m_size.y);
388
389 dc.DrawLine(p1, p2);
390 dc.DrawLine(p2, p3);
391 dc.DrawLine(p3, p1);
392
393 //works in multicolor modes; on GTK (at least) will fail in 16-bit color
394 dc.SetBrush(wxBrush(m_col));
395 dc.FloodFill(GetCentre(), m_col, wxFLOOD_BORDER);
396 }
397 };
398
399 class DnDRectangularShape : public DnDShape
400 {
401 public:
DnDRectangularShape(const wxPoint & pos,const wxSize & size,const wxColour & col)402 DnDRectangularShape(const wxPoint& pos,
403 const wxSize& size,
404 const wxColour& col)
405 : DnDShape(pos, size, col)
406 {
407 wxLogMessage("DnDRectangularShape is being created");
408 }
409
~DnDRectangularShape()410 virtual ~DnDRectangularShape()
411 {
412 wxLogMessage("DnDRectangularShape is being deleted");
413 }
414
GetKind() const415 virtual Kind GetKind() const wxOVERRIDE { return Rectangle; }
Draw(wxDC & dc)416 virtual void Draw(wxDC& dc) wxOVERRIDE
417 {
418 DnDShape::Draw(dc);
419
420 wxPoint p1(m_pos);
421 wxPoint p2(p1.x + m_size.x, p1.y);
422 wxPoint p3(p2.x, p2.y + m_size.y);
423 wxPoint p4(p1.x, p3.y);
424
425 dc.DrawLine(p1, p2);
426 dc.DrawLine(p2, p3);
427 dc.DrawLine(p3, p4);
428 dc.DrawLine(p4, p1);
429
430 dc.SetBrush(wxBrush(m_col));
431 dc.FloodFill(GetCentre(), m_col, wxFLOOD_BORDER);
432 }
433 };
434
435 class DnDEllipticShape : public DnDShape
436 {
437 public:
DnDEllipticShape(const wxPoint & pos,const wxSize & size,const wxColour & col)438 DnDEllipticShape(const wxPoint& pos,
439 const wxSize& size,
440 const wxColour& col)
441 : DnDShape(pos, size, col)
442 {
443 wxLogMessage("DnDEllipticShape is being created");
444 }
445
~DnDEllipticShape()446 virtual ~DnDEllipticShape()
447 {
448 wxLogMessage("DnDEllipticShape is being deleted");
449 }
450
GetKind() const451 virtual Kind GetKind() const wxOVERRIDE { return Ellipse; }
Draw(wxDC & dc)452 virtual void Draw(wxDC& dc) wxOVERRIDE
453 {
454 DnDShape::Draw(dc);
455
456 dc.DrawEllipse(m_pos, m_size);
457
458 dc.SetBrush(wxBrush(m_col));
459 dc.FloodFill(GetCentre(), m_col, wxFLOOD_BORDER);
460 }
461 };
462
463 // ----------------------------------------------------------------------------
464 // A wxDataObject specialisation for the application-specific data
465 // ----------------------------------------------------------------------------
466
ShapeFormatId()467 static wxString ShapeFormatId()
468 {
469 return "wxShape";
470 }
471
472 class DnDShapeDataObject : public wxDataObject
473 {
474 public:
475 // ctor doesn't copy the pointer, so it shouldn't go away while this object
476 // is alive
DnDShapeDataObject(DnDShape * shape=(DnDShape *)NULL)477 DnDShapeDataObject(DnDShape *shape = (DnDShape *)NULL)
478 {
479 if ( shape )
480 {
481 // we need to copy the shape because the one we're handled may be
482 // deleted while it's still on the clipboard (for example) - and we
483 // reuse the serialisation methods here to copy it
484 void *buf = malloc(shape->DnDShape::GetDataSize());
485 shape->GetDataHere(buf);
486 m_shape = DnDShape::New(buf);
487
488 free(buf);
489 }
490 else
491 {
492 // nothing to copy
493 m_shape = NULL;
494 }
495
496 // this string should uniquely identify our format, but is otherwise
497 // arbitrary
498 m_formatShape.SetId(ShapeFormatId());
499
500 // we don't draw the shape to a bitmap until it's really needed (i.e.
501 // we're asked to do so)
502 m_hasBitmap = false;
503 #if wxUSE_METAFILE
504 m_hasMetaFile = false;
505 #endif // wxUSE_METAFILE
506 }
507
~DnDShapeDataObject()508 virtual ~DnDShapeDataObject() { delete m_shape; }
509
510 // after a call to this function, the shape is owned by the caller and it
511 // is responsible for deleting it!
512 //
513 // NB: a better solution would be to make DnDShapes ref counted and this
514 // is what should probably be done in a real life program, otherwise
515 // the ownership problems become too complicated really fast
GetShape()516 DnDShape *GetShape()
517 {
518 DnDShape *shape = m_shape;
519
520 m_shape = (DnDShape *)NULL;
521 m_hasBitmap = false;
522 #if wxUSE_METAFILE
523 m_hasMetaFile = false;
524 #endif // wxUSE_METAFILE
525
526 return shape;
527 }
528
529 // implement base class pure virtuals
530 // ----------------------------------
531
GetPreferredFormat(Direction WXUNUSED (dir)) const532 virtual wxDataFormat GetPreferredFormat(Direction WXUNUSED(dir)) const wxOVERRIDE
533 {
534 return m_formatShape;
535 }
536
GetFormatCount(Direction dir) const537 virtual size_t GetFormatCount(Direction dir) const wxOVERRIDE
538 {
539 // our custom format is supported by both GetData() and SetData()
540 size_t nFormats = 1;
541 if ( dir == Get )
542 {
543 // but the bitmap format(s) are only supported for output
544 nFormats += m_dobjBitmap.GetFormatCount(dir);
545
546 #if wxUSE_METAFILE
547 nFormats += m_dobjMetaFile.GetFormatCount(dir);
548 #endif // wxUSE_METAFILE
549 }
550
551 return nFormats;
552 }
553
GetAllFormats(wxDataFormat * formats,Direction dir) const554 virtual void GetAllFormats(wxDataFormat *formats, Direction dir) const wxOVERRIDE
555 {
556 formats[0] = m_formatShape;
557 if ( dir == Get )
558 {
559 // in Get direction we additionally support bitmaps and metafiles
560 // under Windows
561 m_dobjBitmap.GetAllFormats(&formats[1], dir);
562
563 #if wxUSE_METAFILE
564 // don't assume that m_dobjBitmap has only 1 format
565 m_dobjMetaFile.GetAllFormats(&formats[1 +
566 m_dobjBitmap.GetFormatCount(dir)], dir);
567 #endif // wxUSE_METAFILE
568 }
569 }
570
GetDataSize(const wxDataFormat & format) const571 virtual size_t GetDataSize(const wxDataFormat& format) const wxOVERRIDE
572 {
573 if ( format == m_formatShape )
574 {
575 return m_shape->GetDataSize();
576 }
577 #if wxUSE_METAFILE
578 else if ( m_dobjMetaFile.IsSupported(format) )
579 {
580 if ( !m_hasMetaFile )
581 CreateMetaFile();
582
583 return m_dobjMetaFile.GetDataSize(format);
584 }
585 #endif // wxUSE_METAFILE
586 else
587 {
588 wxASSERT_MSG( m_dobjBitmap.IsSupported(format),
589 "unexpected format" );
590
591 if ( !m_hasBitmap )
592 CreateBitmap();
593
594 return m_dobjBitmap.GetDataSize();
595 }
596 }
597
GetDataHere(const wxDataFormat & format,void * pBuf) const598 virtual bool GetDataHere(const wxDataFormat& format, void *pBuf) const wxOVERRIDE
599 {
600 if ( format == m_formatShape )
601 {
602 m_shape->GetDataHere(pBuf);
603
604 return true;
605 }
606 #if wxUSE_METAFILE
607 else if ( m_dobjMetaFile.IsSupported(format) )
608 {
609 if ( !m_hasMetaFile )
610 CreateMetaFile();
611
612 return m_dobjMetaFile.GetDataHere(format, pBuf);
613 }
614 #endif // wxUSE_METAFILE
615 else
616 {
617 wxASSERT_MSG( m_dobjBitmap.IsSupported(format),
618 "unexpected format" );
619
620 if ( !m_hasBitmap )
621 CreateBitmap();
622
623 return m_dobjBitmap.GetDataHere(pBuf);
624 }
625 }
626
SetData(const wxDataFormat & format,size_t WXUNUSED (len),const void * buf)627 virtual bool SetData(const wxDataFormat& format,
628 size_t WXUNUSED(len), const void *buf) wxOVERRIDE
629 {
630 wxCHECK_MSG( format == m_formatShape, false,
631 "unsupported format");
632
633 delete m_shape;
634 m_shape = DnDShape::New(buf);
635
636 // the shape has changed
637 m_hasBitmap = false;
638
639 #if wxUSE_METAFILE
640 m_hasMetaFile = false;
641 #endif // wxUSE_METAFILE
642
643 return true;
644 }
645
646 private:
647 // creates a bitmap and assigns it to m_dobjBitmap (also sets m_hasBitmap)
648 void CreateBitmap() const;
649 #if wxUSE_METAFILE
650 void CreateMetaFile() const;
651 #endif // wxUSE_METAFILE
652
653 wxDataFormat m_formatShape; // our custom format
654
655 wxBitmapDataObject m_dobjBitmap; // it handles bitmaps
656 bool m_hasBitmap; // true if m_dobjBitmap has valid bitmap
657
658 #if wxUSE_METAFILE
659 wxMetaFileDataObject m_dobjMetaFile;// handles metafiles
660 bool m_hasMetaFile; // true if we have valid metafile
661 #endif // wxUSE_METAFILE
662
663 DnDShape *m_shape; // our data
664 };
665
666 // ----------------------------------------------------------------------------
667 // A dialog to edit shape properties
668 // ----------------------------------------------------------------------------
669
670 class DnDShapeDialog : public wxDialog
671 {
672 public:
673 DnDShapeDialog(wxFrame *parent, DnDShape *shape);
674
675 DnDShape *GetShape() const;
676
677 virtual bool TransferDataToWindow() wxOVERRIDE;
678 virtual bool TransferDataFromWindow() wxOVERRIDE;
679
680 void OnColour(wxCommandEvent& event);
681
682 private:
683 // input
684 DnDShape *m_shape;
685
686 // output
687 DnDShape::Kind m_shapeKind;
688 wxPoint m_pos;
689 wxSize m_size;
690 wxColour m_col;
691
692 // controls
693 wxRadioBox *m_radio;
694 wxTextCtrl *m_textX,
695 *m_textY,
696 *m_textW,
697 *m_textH;
698
699 wxDECLARE_EVENT_TABLE();
700 };
701
702 // ----------------------------------------------------------------------------
703 // A frame for the shapes which can be drag-and-dropped between frames
704 // ----------------------------------------------------------------------------
705
706 class DnDShapeFrame : public wxFrame
707 {
708 public:
709 DnDShapeFrame(wxFrame *parent);
710 ~DnDShapeFrame();
711
712 void SetShape(DnDShape *shape);
SetShape(const wxRegion & region)713 virtual bool SetShape(const wxRegion ®ion)
714 {
715 return wxFrame::SetShape( region );
716 }
717
718 // callbacks
719 void OnNewShape(wxCommandEvent& event);
720 void OnEditShape(wxCommandEvent& event);
721 void OnClearShape(wxCommandEvent& event);
722
723 void OnCopyShape(wxCommandEvent& event);
724 void OnPasteShape(wxCommandEvent& event);
725
726 void OnUpdateUICopy(wxUpdateUIEvent& event);
727 void OnUpdateUIPaste(wxUpdateUIEvent& event);
728
729 void OnDrag(wxMouseEvent& event);
730 void OnPaint(wxPaintEvent& event);
731 void OnDrop(wxCoord x, wxCoord y, DnDShape *shape);
732
733 private:
734 DnDShape *m_shape;
735
736 static DnDShapeFrame *ms_lastDropTarget;
737
738 wxDECLARE_EVENT_TABLE();
739 };
740
741 // ----------------------------------------------------------------------------
742 // wxDropTarget derivation for DnDShapes
743 // ----------------------------------------------------------------------------
744
745 class DnDShapeDropTarget : public wxDropTarget
746 {
747 public:
DnDShapeDropTarget(DnDShapeFrame * frame)748 DnDShapeDropTarget(DnDShapeFrame *frame)
749 : wxDropTarget(new DnDShapeDataObject)
750 {
751 m_frame = frame;
752 }
753
754 // override base class (pure) virtuals
OnEnter(wxCoord x,wxCoord y,wxDragResult def)755 virtual wxDragResult OnEnter(wxCoord x, wxCoord y, wxDragResult def) wxOVERRIDE
756 {
757 #if wxUSE_STATUSBAR
758 m_frame->SetStatusText("Mouse entered the frame");
759 #endif // wxUSE_STATUSBAR
760 return OnDragOver(x, y, def);
761 }
OnLeave()762 virtual void OnLeave() wxOVERRIDE
763 {
764 #if wxUSE_STATUSBAR
765 m_frame->SetStatusText("Mouse left the frame");
766 #endif // wxUSE_STATUSBAR
767 }
OnData(wxCoord x,wxCoord y,wxDragResult def)768 virtual wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult def) wxOVERRIDE
769 {
770 if ( !GetData() )
771 {
772 wxLogError("Failed to get drag and drop data");
773
774 return wxDragNone;
775 }
776
777 m_frame->OnDrop(x, y,
778 ((DnDShapeDataObject *)GetDataObject())->GetShape());
779
780 return def;
781 }
782
783 private:
784 DnDShapeFrame *m_frame;
785 };
786
787 #endif // wxUSE_DRAG_AND_DROP
788
789 // ----------------------------------------------------------------------------
790 // functions prototypes
791 // ----------------------------------------------------------------------------
792
793 static void ShowBitmap(const wxBitmap& bitmap);
794
795 #if wxUSE_METAFILE
796 static void ShowMetaFile(const wxMetaFile& metafile);
797 #endif // wxUSE_METAFILE
798
799 // ----------------------------------------------------------------------------
800 // IDs for the menu commands
801 // ----------------------------------------------------------------------------
802
803 enum
804 {
805 Menu_Quit = 1,
806 Menu_Drag,
807 Menu_DragMoveDef,
808 Menu_DragMoveAllow,
809 Menu_NewFrame,
810 Menu_About = 101,
811 Menu_Help,
812 Menu_Clear,
813 Menu_Copy,
814 Menu_Paste,
815 Menu_CopyBitmap,
816 Menu_PasteBitmap,
817 Menu_PasteMFile,
818 Menu_CopyFiles,
819 Menu_CopyURL,
820 Menu_UsePrimary,
821 Menu_Shape_New = 500,
822 Menu_Shape_Edit,
823 Menu_Shape_Clear,
824 Menu_ShapeClipboard_Copy,
825 Menu_ShapeClipboard_Paste,
826 Button_Colour = 1001
827 };
828
wxBEGIN_EVENT_TABLE(DnDFrame,wxFrame)829 wxBEGIN_EVENT_TABLE(DnDFrame, wxFrame)
830 EVT_MENU(Menu_Quit, DnDFrame::OnQuit)
831 EVT_MENU(Menu_About, DnDFrame::OnAbout)
832 EVT_MENU(Menu_Drag, DnDFrame::OnDrag)
833 EVT_MENU(Menu_DragMoveDef, DnDFrame::OnDragMoveByDefault)
834 EVT_MENU(Menu_DragMoveAllow,DnDFrame::OnDragMoveAllow)
835 EVT_MENU(Menu_NewFrame, DnDFrame::OnNewFrame)
836 EVT_MENU(Menu_Help, DnDFrame::OnHelp)
837 #if wxUSE_LOG
838 EVT_MENU(Menu_Clear, DnDFrame::OnLogClear)
839 #endif // wxUSE_LOG
840 EVT_MENU(Menu_Copy, DnDFrame::OnCopy)
841 EVT_MENU(Menu_Paste, DnDFrame::OnPaste)
842 EVT_MENU(Menu_CopyBitmap, DnDFrame::OnCopyBitmap)
843 EVT_MENU(Menu_PasteBitmap,DnDFrame::OnPasteBitmap)
844 #if wxUSE_METAFILE
845 EVT_MENU(Menu_PasteMFile, DnDFrame::OnPasteMetafile)
846 #endif // wxUSE_METAFILE
847 EVT_MENU(Menu_CopyFiles, DnDFrame::OnCopyFiles)
848 EVT_MENU(Menu_CopyURL, DnDFrame::OnCopyURL)
849 EVT_MENU(Menu_UsePrimary, DnDFrame::OnUsePrimary)
850
851 EVT_UPDATE_UI(Menu_DragMoveDef, DnDFrame::OnUpdateUIMoveByDefault)
852
853 EVT_UPDATE_UI(Menu_Paste, DnDFrame::OnUpdateUIPasteText)
854 EVT_UPDATE_UI(Menu_PasteBitmap, DnDFrame::OnUpdateUIPasteBitmap)
855
856 EVT_LEFT_DOWN( DnDFrame::OnLeftDown)
857 EVT_RIGHT_DOWN( DnDFrame::OnRightDown)
858 EVT_PAINT( DnDFrame::OnPaint)
859 EVT_SIZE( DnDFrame::OnSize)
860 wxEND_EVENT_TABLE()
861
862 #if wxUSE_DRAG_AND_DROP
863
864 wxBEGIN_EVENT_TABLE(DnDShapeFrame, wxFrame)
865 EVT_MENU(Menu_Shape_New, DnDShapeFrame::OnNewShape)
866 EVT_MENU(Menu_Shape_Edit, DnDShapeFrame::OnEditShape)
867 EVT_MENU(Menu_Shape_Clear, DnDShapeFrame::OnClearShape)
868
869 EVT_MENU(Menu_ShapeClipboard_Copy, DnDShapeFrame::OnCopyShape)
870 EVT_MENU(Menu_ShapeClipboard_Paste, DnDShapeFrame::OnPasteShape)
871
872 EVT_UPDATE_UI(Menu_ShapeClipboard_Copy, DnDShapeFrame::OnUpdateUICopy)
873 EVT_UPDATE_UI(Menu_ShapeClipboard_Paste, DnDShapeFrame::OnUpdateUIPaste)
874
875 EVT_LEFT_DOWN(DnDShapeFrame::OnDrag)
876
877 EVT_PAINT(DnDShapeFrame::OnPaint)
878 wxEND_EVENT_TABLE()
879
880 wxBEGIN_EVENT_TABLE(DnDShapeDialog, wxDialog)
881 EVT_BUTTON(Button_Colour, DnDShapeDialog::OnColour)
882 wxEND_EVENT_TABLE()
883
884 #endif // wxUSE_DRAG_AND_DROP
885
886 wxBEGIN_EVENT_TABLE(DnDCanvasBitmap, wxScrolledWindow)
887 EVT_PAINT(DnDCanvasBitmap::OnPaint)
888 wxEND_EVENT_TABLE()
889
890 #if wxUSE_METAFILE
891 wxBEGIN_EVENT_TABLE(DnDCanvasMetafile, wxScrolledWindow)
892 EVT_PAINT(DnDCanvasMetafile::OnPaint)
893 wxEND_EVENT_TABLE()
894 #endif // wxUSE_METAFILE
895
896 #endif // wxUSE_DRAG_AND_DROP
897
898 // ============================================================================
899 // implementation
900 // ============================================================================
901
902 // `Main program' equivalent, creating windows and returning main app frame
903 bool DnDApp::OnInit()
904 {
905 if ( !wxApp::OnInit() )
906 return false;
907
908 #if wxUSE_DRAG_AND_DROP || wxUSE_CLIPBOARD
909 // switch on trace messages
910 #if wxUSE_LOG
911 #if defined(__WXGTK__)
912 wxLog::AddTraceMask("clipboard");
913 #elif defined(__WXMSW__)
914 wxLog::AddTraceMask(wxTRACE_OleCalls);
915 #endif
916 #endif // wxUSE_LOG
917
918 #if wxUSE_LIBPNG
919 wxImage::AddHandler( new wxPNGHandler );
920 #endif
921
922 // create the main frame window
923 new DnDFrame();
924
925 return true;
926 #else
927 wxMessageBox( "This sample has to be compiled with wxUSE_DRAG_AND_DROP", "Building error", wxOK);
928 return false;
929 #endif // wxUSE_DRAG_AND_DROP
930 }
931
932 #if wxUSE_DRAG_AND_DROP || wxUSE_CLIPBOARD
933
DnDFrame()934 DnDFrame::DnDFrame()
935 : wxFrame(NULL, wxID_ANY, "Drag-and-Drop/Clipboard wxWidgets Sample",
936 wxPoint(10, 100)),
937 m_strText("wxWidgets drag & drop works :-)")
938
939 {
940 // frame icon and status bar
941 SetIcon(wxICON(sample));
942
943 #if wxUSE_STATUSBAR
944 CreateStatusBar();
945 #endif // wxUSE_STATUSBAR
946
947 // construct menu
948 wxMenu *file_menu = new wxMenu;
949 file_menu->Append(Menu_Drag, "&Test drag...");
950 file_menu->AppendCheckItem(Menu_DragMoveDef, "&Move by default");
951 file_menu->AppendCheckItem(Menu_DragMoveAllow, "&Allow moving");
952 file_menu->AppendSeparator();
953 file_menu->Append(Menu_NewFrame, "&New frame\tCtrl-N");
954 file_menu->AppendSeparator();
955 file_menu->Append(Menu_Quit, "E&xit\tCtrl-Q");
956
957 #if wxUSE_LOG
958 wxMenu *log_menu = new wxMenu;
959 log_menu->Append(Menu_Clear, "Clear\tCtrl-L");
960 #endif // wxUSE_LOG
961
962 wxMenu *help_menu = new wxMenu;
963 help_menu->Append(Menu_Help, "&Help...");
964 help_menu->AppendSeparator();
965 help_menu->Append(Menu_About, "&About");
966
967 wxMenu *clip_menu = new wxMenu;
968 clip_menu->Append(Menu_Copy, "&Copy text\tCtrl-C");
969 clip_menu->Append(Menu_Paste, "&Paste text\tCtrl-V");
970 clip_menu->AppendSeparator();
971 clip_menu->Append(Menu_CopyBitmap, "Copy &bitmap\tCtrl-Shift-C");
972 clip_menu->Append(Menu_PasteBitmap, "Paste b&itmap\tCtrl-Shift-V");
973 #if wxUSE_METAFILE
974 clip_menu->AppendSeparator();
975 clip_menu->Append(Menu_PasteMFile, "Paste &metafile\tCtrl-M");
976 #endif // wxUSE_METAFILE
977 clip_menu->AppendSeparator();
978 clip_menu->Append(Menu_CopyFiles, "Copy &files\tCtrl-F");
979 clip_menu->Append(Menu_CopyURL, "Copy &URL\tCtrl-U");
980 clip_menu->AppendSeparator();
981 clip_menu->AppendCheckItem(Menu_UsePrimary, "Use &primary selection\tCtrl-P");
982
983 wxMenuBar *menu_bar = new wxMenuBar;
984 menu_bar->Append(file_menu, "&File");
985 #if wxUSE_LOG
986 menu_bar->Append(log_menu, "&Log");
987 #endif // wxUSE_LOG
988 menu_bar->Append(clip_menu, "&Clipboard");
989 menu_bar->Append(help_menu, "&Help");
990
991 SetMenuBar(menu_bar);
992
993 // create the child controls
994 SetBackgroundColour(*wxWHITE); // labels read better on this background
995
996 wxString strFile("Drop files here!"), strText("Drop text on me");
997
998 m_ctrlFile = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 1, &strFile,
999 wxLB_HSCROLL | wxLB_ALWAYS_SB );
1000 m_ctrlText = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 1, &strText,
1001 wxLB_HSCROLL | wxLB_ALWAYS_SB );
1002 m_ctrlDir = new wxGenericDirCtrl(this);
1003
1004 #if wxUSE_LOG
1005 m_ctrlLog = new wxTextCtrl(this, wxID_ANY, wxEmptyString,
1006 wxDefaultPosition, wxDefaultSize,
1007 wxTE_MULTILINE | wxTE_READONLY |
1008 wxSUNKEN_BORDER );
1009
1010 // redirect log messages to the text window
1011 m_pLog = new wxLogTextCtrl(m_ctrlLog);
1012 m_pLogPrev = wxLog::SetActiveTarget(m_pLog);
1013 #endif // wxUSE_LOG
1014
1015 #if wxUSE_DRAG_AND_DROP
1016 // associate drop targets with the controls
1017 m_ctrlFile->SetDropTarget(new DnDFile(m_ctrlFile));
1018 m_ctrlText->SetDropTarget(new DnDText(m_ctrlText));
1019
1020 #if wxUSE_DRAG_AND_DROP
1021 m_ctrlDir->Bind(wxEVT_TREE_BEGIN_DRAG, &DnDFrame::OnBeginDrag, this);
1022 #endif // wxUSE_DRAG_AND_DROP
1023
1024 #if wxUSE_LOG
1025 m_ctrlLog->SetDropTarget(new URLDropTarget);
1026 #endif // wxUSE_LOG
1027 #endif // wxUSE_DRAG_AND_DROP
1028
1029 wxBoxSizer *sizer_top = new wxBoxSizer( wxHORIZONTAL );
1030 sizer_top->Add(m_ctrlFile, 1, wxEXPAND );
1031 sizer_top->Add(m_ctrlText, 1, wxEXPAND );
1032
1033 wxBoxSizer *sizerDirCtrl = new wxBoxSizer(wxVERTICAL);
1034 sizerDirCtrl->Add(new wxStaticText(this, wxID_ANY, "Drag files from here"),
1035 wxSizerFlags().Centre().Border());
1036 sizerDirCtrl->Add(m_ctrlDir, wxSizerFlags(1).Expand());
1037 sizer_top->Add(sizerDirCtrl, 1, wxEXPAND );
1038
1039 // make all columns of reasonable minimal size
1040 for ( unsigned n = 0; n < sizer_top->GetChildren().size(); n++ )
1041 sizer_top->SetItemMinSize(n, 200, 300);
1042
1043 wxBoxSizer *sizer = new wxBoxSizer( wxVERTICAL );
1044 sizer->Add(sizer_top, 1, wxEXPAND );
1045 #if wxUSE_LOG
1046 sizer->Add(m_ctrlLog, 1, wxEXPAND);
1047 sizer->SetItemMinSize(m_ctrlLog, 450, 200);
1048 #endif // wxUSE_LOG
1049 sizer->AddSpacer(50);
1050
1051 // copy data by default but allow moving it as well
1052 m_moveByDefault = false;
1053 m_moveAllow = true;
1054 menu_bar->Check(Menu_DragMoveAllow, true);
1055
1056 // set the correct size and show the frame
1057 SetSizerAndFit(sizer);
1058 Show();
1059 }
1060
OnQuit(wxCommandEvent & WXUNUSED (event))1061 void DnDFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
1062 {
1063 Close(true);
1064 }
1065
OnSize(wxSizeEvent & event)1066 void DnDFrame::OnSize(wxSizeEvent& event)
1067 {
1068 Refresh();
1069
1070 event.Skip();
1071 }
1072
OnPaint(wxPaintEvent & WXUNUSED (event))1073 void DnDFrame::OnPaint(wxPaintEvent& WXUNUSED(event))
1074 {
1075 int w = 0;
1076 int h = 0;
1077 GetClientSize( &w, &h );
1078
1079 wxPaintDC dc(this);
1080 dc.SetFont( wxFontInfo(24).Family(wxFONTFAMILY_DECORATIVE).FaceName("charter") );
1081 dc.DrawText( "Drag text from here!", 100, h-50 );
1082 }
1083
OnUpdateUIMoveByDefault(wxUpdateUIEvent & event)1084 void DnDFrame::OnUpdateUIMoveByDefault(wxUpdateUIEvent& event)
1085 {
1086 // only can move by default if moving is allowed at all
1087 event.Enable(m_moveAllow);
1088 }
1089
OnUpdateUIPasteText(wxUpdateUIEvent & event)1090 void DnDFrame::OnUpdateUIPasteText(wxUpdateUIEvent& event)
1091 {
1092 #ifdef __WXDEBUG__
1093 // too many trace messages if we don't do it - this function is called
1094 // very often
1095 wxLogNull nolog;
1096 #endif
1097
1098 event.Enable( wxTheClipboard->IsSupported(wxDF_TEXT) );
1099 }
1100
OnUpdateUIPasteBitmap(wxUpdateUIEvent & event)1101 void DnDFrame::OnUpdateUIPasteBitmap(wxUpdateUIEvent& event)
1102 {
1103 #ifdef __WXDEBUG__
1104 // too many trace messages if we don't do it - this function is called
1105 // very often
1106 wxLogNull nolog;
1107 #endif
1108
1109 event.Enable( wxTheClipboard->IsSupported(wxDF_BITMAP) );
1110 }
1111
OnNewFrame(wxCommandEvent & WXUNUSED (event))1112 void DnDFrame::OnNewFrame(wxCommandEvent& WXUNUSED(event))
1113 {
1114 #if wxUSE_DRAG_AND_DROP
1115 (new DnDShapeFrame(this))->Show(true);
1116
1117 wxLogStatus(this, "Double click the new frame to select a shape for it");
1118 #endif // wxUSE_DRAG_AND_DROP
1119 }
1120
OnDrag(wxCommandEvent & WXUNUSED (event))1121 void DnDFrame::OnDrag(wxCommandEvent& WXUNUSED(event))
1122 {
1123 #if wxUSE_DRAG_AND_DROP
1124 wxString strText = wxGetTextFromUser
1125 (
1126 "After you enter text in this dialog, press any mouse\n"
1127 "button in the bottom (empty) part of the frame and \n"
1128 "drag it anywhere - you will be in fact dragging the\n"
1129 "text object containing this text",
1130 "Please enter some text", m_strText, this
1131 );
1132
1133 m_strText = strText;
1134 #endif // wxUSE_DRAG_AND_DROP
1135 }
1136
OnDragMoveByDefault(wxCommandEvent & event)1137 void DnDFrame::OnDragMoveByDefault(wxCommandEvent& event)
1138 {
1139 m_moveByDefault = event.IsChecked();
1140 }
1141
OnDragMoveAllow(wxCommandEvent & event)1142 void DnDFrame::OnDragMoveAllow(wxCommandEvent& event)
1143 {
1144 m_moveAllow = event.IsChecked();
1145 }
1146
OnAbout(wxCommandEvent & WXUNUSED (event))1147 void DnDFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
1148 {
1149 wxMessageBox("Drag-&-Drop Demo\n"
1150 "Please see \"Help|Help...\" for details\n"
1151 "Copyright (c) 1998 Vadim Zeitlin",
1152 "About wxDnD",
1153 wxICON_INFORMATION | wxOK,
1154 this);
1155 }
1156
OnHelp(wxCommandEvent &)1157 void DnDFrame::OnHelp(wxCommandEvent& /* event */)
1158 {
1159 wxMessageDialog dialog(this,
1160 "This small program demonstrates drag & drop support in wxWidgets. The program window\n"
1161 "consists of 3 parts: the bottom pane is for debug messages, so that you can see what's\n"
1162 "going on inside. The top part is split into 2 listboxes, the left one accepts files\n"
1163 "and the right one accepts text.\n"
1164 "\n"
1165 "To test wxDropTarget: open wordpad (write.exe), select some text in it and drag it to\n"
1166 "the right listbox (you'll notice the usual visual feedback, i.e. the cursor will change).\n"
1167 "Also, try dragging some files (you can select several at once) from Windows Explorer (or \n"
1168 "File Manager) to the left pane. Hold down Ctrl/Shift keys when you drop text (doesn't \n"
1169 "work with files) and see what changes.\n"
1170 "\n"
1171 "To test wxDropSource: just press any mouse button on the empty zone of the window and drag\n"
1172 "it to wordpad or any other droptarget accepting text (and of course you can just drag it\n"
1173 "to the right pane). Due to a lot of trace messages, the cursor might take some time to \n"
1174 "change, don't release the mouse button until it does. You can change the string being\n"
1175 "dragged in \"File|Test drag...\" dialog.\n"
1176 "\n"
1177 "\n"
1178 "Please send all questions/bug reports/suggestions &c to \n"
1179 "Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>",
1180 "wxDnD Help");
1181
1182 dialog.ShowModal();
1183 }
1184
1185 #if wxUSE_LOG
OnLogClear(wxCommandEvent &)1186 void DnDFrame::OnLogClear(wxCommandEvent& /* event */ )
1187 {
1188 m_ctrlLog->Clear();
1189 m_ctrlText->Clear();
1190 m_ctrlFile->Clear();
1191 }
1192 #endif // wxUSE_LOG
1193
1194 #if wxUSE_DRAG_AND_DROP
1195
LogDragResult(wxDragResult result)1196 void DnDFrame::LogDragResult(wxDragResult result)
1197 {
1198 #if wxUSE_STATUSBAR
1199 wxString msg;
1200 switch ( result )
1201 {
1202 case wxDragError: msg = "Error!"; break;
1203 case wxDragNone: msg = "Nothing"; break;
1204 case wxDragCopy: msg = "Copied"; break;
1205 case wxDragMove: msg = "Moved"; break;
1206 case wxDragCancel: msg = "Cancelled"; break;
1207 default: msg = "Huh?"; break;
1208 }
1209
1210 SetStatusText(wxString("Drag result: ") + msg);
1211 #else
1212 wxUnusedVar(result);
1213 #endif // wxUSE_STATUSBAR
1214 }
1215
1216 #endif // wxUSE_DRAG_AND_DROP
1217
OnLeftDown(wxMouseEvent & WXUNUSED (event))1218 void DnDFrame::OnLeftDown(wxMouseEvent &WXUNUSED(event) )
1219 {
1220 #if wxUSE_DRAG_AND_DROP
1221 if ( !m_strText.empty() )
1222 {
1223 // start drag operation
1224 wxTextDataObject textData(m_strText);
1225 wxDropSource source(textData, this,
1226 wxDROP_ICON(dnd_copy),
1227 wxDROP_ICON(dnd_move),
1228 wxDROP_ICON(dnd_none));
1229
1230 int flags = 0;
1231 if ( m_moveByDefault )
1232 flags |= wxDrag_DefaultMove;
1233 else if ( m_moveAllow )
1234 flags |= wxDrag_AllowMove;
1235
1236 LogDragResult(source.DoDragDrop(flags));
1237 }
1238 #endif // wxUSE_DRAG_AND_DROP
1239 }
1240
OnRightDown(wxMouseEvent & event)1241 void DnDFrame::OnRightDown(wxMouseEvent &event )
1242 {
1243 wxMenu menu("Dnd sample menu");
1244
1245 menu.Append(Menu_Drag, "&Test drag...");
1246 menu.AppendSeparator();
1247 menu.Append(Menu_About, "&About");
1248
1249 PopupMenu( &menu, event.GetX(), event.GetY() );
1250 }
1251
~DnDFrame()1252 DnDFrame::~DnDFrame()
1253 {
1254 #if wxUSE_LOG
1255 if ( m_pLog != NULL ) {
1256 if ( wxLog::SetActiveTarget(m_pLogPrev) == m_pLog )
1257 delete m_pLog;
1258 }
1259 #endif // wxUSE_LOG
1260 }
1261
OnUsePrimary(wxCommandEvent & event)1262 void DnDFrame::OnUsePrimary(wxCommandEvent& event)
1263 {
1264 const bool usePrimary = event.IsChecked();
1265 wxTheClipboard->UsePrimarySelection(usePrimary);
1266
1267 wxLogStatus("Now using %s selection", usePrimary ? "primary"
1268 : "clipboard");
1269 }
1270
1271 #if wxUSE_DRAG_AND_DROP
1272
OnBeginDrag(wxTreeEvent & event)1273 void DnDFrame::OnBeginDrag(wxTreeEvent& event)
1274 {
1275 wxFileDataObject data;
1276 data.AddFile(m_ctrlDir->GetPath(event.GetItem()));
1277
1278 wxDropSource dragSource(this);
1279 dragSource.SetData(data);
1280
1281 LogDragResult(dragSource.DoDragDrop());
1282 }
1283
1284 #endif // wxUSE_DRAG_AND_DROP
1285
1286 // ---------------------------------------------------------------------------
1287 // bitmap clipboard
1288 // ---------------------------------------------------------------------------
1289
OnCopyBitmap(wxCommandEvent & WXUNUSED (event))1290 void DnDFrame::OnCopyBitmap(wxCommandEvent& WXUNUSED(event))
1291 {
1292 // PNG support is not always compiled in under Windows, so use BMP there
1293 #if wxUSE_LIBPNG
1294 wxFileDialog dialog(this, "Open a PNG file", wxEmptyString, wxEmptyString, "PNG files (*.png)|*.png", 0);
1295 #else
1296 wxFileDialog dialog(this, "Open a BMP file", wxEmptyString, wxEmptyString, "BMP files (*.bmp)|*.bmp", 0);
1297 #endif
1298
1299 if (dialog.ShowModal() != wxID_OK)
1300 {
1301 wxLogMessage( "Aborted file open" );
1302 return;
1303 }
1304
1305 if (dialog.GetPath().empty())
1306 {
1307 wxLogMessage( "Returned empty string." );
1308 return;
1309 }
1310
1311 if (!wxFileExists(dialog.GetPath()))
1312 {
1313 wxLogMessage( "File doesn't exist." );
1314 return;
1315 }
1316
1317 wxImage image;
1318 image.LoadFile( dialog.GetPath(),
1319 #if wxUSE_LIBPNG
1320 wxBITMAP_TYPE_PNG
1321 #else
1322 wxBITMAP_TYPE_BMP
1323 #endif
1324 );
1325 if (!image.IsOk())
1326 {
1327 wxLogError( "Invalid image file..." );
1328 return;
1329 }
1330
1331 wxLogStatus( "Decoding image file..." );
1332 wxYield();
1333
1334 wxBitmap bitmap( image );
1335
1336 if ( !wxTheClipboard->Open() )
1337 {
1338 wxLogError("Can't open clipboard.");
1339
1340 return;
1341 }
1342
1343 wxLogMessage( "Creating wxBitmapDataObject..." );
1344 wxYield();
1345
1346 if ( !wxTheClipboard->AddData(new wxBitmapDataObject(bitmap)) )
1347 {
1348 wxLogError("Can't copy image to the clipboard.");
1349 }
1350 else
1351 {
1352 wxLogMessage("Image has been put on the clipboard." );
1353 wxLogMessage("You can paste it now and look at it." );
1354 }
1355
1356 wxTheClipboard->Close();
1357 }
1358
OnPasteBitmap(wxCommandEvent & WXUNUSED (event))1359 void DnDFrame::OnPasteBitmap(wxCommandEvent& WXUNUSED(event))
1360 {
1361 if ( !wxTheClipboard->Open() )
1362 {
1363 wxLogError("Can't open clipboard.");
1364
1365 return;
1366 }
1367
1368 if ( !wxTheClipboard->IsSupported(wxDF_BITMAP) )
1369 {
1370 wxLogWarning("No bitmap on clipboard");
1371
1372 wxTheClipboard->Close();
1373 return;
1374 }
1375
1376 wxBitmapDataObject data;
1377 if ( !wxTheClipboard->GetData(data) )
1378 {
1379 wxLogError("Can't paste bitmap from the clipboard");
1380 }
1381 else
1382 {
1383 const wxBitmap& bmp = data.GetBitmap();
1384
1385 wxLogMessage("Bitmap %dx%d pasted from the clipboard",
1386 bmp.GetWidth(), bmp.GetHeight());
1387 ShowBitmap(bmp);
1388 }
1389
1390 wxTheClipboard->Close();
1391 }
1392
1393 #if wxUSE_METAFILE
1394
OnPasteMetafile(wxCommandEvent & WXUNUSED (event))1395 void DnDFrame::OnPasteMetafile(wxCommandEvent& WXUNUSED(event))
1396 {
1397 if ( !wxTheClipboard->Open() )
1398 {
1399 wxLogError("Can't open clipboard.");
1400
1401 return;
1402 }
1403
1404 if ( !wxTheClipboard->IsSupported(wxDF_METAFILE) )
1405 {
1406 wxLogWarning("No metafile on clipboard");
1407 }
1408 else
1409 {
1410 wxMetaFileDataObject data;
1411 if ( !wxTheClipboard->GetData(data) )
1412 {
1413 wxLogError("Can't paste metafile from the clipboard");
1414 }
1415 else
1416 {
1417 const wxMetaFile& mf = data.GetMetafile();
1418
1419 wxLogMessage("Metafile %dx%d pasted from the clipboard",
1420 mf.GetWidth(), mf.GetHeight());
1421
1422 ShowMetaFile(mf);
1423 }
1424 }
1425
1426 wxTheClipboard->Close();
1427 }
1428
1429 #endif // wxUSE_METAFILE
1430
1431 // ----------------------------------------------------------------------------
1432 // file clipboard
1433 // ----------------------------------------------------------------------------
1434
OnCopyFiles(wxCommandEvent & WXUNUSED (event))1435 void DnDFrame::OnCopyFiles(wxCommandEvent& WXUNUSED(event))
1436 {
1437 #ifdef __WXMSW__
1438 wxFileDialog dialog(this, "Select a file to copy", wxEmptyString, wxEmptyString,
1439 "All files (*.*)|*.*", 0);
1440
1441 wxArrayString filenames;
1442 while ( dialog.ShowModal() == wxID_OK )
1443 {
1444 filenames.Add(dialog.GetPath());
1445 }
1446
1447 if ( !filenames.IsEmpty() )
1448 {
1449 wxFileDataObject *dobj = new wxFileDataObject;
1450 size_t count = filenames.GetCount();
1451 for ( size_t n = 0; n < count; n++ )
1452 {
1453 dobj->AddFile(filenames[n]);
1454 }
1455
1456 wxClipboardLocker locker;
1457 if ( !locker )
1458 {
1459 wxLogError("Can't open clipboard");
1460 }
1461 else
1462 {
1463 if ( !wxTheClipboard->AddData(dobj) )
1464 {
1465 wxLogError("Can't copy file(s) to the clipboard");
1466 }
1467 else
1468 {
1469 wxLogStatus(this, "%d file%s copied to the clipboard",
1470 count, count == 1 ? wxEmptyString : wxEmptyString);
1471 }
1472 }
1473 }
1474 else
1475 {
1476 wxLogStatus(this, "Aborted");
1477 }
1478 #else // !MSW
1479 wxLogError("Sorry, not implemented");
1480 #endif // MSW/!MSW
1481 }
1482
OnCopyURL(wxCommandEvent & WXUNUSED (event))1483 void DnDFrame::OnCopyURL(wxCommandEvent& WXUNUSED(event))
1484 {
1485 // Just hard code it for now, we could ask the user but the point here is
1486 // to test copying URLs, it doesn't really matter what it is.
1487 const wxString url("http://www.wxwidgets.org/");
1488
1489 wxClipboardLocker locker;
1490 if ( !!locker && wxTheClipboard->AddData(new wxURLDataObject(url)) )
1491 {
1492 wxLogStatus(this, "Copied URL \"%s\" to %s.",
1493 url,
1494 GetMenuBar()->IsChecked(Menu_UsePrimary)
1495 ? "primary selection"
1496 : "clipboard");
1497 }
1498 else
1499 {
1500 wxLogError("Failed to copy URL.");
1501 }
1502 }
1503
1504 // ---------------------------------------------------------------------------
1505 // text clipboard
1506 // ---------------------------------------------------------------------------
1507
OnCopy(wxCommandEvent & WXUNUSED (event))1508 void DnDFrame::OnCopy(wxCommandEvent& WXUNUSED(event))
1509 {
1510 if ( !wxTheClipboard->Open() )
1511 {
1512 wxLogError("Can't open clipboard.");
1513
1514 return;
1515 }
1516
1517 if ( !wxTheClipboard->AddData(new wxTextDataObject(m_strText)) )
1518 {
1519 wxLogError("Can't copy data to the clipboard");
1520 }
1521 else
1522 {
1523 wxLogMessage("Text '%s' put on the clipboard", m_strText);
1524 }
1525
1526 wxTheClipboard->Close();
1527 }
1528
OnPaste(wxCommandEvent & WXUNUSED (event))1529 void DnDFrame::OnPaste(wxCommandEvent& WXUNUSED(event))
1530 {
1531 if ( !wxTheClipboard->Open() )
1532 {
1533 wxLogError("Can't open clipboard.");
1534
1535 return;
1536 }
1537
1538 if ( !wxTheClipboard->IsSupported(wxDF_TEXT) )
1539 {
1540 wxLogWarning("No text data on clipboard");
1541
1542 wxTheClipboard->Close();
1543 return;
1544 }
1545
1546 wxTextDataObject text;
1547 if ( !wxTheClipboard->GetData(text) )
1548 {
1549 wxLogError("Can't paste data from the clipboard");
1550 }
1551 else
1552 {
1553 wxLogMessage("Text '%s' pasted from the clipboard",
1554 text.GetText());
1555 }
1556
1557 wxTheClipboard->Close();
1558 }
1559
1560 #if wxUSE_DRAG_AND_DROP
1561
1562 // ----------------------------------------------------------------------------
1563 // Notifications called by the base class
1564 // ----------------------------------------------------------------------------
1565
OnDropText(wxCoord,wxCoord,const wxString & text)1566 bool DnDText::OnDropText(wxCoord, wxCoord, const wxString& text)
1567 {
1568 m_pOwner->Append(text);
1569
1570 return true;
1571 }
1572
OnDropFiles(wxCoord,wxCoord,const wxArrayString & filenames)1573 bool DnDFile::OnDropFiles(wxCoord, wxCoord, const wxArrayString& filenames)
1574 {
1575 size_t nFiles = filenames.GetCount();
1576 wxString str;
1577 str.Printf( "%d files dropped", (int)nFiles);
1578
1579 if (m_pOwner != NULL)
1580 {
1581 m_pOwner->Append(str);
1582 for ( size_t n = 0; n < nFiles; n++ )
1583 m_pOwner->Append(filenames[n]);
1584 }
1585
1586 return true;
1587 }
1588
1589 // ----------------------------------------------------------------------------
1590 // DnDShapeDialog
1591 // ----------------------------------------------------------------------------
1592
DnDShapeDialog(wxFrame * parent,DnDShape * shape)1593 DnDShapeDialog::DnDShapeDialog(wxFrame *parent, DnDShape *shape)
1594 :wxDialog( parent, 6001, "Choose Shape", wxPoint( 10, 10 ),
1595 wxSize( 40, 40 ),
1596 wxDEFAULT_DIALOG_STYLE | wxRAISED_BORDER | wxRESIZE_BORDER )
1597 {
1598 m_shape = shape;
1599 wxBoxSizer* topSizer = new wxBoxSizer( wxVERTICAL );
1600
1601 // radio box
1602 wxBoxSizer* shapesSizer = new wxBoxSizer( wxHORIZONTAL );
1603 const wxString choices[] = { "None", "Triangle",
1604 "Rectangle", "Ellipse" };
1605
1606 m_radio = new wxRadioBox( this, wxID_ANY, "&Shape",
1607 wxDefaultPosition, wxDefaultSize, 4, choices, 4,
1608 wxRA_SPECIFY_COLS );
1609 shapesSizer->Add( m_radio, 0, wxGROW|wxALL, 5 );
1610 topSizer->Add( shapesSizer, 0, wxALL, 2 );
1611
1612 // attributes
1613 wxStaticBox* box = new wxStaticBox( this, wxID_ANY, "&Attributes" );
1614 wxStaticBoxSizer* attrSizer = new wxStaticBoxSizer( box, wxHORIZONTAL );
1615 wxFlexGridSizer* xywhSizer = new wxFlexGridSizer( 2 );
1616
1617 wxStaticText* st;
1618
1619 st = new wxStaticText( this, wxID_ANY, "Position &X:" );
1620 m_textX = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition,
1621 wxSize( 30, 20 ) );
1622 xywhSizer->Add( st, 1, wxGROW|wxALL, 2 );
1623 xywhSizer->Add( m_textX, 1, wxGROW|wxALL, 2 );
1624
1625 st = new wxStaticText( this, wxID_ANY, "Size &width:" );
1626 m_textW = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition,
1627 wxSize( 30, 20 ) );
1628 xywhSizer->Add( st, 1, wxGROW|wxALL, 2 );
1629 xywhSizer->Add( m_textW, 1, wxGROW|wxALL, 2 );
1630
1631 st = new wxStaticText( this, wxID_ANY, "&Y:" );
1632 m_textY = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition,
1633 wxSize( 30, 20 ) );
1634 xywhSizer->Add( st, 1, wxALL|wxALIGN_RIGHT, 2 );
1635 xywhSizer->Add( m_textY, 1, wxGROW|wxALL, 2 );
1636
1637 st = new wxStaticText( this, wxID_ANY, "&height:" );
1638 m_textH = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition,
1639 wxSize( 30, 20 ) );
1640 xywhSizer->Add( st, 1, wxALL|wxALIGN_RIGHT, 2 );
1641 xywhSizer->Add( m_textH, 1, wxGROW|wxALL, 2 );
1642
1643 wxButton* col = new wxButton( this, Button_Colour, "&Colour..." );
1644 attrSizer->Add( xywhSizer, 1, wxGROW );
1645 attrSizer->Add( col, 0, wxALL|wxALIGN_CENTRE_VERTICAL, 2 );
1646 topSizer->Add( attrSizer, 0, wxGROW|wxALL, 5 );
1647
1648 // buttons
1649 wxBoxSizer* buttonSizer = new wxBoxSizer( wxHORIZONTAL );
1650 wxButton* bt;
1651 bt = new wxButton( this, wxID_OK, "Ok" );
1652 buttonSizer->Add( bt, 0, wxALL, 2 );
1653 bt = new wxButton( this, wxID_CANCEL, "Cancel" );
1654 buttonSizer->Add( bt, 0, wxALL, 2 );
1655 topSizer->Add( buttonSizer, 0, wxALL|wxALIGN_RIGHT, 2 );
1656
1657 SetSizerAndFit( topSizer );
1658 }
1659
GetShape() const1660 DnDShape *DnDShapeDialog::GetShape() const
1661 {
1662 switch ( m_shapeKind )
1663 {
1664 default:
1665 case DnDShape::None: return NULL;
1666 case DnDShape::Triangle: return new DnDTriangularShape(m_pos, m_size, m_col);
1667 case DnDShape::Rectangle: return new DnDRectangularShape(m_pos, m_size, m_col);
1668 case DnDShape::Ellipse: return new DnDEllipticShape(m_pos, m_size, m_col);
1669 }
1670 }
1671
TransferDataToWindow()1672 bool DnDShapeDialog::TransferDataToWindow()
1673 {
1674
1675 if ( m_shape )
1676 {
1677 m_radio->SetSelection(m_shape->GetKind());
1678 m_pos = m_shape->GetPosition();
1679 m_size = m_shape->GetSize();
1680 m_col = m_shape->GetColour();
1681 }
1682 else
1683 {
1684 m_radio->SetSelection(DnDShape::None);
1685 m_pos = wxPoint(1, 1);
1686 m_size = wxSize(100, 100);
1687 }
1688
1689 m_textX->SetValue(wxString() << m_pos.x);
1690 m_textY->SetValue(wxString() << m_pos.y);
1691 m_textW->SetValue(wxString() << m_size.x);
1692 m_textH->SetValue(wxString() << m_size.y);
1693
1694 return true;
1695 }
1696
TransferDataFromWindow()1697 bool DnDShapeDialog::TransferDataFromWindow()
1698 {
1699 m_shapeKind = (DnDShape::Kind)m_radio->GetSelection();
1700
1701 m_pos.x = wxAtoi(m_textX->GetValue());
1702 m_pos.y = wxAtoi(m_textY->GetValue());
1703 m_size.x = wxAtoi(m_textW->GetValue());
1704 m_size.y = wxAtoi(m_textH->GetValue());
1705
1706 if ( !m_pos.x || !m_pos.y || !m_size.x || !m_size.y )
1707 {
1708 wxMessageBox("All sizes and positions should be non null!",
1709 "Invalid shape", wxICON_HAND | wxOK, this);
1710
1711 return false;
1712 }
1713
1714 return true;
1715 }
1716
OnColour(wxCommandEvent & WXUNUSED (event))1717 void DnDShapeDialog::OnColour(wxCommandEvent& WXUNUSED(event))
1718 {
1719 wxColourData data;
1720 data.SetChooseFull(true);
1721 for (int i = 0; i < 16; i++)
1722 {
1723 wxColour colour((unsigned char)(i*16), (unsigned char)(i*16), (unsigned char)(i*16));
1724 data.SetCustomColour(i, colour);
1725 }
1726
1727 wxColourDialog dialog(this, &data);
1728 if ( dialog.ShowModal() == wxID_OK )
1729 {
1730 m_col = dialog.GetColourData().GetColour();
1731 }
1732 }
1733
1734 // ----------------------------------------------------------------------------
1735 // DnDShapeFrame
1736 // ----------------------------------------------------------------------------
1737
1738 DnDShapeFrame *DnDShapeFrame::ms_lastDropTarget = NULL;
1739
DnDShapeFrame(wxFrame * parent)1740 DnDShapeFrame::DnDShapeFrame(wxFrame *parent)
1741 : wxFrame(parent, wxID_ANY, "Shape Frame")
1742 {
1743 #if wxUSE_STATUSBAR
1744 CreateStatusBar();
1745 #endif // wxUSE_STATUSBAR
1746
1747 wxMenu *menuShape = new wxMenu;
1748 menuShape->Append(Menu_Shape_New, "&New default shape\tCtrl-S");
1749 menuShape->Append(Menu_Shape_Edit, "&Edit shape\tCtrl-E");
1750 menuShape->AppendSeparator();
1751 menuShape->Append(Menu_Shape_Clear, "&Clear shape\tCtrl-L");
1752
1753 wxMenu *menuClipboard = new wxMenu;
1754 menuClipboard->Append(Menu_ShapeClipboard_Copy, "&Copy\tCtrl-C");
1755 menuClipboard->Append(Menu_ShapeClipboard_Paste, "&Paste\tCtrl-V");
1756
1757 wxMenuBar *menubar = new wxMenuBar;
1758 menubar->Append(menuShape, "&Shape");
1759 menubar->Append(menuClipboard, "&Clipboard");
1760
1761 SetMenuBar(menubar);
1762
1763 #if wxUSE_STATUSBAR
1764 SetStatusText("Press Ctrl-S to create a new shape");
1765 #endif // wxUSE_STATUSBAR
1766
1767 SetDropTarget(new DnDShapeDropTarget(this));
1768
1769 m_shape = NULL;
1770
1771 SetBackgroundColour(*wxWHITE);
1772 }
1773
~DnDShapeFrame()1774 DnDShapeFrame::~DnDShapeFrame()
1775 {
1776 if (m_shape)
1777 delete m_shape;
1778 }
1779
SetShape(DnDShape * shape)1780 void DnDShapeFrame::SetShape(DnDShape *shape)
1781 {
1782 if (m_shape)
1783 delete m_shape;
1784 m_shape = shape;
1785 Refresh();
1786 }
1787
1788 // callbacks
OnDrag(wxMouseEvent & event)1789 void DnDShapeFrame::OnDrag(wxMouseEvent& event)
1790 {
1791 if ( !m_shape )
1792 {
1793 event.Skip();
1794
1795 return;
1796 }
1797
1798 // start drag operation
1799 DnDShapeDataObject shapeData(m_shape);
1800 wxDropSource source(shapeData, this);
1801
1802 wxString msg;
1803 switch ( source.DoDragDrop(true) )
1804 {
1805 default:
1806 case wxDragError:
1807 wxLogError("An error occurred during drag and drop operation");
1808 break;
1809
1810 case wxDragNone:
1811 #if wxUSE_STATUSBAR
1812 SetStatusText("Nothing happened");
1813 #endif // wxUSE_STATUSBAR
1814 break;
1815
1816 case wxDragCopy:
1817 msg = "copied";
1818 break;
1819
1820 case wxDragMove:
1821 msg = "moved";
1822 if ( ms_lastDropTarget != this )
1823 {
1824 // don't delete the shape if we dropped it on ourselves!
1825 SetShape(NULL);
1826 }
1827 break;
1828
1829 case wxDragCancel:
1830 #if wxUSE_STATUSBAR
1831 SetStatusText("Drag and drop operation cancelled");
1832 #endif // wxUSE_STATUSBAR
1833 break;
1834 }
1835
1836 if (msg.length() )
1837 {
1838 #if wxUSE_STATUSBAR
1839 SetStatusText(wxString("Shape successfully ") + msg);
1840 #endif // wxUSE_STATUSBAR
1841 }
1842 //else: status text already set
1843 }
1844
OnDrop(wxCoord x,wxCoord y,DnDShape * shape)1845 void DnDShapeFrame::OnDrop(wxCoord x, wxCoord y, DnDShape *shape)
1846 {
1847 ms_lastDropTarget = this;
1848
1849 wxPoint pt(x, y);
1850
1851 #if wxUSE_STATUSBAR
1852 wxString s;
1853 s.Printf("Shape dropped at (%d, %d)", pt.x, pt.y);
1854 SetStatusText(s);
1855 #endif // wxUSE_STATUSBAR
1856
1857 shape->Move(pt);
1858 SetShape(shape);
1859 }
1860
OnEditShape(wxCommandEvent & WXUNUSED (event))1861 void DnDShapeFrame::OnEditShape(wxCommandEvent& WXUNUSED(event))
1862 {
1863 DnDShapeDialog dlg(this, m_shape);
1864 if ( dlg.ShowModal() == wxID_OK )
1865 {
1866 SetShape(dlg.GetShape());
1867
1868 #if wxUSE_STATUSBAR
1869 if ( m_shape )
1870 {
1871 SetStatusText("You can now drag the shape to another frame");
1872 }
1873 #endif // wxUSE_STATUSBAR
1874 }
1875 }
1876
OnNewShape(wxCommandEvent & WXUNUSED (event))1877 void DnDShapeFrame::OnNewShape(wxCommandEvent& WXUNUSED(event))
1878 {
1879 SetShape(new DnDEllipticShape(wxPoint(10, 10), wxSize(80, 60), *wxRED));
1880
1881 #if wxUSE_STATUSBAR
1882 SetStatusText("You can now drag the shape to another frame");
1883 #endif // wxUSE_STATUSBAR
1884 }
1885
OnClearShape(wxCommandEvent & WXUNUSED (event))1886 void DnDShapeFrame::OnClearShape(wxCommandEvent& WXUNUSED(event))
1887 {
1888 SetShape(NULL);
1889 }
1890
OnCopyShape(wxCommandEvent & WXUNUSED (event))1891 void DnDShapeFrame::OnCopyShape(wxCommandEvent& WXUNUSED(event))
1892 {
1893 if ( m_shape )
1894 {
1895 wxClipboardLocker clipLocker;
1896 if ( !clipLocker )
1897 {
1898 wxLogError("Can't open the clipboard");
1899
1900 return;
1901 }
1902
1903 wxTheClipboard->AddData(new DnDShapeDataObject(m_shape));
1904 }
1905 }
1906
OnPasteShape(wxCommandEvent & WXUNUSED (event))1907 void DnDShapeFrame::OnPasteShape(wxCommandEvent& WXUNUSED(event))
1908 {
1909 wxClipboardLocker clipLocker;
1910 if ( !clipLocker )
1911 {
1912 wxLogError("Can't open the clipboard");
1913
1914 return;
1915 }
1916
1917 DnDShapeDataObject shapeDataObject(NULL);
1918 if ( wxTheClipboard->GetData(shapeDataObject) )
1919 {
1920 SetShape(shapeDataObject.GetShape());
1921 }
1922 else
1923 {
1924 wxLogStatus("No shape on the clipboard");
1925 }
1926 }
1927
OnUpdateUICopy(wxUpdateUIEvent & event)1928 void DnDShapeFrame::OnUpdateUICopy(wxUpdateUIEvent& event)
1929 {
1930 event.Enable( m_shape != NULL );
1931 }
1932
OnUpdateUIPaste(wxUpdateUIEvent & event)1933 void DnDShapeFrame::OnUpdateUIPaste(wxUpdateUIEvent& event)
1934 {
1935 event.Enable( wxTheClipboard->IsSupported(wxDataFormat(ShapeFormatId())) );
1936 }
1937
OnPaint(wxPaintEvent & event)1938 void DnDShapeFrame::OnPaint(wxPaintEvent& event)
1939 {
1940 if ( m_shape )
1941 {
1942 wxPaintDC dc(this);
1943
1944 m_shape->Draw(dc);
1945 }
1946 else
1947 {
1948 event.Skip();
1949 }
1950 }
1951
1952 // ----------------------------------------------------------------------------
1953 // DnDShape
1954 // ----------------------------------------------------------------------------
1955
New(const void * buf)1956 DnDShape *DnDShape::New(const void *buf)
1957 {
1958 const ShapeDump& dump = *(const ShapeDump *)buf;
1959 switch ( dump.k )
1960 {
1961 case Triangle:
1962 return new DnDTriangularShape(wxPoint(dump.x, dump.y),
1963 wxSize(dump.w, dump.h),
1964 wxColour(dump.r, dump.g, dump.b));
1965
1966 case Rectangle:
1967 return new DnDRectangularShape(wxPoint(dump.x, dump.y),
1968 wxSize(dump.w, dump.h),
1969 wxColour(dump.r, dump.g, dump.b));
1970
1971 case Ellipse:
1972 return new DnDEllipticShape(wxPoint(dump.x, dump.y),
1973 wxSize(dump.w, dump.h),
1974 wxColour(dump.r, dump.g, dump.b));
1975
1976 default:
1977 wxFAIL_MSG("invalid shape!");
1978 return NULL;
1979 }
1980 }
1981
1982 // ----------------------------------------------------------------------------
1983 // DnDShapeDataObject
1984 // ----------------------------------------------------------------------------
1985
1986 #if wxUSE_METAFILE
1987
CreateMetaFile() const1988 void DnDShapeDataObject::CreateMetaFile() const
1989 {
1990 wxPoint pos = m_shape->GetPosition();
1991 wxSize size = m_shape->GetSize();
1992
1993 wxMetaFileDC dcMF(wxEmptyString, pos.x + size.x, pos.y + size.y);
1994
1995 m_shape->Draw(dcMF);
1996
1997 wxMetafile *mf = dcMF.Close();
1998
1999 DnDShapeDataObject* self = const_cast<DnDShapeDataObject*>(this);
2000 self->m_dobjMetaFile.SetMetafile(*mf);
2001 self->m_hasMetaFile = true;
2002
2003 delete mf;
2004 }
2005
2006 #endif // wxUSE_METAFILE
2007
CreateBitmap() const2008 void DnDShapeDataObject::CreateBitmap() const
2009 {
2010 wxPoint pos = m_shape->GetPosition();
2011 wxSize size = m_shape->GetSize();
2012 int x = pos.x + size.x,
2013 y = pos.y + size.y;
2014 wxBitmap bitmap(x, y);
2015 wxMemoryDC dc;
2016 dc.SelectObject(bitmap);
2017 dc.SetBrush(*wxWHITE_BRUSH);
2018 dc.Clear();
2019 m_shape->Draw(dc);
2020 dc.SelectObject(wxNullBitmap);
2021
2022 DnDShapeDataObject* self = const_cast<DnDShapeDataObject*>(this);
2023 self->m_dobjBitmap.SetBitmap(bitmap);
2024 self->m_hasBitmap = true;
2025 }
2026
2027 #endif // wxUSE_DRAG_AND_DROP
2028
2029 // ----------------------------------------------------------------------------
2030 // global functions
2031 // ----------------------------------------------------------------------------
2032
ShowBitmap(const wxBitmap & bitmap)2033 static void ShowBitmap(const wxBitmap& bitmap)
2034 {
2035 wxFrame *frame = new wxFrame(NULL, wxID_ANY, "Bitmap view");
2036 #if wxUSE_STATUSBAR
2037 frame->CreateStatusBar();
2038 #endif // wxUSE_STATUSBAR
2039 DnDCanvasBitmap *canvas = new DnDCanvasBitmap(frame);
2040 canvas->SetBitmap(bitmap);
2041
2042 int w = bitmap.GetWidth(),
2043 h = bitmap.GetHeight();
2044 #if wxUSE_STATUSBAR
2045 frame->SetStatusText(wxString::Format("%dx%d", w, h));
2046 #endif // wxUSE_STATUSBAR
2047
2048 frame->SetClientSize(w > 100 ? 100 : w, h > 100 ? 100 : h);
2049 frame->Show(true);
2050 }
2051
2052 #if wxUSE_METAFILE
2053
ShowMetaFile(const wxMetaFile & metafile)2054 static void ShowMetaFile(const wxMetaFile& metafile)
2055 {
2056 wxFrame *frame = new wxFrame(NULL, wxID_ANY, "Metafile view");
2057 frame->CreateStatusBar();
2058 DnDCanvasMetafile *canvas = new DnDCanvasMetafile(frame);
2059 canvas->SetMetafile(metafile);
2060
2061 wxSize size = metafile.GetSize();
2062 frame->SetStatusText(wxString::Format("%dx%d", size.x, size.y));
2063
2064 frame->SetClientSize(size.x > 100 ? 100 : size.x,
2065 size.y > 100 ? 100 : size.y);
2066 frame->Show();
2067 }
2068
2069 #endif // wxUSE_METAFILE
2070
2071 #endif // wxUSE_DRAG_AND_DROP || wxUSE_CLIPBOARD
2072