]> git.saurik.com Git - wxWidgets.git/blame - samples/dnd/dnd.cpp
part of dnd sample I forgot
[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
c50f1fb9
VZ
26#include "wx/intl.h"
27#include "wx/log.h"
457814b5 28
c50f1fb9 29#include "wx/dnd.h"
956dbab1 30#include "wx/dirdlg.h"
e2acb9ae
RR
31#include "wx/filedlg.h"
32#include "wx/image.h"
33#include "wx/clipbrd.h"
8e193f38
VZ
34#include "wx/colordlg.h"
35#include "wx/resource.h"
acbd13a3
JS
36
37#if defined(__WXGTK__) || defined(__WXMOTIF__)
c50f1fb9 38 #include "mondrian.xpm"
47908e25
RR
39#endif
40
457814b5 41// ----------------------------------------------------------------------------
2845ddc2 42// Derive two simple classes which just put in the listbox the strings (text or
457814b5
JS
43// file names) we drop on them
44// ----------------------------------------------------------------------------
ab8884ac 45
8dbf4589 46typedef long wxDropPointCoord;
88ac883a 47
457814b5
JS
48class DnDText : public wxTextDropTarget
49{
50public:
c50f1fb9 51 DnDText(wxListBox *pOwner) { m_pOwner = pOwner; }
457814b5 52
c50f1fb9
VZ
53 virtual bool OnDropText(wxDropPointCoord x, wxDropPointCoord y,
54 const wxChar* psz);
457814b5
JS
55
56private:
c50f1fb9 57 wxListBox *m_pOwner;
457814b5
JS
58};
59
60class DnDFile : public wxFileDropTarget
61{
62public:
c50f1fb9 63 DnDFile(wxListBox *pOwner) { m_pOwner = pOwner; }
457814b5 64
88ac883a 65 virtual bool OnDropFiles(wxDropPointCoord x, wxDropPointCoord y,
b03b33e2 66 size_t nFiles, const wxChar* const aszFiles[] );
457814b5
JS
67
68private:
c50f1fb9 69 wxListBox *m_pOwner;
457814b5
JS
70};
71
72// ----------------------------------------------------------------------------
73// Define a new application type
74// ----------------------------------------------------------------------------
ab8884ac 75
457814b5 76class DnDApp : public wxApp
8bbe427f 77{
457814b5 78public:
8e193f38 79 virtual bool OnInit();
457814b5
JS
80};
81
82IMPLEMENT_APP(DnDApp);
83
84// ----------------------------------------------------------------------------
8e193f38 85// Define a new frame type for the main frame
457814b5 86// ----------------------------------------------------------------------------
8e193f38 87
457814b5 88class DnDFrame : public wxFrame
8bbe427f 89{
457814b5 90public:
c50f1fb9
VZ
91 DnDFrame(wxFrame *frame, char *title, int x, int y, int w, int h);
92 ~DnDFrame();
457814b5 93
c50f1fb9
VZ
94 void OnPaint(wxPaintEvent& event);
95 void OnQuit (wxCommandEvent& event);
96 void OnAbout(wxCommandEvent& event);
97 void OnDrag (wxCommandEvent& event);
8e193f38 98 void OnNewFrame(wxCommandEvent& event);
c50f1fb9
VZ
99 void OnHelp (wxCommandEvent& event);
100 void OnLogClear(wxCommandEvent& event);
101 void OnCopy(wxCommandEvent& event);
102 void OnPaste(wxCommandEvent& event);
e2acb9ae
RR
103 void OnCopyBitmap(wxCommandEvent& event);
104 void OnPasteBitmap(wxCommandEvent& event);
43d811ea 105
c50f1fb9
VZ
106 void OnLeftDown(wxMouseEvent& event);
107 void OnRightDown(wxMouseEvent& event);
8bbe427f 108
d59ceba5
VZ
109 void OnUpdateUIPasteText(wxUpdateUIEvent& event);
110 void OnUpdateUIPasteBitmap(wxUpdateUIEvent& event);
111
c50f1fb9 112 DECLARE_EVENT_TABLE()
457814b5
JS
113
114private:
e2acb9ae
RR
115 wxListBox *m_ctrlFile,
116 *m_ctrlText;
117 wxTextCtrl *m_ctrlLog;
457814b5 118
e2acb9ae 119 wxLog *m_pLog, *m_pLogPrev;
43d811ea 120
e2acb9ae
RR
121 wxString m_strText;
122 wxBitmap m_bitmap;
457814b5
JS
123};
124
8e193f38
VZ
125// ----------------------------------------------------------------------------
126// A shape is an example of application-specific data which may be transported
127// via drag-and-drop or clipboard: in our case, we have different geometric
128// shapes, each one with its own colour and position
129// ----------------------------------------------------------------------------
130
131class DnDShape
132{
133public:
134 enum Kind
135 {
136 None,
137 Triangle,
138 Rectangle,
139 Ellipse
140 };
141
142 DnDShape(const wxPoint& pos,
143 const wxSize& size,
144 const wxColour& col)
145 : m_pos(pos), m_size(size), m_col(col)
146 {
147 }
148
149 // the functions used for drag-and-drop: they dump and restore a shape into
d59ceba5 150 // some bitwise-copiable data (might use streams too...)
8e193f38
VZ
151 // ------------------------------------------------------------------------
152
153 // restore from buffer
154 static DnDShape *New(const void *buf);
155
156 virtual size_t GetDataSize() const
157 {
158 return sizeof(ShapeDump);
159 }
160
161 virtual void GetDataHere(void *buf) const
162 {
163 ShapeDump& dump = *(ShapeDump *)buf;
164 dump.x = m_pos.x;
165 dump.y = m_pos.y;
166 dump.w = m_size.x;
167 dump.h = m_size.y;
168 dump.r = m_col.Red();
169 dump.g = m_col.Green();
170 dump.b = m_col.Blue();
171 dump.k = GetKind();
172 }
173
174 // accessors
175 const wxPoint& GetPosition() const { return m_pos; }
176 const wxColour& GetColour() const { return m_col; }
177 const wxSize& GetSize() const { return m_size; }
178
d59ceba5
VZ
179 void Move(const wxPoint& pos) { m_pos = pos; }
180
8e193f38
VZ
181 // to implement in derived classes
182 virtual Kind GetKind() const = 0;
183
184 virtual void Draw(wxDC& dc) = 0
185 {
186 dc.SetPen(wxPen(m_col, 1, wxSOLID));
187 }
188
189protected:
190 wxPoint GetCentre() const
191 { return wxPoint(m_pos.x + m_size.x / 2, m_pos.y + m_size.y / 2); }
192
193 struct ShapeDump
194 {
195 int x, y, // position
196 w, h, // size
197 r, g, b, // colour
198 k; // kind
199 };
200
201 wxPoint m_pos;
202 wxSize m_size;
203 wxColour m_col;
204};
205
206class DnDTriangularShape : public DnDShape
207{
208public:
209 DnDTriangularShape(const wxPoint& pos,
210 const wxSize& size,
211 const wxColour& col)
212 : DnDShape(pos, size, col)
213 {
214 }
215
216 virtual Kind GetKind() const { return Triangle; }
217 virtual void Draw(wxDC& dc)
218 {
219 DnDShape::Draw(dc);
220
221 // well, it's a bit difficult to describe a triangle by position and
222 // size, but we're not doing geometry here, do we? ;-)
223 wxPoint p1(m_pos);
224 wxPoint p2(m_pos.x + m_size.x, m_pos.y);
225 wxPoint p3(m_pos.x, m_pos.y + m_size.y);
226
227 dc.DrawLine(p1, p2);
228 dc.DrawLine(p2, p3);
229 dc.DrawLine(p3, p1);
230
231 dc.FloodFill(GetCentre(), m_col, wxFLOOD_BORDER);
232 }
233};
234
235class DnDRectangularShape : public DnDShape
236{
237public:
238 DnDRectangularShape(const wxPoint& pos,
239 const wxSize& size,
240 const wxColour& col)
241 : DnDShape(pos, size, col)
242 {
243 }
244
245 virtual Kind GetKind() const { return Rectangle; }
246 virtual void Draw(wxDC& dc)
247 {
248 DnDShape::Draw(dc);
249
250 wxPoint p1(m_pos);
251 wxPoint p2(p1.x + m_size.x, p1.y);
252 wxPoint p3(p2.x, p2.y + m_size.y);
253 wxPoint p4(p1.x, p3.y);
254
255 dc.DrawLine(p1, p2);
256 dc.DrawLine(p2, p3);
257 dc.DrawLine(p3, p4);
258 dc.DrawLine(p4, p1);
259
260 dc.FloodFill(GetCentre(), m_col, wxFLOOD_BORDER);
261 }
262};
263
264class DnDEllipticShape : public DnDShape
265{
266public:
267 DnDEllipticShape(const wxPoint& pos,
268 const wxSize& size,
269 const wxColour& col)
270 : DnDShape(pos, size, col)
271 {
272 }
273
274 virtual Kind GetKind() const { return Ellipse; }
275 virtual void Draw(wxDC& dc)
276 {
277 DnDShape::Draw(dc);
278
279 dc.DrawEllipse(m_pos, m_size);
280
281 dc.FloodFill(GetCentre(), m_col, wxFLOOD_BORDER);
282 }
283};
284
285// ----------------------------------------------------------------------------
286// A wxDataObject specialisation for the application-specific data
287// ----------------------------------------------------------------------------
288
289static const char *shapeFormatId = "wxShape";
290
291class DnDShapeDataObject : public wxDataObject
292{
293public:
294 // ctor doesn't copy the pointer, so it shouldn't go away while this object
295 // is alive
296 DnDShapeDataObject(DnDShape *shape)
297 {
298 m_shape = shape;
299
300 // this string should uniquely identify our format, but is otherwise
301 // arbitrary
302 m_formatShape.SetId(shapeFormatId);
303
304 // we don't draw the shape to a bitmap until it's really needed (i.e.
305 // we're asked to do so)
306 m_hasBitmap = FALSE;
307 }
308
d59ceba5
VZ
309 // accessors
310 DnDShape *GetShape() const { return m_shape; }
311
8e193f38
VZ
312 // implement base class pure virtuals
313 // ----------------------------------
314
315 virtual wxDataFormat GetPreferredFormat() const
316 {
317 return m_formatShape;
318 }
319
d59ceba5 320 virtual size_t GetFormatCount(bool outputOnlyToo) const
8e193f38 321 {
d59ceba5
VZ
322 // our custom format is supported by both GetData() and SetData()
323 size_t nFormats = 1;
324 if ( outputOnlyToo )
325 {
326 // but the bitmap format(s) are only supported for output
327 nFormats += m_dataobj.GetFormatCount();
328 }
329
330 return nFormats;
8e193f38
VZ
331 }
332
d59ceba5 333 virtual void GetAllFormats(wxDataFormat *formats, bool outputOnlyToo) const
8e193f38
VZ
334 {
335 formats[0] = m_formatShape;
d59ceba5
VZ
336 if ( outputOnlyToo )
337 {
338 m_dataobj.GetAllFormats(&formats[1]);
339 }
8e193f38
VZ
340 }
341
342 virtual size_t GetDataSize(const wxDataFormat& format) const
343 {
344 if ( format == m_formatShape )
345 {
346 return m_shape->GetDataSize();
347 }
348 else
349 {
8e193f38
VZ
350 if ( !m_hasBitmap )
351 CreateBitmap();
352
353 return m_dataobj.GetDataSize(format);
354 }
355 }
356
d59ceba5 357 virtual bool GetDataHere(const wxDataFormat& format, void *pBuf) const
8e193f38
VZ
358 {
359 if ( format == m_formatShape )
360 {
361 m_shape->GetDataHere(pBuf);
d59ceba5
VZ
362
363 return TRUE;
8e193f38
VZ
364 }
365 else
366 {
367 wxASSERT_MSG( format == wxDF_BITMAP, "unsupported format" );
368
369 if ( !m_hasBitmap )
370 CreateBitmap();
371
d59ceba5 372 return m_dataobj.GetDataHere(format, pBuf);
8e193f38
VZ
373 }
374 }
375
d59ceba5
VZ
376 virtual bool SetData(const wxDataFormat& format, const void *buf)
377 {
378 wxCHECK_MSG( format == m_formatShape, FALSE, "unsupported format" );
379
380 delete m_shape;
381 m_shape = DnDShape::New(buf);
382
383 // the shape has changed
384 m_hasBitmap = FALSE;
385
386 return TRUE;
387 }
388
8e193f38
VZ
389private:
390 // creates a bitmap and assigns it to m_dataobj (also sets m_hasBitmap)
391 void CreateBitmap() const;
392
393 wxDataFormat m_formatShape; // our custom format
394
395 wxBitmapDataObject m_dataobj; // it handles bitmaps
396 bool m_hasBitmap; // true if m_dataobj has valid bitmap
397
398 DnDShape *m_shape; // our data
399};
400
401// ----------------------------------------------------------------------------
402// A dialog to edit shape properties
403// ----------------------------------------------------------------------------
404
405class DnDShapeDialog : public wxDialog
406{
407public:
408 DnDShapeDialog(wxFrame *parent, DnDShape *shape);
409
410 DnDShape *GetShape() const;
411
412 virtual bool TransferDataToWindow();
413 virtual bool TransferDataFromWindow();
414
415 void OnColour(wxCommandEvent& event);
416
417private:
418 // input
419 DnDShape *m_shape;
420
421 // output
422 DnDShape::Kind m_shapeKind;
423 wxPoint m_pos;
424 wxSize m_size;
425 wxColour m_col;
426
427 // controls
428 wxRadioBox *m_radio;
429 wxTextCtrl *m_textX,
430 *m_textY,
431 *m_textW,
432 *m_textH;
433
434 DECLARE_EVENT_TABLE()
435};
436
437// ----------------------------------------------------------------------------
438// A frame for the shapes which can be drag-and-dropped between frames
439// ----------------------------------------------------------------------------
440
441class DnDShapeFrame : public wxFrame
442{
443public:
444 DnDShapeFrame(wxFrame *parent);
445 ~DnDShapeFrame();
446
447 void SetShape(DnDShape *shape);
448
449 // callbacks
d59ceba5
VZ
450 void OnNewShape(wxCommandEvent& event);
451 void OnEditShape(wxCommandEvent& event);
452 void OnClearShape(wxCommandEvent& event);
453
454 void OnCopyShape(wxCommandEvent& event);
455 void OnPasteShape(wxCommandEvent& event);
456
457 void OnUpdateUICopy(wxUpdateUIEvent& event);
458 void OnUpdateUIPaste(wxUpdateUIEvent& event);
459
8e193f38 460 void OnDrag(wxMouseEvent& event);
8e193f38
VZ
461 void OnPaint(wxPaintEvent& event);
462 void OnDrop(long x, long y, DnDShape *shape);
463
464private:
465 DnDShape *m_shape;
466
d59ceba5
VZ
467 static DnDShapeFrame *ms_lastDropTarget;
468
8e193f38
VZ
469 DECLARE_EVENT_TABLE()
470};
471
472// ----------------------------------------------------------------------------
473// wxDropTarget derivation for DnDShapes
474// ----------------------------------------------------------------------------
475
476class DnDShapeDropTarget : public wxDropTarget
477{
478public:
479 DnDShapeDropTarget(DnDShapeFrame *frame)
480 {
481 m_frame = frame;
482
483 // the same as used by DnDShapeDataObject
484 m_formatShape.SetId(shapeFormatId);
485 }
486
487 // override base class (pure) virtuals
488 virtual void OnEnter()
489 { m_frame->SetStatusText("Mouse entered the frame"); }
490 virtual void OnLeave()
491 { m_frame->SetStatusText("Mouse left the frame"); }
492 virtual bool OnDrop(long x, long y, const void *pData)
493 {
494 m_frame->OnDrop(x, y, DnDShape::New(pData));
495
496 return TRUE;
497 }
498
499protected:
500 virtual size_t GetFormatCount() const { return 1; }
501 virtual wxDataFormat GetFormat(size_t WXUNUSED(n)) const
502 { return m_formatShape; }
503
504private:
505 DnDShapeFrame *m_frame;
506 wxDataFormat m_formatShape;
507};
508
457814b5
JS
509// ----------------------------------------------------------------------------
510// IDs for the menu commands
511// ----------------------------------------------------------------------------
ab8884ac 512
457814b5
JS
513enum
514{
c50f1fb9
VZ
515 Menu_Quit = 1,
516 Menu_Drag,
8e193f38 517 Menu_NewFrame,
c50f1fb9
VZ
518 Menu_About = 101,
519 Menu_Help,
520 Menu_Clear,
521 Menu_Copy,
e2acb9ae
RR
522 Menu_Paste,
523 Menu_CopyBitmap,
524 Menu_PasteBitmap,
d1b15f03 525 Menu_ToBeGreyed, /* for testing */
8e193f38 526 Menu_ToBeDeleted, /* for testing */
d59ceba5
VZ
527 Menu_Shape_New = 500,
528 Menu_Shape_Edit,
529 Menu_Shape_Clear,
530 Menu_ShapeClipboard_Copy,
531 Menu_ShapeClipboard_Paste,
8e193f38 532 Button_Colour = 1001
457814b5
JS
533};
534
535BEGIN_EVENT_TABLE(DnDFrame, wxFrame)
e2acb9ae
RR
536 EVT_MENU(Menu_Quit, DnDFrame::OnQuit)
537 EVT_MENU(Menu_About, DnDFrame::OnAbout)
538 EVT_MENU(Menu_Drag, DnDFrame::OnDrag)
8e193f38 539 EVT_MENU(Menu_NewFrame, DnDFrame::OnNewFrame)
e2acb9ae
RR
540 EVT_MENU(Menu_Help, DnDFrame::OnHelp)
541 EVT_MENU(Menu_Clear, DnDFrame::OnLogClear)
542 EVT_MENU(Menu_Copy, DnDFrame::OnCopy)
543 EVT_MENU(Menu_Paste, DnDFrame::OnPaste)
544 EVT_MENU(Menu_CopyBitmap, DnDFrame::OnCopyBitmap)
545 EVT_MENU(Menu_PasteBitmap,DnDFrame::OnPasteBitmap)
d59ceba5
VZ
546
547 EVT_UPDATE_UI(Menu_Paste, DnDFrame::OnUpdateUIPasteText)
548 EVT_UPDATE_UI(Menu_PasteBitmap, DnDFrame::OnUpdateUIPasteBitmap)
e2acb9ae
RR
549
550 EVT_LEFT_DOWN( DnDFrame::OnLeftDown)
551 EVT_RIGHT_DOWN( DnDFrame::OnRightDown)
552 EVT_PAINT( DnDFrame::OnPaint)
457814b5
JS
553END_EVENT_TABLE()
554
8e193f38 555BEGIN_EVENT_TABLE(DnDShapeFrame, wxFrame)
d59ceba5
VZ
556 EVT_MENU(Menu_Shape_New, DnDShapeFrame::OnNewShape)
557 EVT_MENU(Menu_Shape_Edit, DnDShapeFrame::OnEditShape)
558 EVT_MENU(Menu_Shape_Clear, DnDShapeFrame::OnClearShape)
559
560 EVT_MENU(Menu_ShapeClipboard_Copy, DnDShapeFrame::OnCopyShape)
561 EVT_MENU(Menu_ShapeClipboard_Paste, DnDShapeFrame::OnPasteShape)
562
563 EVT_UPDATE_UI(Menu_ShapeClipboard_Copy, DnDShapeFrame::OnUpdateUICopy)
564 EVT_UPDATE_UI(Menu_ShapeClipboard_Paste, DnDShapeFrame::OnUpdateUIPaste)
565
566 EVT_LEFT_DOWN(DnDShapeFrame::OnDrag)
567
8e193f38
VZ
568 EVT_PAINT(DnDShapeFrame::OnPaint)
569END_EVENT_TABLE()
570
571BEGIN_EVENT_TABLE(DnDShapeDialog, wxDialog)
572 EVT_BUTTON(Button_Colour, OnColour)
573END_EVENT_TABLE()
574
575// ============================================================================
576// implementation
577// ============================================================================
578
579// `Main program' equivalent, creating windows and returning main app frame
8bbe427f 580bool DnDApp::OnInit()
457814b5 581{
e2acb9ae
RR
582#if wxUSE_LIBPNG
583 wxImage::AddHandler( new wxPNGHandler );
584#endif
585
c50f1fb9
VZ
586 // create the main frame window
587 DnDFrame *frame = new DnDFrame((wxFrame *) NULL,
588 "Drag-and-Drop/Clipboard wxWindows Sample",
589 50, 50, 450, 340);
457814b5 590
c50f1fb9
VZ
591 // activate it
592 frame->Show(TRUE);
457814b5 593
c50f1fb9 594 SetTopWindow(frame);
457814b5 595
8e193f38
VZ
596 wxDefaultResourceTable->ParseResourceFile("dnd.wxr");
597
c50f1fb9 598 return TRUE;
457814b5
JS
599}
600
601DnDFrame::DnDFrame(wxFrame *frame, char *title, int x, int y, int w, int h)
43d811ea
JS
602 : wxFrame(frame, -1, title, wxPoint(x, y), wxSize(w, h)),
603 m_strText("wxWindows drag & drop works :-)")
604
457814b5 605{
c50f1fb9
VZ
606 // frame icon and status bar
607 SetIcon(wxICON(mondrian));
608
609 CreateStatusBar();
610
611 // construct menu
612 wxMenu *file_menu = new wxMenu;
613 file_menu->Append(Menu_Drag, "&Test drag...");
614 file_menu->AppendSeparator();
8e193f38 615 file_menu->Append(Menu_NewFrame, "&New frame\tCtrl-N");
d1b15f03 616 file_menu->AppendSeparator();
8e193f38 617 file_menu->Append(Menu_Quit, "E&xit");
c50f1fb9
VZ
618
619 wxMenu *log_menu = new wxMenu;
d59ceba5 620 log_menu->Append(Menu_Clear, "Clear\tDel");
c50f1fb9
VZ
621
622 wxMenu *help_menu = new wxMenu;
623 help_menu->Append(Menu_Help, "&Help...");
624 help_menu->AppendSeparator();
625 help_menu->Append(Menu_About, "&About");
626
627 wxMenu *clip_menu = new wxMenu;
e2acb9ae
RR
628 clip_menu->Append(Menu_Copy, "&Copy text\tCtrl+C");
629 clip_menu->Append(Menu_Paste, "&Paste text\tCtrl+V");
630 clip_menu->AppendSeparator();
d59ceba5
VZ
631 clip_menu->Append(Menu_CopyBitmap, "&Copy bitmap\tAlt+C");
632 clip_menu->Append(Menu_PasteBitmap, "&Paste bitmap\tAlt+V");
8e193f38 633
c50f1fb9
VZ
634 wxMenuBar *menu_bar = new wxMenuBar;
635 menu_bar->Append(file_menu, "&File");
636 menu_bar->Append(log_menu, "&Log");
637 menu_bar->Append(clip_menu, "&Clipboard");
638 menu_bar->Append(help_menu, "&Help");
639
640 SetMenuBar(menu_bar);
641
642 // make a panel with 3 subwindows
643 wxPoint pos(0, 0);
644 wxSize size(400, 200);
645
646 wxString strFile("Drop files here!"), strText("Drop text on me");
647
d59ceba5
VZ
648 m_ctrlFile = new wxListBox(this, -1, pos, size, 1, &strFile,
649 wxLB_HSCROLL | wxLB_ALWAYS_SB );
650 m_ctrlText = new wxListBox(this, -1, pos, size, 1, &strText,
651 wxLB_HSCROLL | wxLB_ALWAYS_SB );
c50f1fb9
VZ
652
653 m_ctrlLog = new wxTextCtrl(this, -1, "", pos, size,
d59ceba5
VZ
654 wxTE_MULTILINE | wxTE_READONLY |
655 wxSUNKEN_BORDER );
8e193f38
VZ
656
657 // redirect log messages to the text window and switch on OLE messages
658 // logging
659 wxLog::AddTraceMask(wxTRACE_OleCalls);
e2acb9ae
RR
660 m_pLog = new wxLogTextCtrl(m_ctrlLog);
661 m_pLogPrev = wxLog::SetActiveTarget(m_pLog);
662
663 // associate drop targets with 2 text controls
664 m_ctrlFile->SetDropTarget(new DnDFile(m_ctrlFile));
665 m_ctrlText->SetDropTarget(new DnDText(m_ctrlText));
666
667 wxLayoutConstraints *c;
668
669 // Top-left listbox
670 c = new wxLayoutConstraints;
671 c->left.SameAs(this, wxLeft);
672 c->top.SameAs(this, wxTop);
673 c->right.PercentOf(this, wxRight, 50);
674 c->height.PercentOf(this, wxHeight, 30);
675 m_ctrlFile->SetConstraints(c);
676
677 // Top-right listbox
678 c = new wxLayoutConstraints;
679 c->left.SameAs (m_ctrlFile, wxRight);
680 c->top.SameAs (this, wxTop);
681 c->right.SameAs (this, wxRight);
682 c->height.PercentOf(this, wxHeight, 30);
683 m_ctrlText->SetConstraints(c);
684
685 // Lower text control
686 c = new wxLayoutConstraints;
687 c->left.SameAs (this, wxLeft);
688 c->right.SameAs (this, wxRight);
d59ceba5 689 c->height.PercentOf(this, wxHeight, 50);
e2acb9ae
RR
690 c->top.SameAs(m_ctrlText, wxBottom);
691 m_ctrlLog->SetConstraints(c);
692
693 SetAutoLayout(TRUE);
457814b5
JS
694}
695
e2acb9ae 696void DnDFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
457814b5 697{
c50f1fb9 698 Close(TRUE);
457814b5
JS
699}
700
e2acb9ae 701void DnDFrame::OnPaint(wxPaintEvent& WXUNUSED(event))
b527aac5 702{
c50f1fb9
VZ
703 int w = 0;
704 int h = 0;
705 GetClientSize( &w, &h );
8bbe427f 706
c50f1fb9
VZ
707 wxPaintDC dc(this);
708 dc.SetFont( wxFont( 24, wxDECORATIVE, wxNORMAL, wxNORMAL, FALSE, "charter" ) );
e2acb9ae 709 dc.DrawText( "Drag text from here!", 20, h-50 );
8e193f38 710
d59ceba5 711 if ( m_bitmap.Ok() )
e2acb9ae 712 {
d59ceba5
VZ
713 // 4/5 is 80% taken by other windows, 20 is arbitrary margin
714 dc.DrawBitmap(m_bitmap,
715 w - m_bitmap.GetWidth() - 20,
716 (4*h)/5 + 20);
e2acb9ae 717 }
e2acb9ae
RR
718}
719
d59ceba5 720void DnDFrame::OnUpdateUIPasteText(wxUpdateUIEvent& event)
e2acb9ae 721{
d59ceba5
VZ
722 event.Enable( wxTheClipboard->IsSupported(wxDF_TEXT) );
723}
e2acb9ae 724
d59ceba5
VZ
725void DnDFrame::OnUpdateUIPasteBitmap(wxUpdateUIEvent& event)
726{
727 event.Enable( wxTheClipboard->IsSupported(wxDF_BITMAP) );
e2acb9ae
RR
728}
729
8e193f38
VZ
730void DnDFrame::OnNewFrame(wxCommandEvent& WXUNUSED(event))
731{
732 (new DnDShapeFrame(this))->Show(TRUE);
733
734 wxLogStatus(this, "Double click the new frame to select a shape for it");
735}
736
e2acb9ae 737void DnDFrame::OnDrag(wxCommandEvent& WXUNUSED(event))
43d811ea 738{
c50f1fb9
VZ
739 wxString strText = wxGetTextFromUser
740 (
741 "After you enter text in this dialog, press any mouse\n"
742 "button in the bottom (empty) part of the frame and \n"
743 "drag it anywhere - you will be in fact dragging the\n"
744 "text object containing this text",
745 "Please enter some text", m_strText, this
746 );
747
748 m_strText = strText;
43d811ea
JS
749}
750
e2acb9ae 751void DnDFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
457814b5 752{
c50f1fb9
VZ
753 wxMessageBox("Drag-&-Drop Demo\n"
754 "Please see \"Help|Help...\" for details\n"
755 "Copyright (c) 1998 Vadim Zeitlin",
756 "About wxDnD",
757 wxICON_INFORMATION | wxOK,
758 this);
457814b5
JS
759}
760
761void DnDFrame::OnHelp(wxCommandEvent& /* event */)
762{
c50f1fb9
VZ
763 wxMessageDialog dialog(this,
764 "This small program demonstrates drag & drop support in wxWindows. The program window\n"
765 "consists of 3 parts: the bottom pane is for debug messages, so that you can see what's\n"
766 "going on inside. The top part is split into 2 listboxes, the left one accepts files\n"
767 "and the right one accepts text.\n"
768 "\n"
769 "To test wxDropTarget: open wordpad (write.exe), select some text in it and drag it to\n"
770 "the right listbox (you'll notice the usual visual feedback, i.e. the cursor will change).\n"
771 "Also, try dragging some files (you can select several at once) from Windows Explorer (or \n"
772 "File Manager) to the left pane. Hold down Ctrl/Shift keys when you drop text (doesn't \n"
773 "work with files) and see what changes.\n"
774 "\n"
775 "To test wxDropSource: just press any mouse button on the empty zone of the window and drag\n"
776 "it to wordpad or any other droptarget accepting text (and of course you can just drag it\n"
777 "to the right pane). Due to a lot of trace messages, the cursor might take some time to \n"
778 "change, don't release the mouse button until it does. You can change the string being\n"
779 "dragged in in \"File|Test drag...\" dialog.\n"
780 "\n"
781 "\n"
782 "Please send all questions/bug reports/suggestions &c to \n"
783 "Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>",
784 "wxDnD Help");
785
786 dialog.ShowModal();
457814b5
JS
787}
788
e3e65dac 789void DnDFrame::OnLogClear(wxCommandEvent& /* event */ )
43d811ea 790{
c50f1fb9 791 m_ctrlLog->Clear();
43d811ea
JS
792}
793
30dea054 794void DnDFrame::OnLeftDown(wxMouseEvent &WXUNUSED(event) )
43d811ea 795{
8e193f38 796 if ( !m_strText.IsEmpty() )
c50f1fb9
VZ
797 {
798 // start drag operation
c50f1fb9 799 wxTextDataObject textData(m_strText);
8e193f38
VZ
800 wxDropSource source(textData, this, wxICON(mondrian));
801
c50f1fb9
VZ
802 const char *pc;
803
8e193f38 804 switch ( source.DoDragDrop(TRUE) )
c50f1fb9
VZ
805 {
806 case wxDragError: pc = "Error!"; break;
807 case wxDragNone: pc = "Nothing"; break;
808 case wxDragCopy: pc = "Copied"; break;
809 case wxDragMove: pc = "Moved"; break;
810 case wxDragCancel: pc = "Cancelled"; break;
811 default: pc = "Huh?"; break;
812 }
813
814 SetStatusText(wxString("Drag result: ") + pc);
43d811ea 815 }
43d811ea
JS
816}
817
30dea054
RR
818void DnDFrame::OnRightDown(wxMouseEvent &event )
819{
c50f1fb9 820 wxMenu *menu = new wxMenu;
8bbe427f 821
c50f1fb9
VZ
822 menu->Append(Menu_Drag, "&Test drag...");
823 menu->Append(Menu_About, "&About");
824 menu->Append(Menu_Quit, "E&xit");
d1b15f03
RR
825 menu->Append(Menu_ToBeDeleted, "To be deleted");
826 menu->Append(Menu_ToBeGreyed, "To be greyed");
8e193f38 827
d1b15f03
RR
828 menu->Delete( Menu_ToBeDeleted );
829 menu->Enable( Menu_ToBeGreyed, FALSE );
8bbe427f 830
c50f1fb9 831 PopupMenu( menu, event.GetX(), event.GetY() );
30dea054
RR
832}
833
457814b5
JS
834DnDFrame::~DnDFrame()
835{
c50f1fb9
VZ
836 if ( m_pLog != NULL ) {
837 if ( wxLog::SetActiveTarget(m_pLogPrev) == m_pLog )
838 delete m_pLog;
839 }
840}
841
842// ---------------------------------------------------------------------------
e2acb9ae
RR
843// bitmap clipboard
844// ---------------------------------------------------------------------------
845
846void DnDFrame::OnCopyBitmap(wxCommandEvent& WXUNUSED(event))
847{
1bd1d102
VZ
848 // PNG support is not always compiled in under Windows, so use BMP there
849#ifdef __WXMSW__
850 wxFileDialog dialog(this, "Open a BMP file", "", "", "BMP files (*.bmp)|*.bmp", 0);
851#else
e2acb9ae 852 wxFileDialog dialog(this, "Open a PNG file", "", "", "PNG files (*.png)|*.png", 0);
1bd1d102 853#endif
e2acb9ae
RR
854
855 if (dialog.ShowModal() != wxID_OK)
8e193f38 856 {
e2acb9ae
RR
857 wxLogMessage( _T("Aborted file open") );
858 return;
859 }
8e193f38 860
e2acb9ae 861 if (dialog.GetPath().IsEmpty())
8e193f38 862 {
e2acb9ae
RR
863 wxLogMessage( _T("Returned empty string.") );
864 return;
865 }
8e193f38 866
e2acb9ae
RR
867 if (!wxFileExists(dialog.GetPath()))
868 {
869 wxLogMessage( _T("File doesn't exist.") );
870 return;
871 }
8e193f38 872
e2acb9ae 873 wxImage image;
8e193f38 874 image.LoadFile( dialog.GetPath(),
1bd1d102
VZ
875#ifdef __WXMSW__
876 wxBITMAP_TYPE_BMP
877#else
878 wxBITMAP_TYPE_PNG
879#endif
880 );
e2acb9ae
RR
881 if (!image.Ok())
882 {
8e193f38 883 wxLogError( _T("Invalid image file...") );
e2acb9ae
RR
884 return;
885 }
8e193f38
VZ
886
887 wxLogStatus( _T("Decoding image file...") );
e2acb9ae 888 wxYield();
8e193f38 889
e2acb9ae
RR
890 wxBitmap bitmap( image.ConvertToBitmap() );
891
892 if ( !wxTheClipboard->Open() )
893 {
894 wxLogError(_T("Can't open clipboard."));
895
896 return;
897 }
898
899 wxLogMessage( _T("Creating wxBitmapDataObject...") );
900 wxYield();
8e193f38 901
e2acb9ae
RR
902 if ( !wxTheClipboard->AddData(new wxBitmapDataObject(bitmap)) )
903 {
904 wxLogError(_T("Can't copy image to the clipboard."));
905 }
906 else
907 {
908 wxLogMessage(_T("Image has been put on the clipboard.") );
909 wxLogMessage(_T("You can paste it now and look at it.") );
910 }
911
912 wxTheClipboard->Close();
913}
914
915void DnDFrame::OnPasteBitmap(wxCommandEvent& WXUNUSED(event))
916{
917 if ( !wxTheClipboard->Open() )
918 {
919 wxLogError(_T("Can't open clipboard."));
920
921 return;
922 }
923
924 if ( !wxTheClipboard->IsSupported(wxDF_BITMAP) )
925 {
926 wxLogWarning(_T("No bitmap on clipboard"));
927
928 wxTheClipboard->Close();
929 return;
930 }
931
932 wxBitmapDataObject data;
933 if ( !wxTheClipboard->GetData(&data) )
934 {
935 wxLogError(_T("Can't paste bitmap from the clipboard"));
936 }
937 else
938 {
939 wxLogMessage(_T("Bitmap pasted from the clipboard") );
8e193f38
VZ
940 m_bitmap = data.GetBitmap();
941 Refresh();
e2acb9ae
RR
942 }
943
944 wxTheClipboard->Close();
945}
946
947// ---------------------------------------------------------------------------
948// text clipboard
c50f1fb9
VZ
949// ---------------------------------------------------------------------------
950
951void DnDFrame::OnCopy(wxCommandEvent& WXUNUSED(event))
952{
953 if ( !wxTheClipboard->Open() )
954 {
b56baa2d 955 wxLogError(_T("Can't open clipboard."));
c50f1fb9
VZ
956
957 return;
958 }
959
960 if ( !wxTheClipboard->AddData(new wxTextDataObject(m_strText)) )
961 {
b56baa2d 962 wxLogError(_T("Can't copy data to the clipboard"));
c50f1fb9
VZ
963 }
964 else
965 {
b56baa2d 966 wxLogMessage(_T("Text '%s' put on the clipboard"), m_strText.c_str());
c50f1fb9
VZ
967 }
968
969 wxTheClipboard->Close();
970}
971
972void DnDFrame::OnPaste(wxCommandEvent& WXUNUSED(event))
973{
974 if ( !wxTheClipboard->Open() )
975 {
b56baa2d 976 wxLogError(_T("Can't open clipboard."));
c50f1fb9
VZ
977
978 return;
979 }
980
981 if ( !wxTheClipboard->IsSupported(wxDF_TEXT) )
982 {
b56baa2d 983 wxLogWarning(_T("No text data on clipboard"));
c50f1fb9 984
e2acb9ae 985 wxTheClipboard->Close();
c50f1fb9
VZ
986 return;
987 }
988
989 wxTextDataObject text;
990 if ( !wxTheClipboard->GetData(&text) )
991 {
b56baa2d 992 wxLogError(_T("Can't paste data from the clipboard"));
c50f1fb9
VZ
993 }
994 else
995 {
b56baa2d 996 wxLogMessage(_T("Text '%s' pasted from the clipboard"),
c50f1fb9
VZ
997 text.GetText().c_str());
998 }
999
1000 wxTheClipboard->Close();
457814b5
JS
1001}
1002
1003// ----------------------------------------------------------------------------
1004// Notifications called by the base class
1005// ----------------------------------------------------------------------------
e2acb9ae 1006
88ac883a 1007bool DnDText::OnDropText( wxDropPointCoord, wxDropPointCoord, const wxChar *psz )
457814b5 1008{
c50f1fb9 1009 m_pOwner->Append(psz);
457814b5 1010
c50f1fb9 1011 return TRUE;
457814b5
JS
1012}
1013
88ac883a 1014bool DnDFile::OnDropFiles( wxDropPointCoord, wxDropPointCoord, size_t nFiles,
b03b33e2 1015 const wxChar* const aszFiles[])
457814b5 1016{
c50f1fb9
VZ
1017 wxString str;
1018 str.Printf( _T("%d files dropped"), nFiles);
1019 m_pOwner->Append(str);
1020 for ( size_t n = 0; n < nFiles; n++ ) {
1021 m_pOwner->Append(aszFiles[n]);
1022 }
1023
1024 return TRUE;
457814b5 1025}
8e193f38
VZ
1026
1027// ----------------------------------------------------------------------------
1028// DnDShapeDialog
1029// ----------------------------------------------------------------------------
1030
1031DnDShapeDialog::DnDShapeDialog(wxFrame *parent, DnDShape *shape)
1032{
1033 m_shape = shape;
1034
1035 LoadFromResource(parent, "dialogShape");
1036
1037 m_textX = (wxTextCtrl *)wxFindWindowByName("textX", this);
1038 m_textY = (wxTextCtrl *)wxFindWindowByName("textY", this);
1039 m_textW = (wxTextCtrl *)wxFindWindowByName("textW", this);
1040 m_textH = (wxTextCtrl *)wxFindWindowByName("textH", this);
1041
1042 m_radio = (wxRadioBox *)wxFindWindowByName("radio", this);
1043}
1044
1045DnDShape *DnDShapeDialog::GetShape() const
1046{
1047 switch ( m_shapeKind )
1048 {
1049 default:
1050 case DnDShape::None: return NULL;
1051 case DnDShape::Triangle: return new DnDTriangularShape(m_pos, m_size, m_col);
1052 case DnDShape::Rectangle: return new DnDRectangularShape(m_pos, m_size, m_col);
1053 case DnDShape::Ellipse: return new DnDEllipticShape(m_pos, m_size, m_col);
1054 }
1055}
1056
1057bool DnDShapeDialog::TransferDataToWindow()
1058{
1059 if ( m_shape )
1060 {
1061 m_radio->SetSelection(m_shape->GetKind());
1062 m_pos = m_shape->GetPosition();
1063 m_size = m_shape->GetSize();
1064 m_col = m_shape->GetColour();
1065 }
1066 else
1067 {
1068 m_radio->SetSelection(DnDShape::None);
1069 m_pos = wxPoint(1, 1);
1070 m_size = wxSize(100, 100);
1071 }
1072
1073 m_textX->SetValue(wxString() << m_pos.x);
1074 m_textY->SetValue(wxString() << m_pos.y);
1075 m_textW->SetValue(wxString() << m_size.x);
1076 m_textH->SetValue(wxString() << m_size.y);
1077
1078 return TRUE;
1079}
1080
1081bool DnDShapeDialog::TransferDataFromWindow()
1082{
1083 m_shapeKind = (DnDShape::Kind)m_radio->GetSelection();
1084
1085 m_pos.x = atoi(m_textX->GetValue());
1086 m_pos.y = atoi(m_textY->GetValue());
1087 m_size.x = atoi(m_textW->GetValue());
1088 m_size.y = atoi(m_textH->GetValue());
1089
1090 if ( !m_pos.x || !m_pos.y || !m_size.x || !m_size.y )
1091 {
1092 wxMessageBox("All sizes and positions should be non null!",
1093 "Invalid shape", wxICON_HAND | wxOK, this);
1094
1095 return FALSE;
1096 }
1097
1098 return TRUE;
1099}
1100
1101void DnDShapeDialog::OnColour(wxCommandEvent& WXUNUSED(event))
1102{
1103 wxColourData data;
1104 data.SetChooseFull(TRUE);
1105 for (int i = 0; i < 16; i++)
1106 {
1107 wxColour colour(i*16, i*16, i*16);
1108 data.SetCustomColour(i, colour);
1109 }
1110
1111 wxColourDialog dialog(this, &data);
1112 if ( dialog.ShowModal() == wxID_OK )
1113 {
1114 m_col = dialog.GetColourData().GetColour();
1115 }
1116}
1117
1118// ----------------------------------------------------------------------------
1119// DnDShapeFrame
1120// ----------------------------------------------------------------------------
1121
d59ceba5
VZ
1122DnDShapeFrame *DnDShapeFrame::ms_lastDropTarget = NULL;
1123
8e193f38
VZ
1124DnDShapeFrame::DnDShapeFrame(wxFrame *parent)
1125 : wxFrame(parent, -1, "Shape Frame",
1126 wxDefaultPosition, wxSize(250, 150))
1127{
1128 SetBackgroundColour(*wxWHITE);
1129
1130 CreateStatusBar();
1131
d59ceba5
VZ
1132 wxMenu *menuShape = new wxMenu;
1133 menuShape->Append(Menu_Shape_New, "&New default shape\tCtrl-S");
1134 menuShape->Append(Menu_Shape_Edit, "&Edit shape\tCtrl-E");
1135 menuShape->AppendSeparator();
1136 menuShape->Append(Menu_Shape_Clear, "&Clear shape\tDel");
1137
1138 wxMenu *menuClipboard = new wxMenu;
1139 menuClipboard->Append(Menu_ShapeClipboard_Copy, "&Copy\tCtrl-C");
1140 menuClipboard->Append(Menu_ShapeClipboard_Paste, "&Paste\tCtrl-V");
1141
1142 wxMenuBar *menubar = new wxMenuBar;
1143 menubar->Append(menuShape, "&Shape");
1144 menubar->Append(menuClipboard, "&Clipboard");
1145
1146 SetMenuBar(menubar);
1147
1148 SetStatusText("Press Ctrl-S to create a new shape");
8e193f38
VZ
1149
1150 SetDropTarget(new DnDShapeDropTarget(this));
1151
1152 m_shape = NULL;
1153}
1154
1155DnDShapeFrame::~DnDShapeFrame()
1156{
1157 delete m_shape;
1158}
1159
1160void DnDShapeFrame::SetShape(DnDShape *shape)
1161{
1162 delete m_shape;
1163 m_shape = shape;
1164 Refresh();
1165}
1166
1167// callbacks
1168void DnDShapeFrame::OnDrag(wxMouseEvent& event)
1169{
1170 if ( !m_shape )
1171 {
1172 event.Skip();
1173
1174 return;
1175 }
1176
1177 // start drag operation
1178 DnDShapeDataObject shapeData(m_shape);
1179 wxDropSource source(shapeData, this, wxICON(mondrian));
1180
1181 const char *pc = NULL;
1182 switch ( source.DoDragDrop(TRUE) )
1183 {
1184 default:
1185 case wxDragError:
1186 wxLogError("An error occured during drag and drop operation");
1187 break;
1188
1189 case wxDragNone:
1190 SetStatusText("Nothing happened");
1191 break;
1192
1193 case wxDragCopy:
1194 pc = "copied";
1195 break;
1196
1197 case wxDragMove:
1198 pc = "moved";
d59ceba5
VZ
1199 if ( ms_lastDropTarget != this )
1200 {
1201 // don't delete the shape if we dropped it on ourselves!
1202 SetShape(NULL);
1203 }
8e193f38
VZ
1204 break;
1205
1206 case wxDragCancel:
1207 SetStatusText("Drag and drop operation cancelled");
1208 break;
1209 }
1210
1211 if ( pc )
1212 {
1213 SetStatusText(wxString("Shape successfully ") + pc);
1214 }
1215 //else: status text already set
1216}
1217
d59ceba5 1218void DnDShapeFrame::OnEditShape(wxCommandEvent& event)
8e193f38
VZ
1219{
1220 DnDShapeDialog dlg(this, m_shape);
1221 if ( dlg.ShowModal() == wxID_OK )
1222 {
1223 SetShape(dlg.GetShape());
1224
1225 if ( m_shape )
1226 {
d59ceba5 1227 SetStatusText("You can now drag the shape to another frame");
8e193f38
VZ
1228 }
1229 }
1230}
1231
d59ceba5
VZ
1232void DnDShapeFrame::OnNewShape(wxCommandEvent& event)
1233{
1234 SetShape(new DnDEllipticShape(wxPoint(10, 10), wxSize(80, 60), *wxRED));
1235
1236 SetStatusText("You can now drag the shape to another frame");
1237}
1238
1239void DnDShapeFrame::OnClearShape(wxCommandEvent& event)
1240{
1241 SetShape(NULL);
1242}
1243
1244void DnDShapeFrame::OnCopyShape(wxCommandEvent& event)
1245{
1246 if ( m_shape )
1247 wxTheClipboard->AddData(new DnDShapeDataObject(m_shape));
1248}
1249
1250void DnDShapeFrame::OnPasteShape(wxCommandEvent& event)
1251{
1252 DnDShapeDataObject shapeDataObject(NULL);
1253 if ( wxTheClipboard->GetData(&shapeDataObject) )
1254 {
1255 SetShape(shapeDataObject.GetShape());
1256 }
1257 else
1258 {
1259 wxLogStatus("No shape on the clipboard");
1260 }
1261}
1262
1263void DnDShapeFrame::OnUpdateUICopy(wxUpdateUIEvent& event)
1264{
1265 event.Enable( m_shape != NULL );
1266}
1267
1268void DnDShapeFrame::OnUpdateUIPaste(wxUpdateUIEvent& event)
1269{
1270 event.Enable( wxTheClipboard->IsSupported(wxDataFormat(shapeFormatId)) );
1271}
1272
8e193f38
VZ
1273void DnDShapeFrame::OnPaint(wxPaintEvent& event)
1274{
1275 if ( m_shape )
1276 m_shape->Draw(wxPaintDC(this));
1277 else
1278 event.Skip();
1279}
1280
1281void DnDShapeFrame::OnDrop(long x, long y, DnDShape *shape)
1282{
d59ceba5
VZ
1283 ms_lastDropTarget = this;
1284
8e193f38 1285 wxString s;
d59ceba5 1286 s.Printf("Shape dropped at (%ld, %ld)", x, y);
8e193f38
VZ
1287 SetStatusText(s);
1288
d59ceba5 1289 shape->Move(ScreenToClient(wxPoint(x, y)));
8e193f38
VZ
1290 SetShape(shape);
1291}
1292
1293// ----------------------------------------------------------------------------
1294// DnDShape
1295// ----------------------------------------------------------------------------
1296
1297DnDShape *DnDShape::New(const void *buf)
1298{
1299 const ShapeDump& dump = *(const ShapeDump *)buf;
1300 switch ( dump.k )
1301 {
1302 case Triangle:
1303 return new DnDTriangularShape(wxPoint(dump.x, dump.y),
1304 wxSize(dump.w, dump.h),
1305 wxColour(dump.r, dump.g, dump.b));
1306
1307 case Rectangle:
1308 return new DnDRectangularShape(wxPoint(dump.x, dump.y),
1309 wxSize(dump.w, dump.h),
1310 wxColour(dump.r, dump.g, dump.b));
1311
1312 case Ellipse:
1313 return new DnDEllipticShape(wxPoint(dump.x, dump.y),
1314 wxSize(dump.w, dump.h),
1315 wxColour(dump.r, dump.g, dump.b));
1316
1317 default:
1318 wxFAIL_MSG("invalid shape!");
1319 return NULL;
1320 }
1321}
1322
1323// ----------------------------------------------------------------------------
1324// DnDShapeDataObject
1325// ----------------------------------------------------------------------------
1326
1327void DnDShapeDataObject::CreateBitmap() const
1328{
d59ceba5
VZ
1329 wxPoint pos = m_shape->GetPosition();
1330 wxSize size = m_shape->GetSize();
1331 int x = pos.x + size.x,
1332 y = pos.y + size.y;
1333 wxBitmap bitmap(x, y);
8e193f38
VZ
1334 wxMemoryDC dc;
1335 dc.SelectObject(bitmap);
d59ceba5
VZ
1336 dc.SetBrush(wxBrush("white", wxSOLID));
1337 dc.Clear();
8e193f38
VZ
1338 m_shape->Draw(dc);
1339 dc.SelectObject(wxNullBitmap);
1340
1341 DnDShapeDataObject *self = (DnDShapeDataObject *)this; // const_cast
1342 self->m_dataobj.SetBitmap(bitmap);
1343 self->m_hasBitmap = TRUE;
1344}
1345