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