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