]> git.saurik.com Git - wxWidgets.git/blame - samples/dnd/dnd.cpp
README file (sparse) added.
[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
c50f1fb9
VZ
22#include "wx/intl.h"
23#include "wx/log.h"
457814b5 24
c50f1fb9 25#include "wx/dnd.h"
956dbab1 26#include "wx/dirdlg.h"
457814b5 27
acbd13a3 28#ifdef __WXMOTIF__
c50f1fb9 29 #error Sorry, drag and drop is not yet implemented on wxMotif.
acbd13a3
JS
30#endif
31
32#if defined(__WXGTK__) || defined(__WXMOTIF__)
c50f1fb9 33 #include "mondrian.xpm"
47908e25
RR
34#endif
35
c50f1fb9
VZ
36#include "wx/clipbrd.h"
37
457814b5 38// ----------------------------------------------------------------------------
2845ddc2 39// Derive two simple classes which just put in the listbox the strings (text or
457814b5
JS
40// file names) we drop on them
41// ----------------------------------------------------------------------------
ab8884ac 42
8dbf4589 43typedef long wxDropPointCoord;
88ac883a 44
457814b5
JS
45class DnDText : public wxTextDropTarget
46{
47public:
c50f1fb9 48 DnDText(wxListBox *pOwner) { m_pOwner = pOwner; }
457814b5 49
c50f1fb9
VZ
50 virtual bool OnDropText(wxDropPointCoord x, wxDropPointCoord y,
51 const wxChar* psz);
457814b5
JS
52
53private:
c50f1fb9 54 wxListBox *m_pOwner;
457814b5
JS
55};
56
57class DnDFile : public wxFileDropTarget
58{
59public:
c50f1fb9 60 DnDFile(wxListBox *pOwner) { m_pOwner = pOwner; }
457814b5 61
88ac883a 62 virtual bool OnDropFiles(wxDropPointCoord x, wxDropPointCoord y,
b03b33e2 63 size_t nFiles, const wxChar* const aszFiles[] );
457814b5
JS
64
65private:
c50f1fb9 66 wxListBox *m_pOwner;
457814b5
JS
67};
68
69// ----------------------------------------------------------------------------
70// Define a new application type
71// ----------------------------------------------------------------------------
ab8884ac 72
457814b5 73class DnDApp : public wxApp
8bbe427f 74{
457814b5 75public:
c50f1fb9 76 bool OnInit();
457814b5
JS
77};
78
79IMPLEMENT_APP(DnDApp);
80
81// ----------------------------------------------------------------------------
82// Define a new frame type
83// ----------------------------------------------------------------------------
84class DnDFrame : public wxFrame
8bbe427f 85{
457814b5 86public:
c50f1fb9
VZ
87 DnDFrame(wxFrame *frame, char *title, int x, int y, int w, int h);
88 ~DnDFrame();
457814b5 89
c50f1fb9
VZ
90 void OnPaint(wxPaintEvent& event);
91 void OnQuit (wxCommandEvent& event);
92 void OnAbout(wxCommandEvent& event);
93 void OnDrag (wxCommandEvent& event);
94 void OnHelp (wxCommandEvent& event);
95 void OnLogClear(wxCommandEvent& event);
96 void OnCopy(wxCommandEvent& event);
97 void OnPaste(wxCommandEvent& event);
43d811ea 98
c50f1fb9
VZ
99 void OnLeftDown(wxMouseEvent& event);
100 void OnRightDown(wxMouseEvent& event);
8bbe427f 101
c50f1fb9 102 DECLARE_EVENT_TABLE()
457814b5
JS
103
104private:
c50f1fb9
VZ
105 wxListBox *m_ctrlFile,
106 *m_ctrlText;
107 wxTextCtrl *m_ctrlLog;
457814b5 108
c50f1fb9 109 wxLog *m_pLog, *m_pLogPrev;
43d811ea 110
c50f1fb9 111 wxString m_strText;
457814b5
JS
112};
113
114// ----------------------------------------------------------------------------
115// IDs for the menu commands
116// ----------------------------------------------------------------------------
ab8884ac 117
457814b5
JS
118enum
119{
c50f1fb9
VZ
120 Menu_Quit = 1,
121 Menu_Drag,
122 Menu_About = 101,
123 Menu_Help,
124 Menu_Clear,
125 Menu_Copy,
126 Menu_Paste
457814b5
JS
127};
128
129BEGIN_EVENT_TABLE(DnDFrame, wxFrame)
c50f1fb9
VZ
130 EVT_MENU(Menu_Quit, DnDFrame::OnQuit)
131 EVT_MENU(Menu_About, DnDFrame::OnAbout)
132 EVT_MENU(Menu_Drag, DnDFrame::OnDrag)
133 EVT_MENU(Menu_Help, DnDFrame::OnHelp)
134 EVT_MENU(Menu_Clear, DnDFrame::OnLogClear)
135 EVT_MENU(Menu_Copy, DnDFrame::OnCopy)
136 EVT_MENU(Menu_Paste, DnDFrame::OnPaste)
137
138 EVT_LEFT_DOWN( DnDFrame::OnLeftDown)
139 EVT_RIGHT_DOWN( DnDFrame::OnRightDown)
140 EVT_PAINT( DnDFrame::OnPaint)
457814b5
JS
141END_EVENT_TABLE()
142
c50f1fb9 143 // `Main program' equivalent, creating windows and returning main app frame
8bbe427f 144bool DnDApp::OnInit()
457814b5 145{
c50f1fb9
VZ
146 // create the main frame window
147 DnDFrame *frame = new DnDFrame((wxFrame *) NULL,
148 "Drag-and-Drop/Clipboard wxWindows Sample",
149 50, 50, 450, 340);
457814b5 150
c50f1fb9
VZ
151 // activate it
152 frame->Show(TRUE);
457814b5 153
c50f1fb9 154 SetTopWindow(frame);
457814b5 155
c50f1fb9 156 return TRUE;
457814b5
JS
157}
158
159DnDFrame::DnDFrame(wxFrame *frame, char *title, int x, int y, int w, int h)
43d811ea
JS
160 : wxFrame(frame, -1, title, wxPoint(x, y), wxSize(w, h)),
161 m_strText("wxWindows drag & drop works :-)")
162
457814b5 163{
c50f1fb9
VZ
164 // frame icon and status bar
165 SetIcon(wxICON(mondrian));
166
167 CreateStatusBar();
168
169 // construct menu
170 wxMenu *file_menu = new wxMenu;
171 file_menu->Append(Menu_Drag, "&Test drag...");
172 file_menu->AppendSeparator();
173 file_menu->Append(Menu_Quit, "E&xit");
174
175 wxMenu *log_menu = new wxMenu;
176 log_menu->Append(Menu_Clear, "Clear");
177
178 wxMenu *help_menu = new wxMenu;
179 help_menu->Append(Menu_Help, "&Help...");
180 help_menu->AppendSeparator();
181 help_menu->Append(Menu_About, "&About");
182
183 wxMenu *clip_menu = new wxMenu;
184 clip_menu->Append(Menu_Copy, "&Copy\tCtrl+C");
185 clip_menu->Append(Menu_Paste, "&Paste\tCtrl+V");
186
187 wxMenuBar *menu_bar = new wxMenuBar;
188 menu_bar->Append(file_menu, "&File");
189 menu_bar->Append(log_menu, "&Log");
190 menu_bar->Append(clip_menu, "&Clipboard");
191 menu_bar->Append(help_menu, "&Help");
192
193 SetMenuBar(menu_bar);
194
195 // make a panel with 3 subwindows
196 wxPoint pos(0, 0);
197 wxSize size(400, 200);
198
199 wxString strFile("Drop files here!"), strText("Drop text on me");
200
201 m_ctrlFile = new wxListBox(this, -1, pos, size, 1, &strFile, wxLB_HSCROLL);
202 m_ctrlText = new wxListBox(this, -1, pos, size, 1, &strText, wxLB_HSCROLL);
203
204 m_ctrlLog = new wxTextCtrl(this, -1, "", pos, size,
8bbe427f 205 wxTE_MULTILINE | wxTE_READONLY |
5b077d48 206 wxSUNKEN_BORDER );
457814b5 207
8dbf4589
RR
208#if wxUSE_STD_IOSTREAM
209// redirect log messages to the text window (don't forget to delete it!)
43d811ea
JS
210 m_pLog = new wxLogTextCtrl(m_ctrlLog);
211 m_pLogPrev = wxLog::SetActiveTarget(m_pLog);
8dbf4589 212#endif
457814b5
JS
213
214 // associate drop targets with 2 text controls
bb14db2d 215 m_ctrlFile->SetDropTarget(new DnDFile(m_ctrlFile));
88ac883a 216 m_ctrlText->SetDropTarget(new DnDText(m_ctrlText));
457814b5 217
bb14db2d 218 wxLayoutConstraints *c;
457814b5 219
40e1a9c0 220 // Top-left listbox
457814b5 221 c = new wxLayoutConstraints;
8bbe427f
VZ
222 c->left.SameAs(this, wxLeft);
223 c->top.SameAs(this, wxTop);
457814b5 224 c->right.PercentOf(this, wxRight, 50);
43d811ea 225 c->height.PercentOf(this, wxHeight, 40);
457814b5
JS
226 m_ctrlFile->SetConstraints(c);
227
40e1a9c0 228 // Top-right listbox
457814b5
JS
229 c = new wxLayoutConstraints;
230 c->left.SameAs (m_ctrlFile, wxRight);
231 c->top.SameAs (this, wxTop);
232 c->right.SameAs (this, wxRight);
43d811ea 233 c->height.PercentOf(this, wxHeight, 40);
457814b5
JS
234 m_ctrlText->SetConstraints(c);
235
40e1a9c0 236 // Lower text control
457814b5
JS
237 c = new wxLayoutConstraints;
238 c->left.SameAs (this, wxLeft);
239 c->right.SameAs (this, wxRight);
43d811ea
JS
240 c->height.PercentOf(this, wxHeight, 40);
241 c->top.SameAs(m_ctrlText, wxBottom);
457814b5
JS
242 m_ctrlLog->SetConstraints(c);
243
244 SetAutoLayout(TRUE);
245}
246
247void DnDFrame::OnQuit(wxCommandEvent& /* event */)
248{
c50f1fb9 249 Close(TRUE);
457814b5
JS
250}
251
b527aac5
RR
252void DnDFrame::OnPaint(wxPaintEvent& /*event*/)
253{
c50f1fb9
VZ
254 int w = 0;
255 int h = 0;
256 GetClientSize( &w, &h );
8bbe427f 257
c50f1fb9
VZ
258 wxPaintDC dc(this);
259 dc.SetFont( wxFont( 24, wxDECORATIVE, wxNORMAL, wxNORMAL, FALSE, "charter" ) );
260 dc.DrawText( "Drag text from here!", 20, h-35 );
b527aac5
RR
261}
262
43d811ea
JS
263void DnDFrame::OnDrag(wxCommandEvent& /* event */)
264{
c50f1fb9
VZ
265 wxString strText = wxGetTextFromUser
266 (
267 "After you enter text in this dialog, press any mouse\n"
268 "button in the bottom (empty) part of the frame and \n"
269 "drag it anywhere - you will be in fact dragging the\n"
270 "text object containing this text",
271 "Please enter some text", m_strText, this
272 );
273
274 m_strText = strText;
43d811ea
JS
275}
276
457814b5
JS
277void DnDFrame::OnAbout(wxCommandEvent& /* event */)
278{
c50f1fb9
VZ
279 wxMessageBox("Drag-&-Drop Demo\n"
280 "Please see \"Help|Help...\" for details\n"
281 "Copyright (c) 1998 Vadim Zeitlin",
282 "About wxDnD",
283 wxICON_INFORMATION | wxOK,
284 this);
457814b5
JS
285}
286
287void DnDFrame::OnHelp(wxCommandEvent& /* event */)
288{
c50f1fb9
VZ
289 wxMessageDialog dialog(this,
290 "This small program demonstrates drag & drop support in wxWindows. The program window\n"
291 "consists of 3 parts: the bottom pane is for debug messages, so that you can see what's\n"
292 "going on inside. The top part is split into 2 listboxes, the left one accepts files\n"
293 "and the right one accepts text.\n"
294 "\n"
295 "To test wxDropTarget: open wordpad (write.exe), select some text in it and drag it to\n"
296 "the right listbox (you'll notice the usual visual feedback, i.e. the cursor will change).\n"
297 "Also, try dragging some files (you can select several at once) from Windows Explorer (or \n"
298 "File Manager) to the left pane. Hold down Ctrl/Shift keys when you drop text (doesn't \n"
299 "work with files) and see what changes.\n"
300 "\n"
301 "To test wxDropSource: just press any mouse button on the empty zone of the window and drag\n"
302 "it to wordpad or any other droptarget accepting text (and of course you can just drag it\n"
303 "to the right pane). Due to a lot of trace messages, the cursor might take some time to \n"
304 "change, don't release the mouse button until it does. You can change the string being\n"
305 "dragged in in \"File|Test drag...\" dialog.\n"
306 "\n"
307 "\n"
308 "Please send all questions/bug reports/suggestions &c to \n"
309 "Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>",
310 "wxDnD Help");
311
312 dialog.ShowModal();
457814b5
JS
313}
314
e3e65dac 315void DnDFrame::OnLogClear(wxCommandEvent& /* event */ )
43d811ea 316{
c50f1fb9 317 m_ctrlLog->Clear();
43d811ea
JS
318}
319
30dea054 320void DnDFrame::OnLeftDown(wxMouseEvent &WXUNUSED(event) )
43d811ea 321{
c50f1fb9
VZ
322 if ( !m_strText.IsEmpty() )
323 {
324 // start drag operation
0c77152e 325#ifdef __WXMSW__
c50f1fb9
VZ
326 wxTextDataObject textData(m_strText);
327 wxDropSource dragSource( textData, this );
0c77152e 328#else
c50f1fb9 329 wxDropSource dragSource( new wxTextDataObject (m_strText), this, wxIcon(mondrian_xpm) );
0c77152e 330#endif
c50f1fb9
VZ
331 const char *pc;
332
333 switch ( dragSource.DoDragDrop(TRUE) )
334 {
335 case wxDragError: pc = "Error!"; break;
336 case wxDragNone: pc = "Nothing"; break;
337 case wxDragCopy: pc = "Copied"; break;
338 case wxDragMove: pc = "Moved"; break;
339 case wxDragCancel: pc = "Cancelled"; break;
340 default: pc = "Huh?"; break;
341 }
342
343 SetStatusText(wxString("Drag result: ") + pc);
43d811ea 344 }
43d811ea
JS
345}
346
30dea054
RR
347void DnDFrame::OnRightDown(wxMouseEvent &event )
348{
c50f1fb9 349 wxMenu *menu = new wxMenu;
8bbe427f 350
c50f1fb9
VZ
351 menu->Append(Menu_Drag, "&Test drag...");
352 menu->Append(Menu_About, "&About");
353 menu->Append(Menu_Quit, "E&xit");
8bbe427f 354
c50f1fb9 355 PopupMenu( menu, event.GetX(), event.GetY() );
30dea054
RR
356}
357
457814b5
JS
358DnDFrame::~DnDFrame()
359{
8dbf4589 360#if wxUSE_STD_IOSTREAM
c50f1fb9
VZ
361 if ( m_pLog != NULL ) {
362 if ( wxLog::SetActiveTarget(m_pLogPrev) == m_pLog )
363 delete m_pLog;
364 }
8dbf4589 365#endif
c50f1fb9
VZ
366}
367
368// ---------------------------------------------------------------------------
369// clipboard
370// ---------------------------------------------------------------------------
371
372void DnDFrame::OnCopy(wxCommandEvent& WXUNUSED(event))
373{
374 if ( !wxTheClipboard->Open() )
375 {
b56baa2d 376 wxLogError(_T("Can't open clipboard."));
c50f1fb9
VZ
377
378 return;
379 }
380
381 if ( !wxTheClipboard->AddData(new wxTextDataObject(m_strText)) )
382 {
b56baa2d 383 wxLogError(_T("Can't copy data to the clipboard"));
c50f1fb9
VZ
384 }
385 else
386 {
b56baa2d 387 wxLogMessage(_T("Text '%s' put on the clipboard"), m_strText.c_str());
c50f1fb9
VZ
388 }
389
390 wxTheClipboard->Close();
391}
392
393void DnDFrame::OnPaste(wxCommandEvent& WXUNUSED(event))
394{
395 if ( !wxTheClipboard->Open() )
396 {
b56baa2d 397 wxLogError(_T("Can't open clipboard."));
c50f1fb9
VZ
398
399 return;
400 }
401
402 if ( !wxTheClipboard->IsSupported(wxDF_TEXT) )
403 {
b56baa2d 404 wxLogWarning(_T("No text data on clipboard"));
c50f1fb9
VZ
405
406 return;
407 }
408
409 wxTextDataObject text;
410 if ( !wxTheClipboard->GetData(&text) )
411 {
b56baa2d 412 wxLogError(_T("Can't paste data from the clipboard"));
c50f1fb9
VZ
413 }
414 else
415 {
b56baa2d 416 wxLogMessage(_T("Text '%s' pasted from the clipboard"),
c50f1fb9
VZ
417 text.GetText().c_str());
418 }
419
420 wxTheClipboard->Close();
457814b5
JS
421}
422
423// ----------------------------------------------------------------------------
424// Notifications called by the base class
425// ----------------------------------------------------------------------------
88ac883a 426bool DnDText::OnDropText( wxDropPointCoord, wxDropPointCoord, const wxChar *psz )
457814b5 427{
c50f1fb9 428 m_pOwner->Append(psz);
457814b5 429
c50f1fb9 430 return TRUE;
457814b5
JS
431}
432
88ac883a 433bool DnDFile::OnDropFiles( wxDropPointCoord, wxDropPointCoord, size_t nFiles,
b03b33e2 434 const wxChar* const aszFiles[])
457814b5 435{
c50f1fb9
VZ
436 wxString str;
437 str.Printf( _T("%d files dropped"), nFiles);
438 m_pOwner->Append(str);
439 for ( size_t n = 0; n < nFiles; n++ ) {
440 m_pOwner->Append(aszFiles[n]);
441 }
442
443 return TRUE;
457814b5 444}