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