Applied patch for stipppled brushes,
[wxWidgets.git] / samples / dnd / dnd.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: dnd.cpp
3 // Purpose: Drag and drop sample
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright:
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13
14 #ifdef __BORLANDC__
15 #pragma hdrstop
16 #endif
17
18 #ifndef WX_PRECOMP
19 #include "wx/wx.h"
20 #endif
21
22 #include "wx/intl.h"
23 #include "wx/log.h"
24
25 #include "wx/dnd.h"
26 #include "wx/dirdlg.h"
27
28 #ifdef __WXMOTIF__
29 #error Sorry, drag and drop is not yet implemented on wxMotif.
30 #endif
31
32 #if defined(__WXGTK__) || defined(__WXMOTIF__)
33 #include "mondrian.xpm"
34 #endif
35
36 #include "wx/clipbrd.h"
37
38 // ----------------------------------------------------------------------------
39 // Derive two simple classes which just put in the listbox the strings (text or
40 // file names) we drop on them
41 // ----------------------------------------------------------------------------
42
43 typedef long wxDropPointCoord;
44
45 class DnDText : public wxTextDropTarget
46 {
47 public:
48 DnDText(wxListBox *pOwner) { m_pOwner = pOwner; }
49
50 virtual bool OnDropText(wxDropPointCoord x, wxDropPointCoord y,
51 const wxChar* psz);
52
53 private:
54 wxListBox *m_pOwner;
55 };
56
57 class DnDFile : public wxFileDropTarget
58 {
59 public:
60 DnDFile(wxListBox *pOwner) { m_pOwner = pOwner; }
61
62 virtual bool OnDropFiles(wxDropPointCoord x, wxDropPointCoord y,
63 size_t nFiles, const wxChar* const aszFiles[] );
64
65 private:
66 wxListBox *m_pOwner;
67 };
68
69 // ----------------------------------------------------------------------------
70 // Define a new application type
71 // ----------------------------------------------------------------------------
72
73 class DnDApp : public wxApp
74 {
75 public:
76 bool OnInit();
77 };
78
79 IMPLEMENT_APP(DnDApp);
80
81 // ----------------------------------------------------------------------------
82 // Define a new frame type
83 // ----------------------------------------------------------------------------
84 class DnDFrame : public wxFrame
85 {
86 public:
87 DnDFrame(wxFrame *frame, char *title, int x, int y, int w, int h);
88 ~DnDFrame();
89
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);
98
99 void OnLeftDown(wxMouseEvent& event);
100 void OnRightDown(wxMouseEvent& event);
101
102 DECLARE_EVENT_TABLE()
103
104 private:
105 wxListBox *m_ctrlFile,
106 *m_ctrlText;
107 wxTextCtrl *m_ctrlLog;
108
109 wxLog *m_pLog, *m_pLogPrev;
110
111 wxString m_strText;
112 };
113
114 // ----------------------------------------------------------------------------
115 // IDs for the menu commands
116 // ----------------------------------------------------------------------------
117
118 enum
119 {
120 Menu_Quit = 1,
121 Menu_Drag,
122 Menu_About = 101,
123 Menu_Help,
124 Menu_Clear,
125 Menu_Copy,
126 Menu_Paste
127 };
128
129 BEGIN_EVENT_TABLE(DnDFrame, wxFrame)
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)
141 END_EVENT_TABLE()
142
143 // `Main program' equivalent, creating windows and returning main app frame
144 bool DnDApp::OnInit()
145 {
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);
150
151 // activate it
152 frame->Show(TRUE);
153
154 SetTopWindow(frame);
155
156 return TRUE;
157 }
158
159 DnDFrame::DnDFrame(wxFrame *frame, char *title, int x, int y, int w, int h)
160 : wxFrame(frame, -1, title, wxPoint(x, y), wxSize(w, h)),
161 m_strText("wxWindows drag & drop works :-)")
162
163 {
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,
205 wxTE_MULTILINE | wxTE_READONLY |
206 wxSUNKEN_BORDER );
207
208 #if wxUSE_STD_IOSTREAM
209 // redirect log messages to the text window (don't forget to delete it!)
210 m_pLog = new wxLogTextCtrl(m_ctrlLog);
211 m_pLogPrev = wxLog::SetActiveTarget(m_pLog);
212 #endif
213
214 // associate drop targets with 2 text controls
215 m_ctrlFile->SetDropTarget(new DnDFile(m_ctrlFile));
216 m_ctrlText->SetDropTarget(new DnDText(m_ctrlText));
217
218 wxLayoutConstraints *c;
219
220 // Top-left listbox
221 c = new wxLayoutConstraints;
222 c->left.SameAs(this, wxLeft);
223 c->top.SameAs(this, wxTop);
224 c->right.PercentOf(this, wxRight, 50);
225 c->height.PercentOf(this, wxHeight, 40);
226 m_ctrlFile->SetConstraints(c);
227
228 // Top-right listbox
229 c = new wxLayoutConstraints;
230 c->left.SameAs (m_ctrlFile, wxRight);
231 c->top.SameAs (this, wxTop);
232 c->right.SameAs (this, wxRight);
233 c->height.PercentOf(this, wxHeight, 40);
234 m_ctrlText->SetConstraints(c);
235
236 // Lower text control
237 c = new wxLayoutConstraints;
238 c->left.SameAs (this, wxLeft);
239 c->right.SameAs (this, wxRight);
240 c->height.PercentOf(this, wxHeight, 40);
241 c->top.SameAs(m_ctrlText, wxBottom);
242 m_ctrlLog->SetConstraints(c);
243
244 SetAutoLayout(TRUE);
245 }
246
247 void DnDFrame::OnQuit(wxCommandEvent& /* event */)
248 {
249 Close(TRUE);
250 }
251
252 void DnDFrame::OnPaint(wxPaintEvent& /*event*/)
253 {
254 int w = 0;
255 int h = 0;
256 GetClientSize( &w, &h );
257
258 wxPaintDC dc(this);
259 dc.SetFont( wxFont( 24, wxDECORATIVE, wxNORMAL, wxNORMAL, FALSE, "charter" ) );
260 dc.DrawText( "Drag text from here!", 20, h-35 );
261 }
262
263 void DnDFrame::OnDrag(wxCommandEvent& /* event */)
264 {
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;
275 }
276
277 void DnDFrame::OnAbout(wxCommandEvent& /* event */)
278 {
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);
285 }
286
287 void DnDFrame::OnHelp(wxCommandEvent& /* event */)
288 {
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();
313 }
314
315 void DnDFrame::OnLogClear(wxCommandEvent& /* event */ )
316 {
317 m_ctrlLog->Clear();
318 }
319
320 void DnDFrame::OnLeftDown(wxMouseEvent &WXUNUSED(event) )
321 {
322 if ( !m_strText.IsEmpty() )
323 {
324 // start drag operation
325 #ifdef __WXMSW__
326 wxTextDataObject textData(m_strText);
327 wxDropSource dragSource( textData, this );
328 #else
329 wxDropSource dragSource( new wxTextDataObject (m_strText), this, wxIcon(mondrian_xpm) );
330 #endif
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);
344 }
345 }
346
347 void DnDFrame::OnRightDown(wxMouseEvent &event )
348 {
349 wxMenu *menu = new wxMenu;
350
351 menu->Append(Menu_Drag, "&Test drag...");
352 menu->Append(Menu_About, "&About");
353 menu->Append(Menu_Quit, "E&xit");
354
355 PopupMenu( menu, event.GetX(), event.GetY() );
356 }
357
358 DnDFrame::~DnDFrame()
359 {
360 #if wxUSE_STD_IOSTREAM
361 if ( m_pLog != NULL ) {
362 if ( wxLog::SetActiveTarget(m_pLogPrev) == m_pLog )
363 delete m_pLog;
364 }
365 #endif
366 }
367
368 // ---------------------------------------------------------------------------
369 // clipboard
370 // ---------------------------------------------------------------------------
371
372 void DnDFrame::OnCopy(wxCommandEvent& WXUNUSED(event))
373 {
374 if ( !wxTheClipboard->Open() )
375 {
376 wxLogError(_T("Can't open clipboard."));
377
378 return;
379 }
380
381 if ( !wxTheClipboard->AddData(new wxTextDataObject(m_strText)) )
382 {
383 wxLogError(_T("Can't copy data to the clipboard"));
384 }
385 else
386 {
387 wxLogMessage(_T("Text '%s' put on the clipboard"), m_strText.c_str());
388 }
389
390 wxTheClipboard->Close();
391 }
392
393 void DnDFrame::OnPaste(wxCommandEvent& WXUNUSED(event))
394 {
395 if ( !wxTheClipboard->Open() )
396 {
397 wxLogError(_T("Can't open clipboard."));
398
399 return;
400 }
401
402 if ( !wxTheClipboard->IsSupported(wxDF_TEXT) )
403 {
404 wxLogWarning(_T("No text data on clipboard"));
405
406 return;
407 }
408
409 wxTextDataObject text;
410 if ( !wxTheClipboard->GetData(&text) )
411 {
412 wxLogError(_T("Can't paste data from the clipboard"));
413 }
414 else
415 {
416 wxLogMessage(_T("Text '%s' pasted from the clipboard"),
417 text.GetText().c_str());
418 }
419
420 wxTheClipboard->Close();
421 }
422
423 // ----------------------------------------------------------------------------
424 // Notifications called by the base class
425 // ----------------------------------------------------------------------------
426 bool DnDText::OnDropText( wxDropPointCoord, wxDropPointCoord, const wxChar *psz )
427 {
428 m_pOwner->Append(psz);
429
430 return TRUE;
431 }
432
433 bool DnDFile::OnDropFiles( wxDropPointCoord, wxDropPointCoord, size_t nFiles,
434 const wxChar* const aszFiles[])
435 {
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;
444 }