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