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