]> git.saurik.com Git - wxWidgets.git/blame - samples/dnd/dnd.cpp
wxDialUpManager class (first draft, works only under Windows NT for now)
[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
e2acb9ae
RR
22#ifdef __WXMOTIF__
23 #error Sorry, drag and drop is not yet implemented on wxMotif.
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"
acbd13a3
JS
34
35#if defined(__WXGTK__) || defined(__WXMOTIF__)
c50f1fb9 36 #include "mondrian.xpm"
47908e25
RR
37#endif
38
457814b5 39// ----------------------------------------------------------------------------
2845ddc2 40// Derive two simple classes which just put in the listbox the strings (text or
457814b5
JS
41// file names) we drop on them
42// ----------------------------------------------------------------------------
ab8884ac 43
8dbf4589 44typedef long wxDropPointCoord;
88ac883a 45
457814b5
JS
46class DnDText : public wxTextDropTarget
47{
48public:
c50f1fb9 49 DnDText(wxListBox *pOwner) { m_pOwner = pOwner; }
457814b5 50
c50f1fb9
VZ
51 virtual bool OnDropText(wxDropPointCoord x, wxDropPointCoord y,
52 const wxChar* psz);
457814b5
JS
53
54private:
c50f1fb9 55 wxListBox *m_pOwner;
457814b5
JS
56};
57
58class DnDFile : public wxFileDropTarget
59{
60public:
c50f1fb9 61 DnDFile(wxListBox *pOwner) { m_pOwner = pOwner; }
457814b5 62
88ac883a 63 virtual bool OnDropFiles(wxDropPointCoord x, wxDropPointCoord y,
b03b33e2 64 size_t nFiles, const wxChar* const aszFiles[] );
457814b5
JS
65
66private:
c50f1fb9 67 wxListBox *m_pOwner;
457814b5
JS
68};
69
70// ----------------------------------------------------------------------------
71// Define a new application type
72// ----------------------------------------------------------------------------
ab8884ac 73
457814b5 74class DnDApp : public wxApp
8bbe427f 75{
457814b5 76public:
c50f1fb9 77 bool OnInit();
457814b5
JS
78};
79
80IMPLEMENT_APP(DnDApp);
81
82// ----------------------------------------------------------------------------
83// Define a new frame type
84// ----------------------------------------------------------------------------
85class DnDFrame : public wxFrame
8bbe427f 86{
457814b5 87public:
c50f1fb9
VZ
88 DnDFrame(wxFrame *frame, char *title, int x, int y, int w, int h);
89 ~DnDFrame();
457814b5 90
c50f1fb9
VZ
91 void OnPaint(wxPaintEvent& event);
92 void OnQuit (wxCommandEvent& event);
93 void OnAbout(wxCommandEvent& event);
94 void OnDrag (wxCommandEvent& event);
95 void OnHelp (wxCommandEvent& event);
96 void OnLogClear(wxCommandEvent& event);
97 void OnCopy(wxCommandEvent& event);
98 void OnPaste(wxCommandEvent& event);
e2acb9ae
RR
99 void OnCopyBitmap(wxCommandEvent& event);
100 void OnPasteBitmap(wxCommandEvent& event);
101 void OnClipboardHasText(wxCommandEvent& event);
102 void OnClipboardHasBitmap(wxCommandEvent& event);
43d811ea 103
c50f1fb9
VZ
104 void OnLeftDown(wxMouseEvent& event);
105 void OnRightDown(wxMouseEvent& event);
8bbe427f 106
c50f1fb9 107 DECLARE_EVENT_TABLE()
457814b5
JS
108
109private:
e2acb9ae
RR
110 wxListBox *m_ctrlFile,
111 *m_ctrlText;
112 wxTextCtrl *m_ctrlLog;
457814b5 113
e2acb9ae 114 wxLog *m_pLog, *m_pLogPrev;
43d811ea 115
e2acb9ae
RR
116 wxString m_strText;
117 wxBitmap m_bitmap;
457814b5
JS
118};
119
120// ----------------------------------------------------------------------------
121// IDs for the menu commands
122// ----------------------------------------------------------------------------
ab8884ac 123
457814b5
JS
124enum
125{
c50f1fb9
VZ
126 Menu_Quit = 1,
127 Menu_Drag,
128 Menu_About = 101,
129 Menu_Help,
130 Menu_Clear,
131 Menu_Copy,
e2acb9ae
RR
132 Menu_Paste,
133 Menu_CopyBitmap,
134 Menu_PasteBitmap,
135 Menu_HasText,
136 Menu_HasBitmap
457814b5
JS
137};
138
139BEGIN_EVENT_TABLE(DnDFrame, wxFrame)
e2acb9ae
RR
140 EVT_MENU(Menu_Quit, DnDFrame::OnQuit)
141 EVT_MENU(Menu_About, DnDFrame::OnAbout)
142 EVT_MENU(Menu_Drag, DnDFrame::OnDrag)
143 EVT_MENU(Menu_Help, DnDFrame::OnHelp)
144 EVT_MENU(Menu_Clear, DnDFrame::OnLogClear)
145 EVT_MENU(Menu_Copy, DnDFrame::OnCopy)
146 EVT_MENU(Menu_Paste, DnDFrame::OnPaste)
147 EVT_MENU(Menu_CopyBitmap, DnDFrame::OnCopyBitmap)
148 EVT_MENU(Menu_PasteBitmap,DnDFrame::OnPasteBitmap)
149 EVT_MENU(Menu_HasText, DnDFrame::OnClipboardHasText)
150 EVT_MENU(Menu_HasBitmap, DnDFrame::OnClipboardHasBitmap)
151
152 EVT_LEFT_DOWN( DnDFrame::OnLeftDown)
153 EVT_RIGHT_DOWN( DnDFrame::OnRightDown)
154 EVT_PAINT( DnDFrame::OnPaint)
457814b5
JS
155END_EVENT_TABLE()
156
c50f1fb9 157 // `Main program' equivalent, creating windows and returning main app frame
8bbe427f 158bool DnDApp::OnInit()
457814b5 159{
e2acb9ae
RR
160#if wxUSE_LIBPNG
161 wxImage::AddHandler( new wxPNGHandler );
162#endif
163
c50f1fb9
VZ
164 // create the main frame window
165 DnDFrame *frame = new DnDFrame((wxFrame *) NULL,
166 "Drag-and-Drop/Clipboard wxWindows Sample",
167 50, 50, 450, 340);
457814b5 168
c50f1fb9
VZ
169 // activate it
170 frame->Show(TRUE);
457814b5 171
c50f1fb9 172 SetTopWindow(frame);
457814b5 173
c50f1fb9 174 return TRUE;
457814b5
JS
175}
176
177DnDFrame::DnDFrame(wxFrame *frame, char *title, int x, int y, int w, int h)
43d811ea
JS
178 : wxFrame(frame, -1, title, wxPoint(x, y), wxSize(w, h)),
179 m_strText("wxWindows drag & drop works :-)")
180
457814b5 181{
c50f1fb9
VZ
182 // frame icon and status bar
183 SetIcon(wxICON(mondrian));
184
185 CreateStatusBar();
186
187 // construct menu
188 wxMenu *file_menu = new wxMenu;
189 file_menu->Append(Menu_Drag, "&Test drag...");
190 file_menu->AppendSeparator();
191 file_menu->Append(Menu_Quit, "E&xit");
192
193 wxMenu *log_menu = new wxMenu;
194 log_menu->Append(Menu_Clear, "Clear");
195
196 wxMenu *help_menu = new wxMenu;
197 help_menu->Append(Menu_Help, "&Help...");
198 help_menu->AppendSeparator();
199 help_menu->Append(Menu_About, "&About");
200
201 wxMenu *clip_menu = new wxMenu;
e2acb9ae
RR
202 clip_menu->Append(Menu_Copy, "&Copy text\tCtrl+C");
203 clip_menu->Append(Menu_Paste, "&Paste text\tCtrl+V");
204 clip_menu->AppendSeparator();
205 clip_menu->Append(Menu_CopyBitmap, "&Copy bitmap");
206 clip_menu->Append(Menu_PasteBitmap, "&Paste bitmap");
207 clip_menu->AppendSeparator();
208 clip_menu->Append(Menu_HasText, "Clipboard has &text\tCtrl+T");
209 clip_menu->Append(Menu_HasBitmap, "Clipboard has a &bitmap\tCtrl+B");
210
c50f1fb9
VZ
211 wxMenuBar *menu_bar = new wxMenuBar;
212 menu_bar->Append(file_menu, "&File");
213 menu_bar->Append(log_menu, "&Log");
214 menu_bar->Append(clip_menu, "&Clipboard");
215 menu_bar->Append(help_menu, "&Help");
216
217 SetMenuBar(menu_bar);
218
219 // make a panel with 3 subwindows
220 wxPoint pos(0, 0);
221 wxSize size(400, 200);
222
223 wxString strFile("Drop files here!"), strText("Drop text on me");
224
e2acb9ae
RR
225 m_ctrlFile = new wxListBox(this, -1, pos, size, 1, &strFile, wxLB_HSCROLL | wxLB_ALWAYS_SB );
226 m_ctrlText = new wxListBox(this, -1, pos, size, 1, &strText, wxLB_HSCROLL | wxLB_ALWAYS_SB );
c50f1fb9
VZ
227
228 m_ctrlLog = new wxTextCtrl(this, -1, "", pos, size,
8bbe427f 229 wxTE_MULTILINE | wxTE_READONLY |
5b077d48 230 wxSUNKEN_BORDER );
e2acb9ae
RR
231 // redirect log messages to the text window (don't forget to delete it!)
232 m_pLog = new wxLogTextCtrl(m_ctrlLog);
233 m_pLogPrev = wxLog::SetActiveTarget(m_pLog);
234
235 // associate drop targets with 2 text controls
236 m_ctrlFile->SetDropTarget(new DnDFile(m_ctrlFile));
237 m_ctrlText->SetDropTarget(new DnDText(m_ctrlText));
238
239 wxLayoutConstraints *c;
240
241 // Top-left listbox
242 c = new wxLayoutConstraints;
243 c->left.SameAs(this, wxLeft);
244 c->top.SameAs(this, wxTop);
245 c->right.PercentOf(this, wxRight, 50);
246 c->height.PercentOf(this, wxHeight, 30);
247 m_ctrlFile->SetConstraints(c);
248
249 // Top-right listbox
250 c = new wxLayoutConstraints;
251 c->left.SameAs (m_ctrlFile, wxRight);
252 c->top.SameAs (this, wxTop);
253 c->right.SameAs (this, wxRight);
254 c->height.PercentOf(this, wxHeight, 30);
255 m_ctrlText->SetConstraints(c);
256
257 // Lower text control
258 c = new wxLayoutConstraints;
259 c->left.SameAs (this, wxLeft);
260 c->right.SameAs (this, wxRight);
261 c->height.PercentOf(this, wxHeight, 30);
262 c->top.SameAs(m_ctrlText, wxBottom);
263 m_ctrlLog->SetConstraints(c);
264
265 SetAutoLayout(TRUE);
457814b5
JS
266}
267
e2acb9ae 268void DnDFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
457814b5 269{
c50f1fb9 270 Close(TRUE);
457814b5
JS
271}
272
e2acb9ae 273void DnDFrame::OnPaint(wxPaintEvent& WXUNUSED(event))
b527aac5 274{
c50f1fb9
VZ
275 int w = 0;
276 int h = 0;
277 GetClientSize( &w, &h );
8bbe427f 278
c50f1fb9
VZ
279 wxPaintDC dc(this);
280 dc.SetFont( wxFont( 24, wxDECORATIVE, wxNORMAL, wxNORMAL, FALSE, "charter" ) );
e2acb9ae
RR
281 dc.DrawText( "Drag text from here!", 20, h-50 );
282
283 if (m_bitmap.Ok())
284 dc.DrawBitmap( m_bitmap, 280, h-120, TRUE );
b527aac5
RR
285}
286
e2acb9ae
RR
287void DnDFrame::OnClipboardHasText(wxCommandEvent& WXUNUSED(event))
288{
289 if ( !wxTheClipboard->Open() )
290 {
291 wxLogError( _T("Can't open clipboard.") );
292
293 return;
294 }
295
296 if ( !wxTheClipboard->IsSupported( wxDF_TEXT ) )
297 {
298 wxLogMessage( _T("No text is on the clipboard") );
299 }
300 else
301 {
302 wxLogMessage( _T("There is text is on the clipboard") );
303 }
304
305 wxTheClipboard->Close();
306}
307
308void DnDFrame::OnClipboardHasBitmap(wxCommandEvent& WXUNUSED(event))
309{
310 if ( !wxTheClipboard->Open() )
311 {
312 wxLogError( _T("Can't open clipboard.") );
313
314 return;
315 }
316
317 if ( !wxTheClipboard->IsSupported( wxDF_BITMAP ) )
318 {
319 wxLogMessage( _T("No bitmap is on the clipboard") );
320 }
321 else
322 {
323 wxLogMessage( _T("A bitmap is on the clipboard") );
324 }
325
326 wxTheClipboard->Close();
327}
328
329void DnDFrame::OnDrag(wxCommandEvent& WXUNUSED(event))
43d811ea 330{
c50f1fb9
VZ
331 wxString strText = wxGetTextFromUser
332 (
333 "After you enter text in this dialog, press any mouse\n"
334 "button in the bottom (empty) part of the frame and \n"
335 "drag it anywhere - you will be in fact dragging the\n"
336 "text object containing this text",
337 "Please enter some text", m_strText, this
338 );
339
340 m_strText = strText;
43d811ea
JS
341}
342
e2acb9ae 343void DnDFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
457814b5 344{
c50f1fb9
VZ
345 wxMessageBox("Drag-&-Drop Demo\n"
346 "Please see \"Help|Help...\" for details\n"
347 "Copyright (c) 1998 Vadim Zeitlin",
348 "About wxDnD",
349 wxICON_INFORMATION | wxOK,
350 this);
457814b5
JS
351}
352
353void DnDFrame::OnHelp(wxCommandEvent& /* event */)
354{
c50f1fb9
VZ
355 wxMessageDialog dialog(this,
356 "This small program demonstrates drag & drop support in wxWindows. The program window\n"
357 "consists of 3 parts: the bottom pane is for debug messages, so that you can see what's\n"
358 "going on inside. The top part is split into 2 listboxes, the left one accepts files\n"
359 "and the right one accepts text.\n"
360 "\n"
361 "To test wxDropTarget: open wordpad (write.exe), select some text in it and drag it to\n"
362 "the right listbox (you'll notice the usual visual feedback, i.e. the cursor will change).\n"
363 "Also, try dragging some files (you can select several at once) from Windows Explorer (or \n"
364 "File Manager) to the left pane. Hold down Ctrl/Shift keys when you drop text (doesn't \n"
365 "work with files) and see what changes.\n"
366 "\n"
367 "To test wxDropSource: just press any mouse button on the empty zone of the window and drag\n"
368 "it to wordpad or any other droptarget accepting text (and of course you can just drag it\n"
369 "to the right pane). Due to a lot of trace messages, the cursor might take some time to \n"
370 "change, don't release the mouse button until it does. You can change the string being\n"
371 "dragged in in \"File|Test drag...\" dialog.\n"
372 "\n"
373 "\n"
374 "Please send all questions/bug reports/suggestions &c to \n"
375 "Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>",
376 "wxDnD Help");
377
378 dialog.ShowModal();
457814b5
JS
379}
380
e3e65dac 381void DnDFrame::OnLogClear(wxCommandEvent& /* event */ )
43d811ea 382{
c50f1fb9 383 m_ctrlLog->Clear();
43d811ea
JS
384}
385
30dea054 386void DnDFrame::OnLeftDown(wxMouseEvent &WXUNUSED(event) )
43d811ea 387{
c50f1fb9
VZ
388 if ( !m_strText.IsEmpty() )
389 {
390 // start drag operation
0c77152e 391#ifdef __WXMSW__
c50f1fb9
VZ
392 wxTextDataObject textData(m_strText);
393 wxDropSource dragSource( textData, this );
0c77152e 394#else
c50f1fb9 395 wxDropSource dragSource( new wxTextDataObject (m_strText), this, wxIcon(mondrian_xpm) );
0c77152e 396#endif
c50f1fb9
VZ
397 const char *pc;
398
399 switch ( dragSource.DoDragDrop(TRUE) )
400 {
401 case wxDragError: pc = "Error!"; break;
402 case wxDragNone: pc = "Nothing"; break;
403 case wxDragCopy: pc = "Copied"; break;
404 case wxDragMove: pc = "Moved"; break;
405 case wxDragCancel: pc = "Cancelled"; break;
406 default: pc = "Huh?"; break;
407 }
408
409 SetStatusText(wxString("Drag result: ") + pc);
43d811ea 410 }
43d811ea
JS
411}
412
30dea054
RR
413void DnDFrame::OnRightDown(wxMouseEvent &event )
414{
c50f1fb9 415 wxMenu *menu = new wxMenu;
8bbe427f 416
c50f1fb9
VZ
417 menu->Append(Menu_Drag, "&Test drag...");
418 menu->Append(Menu_About, "&About");
419 menu->Append(Menu_Quit, "E&xit");
8bbe427f 420
c50f1fb9 421 PopupMenu( menu, event.GetX(), event.GetY() );
30dea054
RR
422}
423
457814b5
JS
424DnDFrame::~DnDFrame()
425{
c50f1fb9
VZ
426 if ( m_pLog != NULL ) {
427 if ( wxLog::SetActiveTarget(m_pLogPrev) == m_pLog )
428 delete m_pLog;
429 }
430}
431
432// ---------------------------------------------------------------------------
e2acb9ae
RR
433// bitmap clipboard
434// ---------------------------------------------------------------------------
435
436void DnDFrame::OnCopyBitmap(wxCommandEvent& WXUNUSED(event))
437{
438 wxFileDialog dialog(this, "Open a PNG file", "", "", "PNG files (*.png)|*.png", 0);
439
440 if (dialog.ShowModal() != wxID_OK)
441 {
442 wxLogMessage( _T("Aborted file open") );
443 return;
444 }
445
446 if (dialog.GetPath().IsEmpty())
447 {
448 wxLogMessage( _T("Returned empty string.") );
449 return;
450 }
451
452 if (!wxFileExists(dialog.GetPath()))
453 {
454 wxLogMessage( _T("File doesn't exist.") );
455 return;
456 }
457
458 wxImage image;
459 image.LoadFile( dialog.GetPath(), wxBITMAP_TYPE_PNG );
460 if (!image.Ok())
461 {
462 wxLogMessage( _T("Invalid image file...") );
463 return;
464 }
465
466 wxLogMessage( _T("Decoding image file...") );
467 wxYield();
468
469 wxBitmap bitmap( image.ConvertToBitmap() );
470
471 if ( !wxTheClipboard->Open() )
472 {
473 wxLogError(_T("Can't open clipboard."));
474
475 return;
476 }
477
478 wxLogMessage( _T("Creating wxBitmapDataObject...") );
479 wxYield();
480
481 if ( !wxTheClipboard->AddData(new wxBitmapDataObject(bitmap)) )
482 {
483 wxLogError(_T("Can't copy image to the clipboard."));
484 }
485 else
486 {
487 wxLogMessage(_T("Image has been put on the clipboard.") );
488 wxLogMessage(_T("You can paste it now and look at it.") );
489 }
490
491 wxTheClipboard->Close();
492}
493
494void DnDFrame::OnPasteBitmap(wxCommandEvent& WXUNUSED(event))
495{
496 if ( !wxTheClipboard->Open() )
497 {
498 wxLogError(_T("Can't open clipboard."));
499
500 return;
501 }
502
503 if ( !wxTheClipboard->IsSupported(wxDF_BITMAP) )
504 {
505 wxLogWarning(_T("No bitmap on clipboard"));
506
507 wxTheClipboard->Close();
508 return;
509 }
510
511 wxBitmapDataObject data;
512 if ( !wxTheClipboard->GetData(&data) )
513 {
514 wxLogError(_T("Can't paste bitmap from the clipboard"));
515 }
516 else
517 {
518 wxLogMessage(_T("Bitmap pasted from the clipboard") );
519 m_bitmap = data.GetBitmap();
520 Refresh();
521 }
522
523 wxTheClipboard->Close();
524}
525
526// ---------------------------------------------------------------------------
527// text clipboard
c50f1fb9
VZ
528// ---------------------------------------------------------------------------
529
530void DnDFrame::OnCopy(wxCommandEvent& WXUNUSED(event))
531{
532 if ( !wxTheClipboard->Open() )
533 {
b56baa2d 534 wxLogError(_T("Can't open clipboard."));
c50f1fb9
VZ
535
536 return;
537 }
538
539 if ( !wxTheClipboard->AddData(new wxTextDataObject(m_strText)) )
540 {
b56baa2d 541 wxLogError(_T("Can't copy data to the clipboard"));
c50f1fb9
VZ
542 }
543 else
544 {
b56baa2d 545 wxLogMessage(_T("Text '%s' put on the clipboard"), m_strText.c_str());
c50f1fb9
VZ
546 }
547
548 wxTheClipboard->Close();
549}
550
551void DnDFrame::OnPaste(wxCommandEvent& WXUNUSED(event))
552{
553 if ( !wxTheClipboard->Open() )
554 {
b56baa2d 555 wxLogError(_T("Can't open clipboard."));
c50f1fb9
VZ
556
557 return;
558 }
559
560 if ( !wxTheClipboard->IsSupported(wxDF_TEXT) )
561 {
b56baa2d 562 wxLogWarning(_T("No text data on clipboard"));
c50f1fb9 563
e2acb9ae 564 wxTheClipboard->Close();
c50f1fb9
VZ
565 return;
566 }
567
568 wxTextDataObject text;
569 if ( !wxTheClipboard->GetData(&text) )
570 {
b56baa2d 571 wxLogError(_T("Can't paste data from the clipboard"));
c50f1fb9
VZ
572 }
573 else
574 {
b56baa2d 575 wxLogMessage(_T("Text '%s' pasted from the clipboard"),
c50f1fb9
VZ
576 text.GetText().c_str());
577 }
578
579 wxTheClipboard->Close();
457814b5
JS
580}
581
582// ----------------------------------------------------------------------------
583// Notifications called by the base class
584// ----------------------------------------------------------------------------
e2acb9ae 585
88ac883a 586bool DnDText::OnDropText( wxDropPointCoord, wxDropPointCoord, const wxChar *psz )
457814b5 587{
c50f1fb9 588 m_pOwner->Append(psz);
457814b5 589
c50f1fb9 590 return TRUE;
457814b5
JS
591}
592
88ac883a 593bool DnDFile::OnDropFiles( wxDropPointCoord, wxDropPointCoord, size_t nFiles,
b03b33e2 594 const wxChar* const aszFiles[])
457814b5 595{
c50f1fb9
VZ
596 wxString str;
597 str.Printf( _T("%d files dropped"), nFiles);
598 m_pOwner->Append(str);
599 for ( size_t n = 0; n < nFiles; n++ ) {
600 m_pOwner->Append(aszFiles[n]);
601 }
602
603 return TRUE;
457814b5 604}