]> git.saurik.com Git - wxWidgets.git/blame - samples/dnd/dnd.cpp
added an error message to wxCopyFile
[wxWidgets.git] / samples / dnd / dnd.cpp
CommitLineData
43d811ea 1/////////////////////////////////////////////////////////////////////////////
457814b5
JS
2// Name: dnd.cpp
3// Purpose: Drag and drop sample
4// Author: Vadim Zeitlin
43d811ea
JS
5// Modified by:
6// Created: 04/01/98
8bbe427f 7// RCS-ID: $Id$
43d811ea 8// Copyright:
8bbe427f 9// Licence: wxWindows licence
43d811ea
JS
10/////////////////////////////////////////////////////////////////////////////
11
c50f1fb9 12#include "wx/wxprec.h"
457814b5
JS
13
14#ifdef __BORLANDC__
15#pragma hdrstop
16#endif
17
18#ifndef WX_PRECOMP
c50f1fb9 19#include "wx/wx.h"
457814b5
JS
20#endif
21
8e193f38
VZ
22#if !wxUSE_DRAG_AND_DROP
23 #error This sample requires drag and drop support in the library
e2acb9ae
RR
24#endif
25
5a1c877f
VZ
26// under Windows we also support data transfer of metafiles as an extra bonus,
27// but they're not available under other platforms
28#ifdef __WINDOWS__
29 #define USE_METAFILES
30#endif // Windows
31
4693b20c
MB
32#define USE_RESOURCES 0
33#if !wxUSE_RESOURCES
34#undef USE_RESOURCES
35#define USE_RESOURCES 0
36#endif
37
c50f1fb9
VZ
38#include "wx/intl.h"
39#include "wx/log.h"
457814b5 40
c50f1fb9 41#include "wx/dnd.h"
956dbab1 42#include "wx/dirdlg.h"
e2acb9ae
RR
43#include "wx/filedlg.h"
44#include "wx/image.h"
45#include "wx/clipbrd.h"
8e193f38 46#include "wx/colordlg.h"
4693b20c
MB
47#if USE_RESOURCES
48 #include "wx/resource.h"
49#else
50 #include "wx/sizer.h"
51#endif
acbd13a3 52
5a1c877f
VZ
53#ifdef USE_METAFILES
54 #include "wx/metafile.h"
55#endif // Windows
56
fb7c3e57 57#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__)
c50f1fb9 58 #include "mondrian.xpm"
f6bcfd97
BP
59
60 #include "dnd_copy.xpm"
61 #include "dnd_move.xpm"
62 #include "dnd_none.xpm"
47908e25
RR
63#endif
64
457814b5 65// ----------------------------------------------------------------------------
2845ddc2 66// Derive two simple classes which just put in the listbox the strings (text or
457814b5
JS
67// file names) we drop on them
68// ----------------------------------------------------------------------------
ab8884ac 69
457814b5
JS
70class DnDText : public wxTextDropTarget
71{
72public:
c50f1fb9 73 DnDText(wxListBox *pOwner) { m_pOwner = pOwner; }
457814b5 74
9e2896e5 75 virtual bool OnDropText(wxCoord x, wxCoord y, const wxString& text);
457814b5
JS
76
77private:
c50f1fb9 78 wxListBox *m_pOwner;
457814b5
JS
79};
80
81class DnDFile : public wxFileDropTarget
82{
83public:
c50f1fb9 84 DnDFile(wxListBox *pOwner) { m_pOwner = pOwner; }
457814b5 85
9e2896e5
VZ
86 virtual bool OnDropFiles(wxCoord x, wxCoord y,
87 const wxArrayString& filenames);
457814b5
JS
88
89private:
c50f1fb9 90 wxListBox *m_pOwner;
457814b5
JS
91};
92
444ad3a7
VZ
93// ----------------------------------------------------------------------------
94// Define a custom dtop target accepting URLs
95// ----------------------------------------------------------------------------
96
4693b20c 97class URLDropTarget : public wxDropTarget
444ad3a7
VZ
98{
99public:
100 URLDropTarget() { SetDataObject(new wxURLDataObject); }
101
102 void OnDropURL(wxCoord x, wxCoord y, const wxString& text)
103 {
104 // of course, a real program would do something more useful here...
105 wxMessageBox(text, _T("wxDnD sample: got URL"),
106 wxICON_INFORMATION | wxOK);
107 }
108
109 // URLs can't be moved, only copied
110 virtual wxDragResult OnDragOver(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y),
111 wxDragResult def)
e6d318c2
RD
112 {
113 return wxDragLink; // At least IE 5.x needs wxDragLink, the
114 // other browsers on MSW seem okay with it too.
115 }
444ad3a7
VZ
116
117 // translate this to calls to OnDropURL() just for convenience
118 virtual wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult def)
119 {
120 if ( !GetData() )
121 return wxDragNone;
122
123 OnDropURL(x, y, ((wxURLDataObject *)m_dataObject)->GetURL());
124
125 return def;
126 }
127};
128
457814b5
JS
129// ----------------------------------------------------------------------------
130// Define a new application type
131// ----------------------------------------------------------------------------
ab8884ac 132
457814b5 133class DnDApp : public wxApp
8bbe427f 134{
457814b5 135public:
8e193f38 136 virtual bool OnInit();
457814b5
JS
137};
138
139IMPLEMENT_APP(DnDApp);
140
ae3dd4a5
VZ
141// ----------------------------------------------------------------------------
142// Define canvas class to show a bitmap
143// ----------------------------------------------------------------------------
144
145class DnDCanvasBitmap : public wxScrolledWindow
146{
147public:
148 DnDCanvasBitmap(wxWindow *parent) : wxScrolledWindow(parent) { }
149
150 void SetBitmap(const wxBitmap& bitmap)
151 {
152 m_bitmap = bitmap;
153
154 SetScrollbars(10, 10,
155 m_bitmap.GetWidth() / 10, m_bitmap.GetHeight() / 10);
156
157 Refresh();
158 }
159
160 void OnPaint(wxPaintEvent& event)
161 {
162 wxPaintDC dc(this);
163
164 if ( m_bitmap.Ok() )
165 {
166 PrepareDC(dc);
167
168 dc.DrawBitmap(m_bitmap, 0, 0);
169 }
170 }
171
172private:
173 wxBitmap m_bitmap;
174
175 DECLARE_EVENT_TABLE()
176};
177
178#ifdef USE_METAFILES
179
180// and the same thing fo metafiles
181class DnDCanvasMetafile : public wxScrolledWindow
182{
183public:
184 DnDCanvasMetafile(wxWindow *parent) : wxScrolledWindow(parent) { }
185
186 void SetMetafile(const wxMetafile& metafile)
187 {
188 m_metafile = metafile;
189
190 SetScrollbars(10, 10,
191 m_metafile.GetWidth() / 10, m_metafile.GetHeight() / 10);
192
193 Refresh();
194 }
195
196 void OnPaint(wxPaintEvent& event)
197 {
198 wxPaintDC dc(this);
199
200 if ( m_metafile.Ok() )
201 {
202 PrepareDC(dc);
203
204 m_metafile.Play(&dc);
205 }
206 }
207
208private:
209 wxMetafile m_metafile;
210
211 DECLARE_EVENT_TABLE()
212};
213
214#endif // USE_METAFILES
215
457814b5 216// ----------------------------------------------------------------------------
8e193f38 217// Define a new frame type for the main frame
457814b5 218// ----------------------------------------------------------------------------
8e193f38 219
457814b5 220class DnDFrame : public wxFrame
8bbe427f 221{
457814b5 222public:
c50f1fb9
VZ
223 DnDFrame(wxFrame *frame, char *title, int x, int y, int w, int h);
224 ~DnDFrame();
457814b5 225
c50f1fb9 226 void OnPaint(wxPaintEvent& event);
fcf689db 227 void OnSize(wxSizeEvent& event);
c50f1fb9
VZ
228 void OnQuit (wxCommandEvent& event);
229 void OnAbout(wxCommandEvent& event);
230 void OnDrag (wxCommandEvent& event);
8e193f38 231 void OnNewFrame(wxCommandEvent& event);
c50f1fb9
VZ
232 void OnHelp (wxCommandEvent& event);
233 void OnLogClear(wxCommandEvent& event);
51edda6a 234
c50f1fb9
VZ
235 void OnCopy(wxCommandEvent& event);
236 void OnPaste(wxCommandEvent& event);
51edda6a 237
e2acb9ae
RR
238 void OnCopyBitmap(wxCommandEvent& event);
239 void OnPasteBitmap(wxCommandEvent& event);
43d811ea 240
5a1c877f
VZ
241#ifdef USE_METAFILES
242 void OnPasteMetafile(wxCommandEvent& event);
243#endif // USE_METAFILES
244
51edda6a
VZ
245 void OnCopyFiles(wxCommandEvent& event);
246
c50f1fb9
VZ
247 void OnLeftDown(wxMouseEvent& event);
248 void OnRightDown(wxMouseEvent& event);
8bbe427f 249
d59ceba5
VZ
250 void OnUpdateUIPasteText(wxUpdateUIEvent& event);
251 void OnUpdateUIPasteBitmap(wxUpdateUIEvent& event);
252
c50f1fb9 253 DECLARE_EVENT_TABLE()
457814b5
JS
254
255private:
e2acb9ae 256 wxListBox *m_ctrlFile,
90e12284 257 *m_ctrlText;
e2acb9ae 258 wxTextCtrl *m_ctrlLog;
457814b5 259
90e12284
VZ
260 wxLog *m_pLog,
261 *m_pLogPrev;
43d811ea 262
e2acb9ae 263 wxString m_strText;
457814b5
JS
264};
265
8e193f38
VZ
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// ----------------------------------------------------------------------------
271
272class DnDShape
273{
274public:
275 enum Kind
276 {
277 None,
278 Triangle,
279 Rectangle,
280 Ellipse
281 };
282
283 DnDShape(const wxPoint& pos,
284 const wxSize& size,
285 const wxColour& col)
286 : m_pos(pos), m_size(size), m_col(col)
287 {
288 }
289
9e2896e5
VZ
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() { }
293
8e193f38 294 // the functions used for drag-and-drop: they dump and restore a shape into
d59ceba5 295 // some bitwise-copiable data (might use streams too...)
8e193f38
VZ
296 // ------------------------------------------------------------------------
297
298 // restore from buffer
299 static DnDShape *New(const void *buf);
300
301 virtual size_t GetDataSize() const
302 {
303 return sizeof(ShapeDump);
304 }
305
306 virtual void GetDataHere(void *buf) const
307 {
308 ShapeDump& dump = *(ShapeDump *)buf;
309 dump.x = m_pos.x;
310 dump.y = m_pos.y;
311 dump.w = m_size.x;
312 dump.h = m_size.y;
313 dump.r = m_col.Red();
314 dump.g = m_col.Green();
315 dump.b = m_col.Blue();
316 dump.k = GetKind();
317 }
318
319 // accessors
320 const wxPoint& GetPosition() const { return m_pos; }
321 const wxColour& GetColour() const { return m_col; }
322 const wxSize& GetSize() const { return m_size; }
323
d59ceba5
VZ
324 void Move(const wxPoint& pos) { m_pos = pos; }
325
8e193f38
VZ
326 // to implement in derived classes
327 virtual Kind GetKind() const = 0;
328
1dd989e1 329 virtual void Draw(wxDC& dc)
8e193f38
VZ
330 {
331 dc.SetPen(wxPen(m_col, 1, wxSOLID));
332 }
333
334protected:
335 wxPoint GetCentre() const
336 { return wxPoint(m_pos.x + m_size.x / 2, m_pos.y + m_size.y / 2); }
337
338 struct ShapeDump
339 {
340 int x, y, // position
341 w, h, // size
342 r, g, b, // colour
343 k; // kind
344 };
345
346 wxPoint m_pos;
347 wxSize m_size;
348 wxColour m_col;
349};
350
351class DnDTriangularShape : public DnDShape
352{
353public:
354 DnDTriangularShape(const wxPoint& pos,
355 const wxSize& size,
356 const wxColour& col)
357 : DnDShape(pos, size, col)
358 {
4693b20c 359 wxLogMessage(wxT("DnDTriangularShape is being created"));
8e193f38
VZ
360 }
361
9e2896e5
VZ
362 virtual ~DnDTriangularShape()
363 {
4693b20c 364 wxLogMessage(wxT("DnDTriangularShape is being deleted"));
9e2896e5
VZ
365 }
366
8e193f38
VZ
367 virtual Kind GetKind() const { return Triangle; }
368 virtual void Draw(wxDC& dc)
369 {
370 DnDShape::Draw(dc);
371
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? ;-)
374 wxPoint p1(m_pos);
375 wxPoint p2(m_pos.x + m_size.x, m_pos.y);
376 wxPoint p3(m_pos.x, m_pos.y + m_size.y);
377
378 dc.DrawLine(p1, p2);
379 dc.DrawLine(p2, p3);
380 dc.DrawLine(p3, p1);
381
1dd989e1 382#ifdef __WXMSW__
8e193f38 383 dc.FloodFill(GetCentre(), m_col, wxFLOOD_BORDER);
1dd989e1 384#endif
8e193f38
VZ
385 }
386};
387
388class DnDRectangularShape : public DnDShape
389{
390public:
391 DnDRectangularShape(const wxPoint& pos,
392 const wxSize& size,
393 const wxColour& col)
394 : DnDShape(pos, size, col)
395 {
4693b20c 396 wxLogMessage(wxT("DnDRectangularShape is being created"));
8e193f38
VZ
397 }
398
9e2896e5
VZ
399 virtual ~DnDRectangularShape()
400 {
4693b20c 401 wxLogMessage(wxT("DnDRectangularShape is being deleted"));
9e2896e5
VZ
402 }
403
8e193f38
VZ
404 virtual Kind GetKind() const { return Rectangle; }
405 virtual void Draw(wxDC& dc)
406 {
407 DnDShape::Draw(dc);
408
409 wxPoint p1(m_pos);
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);
413
414 dc.DrawLine(p1, p2);
415 dc.DrawLine(p2, p3);
416 dc.DrawLine(p3, p4);
417 dc.DrawLine(p4, p1);
418
1dd989e1 419#ifdef __WXMSW__
8e193f38 420 dc.FloodFill(GetCentre(), m_col, wxFLOOD_BORDER);
1dd989e1 421#endif
8e193f38
VZ
422 }
423};
424
425class DnDEllipticShape : public DnDShape
426{
427public:
428 DnDEllipticShape(const wxPoint& pos,
429 const wxSize& size,
430 const wxColour& col)
431 : DnDShape(pos, size, col)
432 {
4693b20c 433 wxLogMessage(wxT("DnDEllipticShape is being created"));
8e193f38
VZ
434 }
435
9e2896e5
VZ
436 virtual ~DnDEllipticShape()
437 {
4693b20c 438 wxLogMessage(wxT("DnDEllipticShape is being deleted"));
9e2896e5
VZ
439 }
440
8e193f38
VZ
441 virtual Kind GetKind() const { return Ellipse; }
442 virtual void Draw(wxDC& dc)
443 {
444 DnDShape::Draw(dc);
445
446 dc.DrawEllipse(m_pos, m_size);
447
1dd989e1 448#ifdef __WXMSW__
8e193f38 449 dc.FloodFill(GetCentre(), m_col, wxFLOOD_BORDER);
1dd989e1 450#endif
8e193f38
VZ
451 }
452};
453
454// ----------------------------------------------------------------------------
455// A wxDataObject specialisation for the application-specific data
456// ----------------------------------------------------------------------------
457
4693b20c 458static const wxChar *shapeFormatId = wxT("wxShape");
8e193f38
VZ
459
460class DnDShapeDataObject : public wxDataObject
461{
462public:
463 // ctor doesn't copy the pointer, so it shouldn't go away while this object
464 // is alive
9e2896e5 465 DnDShapeDataObject(DnDShape *shape = (DnDShape *)NULL)
8e193f38 466 {
9e2896e5
VZ
467 if ( shape )
468 {
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);
475
476 free(buf);
477 }
478 else
479 {
480 // nothing to copy
481 m_shape = NULL;
482 }
8e193f38
VZ
483
484 // this string should uniquely identify our format, but is otherwise
485 // arbitrary
486 m_formatShape.SetId(shapeFormatId);
487
488 // we don't draw the shape to a bitmap until it's really needed (i.e.
489 // we're asked to do so)
490 m_hasBitmap = FALSE;
5a1c877f
VZ
491#ifdef USE_METAFILES
492 m_hasMetaFile = FALSE;
493#endif // Windows
8e193f38
VZ
494 }
495
9e2896e5
VZ
496 virtual ~DnDShapeDataObject() { delete m_shape; }
497
90e12284
VZ
498 // after a call to this function, the shape is owned by the caller and it
499 // is responsible for deleting it!
500 //
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
504 DnDShape *GetShape()
505 {
506 DnDShape *shape = m_shape;
507
508 m_shape = (DnDShape *)NULL;
509 m_hasBitmap = FALSE;
5a1c877f
VZ
510#ifdef USE_METAFILES
511 m_hasMetaFile = FALSE;
512#endif // Windows
90e12284
VZ
513
514 return shape;
515 }
d59ceba5 516
8e193f38
VZ
517 // implement base class pure virtuals
518 // ----------------------------------
519
9e2896e5 520 virtual wxDataFormat GetPreferredFormat(Direction WXUNUSED(dir)) const
8e193f38
VZ
521 {
522 return m_formatShape;
523 }
524
9e2896e5 525 virtual size_t GetFormatCount(Direction dir) const
8e193f38 526 {
d59ceba5
VZ
527 // our custom format is supported by both GetData() and SetData()
528 size_t nFormats = 1;
9e2896e5 529 if ( dir == Get )
d59ceba5
VZ
530 {
531 // but the bitmap format(s) are only supported for output
5a1c877f
VZ
532 nFormats += m_dobjBitmap.GetFormatCount(dir);
533
534#ifdef USE_METAFILES
535 nFormats += m_dobjMetaFile.GetFormatCount(dir);
536#endif // Windows
d59ceba5
VZ
537 }
538
539 return nFormats;
8e193f38
VZ
540 }
541
9e2896e5 542 virtual void GetAllFormats(wxDataFormat *formats, Direction dir) const
8e193f38
VZ
543 {
544 formats[0] = m_formatShape;
9e2896e5 545 if ( dir == Get )
d59ceba5 546 {
5a1c877f
VZ
547 // in Get direction we additionally support bitmaps and metafiles
548 // under Windows
549 m_dobjBitmap.GetAllFormats(&formats[1], dir);
550
551#ifdef USE_METAFILES
552 // don't assume that m_dobjBitmap has only 1 format
553 m_dobjMetaFile.GetAllFormats(&formats[1 +
554 m_dobjBitmap.GetFormatCount(dir)], dir);
555#endif // Windows
d59ceba5 556 }
8e193f38
VZ
557 }
558
559 virtual size_t GetDataSize(const wxDataFormat& format) const
560 {
561 if ( format == m_formatShape )
562 {
563 return m_shape->GetDataSize();
564 }
5a1c877f 565#ifdef USE_METAFILES
ae3dd4a5 566 else if ( m_dobjMetaFile.IsSupported(format) )
5a1c877f
VZ
567 {
568 if ( !m_hasMetaFile )
569 CreateMetaFile();
570
ae3dd4a5 571 return m_dobjMetaFile.GetDataSize(format);
5a1c877f
VZ
572 }
573#endif // Windows
8e193f38
VZ
574 else
575 {
ae3dd4a5 576 wxASSERT_MSG( m_dobjBitmap.IsSupported(format),
4693b20c 577 wxT("unexpected format") );
ae3dd4a5 578
8e193f38
VZ
579 if ( !m_hasBitmap )
580 CreateBitmap();
581
5a1c877f 582 return m_dobjBitmap.GetDataSize();
8e193f38
VZ
583 }
584 }
585
d59ceba5 586 virtual bool GetDataHere(const wxDataFormat& format, void *pBuf) const
8e193f38
VZ
587 {
588 if ( format == m_formatShape )
589 {
590 m_shape->GetDataHere(pBuf);
d59ceba5
VZ
591
592 return TRUE;
8e193f38 593 }
5a1c877f 594#ifdef USE_METAFILES
ae3dd4a5 595 else if ( m_dobjMetaFile.IsSupported(format) )
5a1c877f
VZ
596 {
597 if ( !m_hasMetaFile )
598 CreateMetaFile();
599
ae3dd4a5 600 return m_dobjMetaFile.GetDataHere(format, pBuf);
5a1c877f
VZ
601 }
602#endif // Windows
8e193f38
VZ
603 else
604 {
ae3dd4a5 605 wxASSERT_MSG( m_dobjBitmap.IsSupported(format),
4693b20c 606 wxT("unexpected format") );
ae3dd4a5 607
8e193f38
VZ
608 if ( !m_hasBitmap )
609 CreateBitmap();
610
5a1c877f 611 return m_dobjBitmap.GetDataHere(pBuf);
8e193f38
VZ
612 }
613 }
614
9e2896e5
VZ
615 virtual bool SetData(const wxDataFormat& format,
616 size_t len, const void *buf)
d59ceba5 617 {
4693b20c
MB
618 wxCHECK_MSG( format == m_formatShape, FALSE,
619 wxT( "unsupported format") );
d59ceba5
VZ
620
621 delete m_shape;
622 m_shape = DnDShape::New(buf);
623
624 // the shape has changed
625 m_hasBitmap = FALSE;
626
5a1c877f
VZ
627#ifdef USE_METAFILES
628 m_hasMetaFile = FALSE;
629#endif // Windows
630
d59ceba5
VZ
631 return TRUE;
632 }
633
8e193f38 634private:
5a1c877f 635 // creates a bitmap and assigns it to m_dobjBitmap (also sets m_hasBitmap)
8e193f38 636 void CreateBitmap() const;
5a1c877f
VZ
637#ifdef USE_METAFILES
638 void CreateMetaFile() const;
639#endif // Windows
8e193f38
VZ
640
641 wxDataFormat m_formatShape; // our custom format
642
5a1c877f
VZ
643 wxBitmapDataObject m_dobjBitmap; // it handles bitmaps
644 bool m_hasBitmap; // true if m_dobjBitmap has valid bitmap
645
646#ifdef USE_METAFILES
647 wxMetaFileDataObject m_dobjMetaFile;// handles metafiles
648 bool m_hasMetaFile; // true if we have valid metafile
649#endif // Windows
8e193f38
VZ
650
651 DnDShape *m_shape; // our data
652};
653
654// ----------------------------------------------------------------------------
655// A dialog to edit shape properties
656// ----------------------------------------------------------------------------
657
658class DnDShapeDialog : public wxDialog
659{
660public:
661 DnDShapeDialog(wxFrame *parent, DnDShape *shape);
662
663 DnDShape *GetShape() const;
664
665 virtual bool TransferDataToWindow();
666 virtual bool TransferDataFromWindow();
667
668 void OnColour(wxCommandEvent& event);
669
670private:
671 // input
672 DnDShape *m_shape;
673
674 // output
675 DnDShape::Kind m_shapeKind;
676 wxPoint m_pos;
677 wxSize m_size;
678 wxColour m_col;
679
680 // controls
681 wxRadioBox *m_radio;
682 wxTextCtrl *m_textX,
683 *m_textY,
684 *m_textW,
685 *m_textH;
686
687 DECLARE_EVENT_TABLE()
688};
689
690// ----------------------------------------------------------------------------
691// A frame for the shapes which can be drag-and-dropped between frames
692// ----------------------------------------------------------------------------
693
694class DnDShapeFrame : public wxFrame
695{
696public:
697 DnDShapeFrame(wxFrame *parent);
698 ~DnDShapeFrame();
699
700 void SetShape(DnDShape *shape);
701
702 // callbacks
d59ceba5
VZ
703 void OnNewShape(wxCommandEvent& event);
704 void OnEditShape(wxCommandEvent& event);
705 void OnClearShape(wxCommandEvent& event);
706
707 void OnCopyShape(wxCommandEvent& event);
708 void OnPasteShape(wxCommandEvent& event);
709
710 void OnUpdateUICopy(wxUpdateUIEvent& event);
711 void OnUpdateUIPaste(wxUpdateUIEvent& event);
712
8e193f38 713 void OnDrag(wxMouseEvent& event);
8e193f38 714 void OnPaint(wxPaintEvent& event);
90e12284 715 void OnDrop(wxCoord x, wxCoord y, DnDShape *shape);
8e193f38
VZ
716
717private:
718 DnDShape *m_shape;
719
d59ceba5
VZ
720 static DnDShapeFrame *ms_lastDropTarget;
721
8e193f38
VZ
722 DECLARE_EVENT_TABLE()
723};
724
725// ----------------------------------------------------------------------------
726// wxDropTarget derivation for DnDShapes
727// ----------------------------------------------------------------------------
728
729class DnDShapeDropTarget : public wxDropTarget
730{
731public:
732 DnDShapeDropTarget(DnDShapeFrame *frame)
9e2896e5 733 : wxDropTarget(new DnDShapeDataObject)
8e193f38
VZ
734 {
735 m_frame = frame;
8e193f38
VZ
736 }
737
738 // override base class (pure) virtuals
72a7edf0 739 virtual wxDragResult OnEnter(wxCoord x, wxCoord y, wxDragResult def)
5a1c877f 740 { m_frame->SetStatusText("Mouse entered the frame"); return OnDragOver(x, y, def); }
8e193f38
VZ
741 virtual void OnLeave()
742 { m_frame->SetStatusText("Mouse left the frame"); }
8ee9d618 743 virtual wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult def)
8e193f38 744 {
9e2896e5
VZ
745 if ( !GetData() )
746 {
4693b20c 747 wxLogError(wxT("Failed to get drag and drop data"));
9e2896e5 748
8ee9d618 749 return wxDragNone;
9e2896e5
VZ
750 }
751
752 m_frame->OnDrop(x, y,
753 ((DnDShapeDataObject *)GetDataObject())->GetShape());
8e193f38 754
8ee9d618 755 return def;
8e193f38
VZ
756 }
757
8e193f38
VZ
758private:
759 DnDShapeFrame *m_frame;
8e193f38
VZ
760};
761
ae3dd4a5
VZ
762// ----------------------------------------------------------------------------
763// functions prototypes
764// ----------------------------------------------------------------------------
765
766static void ShowBitmap(const wxBitmap& bitmap);
767
768#ifdef USE_METAFILES
769static void ShowMetaFile(const wxMetaFile& metafile);
770#endif // USE_METAFILES
771
457814b5
JS
772// ----------------------------------------------------------------------------
773// IDs for the menu commands
774// ----------------------------------------------------------------------------
ab8884ac 775
457814b5
JS
776enum
777{
c50f1fb9
VZ
778 Menu_Quit = 1,
779 Menu_Drag,
8e193f38 780 Menu_NewFrame,
c50f1fb9
VZ
781 Menu_About = 101,
782 Menu_Help,
783 Menu_Clear,
784 Menu_Copy,
e2acb9ae
RR
785 Menu_Paste,
786 Menu_CopyBitmap,
787 Menu_PasteBitmap,
5a1c877f 788 Menu_PasteMFile,
51edda6a 789 Menu_CopyFiles,
d59ceba5
VZ
790 Menu_Shape_New = 500,
791 Menu_Shape_Edit,
792 Menu_Shape_Clear,
793 Menu_ShapeClipboard_Copy,
794 Menu_ShapeClipboard_Paste,
8e193f38 795 Button_Colour = 1001
457814b5
JS
796};
797
798BEGIN_EVENT_TABLE(DnDFrame, wxFrame)
e2acb9ae
RR
799 EVT_MENU(Menu_Quit, DnDFrame::OnQuit)
800 EVT_MENU(Menu_About, DnDFrame::OnAbout)
801 EVT_MENU(Menu_Drag, DnDFrame::OnDrag)
8e193f38 802 EVT_MENU(Menu_NewFrame, DnDFrame::OnNewFrame)
e2acb9ae
RR
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)
5a1c877f
VZ
809#ifdef USE_METAFILES
810 EVT_MENU(Menu_PasteMFile, DnDFrame::OnPasteMetafile)
811#endif // USE_METAFILES
51edda6a 812 EVT_MENU(Menu_CopyFiles, DnDFrame::OnCopyFiles)
d59ceba5
VZ
813
814 EVT_UPDATE_UI(Menu_Paste, DnDFrame::OnUpdateUIPasteText)
815 EVT_UPDATE_UI(Menu_PasteBitmap, DnDFrame::OnUpdateUIPasteBitmap)
e2acb9ae
RR
816
817 EVT_LEFT_DOWN( DnDFrame::OnLeftDown)
818 EVT_RIGHT_DOWN( DnDFrame::OnRightDown)
819 EVT_PAINT( DnDFrame::OnPaint)
fcf689db 820 EVT_SIZE( DnDFrame::OnSize)
457814b5
JS
821END_EVENT_TABLE()
822
8e193f38 823BEGIN_EVENT_TABLE(DnDShapeFrame, wxFrame)
d59ceba5
VZ
824 EVT_MENU(Menu_Shape_New, DnDShapeFrame::OnNewShape)
825 EVT_MENU(Menu_Shape_Edit, DnDShapeFrame::OnEditShape)
826 EVT_MENU(Menu_Shape_Clear, DnDShapeFrame::OnClearShape)
827
828 EVT_MENU(Menu_ShapeClipboard_Copy, DnDShapeFrame::OnCopyShape)
829 EVT_MENU(Menu_ShapeClipboard_Paste, DnDShapeFrame::OnPasteShape)
830
831 EVT_UPDATE_UI(Menu_ShapeClipboard_Copy, DnDShapeFrame::OnUpdateUICopy)
832 EVT_UPDATE_UI(Menu_ShapeClipboard_Paste, DnDShapeFrame::OnUpdateUIPaste)
833
834 EVT_LEFT_DOWN(DnDShapeFrame::OnDrag)
835
8e193f38
VZ
836 EVT_PAINT(DnDShapeFrame::OnPaint)
837END_EVENT_TABLE()
838
839BEGIN_EVENT_TABLE(DnDShapeDialog, wxDialog)
b0a6c154 840 EVT_BUTTON(Button_Colour, DnDShapeDialog::OnColour)
8e193f38
VZ
841END_EVENT_TABLE()
842
ae3dd4a5
VZ
843BEGIN_EVENT_TABLE(DnDCanvasBitmap, wxScrolledWindow)
844 EVT_PAINT(DnDCanvasBitmap::OnPaint)
845END_EVENT_TABLE()
846
847#ifdef USE_METAFILES
848BEGIN_EVENT_TABLE(DnDCanvasMetafile, wxScrolledWindow)
849 EVT_PAINT(DnDCanvasMetafile::OnPaint)
850END_EVENT_TABLE()
851#endif // USE_METAFILES
852
8e193f38
VZ
853// ============================================================================
854// implementation
855// ============================================================================
856
857// `Main program' equivalent, creating windows and returning main app frame
8bbe427f 858bool DnDApp::OnInit()
457814b5 859{
4693b20c 860#if USE_RESOURCES
ae125753
VZ
861 // load our ressources
862 wxPathList pathList;
863 pathList.Add(".");
864#ifdef __WXMSW__
865 pathList.Add("./Debug");
866 pathList.Add("./Release");
867#endif // wxMSW
868
869 wxString path = pathList.FindValidPath("dnd.wxr");
870 if ( !path )
871 {
4693b20c
MB
872 wxLogError(wxT("Can't find the resource file dnd.wxr in the current ")
873 wxT("directory, aborting."));
ae125753
VZ
874
875 return FALSE;
876 }
877
878 wxDefaultResourceTable->ParseResourceFile(path);
4693b20c 879#endif
ae125753 880
61b04ac6
VZ
881 // switch on trace messages
882#if defined(__WXGTK__)
883 wxLog::AddTraceMask(_T("clipboard"));
884#elif defined(__WXMSW__)
885 wxLog::AddTraceMask(wxTRACE_OleCalls);
886#endif
887
e2acb9ae
RR
888#if wxUSE_LIBPNG
889 wxImage::AddHandler( new wxPNGHandler );
890#endif
891
74d38ad8
VZ
892 // under X we usually want to use the primary selection by default (which
893 // is shared with other apps)
894 wxTheClipboard->UsePrimarySelection();
895
c50f1fb9
VZ
896 // create the main frame window
897 DnDFrame *frame = new DnDFrame((wxFrame *) NULL,
898 "Drag-and-Drop/Clipboard wxWindows Sample",
5a1c877f 899 10, 100, 650, 340);
457814b5 900
c50f1fb9
VZ
901 // activate it
902 frame->Show(TRUE);
457814b5 903
c50f1fb9 904 SetTopWindow(frame);
457814b5 905
c50f1fb9 906 return TRUE;
457814b5
JS
907}
908
909DnDFrame::DnDFrame(wxFrame *frame, char *title, int x, int y, int w, int h)
43d811ea
JS
910 : wxFrame(frame, -1, title, wxPoint(x, y), wxSize(w, h)),
911 m_strText("wxWindows drag & drop works :-)")
912
457814b5 913{
c50f1fb9
VZ
914 // frame icon and status bar
915 SetIcon(wxICON(mondrian));
916
917 CreateStatusBar();
918
919 // construct menu
920 wxMenu *file_menu = new wxMenu;
921 file_menu->Append(Menu_Drag, "&Test drag...");
922 file_menu->AppendSeparator();
8e193f38 923 file_menu->Append(Menu_NewFrame, "&New frame\tCtrl-N");
d1b15f03 924 file_menu->AppendSeparator();
8e193f38 925 file_menu->Append(Menu_Quit, "E&xit");
c50f1fb9
VZ
926
927 wxMenu *log_menu = new wxMenu;
810b5e1f 928 log_menu->Append(Menu_Clear, "Clear\tCtrl-L");
c50f1fb9
VZ
929
930 wxMenu *help_menu = new wxMenu;
931 help_menu->Append(Menu_Help, "&Help...");
932 help_menu->AppendSeparator();
933 help_menu->Append(Menu_About, "&About");
934
935 wxMenu *clip_menu = new wxMenu;
58a9336b
VZ
936 clip_menu->Append(Menu_Copy, "&Copy text\tCtrl-C");
937 clip_menu->Append(Menu_Paste, "&Paste text\tCtrl-V");
e2acb9ae 938 clip_menu->AppendSeparator();
58a9336b
VZ
939 clip_menu->Append(Menu_CopyBitmap, "Copy &bitmap\tCtrl-Shift-C");
940 clip_menu->Append(Menu_PasteBitmap, "Paste b&itmap\tCtrl-Shift-V");
5a1c877f 941#ifdef USE_METAFILES
51edda6a 942 clip_menu->AppendSeparator();
5a1c877f
VZ
943 clip_menu->Append(Menu_PasteMFile, "Paste &metafile\tCtrl-M");
944#endif // USE_METAFILES
945 clip_menu->AppendSeparator();
58a9336b 946 clip_menu->Append(Menu_CopyFiles, "Copy &files\tCtrl-F");
8e193f38 947
c50f1fb9
VZ
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");
953
954 SetMenuBar(menu_bar);
955
956 // make a panel with 3 subwindows
957 wxPoint pos(0, 0);
958 wxSize size(400, 200);
959
960 wxString strFile("Drop files here!"), strText("Drop text on me");
961
d59ceba5
VZ
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 );
c50f1fb9
VZ
966
967 m_ctrlLog = new wxTextCtrl(this, -1, "", pos, size,
d59ceba5
VZ
968 wxTE_MULTILINE | wxTE_READONLY |
969 wxSUNKEN_BORDER );
8e193f38 970
61b04ac6 971 // redirect log messages to the text window
e2acb9ae
RR
972 m_pLog = new wxLogTextCtrl(m_ctrlLog);
973 m_pLogPrev = wxLog::SetActiveTarget(m_pLog);
974
444ad3a7 975 // associate drop targets with the controls
e2acb9ae
RR
976 m_ctrlFile->SetDropTarget(new DnDFile(m_ctrlFile));
977 m_ctrlText->SetDropTarget(new DnDText(m_ctrlText));
444ad3a7 978 m_ctrlLog->SetDropTarget(new URLDropTarget);
e2acb9ae
RR
979
980 wxLayoutConstraints *c;
981
982 // Top-left listbox
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);
989
990 // Top-right listbox
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);
997
998 // Lower text control
999 c = new wxLayoutConstraints;
1000 c->left.SameAs (this, wxLeft);
1001 c->right.SameAs (this, wxRight);
d59ceba5 1002 c->height.PercentOf(this, wxHeight, 50);
e2acb9ae
RR
1003 c->top.SameAs(m_ctrlText, wxBottom);
1004 m_ctrlLog->SetConstraints(c);
1005
1006 SetAutoLayout(TRUE);
457814b5
JS
1007}
1008
e2acb9ae 1009void DnDFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
457814b5 1010{
c50f1fb9 1011 Close(TRUE);
457814b5
JS
1012}
1013
fcf689db
VZ
1014void DnDFrame::OnSize(wxSizeEvent& event)
1015{
1016 Refresh();
1017
1018 event.Skip();
1019}
1020
e2acb9ae 1021void DnDFrame::OnPaint(wxPaintEvent& WXUNUSED(event))
b527aac5 1022{
c50f1fb9
VZ
1023 int w = 0;
1024 int h = 0;
1025 GetClientSize( &w, &h );
8bbe427f 1026
c50f1fb9 1027 wxPaintDC dc(this);
fcf689db 1028 dc.Clear();
c50f1fb9 1029 dc.SetFont( wxFont( 24, wxDECORATIVE, wxNORMAL, wxNORMAL, FALSE, "charter" ) );
ae3dd4a5 1030 dc.DrawText( "Drag text from here!", 100, h-50 );
e2acb9ae
RR
1031}
1032
d59ceba5 1033void DnDFrame::OnUpdateUIPasteText(wxUpdateUIEvent& event)
e2acb9ae 1034{
61b04ac6
VZ
1035#ifdef __WXDEBUG__
1036 // too many trace messages if we don't do it - this function is called
1037 // very often
1038 wxLogNull nolog;
1039#endif
1040
d59ceba5
VZ
1041 event.Enable( wxTheClipboard->IsSupported(wxDF_TEXT) );
1042}
e2acb9ae 1043
d59ceba5
VZ
1044void DnDFrame::OnUpdateUIPasteBitmap(wxUpdateUIEvent& event)
1045{
61b04ac6
VZ
1046#ifdef __WXDEBUG__
1047 // too many trace messages if we don't do it - this function is called
1048 // very often
1049 wxLogNull nolog;
1050#endif
1051
d59ceba5 1052 event.Enable( wxTheClipboard->IsSupported(wxDF_BITMAP) );
e2acb9ae
RR
1053}
1054
8e193f38
VZ
1055void DnDFrame::OnNewFrame(wxCommandEvent& WXUNUSED(event))
1056{
1057 (new DnDShapeFrame(this))->Show(TRUE);
1058
4693b20c 1059 wxLogStatus(this, wxT("Double click the new frame to select a shape for it"));
8e193f38
VZ
1060}
1061
e2acb9ae 1062void DnDFrame::OnDrag(wxCommandEvent& WXUNUSED(event))
43d811ea 1063{
c50f1fb9
VZ
1064 wxString strText = wxGetTextFromUser
1065 (
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
1071 );
1072
1073 m_strText = strText;
43d811ea
JS
1074}
1075
e2acb9ae 1076void DnDFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
457814b5 1077{
c50f1fb9
VZ
1078 wxMessageBox("Drag-&-Drop Demo\n"
1079 "Please see \"Help|Help...\" for details\n"
1080 "Copyright (c) 1998 Vadim Zeitlin",
1081 "About wxDnD",
1082 wxICON_INFORMATION | wxOK,
1083 this);
457814b5
JS
1084}
1085
1086void DnDFrame::OnHelp(wxCommandEvent& /* event */)
1087{
c50f1fb9
VZ
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"
1093 "\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"
1099 "\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"
1105 "\n"
1106 "\n"
1107 "Please send all questions/bug reports/suggestions &c to \n"
1108 "Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>",
1109 "wxDnD Help");
1110
1111 dialog.ShowModal();
457814b5
JS
1112}
1113
e3e65dac 1114void DnDFrame::OnLogClear(wxCommandEvent& /* event */ )
43d811ea 1115{
c50f1fb9 1116 m_ctrlLog->Clear();
810b5e1f
VZ
1117 m_ctrlText->Clear();
1118 m_ctrlFile->Clear();
43d811ea
JS
1119}
1120
30dea054 1121void DnDFrame::OnLeftDown(wxMouseEvent &WXUNUSED(event) )
43d811ea 1122{
8e193f38 1123 if ( !m_strText.IsEmpty() )
c50f1fb9
VZ
1124 {
1125 // start drag operation
c50f1fb9 1126 wxTextDataObject textData(m_strText);
2d68e1b4
RR
1127/*
1128 wxFileDataObject textData;
810b5e1f
VZ
1129 textData.AddFile( "/file1.txt" );
1130 textData.AddFile( "/file2.txt" );
2d68e1b4 1131*/
f6bcfd97
BP
1132 wxDropSource source(textData, this,
1133 wxDROP_ICON(dnd_copy),
1134 wxDROP_ICON(dnd_move),
1135 wxDROP_ICON(dnd_none));
8e193f38 1136
c50f1fb9
VZ
1137 const char *pc;
1138
8e193f38 1139 switch ( source.DoDragDrop(TRUE) )
c50f1fb9
VZ
1140 {
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;
1147 }
1148
1149 SetStatusText(wxString("Drag result: ") + pc);
43d811ea 1150 }
43d811ea
JS
1151}
1152
30dea054
RR
1153void DnDFrame::OnRightDown(wxMouseEvent &event )
1154{
51edda6a 1155 wxMenu menu("Dnd sample menu");
8bbe427f 1156
51edda6a
VZ
1157 menu.Append(Menu_Drag, "&Test drag...");
1158 menu.AppendSeparator();
1159 menu.Append(Menu_About, "&About");
8e193f38 1160
51edda6a 1161 PopupMenu( &menu, event.GetX(), event.GetY() );
30dea054
RR
1162}
1163
457814b5
JS
1164DnDFrame::~DnDFrame()
1165{
c50f1fb9
VZ
1166 if ( m_pLog != NULL ) {
1167 if ( wxLog::SetActiveTarget(m_pLogPrev) == m_pLog )
1168 delete m_pLog;
1169 }
1170}
1171
1172// ---------------------------------------------------------------------------
e2acb9ae
RR
1173// bitmap clipboard
1174// ---------------------------------------------------------------------------
1175
1176void DnDFrame::OnCopyBitmap(wxCommandEvent& WXUNUSED(event))
1177{
1bd1d102
VZ
1178 // PNG support is not always compiled in under Windows, so use BMP there
1179#ifdef __WXMSW__
1180 wxFileDialog dialog(this, "Open a BMP file", "", "", "BMP files (*.bmp)|*.bmp", 0);
1181#else
e2acb9ae 1182 wxFileDialog dialog(this, "Open a PNG file", "", "", "PNG files (*.png)|*.png", 0);
1bd1d102 1183#endif
e2acb9ae
RR
1184
1185 if (dialog.ShowModal() != wxID_OK)
8e193f38 1186 {
e2acb9ae
RR
1187 wxLogMessage( _T("Aborted file open") );
1188 return;
1189 }
8e193f38 1190
e2acb9ae 1191 if (dialog.GetPath().IsEmpty())
8e193f38 1192 {
e2acb9ae
RR
1193 wxLogMessage( _T("Returned empty string.") );
1194 return;
1195 }
8e193f38 1196
e2acb9ae
RR
1197 if (!wxFileExists(dialog.GetPath()))
1198 {
1199 wxLogMessage( _T("File doesn't exist.") );
1200 return;
1201 }
8e193f38 1202
e2acb9ae 1203 wxImage image;
8e193f38 1204 image.LoadFile( dialog.GetPath(),
1bd1d102
VZ
1205#ifdef __WXMSW__
1206 wxBITMAP_TYPE_BMP
1207#else
1208 wxBITMAP_TYPE_PNG
1209#endif
1210 );
e2acb9ae
RR
1211 if (!image.Ok())
1212 {
8e193f38 1213 wxLogError( _T("Invalid image file...") );
e2acb9ae
RR
1214 return;
1215 }
8e193f38
VZ
1216
1217 wxLogStatus( _T("Decoding image file...") );
e2acb9ae 1218 wxYield();
8e193f38 1219
e2acb9ae
RR
1220 wxBitmap bitmap( image.ConvertToBitmap() );
1221
1222 if ( !wxTheClipboard->Open() )
1223 {
1224 wxLogError(_T("Can't open clipboard."));
1225
1226 return;
1227 }
1228
1229 wxLogMessage( _T("Creating wxBitmapDataObject...") );
1230 wxYield();
8e193f38 1231
e2acb9ae
RR
1232 if ( !wxTheClipboard->AddData(new wxBitmapDataObject(bitmap)) )
1233 {
1234 wxLogError(_T("Can't copy image to the clipboard."));
1235 }
1236 else
1237 {
1238 wxLogMessage(_T("Image has been put on the clipboard.") );
1239 wxLogMessage(_T("You can paste it now and look at it.") );
1240 }
1241
1242 wxTheClipboard->Close();
1243}
1244
1245void DnDFrame::OnPasteBitmap(wxCommandEvent& WXUNUSED(event))
1246{
1247 if ( !wxTheClipboard->Open() )
1248 {
1249 wxLogError(_T("Can't open clipboard."));
1250
1251 return;
1252 }
1253
1254 if ( !wxTheClipboard->IsSupported(wxDF_BITMAP) )
1255 {
1256 wxLogWarning(_T("No bitmap on clipboard"));
1257
1258 wxTheClipboard->Close();
1259 return;
1260 }
1261
1262 wxBitmapDataObject data;
79ec2ce2 1263 if ( !wxTheClipboard->GetData(data) )
e2acb9ae
RR
1264 {
1265 wxLogError(_T("Can't paste bitmap from the clipboard"));
1266 }
1267 else
1268 {
ae3dd4a5
VZ
1269 const wxBitmap& bmp = data.GetBitmap();
1270
1271 wxLogMessage(_T("Bitmap %dx%d pasted from the clipboard"),
1272 bmp.GetWidth(), bmp.GetHeight());
1273 ShowBitmap(bmp);
e2acb9ae
RR
1274 }
1275
1276 wxTheClipboard->Close();
1277}
1278
5a1c877f
VZ
1279#ifdef USE_METAFILES
1280
1281void DnDFrame::OnPasteMetafile(wxCommandEvent& WXUNUSED(event))
1282{
1283 if ( !wxTheClipboard->Open() )
1284 {
1285 wxLogError(_T("Can't open clipboard."));
1286
1287 return;
1288 }
1289
1290 if ( !wxTheClipboard->IsSupported(wxDF_METAFILE) )
1291 {
1292 wxLogWarning(_T("No metafile on clipboard"));
1293 }
1294 else
1295 {
1296 wxMetaFileDataObject data;
1297 if ( !wxTheClipboard->GetData(data) )
1298 {
1299 wxLogError(_T("Can't paste metafile from the clipboard"));
1300 }
1301 else
1302 {
ae3dd4a5 1303 const wxMetaFile& mf = data.GetMetafile();
5a1c877f 1304
ae3dd4a5
VZ
1305 wxLogMessage(_T("Metafile %dx%d pasted from the clipboard"),
1306 mf.GetWidth(), mf.GetHeight());
1307
1308 ShowMetaFile(mf);
5a1c877f
VZ
1309 }
1310 }
1311
1312 wxTheClipboard->Close();
1313}
1314
1315#endif // USE_METAFILES
1316
51edda6a
VZ
1317// ----------------------------------------------------------------------------
1318// file clipboard
1319// ----------------------------------------------------------------------------
1320
1321void DnDFrame::OnCopyFiles(wxCommandEvent& WXUNUSED(event))
1322{
1323#ifdef __WXMSW__
51edda6a
VZ
1324 wxFileDialog dialog(this, "Select a file to copy", "", "",
1325 "All files (*.*)|*.*", 0);
1326
3f2711d5
VZ
1327 wxArrayString filenames;
1328 while ( dialog.ShowModal() == wxID_OK )
51edda6a 1329 {
3f2711d5
VZ
1330 filenames.Add(dialog.GetPath());
1331 }
1332
1333 if ( !filenames.IsEmpty() )
1334 {
1335 wxFileDataObject *dobj = new wxFileDataObject;
1336 size_t count = filenames.GetCount();
1337 for ( size_t n = 0; n < count; n++ )
1338 {
1339 dobj->AddFile(filenames[n]);
1340 }
51edda6a
VZ
1341
1342 wxClipboardLocker locker;
1343 if ( !locker )
1344 {
4693b20c 1345 wxLogError(wxT("Can't open clipboard"));
51edda6a
VZ
1346 }
1347 else
1348 {
1349 if ( !wxTheClipboard->AddData(dobj) )
1350 {
4693b20c 1351 wxLogError(wxT("Can't copy file(s) to the clipboard"));
51edda6a
VZ
1352 }
1353 else
1354 {
4693b20c
MB
1355 wxLogStatus(this, wxT("%d file%s copied to the clipboard"),
1356 count, count == 1 ? wxT("") : wxT("s"));
51edda6a
VZ
1357 }
1358 }
1359 }
1360 else
1361 {
4693b20c 1362 wxLogStatus(this, wxT("Aborted"));
51edda6a
VZ
1363 }
1364#else // !MSW
4693b20c 1365 wxLogError(wxT("Sorry, not implemented"));
51edda6a
VZ
1366#endif // MSW/!MSW
1367}
1368
e2acb9ae
RR
1369// ---------------------------------------------------------------------------
1370// text clipboard
c50f1fb9
VZ
1371// ---------------------------------------------------------------------------
1372
1373void DnDFrame::OnCopy(wxCommandEvent& WXUNUSED(event))
1374{
1375 if ( !wxTheClipboard->Open() )
1376 {
b56baa2d 1377 wxLogError(_T("Can't open clipboard."));
c50f1fb9
VZ
1378
1379 return;
1380 }
1381
1382 if ( !wxTheClipboard->AddData(new wxTextDataObject(m_strText)) )
1383 {
b56baa2d 1384 wxLogError(_T("Can't copy data to the clipboard"));
c50f1fb9
VZ
1385 }
1386 else
1387 {
b56baa2d 1388 wxLogMessage(_T("Text '%s' put on the clipboard"), m_strText.c_str());
c50f1fb9
VZ
1389 }
1390
1391 wxTheClipboard->Close();
1392}
1393
1394void DnDFrame::OnPaste(wxCommandEvent& WXUNUSED(event))
1395{
1396 if ( !wxTheClipboard->Open() )
1397 {
b56baa2d 1398 wxLogError(_T("Can't open clipboard."));
c50f1fb9
VZ
1399
1400 return;
1401 }
1402
1403 if ( !wxTheClipboard->IsSupported(wxDF_TEXT) )
1404 {
b56baa2d 1405 wxLogWarning(_T("No text data on clipboard"));
c50f1fb9 1406
e2acb9ae 1407 wxTheClipboard->Close();
c50f1fb9
VZ
1408 return;
1409 }
1410
1411 wxTextDataObject text;
79ec2ce2 1412 if ( !wxTheClipboard->GetData(text) )
c50f1fb9 1413 {
b56baa2d 1414 wxLogError(_T("Can't paste data from the clipboard"));
c50f1fb9
VZ
1415 }
1416 else
1417 {
b56baa2d 1418 wxLogMessage(_T("Text '%s' pasted from the clipboard"),
c50f1fb9
VZ
1419 text.GetText().c_str());
1420 }
1421
1422 wxTheClipboard->Close();
457814b5
JS
1423}
1424
1425// ----------------------------------------------------------------------------
1426// Notifications called by the base class
1427// ----------------------------------------------------------------------------
e2acb9ae 1428
9e2896e5 1429bool DnDText::OnDropText(wxCoord, wxCoord, const wxString& text)
457814b5 1430{
9e2896e5 1431 m_pOwner->Append(text);
457814b5 1432
c50f1fb9 1433 return TRUE;
457814b5
JS
1434}
1435
9e2896e5 1436bool DnDFile::OnDropFiles(wxCoord, wxCoord, const wxArrayString& filenames)
457814b5 1437{
9e2896e5 1438 size_t nFiles = filenames.GetCount();
c50f1fb9
VZ
1439 wxString str;
1440 str.Printf( _T("%d files dropped"), nFiles);
1441 m_pOwner->Append(str);
1442 for ( size_t n = 0; n < nFiles; n++ ) {
9e2896e5 1443 m_pOwner->Append(filenames[n]);
c50f1fb9
VZ
1444 }
1445
1446 return TRUE;
457814b5 1447}
8e193f38
VZ
1448
1449// ----------------------------------------------------------------------------
1450// DnDShapeDialog
1451// ----------------------------------------------------------------------------
1452
1453DnDShapeDialog::DnDShapeDialog(wxFrame *parent, DnDShape *shape)
4693b20c
MB
1454#if !USE_RESOURCES
1455 :wxDialog( parent, 6001, wxT("Choose Shape"), wxPoint( 10, 10 ),
1456 wxSize( 40, 40 ),
1457 wxRAISED_BORDER|wxCAPTION|wxTHICK_FRAME|wxSYSTEM_MENU )
1458#endif
8e193f38
VZ
1459{
1460 m_shape = shape;
4693b20c 1461#if USE_RESOURCES
8e193f38
VZ
1462 LoadFromResource(parent, "dialogShape");
1463
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);
1468
1469 m_radio = (wxRadioBox *)wxFindWindowByName("radio", this);
4693b20c
MB
1470#else
1471 wxBoxSizer* topSizer = new wxBoxSizer( wxVERTICAL );
1472
1473 // radio box
1474 wxBoxSizer* shapesSizer = new wxBoxSizer( wxHORIZONTAL );
1475 const wxString choices[] = { wxT("None"), wxT("Triangle"),
1476 wxT("Rectangle"), wxT("Ellipse") };
1477
e6d318c2 1478 m_radio = new wxRadioBox( this, -1, wxT("&Shape"),
4693b20c
MB
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 );
1483
1484 // attributes
1485 wxStaticBox* box = new wxStaticBox( this, -1, wxT("&Attributes") );
1486 wxStaticBoxSizer* attrSizer = new wxStaticBoxSizer( box, wxHORIZONTAL );
1487 wxFlexGridSizer* xywhSizer = new wxFlexGridSizer( 4, 2 );
e6d318c2 1488
4693b20c
MB
1489 wxStaticText* st;
1490
1491 st = new wxStaticText( this, -1, wxT("Position &X:") );
1492 m_textX = new wxTextCtrl( this, -1, wxEmptyString, wxDefaultPosition,
1493 wxSize( 30, 20 ) );
e6d318c2
RD
1494 xywhSizer->Add( st, 1, wxGROW|wxALL, 2 );
1495 xywhSizer->Add( m_textX, 1, wxGROW|wxALL, 2 );
4693b20c
MB
1496
1497 st = new wxStaticText( this, -1, wxT("Size &width:") );
1498 m_textW = new wxTextCtrl( this, -1, wxEmptyString, wxDefaultPosition,
1499 wxSize( 30, 20 ) );
e6d318c2
RD
1500 xywhSizer->Add( st, 1, wxGROW|wxALL, 2 );
1501 xywhSizer->Add( m_textW, 1, wxGROW|wxALL, 2 );
4693b20c
MB
1502
1503 st = new wxStaticText( this, -1, wxT("&Y:") );
1504 m_textY = new wxTextCtrl( this, -1, wxEmptyString, wxDefaultPosition,
1505 wxSize( 30, 20 ) );
e6d318c2
RD
1506 xywhSizer->Add( st, 1, wxALL|wxALIGN_RIGHT, 2 );
1507 xywhSizer->Add( m_textY, 1, wxGROW|wxALL, 2 );
4693b20c
MB
1508
1509 st = new wxStaticText( this, -1, wxT("&height:") );
1510 m_textH = new wxTextCtrl( this, -1, wxEmptyString, wxDefaultPosition,
1511 wxSize( 30, 20 ) );
e6d318c2
RD
1512 xywhSizer->Add( st, 1, wxALL|wxALIGN_RIGHT, 2 );
1513 xywhSizer->Add( m_textH, 1, wxGROW|wxALL, 2 );
4693b20c
MB
1514
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 );
1519
1520 // buttons
1521 wxBoxSizer* buttonSizer = new wxBoxSizer( wxHORIZONTAL );
1522 wxButton* bt;
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 );
1528
1529 SetAutoLayout( TRUE );
1530 SetSizer( topSizer );
1531 topSizer->Fit( this );
1532#endif
8e193f38
VZ
1533}
1534
1535DnDShape *DnDShapeDialog::GetShape() const
1536{
1537 switch ( m_shapeKind )
1538 {
1539 default:
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);
1544 }
1545}
1546
1547bool DnDShapeDialog::TransferDataToWindow()
1548{
a3e7d24d 1549
8e193f38
VZ
1550 if ( m_shape )
1551 {
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();
1556 }
1557 else
1558 {
1559 m_radio->SetSelection(DnDShape::None);
1560 m_pos = wxPoint(1, 1);
1561 m_size = wxSize(100, 100);
1562 }
1563
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);
1568
1569 return TRUE;
1570}
1571
1572bool DnDShapeDialog::TransferDataFromWindow()
1573{
1574 m_shapeKind = (DnDShape::Kind)m_radio->GetSelection();
1575
4693b20c
MB
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());
8e193f38
VZ
1580
1581 if ( !m_pos.x || !m_pos.y || !m_size.x || !m_size.y )
1582 {
1583 wxMessageBox("All sizes and positions should be non null!",
1584 "Invalid shape", wxICON_HAND | wxOK, this);
1585
1586 return FALSE;
1587 }
1588
1589 return TRUE;
1590}
1591
1592void DnDShapeDialog::OnColour(wxCommandEvent& WXUNUSED(event))
1593{
1594 wxColourData data;
1595 data.SetChooseFull(TRUE);
1596 for (int i = 0; i < 16; i++)
1597 {
1598 wxColour colour(i*16, i*16, i*16);
1599 data.SetCustomColour(i, colour);
1600 }
1601
1602 wxColourDialog dialog(this, &data);
1603 if ( dialog.ShowModal() == wxID_OK )
1604 {
1605 m_col = dialog.GetColourData().GetColour();
1606 }
1607}
1608
1609// ----------------------------------------------------------------------------
1610// DnDShapeFrame
1611// ----------------------------------------------------------------------------
1612
d59ceba5
VZ
1613DnDShapeFrame *DnDShapeFrame::ms_lastDropTarget = NULL;
1614
8e193f38
VZ
1615DnDShapeFrame::DnDShapeFrame(wxFrame *parent)
1616 : wxFrame(parent, -1, "Shape Frame",
1617 wxDefaultPosition, wxSize(250, 150))
1618{
8e193f38
VZ
1619 CreateStatusBar();
1620
d59ceba5
VZ
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();
5a1c877f 1625 menuShape->Append(Menu_Shape_Clear, "&Clear shape\tCtrl-L");
d59ceba5
VZ
1626
1627 wxMenu *menuClipboard = new wxMenu;
1628 menuClipboard->Append(Menu_ShapeClipboard_Copy, "&Copy\tCtrl-C");
1629 menuClipboard->Append(Menu_ShapeClipboard_Paste, "&Paste\tCtrl-V");
1630
1631 wxMenuBar *menubar = new wxMenuBar;
1632 menubar->Append(menuShape, "&Shape");
1633 menubar->Append(menuClipboard, "&Clipboard");
1634
1635 SetMenuBar(menubar);
1636
1637 SetStatusText("Press Ctrl-S to create a new shape");
8e193f38
VZ
1638
1639 SetDropTarget(new DnDShapeDropTarget(this));
1640
1641 m_shape = NULL;
f6bcfd97 1642
572c6194 1643 SetBackgroundColour(*wxWHITE);
8e193f38
VZ
1644}
1645
1646DnDShapeFrame::~DnDShapeFrame()
1647{
f6bcfd97 1648 if (m_shape)
572c6194 1649 delete m_shape;
8e193f38
VZ
1650}
1651
1652void DnDShapeFrame::SetShape(DnDShape *shape)
1653{
f6bcfd97 1654 if (m_shape)
572c6194 1655 delete m_shape;
8e193f38
VZ
1656 m_shape = shape;
1657 Refresh();
1658}
1659
1660// callbacks
1661void DnDShapeFrame::OnDrag(wxMouseEvent& event)
1662{
1663 if ( !m_shape )
1664 {
1665 event.Skip();
1666
1667 return;
1668 }
1669
1670 // start drag operation
1671 DnDShapeDataObject shapeData(m_shape);
2d93e133 1672 wxDropSource source(shapeData, this);
8e193f38
VZ
1673
1674 const char *pc = NULL;
1675 switch ( source.DoDragDrop(TRUE) )
1676 {
1677 default:
1678 case wxDragError:
4693b20c 1679 wxLogError(wxT("An error occured during drag and drop operation"));
8e193f38
VZ
1680 break;
1681
1682 case wxDragNone:
1683 SetStatusText("Nothing happened");
1684 break;
1685
1686 case wxDragCopy:
1687 pc = "copied";
1688 break;
1689
1690 case wxDragMove:
1691 pc = "moved";
d59ceba5
VZ
1692 if ( ms_lastDropTarget != this )
1693 {
1694 // don't delete the shape if we dropped it on ourselves!
1695 SetShape(NULL);
1696 }
8e193f38
VZ
1697 break;
1698
1699 case wxDragCancel:
1700 SetStatusText("Drag and drop operation cancelled");
1701 break;
1702 }
1703
1704 if ( pc )
1705 {
1706 SetStatusText(wxString("Shape successfully ") + pc);
1707 }
1708 //else: status text already set
1709}
1710
90e12284 1711void DnDShapeFrame::OnDrop(wxCoord x, wxCoord y, DnDShape *shape)
9e2896e5
VZ
1712{
1713 ms_lastDropTarget = this;
1714
90e12284 1715 wxPoint pt(x, y);
90e12284 1716
9e2896e5 1717 wxString s;
4693b20c 1718 s.Printf(wxT("Shape dropped at (%ld, %ld)"), pt.x, pt.y);
9e2896e5
VZ
1719 SetStatusText(s);
1720
90e12284 1721 shape->Move(pt);
9e2896e5
VZ
1722 SetShape(shape);
1723}
1724
d59ceba5 1725void DnDShapeFrame::OnEditShape(wxCommandEvent& event)
8e193f38
VZ
1726{
1727 DnDShapeDialog dlg(this, m_shape);
1728 if ( dlg.ShowModal() == wxID_OK )
1729 {
1730 SetShape(dlg.GetShape());
1731
1732 if ( m_shape )
1733 {
d59ceba5 1734 SetStatusText("You can now drag the shape to another frame");
8e193f38
VZ
1735 }
1736 }
1737}
1738
d59ceba5
VZ
1739void DnDShapeFrame::OnNewShape(wxCommandEvent& event)
1740{
1741 SetShape(new DnDEllipticShape(wxPoint(10, 10), wxSize(80, 60), *wxRED));
1742
1743 SetStatusText("You can now drag the shape to another frame");
1744}
1745
1746void DnDShapeFrame::OnClearShape(wxCommandEvent& event)
1747{
1748 SetShape(NULL);
1749}
1750
1751void DnDShapeFrame::OnCopyShape(wxCommandEvent& event)
1752{
1753 if ( m_shape )
ae125753
VZ
1754 {
1755 wxClipboardLocker clipLocker;
1756 if ( !clipLocker )
1757 {
4693b20c 1758 wxLogError(wxT("Can't open the clipboard"));
ae125753
VZ
1759
1760 return;
1761 }
1762
d59ceba5 1763 wxTheClipboard->AddData(new DnDShapeDataObject(m_shape));
ae125753 1764 }
d59ceba5
VZ
1765}
1766
1767void DnDShapeFrame::OnPasteShape(wxCommandEvent& event)
1768{
ae125753
VZ
1769 wxClipboardLocker clipLocker;
1770 if ( !clipLocker )
1771 {
4693b20c 1772 wxLogError(wxT("Can't open the clipboard"));
ae125753
VZ
1773
1774 return;
1775 }
1776
d59ceba5 1777 DnDShapeDataObject shapeDataObject(NULL);
79ec2ce2 1778 if ( wxTheClipboard->GetData(shapeDataObject) )
d59ceba5
VZ
1779 {
1780 SetShape(shapeDataObject.GetShape());
1781 }
1782 else
1783 {
4693b20c 1784 wxLogStatus(wxT("No shape on the clipboard"));
d59ceba5
VZ
1785 }
1786}
1787
1788void DnDShapeFrame::OnUpdateUICopy(wxUpdateUIEvent& event)
1789{
1790 event.Enable( m_shape != NULL );
1791}
1792
1793void DnDShapeFrame::OnUpdateUIPaste(wxUpdateUIEvent& event)
1794{
1795 event.Enable( wxTheClipboard->IsSupported(wxDataFormat(shapeFormatId)) );
1796}
1797
8e193f38
VZ
1798void DnDShapeFrame::OnPaint(wxPaintEvent& event)
1799{
1800 if ( m_shape )
79ec2ce2
VZ
1801 {
1802 wxPaintDC dc(this);
1803
1804 m_shape->Draw(dc);
1805 }
8e193f38 1806 else
79ec2ce2 1807 {
8e193f38 1808 event.Skip();
79ec2ce2 1809 }
8e193f38
VZ
1810}
1811
8e193f38
VZ
1812// ----------------------------------------------------------------------------
1813// DnDShape
1814// ----------------------------------------------------------------------------
1815
1816DnDShape *DnDShape::New(const void *buf)
1817{
1818 const ShapeDump& dump = *(const ShapeDump *)buf;
1819 switch ( dump.k )
1820 {
1821 case Triangle:
1822 return new DnDTriangularShape(wxPoint(dump.x, dump.y),
1823 wxSize(dump.w, dump.h),
1824 wxColour(dump.r, dump.g, dump.b));
1825
1826 case Rectangle:
1827 return new DnDRectangularShape(wxPoint(dump.x, dump.y),
1828 wxSize(dump.w, dump.h),
1829 wxColour(dump.r, dump.g, dump.b));
1830
1831 case Ellipse:
1832 return new DnDEllipticShape(wxPoint(dump.x, dump.y),
1833 wxSize(dump.w, dump.h),
1834 wxColour(dump.r, dump.g, dump.b));
1835
1836 default:
4693b20c 1837 wxFAIL_MSG(wxT("invalid shape!"));
8e193f38
VZ
1838 return NULL;
1839 }
1840}
1841
1842// ----------------------------------------------------------------------------
1843// DnDShapeDataObject
1844// ----------------------------------------------------------------------------
1845
5a1c877f
VZ
1846#ifdef USE_METAFILES
1847
1848void DnDShapeDataObject::CreateMetaFile() const
1849{
ae3dd4a5
VZ
1850 wxPoint pos = m_shape->GetPosition();
1851 wxSize size = m_shape->GetSize();
1852
1853 wxMetaFileDC dcMF(wxEmptyString, pos.x + size.x, pos.y + size.y);
5a1c877f
VZ
1854
1855 m_shape->Draw(dcMF);
1856
1857 wxMetafile *mf = dcMF.Close();
1858
5a1c877f
VZ
1859 DnDShapeDataObject *self = (DnDShapeDataObject *)this; // const_cast
1860 self->m_dobjMetaFile.SetMetafile(*mf);
1861 self->m_hasMetaFile = TRUE;
ae3dd4a5
VZ
1862
1863 delete mf;
5a1c877f
VZ
1864}
1865
1866#endif // Windows
1867
8e193f38
VZ
1868void DnDShapeDataObject::CreateBitmap() const
1869{
d59ceba5
VZ
1870 wxPoint pos = m_shape->GetPosition();
1871 wxSize size = m_shape->GetSize();
1872 int x = pos.x + size.x,
1873 y = pos.y + size.y;
1874 wxBitmap bitmap(x, y);
8e193f38
VZ
1875 wxMemoryDC dc;
1876 dc.SelectObject(bitmap);
a60b1f5d 1877 dc.SetBrush(wxBrush(wxT("white"), wxSOLID));
d59ceba5 1878 dc.Clear();
8e193f38
VZ
1879 m_shape->Draw(dc);
1880 dc.SelectObject(wxNullBitmap);
1881
1882 DnDShapeDataObject *self = (DnDShapeDataObject *)this; // const_cast
5a1c877f 1883 self->m_dobjBitmap.SetBitmap(bitmap);
8e193f38
VZ
1884 self->m_hasBitmap = TRUE;
1885}
1886
ae3dd4a5
VZ
1887// ----------------------------------------------------------------------------
1888// global functions
1889// ----------------------------------------------------------------------------
1890
1891static void ShowBitmap(const wxBitmap& bitmap)
1892{
1893 wxFrame *frame = new wxFrame(NULL, -1, _T("Bitmap view"));
1894 frame->CreateStatusBar();
1895 DnDCanvasBitmap *canvas = new DnDCanvasBitmap(frame);
1896 canvas->SetBitmap(bitmap);
1897
1898 int w = bitmap.GetWidth(),
1899 h = bitmap.GetHeight();
1900 frame->SetStatusText(wxString::Format(_T("%dx%d"), w, h));
1901
1902 frame->SetClientSize(w > 100 ? 100 : w, h > 100 ? 100 : h);
e680a378 1903 frame->Show(TRUE);
ae3dd4a5
VZ
1904}
1905
1906#ifdef USE_METAFILES
1907
1908static void ShowMetaFile(const wxMetaFile& metafile)
1909{
1910 wxFrame *frame = new wxFrame(NULL, -1, _T("Metafile view"));
1911 frame->CreateStatusBar();
1912 DnDCanvasMetafile *canvas = new DnDCanvasMetafile(frame);
1913 canvas->SetMetafile(metafile);
1914
1915 wxSize size = metafile.GetSize();
1916 frame->SetStatusText(wxString::Format(_T("%dx%d"), size.x, size.y));
1917
1918 frame->SetClientSize(size.x > 100 ? 100 : size.x,
1919 size.y > 100 ? 100 : size.y);
1920 frame->Show();
1921}
1922
1923#endif // USE_METAFILES