]> git.saurik.com Git - wxWidgets.git/blob - samples/dnd/dnd.cpp
Unicode fixes. Appears that this may be the last before wxMSW will link
[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 // FIXME this is ugly and should be fixed in the library itself
41 #ifdef __WXMSW__
42 typedef long wxDropPointCoord;
43 #else // wxGTK
44 typedef int wxDropPointCoord;
45 #endif // MSW/GTK
46
47 class DnDText : public wxTextDropTarget
48 {
49 public:
50 DnDText(wxListBox *pOwner) { m_pOwner = pOwner; }
51
52 virtual bool OnDropText(wxDropPointCoord x, wxDropPointCoord y, const wxChar* psz );
53
54 private:
55 wxListBox *m_pOwner;
56 };
57
58 class DnDFile : public wxFileDropTarget
59 {
60 public:
61 DnDFile(wxListBox *pOwner) { m_pOwner = pOwner; }
62
63 virtual bool OnDropFiles(wxDropPointCoord x, wxDropPointCoord y,
64 size_t nFiles, const wxChar* const aszFiles[] );
65
66 private:
67 wxListBox *m_pOwner;
68 };
69
70 // ----------------------------------------------------------------------------
71 // Define a new application type
72 // ----------------------------------------------------------------------------
73
74 class DnDApp : public wxApp
75 {
76 public:
77 bool OnInit();
78 };
79
80 IMPLEMENT_APP(DnDApp);
81
82 // ----------------------------------------------------------------------------
83 // Define a new frame type
84 // ----------------------------------------------------------------------------
85 class DnDFrame : public wxFrame
86 {
87 public:
88 DnDFrame(wxFrame *frame, char *title, int x, int y, int w, int h);
89 ~DnDFrame();
90
91 void OnPaint(wxPaintEvent& event);
92 void OnQuit (wxCommandEvent& event);
93 void OnAbout(wxCommandEvent& event);
94 void OnDrag (wxCommandEvent& event);
95 void OnHelp (wxCommandEvent& event);
96 void OnLogClear(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 };
125
126 BEGIN_EVENT_TABLE(DnDFrame, wxFrame)
127 EVT_MENU(Menu_Quit, DnDFrame::OnQuit)
128 EVT_MENU(Menu_About, DnDFrame::OnAbout)
129 EVT_MENU(Menu_Drag, DnDFrame::OnDrag)
130 EVT_MENU(Menu_Help, DnDFrame::OnHelp)
131 EVT_MENU(Menu_Clear, DnDFrame::OnLogClear)
132 EVT_LEFT_DOWN( DnDFrame::OnLeftDown)
133 EVT_RIGHT_DOWN( DnDFrame::OnRightDown)
134 EVT_PAINT( DnDFrame::OnPaint)
135 END_EVENT_TABLE()
136
137 // `Main program' equivalent, creating windows and returning main app frame
138 bool DnDApp::OnInit()
139 {
140 // create the main frame window
141 DnDFrame *frame = new DnDFrame((wxFrame *) NULL, "Drag & Drop wxWindows App",
142 50, 50, 450, 340);
143
144 // activate it
145 frame->Show(TRUE);
146
147 SetTopWindow(frame);
148
149 return TRUE;
150 }
151
152 DnDFrame::DnDFrame(wxFrame *frame, char *title, int x, int y, int w, int h)
153 : wxFrame(frame, -1, title, wxPoint(x, y), wxSize(w, h)),
154 m_strText("wxWindows drag & drop works :-)")
155
156 {
157 // SetBackgroundColour(* wxWHITE);
158
159 // frame icon and status bar
160 SetIcon(wxICON(mondrian));
161
162 // const int widths[] = { -1 };
163 CreateStatusBar();
164
165 // construct menu
166 wxMenu *file_menu = new wxMenu;
167 file_menu->Append(Menu_Drag, "&Test drag...");
168 file_menu->AppendSeparator();
169 file_menu->Append(Menu_Quit, "E&xit");
170
171 wxMenu *log_menu = new wxMenu;
172 log_menu->Append(Menu_Clear, "Clear");
173
174 wxMenu *help_menu = new wxMenu;
175 help_menu->Append(Menu_Help, "&Help...");
176 help_menu->AppendSeparator();
177 help_menu->Append(Menu_About, "&About");
178
179 wxMenuBar *menu_bar = new wxMenuBar;
180 menu_bar->Append(file_menu, "&File");
181 menu_bar->Append(log_menu, "&Log");
182 menu_bar->Append(help_menu, "&Help");
183
184 SetMenuBar(menu_bar);
185
186 // make a panel with 3 subwindows
187 wxPoint pos(0, 0);
188 wxSize size(400, 200);
189
190 wxString strFile("Drop files here!"), strText("Drop text on me");
191
192 m_ctrlFile = new wxListBox(this, -1, pos, size, 1, &strFile, wxLB_HSCROLL);
193 m_ctrlText = new wxListBox(this, -1, pos, size, 1, &strText, wxLB_HSCROLL);
194
195 m_ctrlLog = new wxTextCtrl(this, -1, "", pos, size,
196 wxTE_MULTILINE | wxTE_READONLY |
197 wxSUNKEN_BORDER );
198
199 // redirect log messages to the text window (don't forget to delete it!)
200 m_pLog = new wxLogTextCtrl(m_ctrlLog);
201 m_pLogPrev = wxLog::SetActiveTarget(m_pLog);
202
203 // associate drop targets with 2 text controls
204 m_ctrlFile->SetDropTarget(new DnDFile(m_ctrlFile));
205 m_ctrlText->SetDropTarget(new DnDText(m_ctrlText));
206
207 wxLayoutConstraints *c;
208
209 // Top-left listbox
210 c = new wxLayoutConstraints;
211 c->left.SameAs(this, wxLeft);
212 c->top.SameAs(this, wxTop);
213 c->right.PercentOf(this, wxRight, 50);
214 c->height.PercentOf(this, wxHeight, 40);
215 m_ctrlFile->SetConstraints(c);
216
217 // Top-right listbox
218 c = new wxLayoutConstraints;
219 c->left.SameAs (m_ctrlFile, wxRight);
220 c->top.SameAs (this, wxTop);
221 c->right.SameAs (this, wxRight);
222 c->height.PercentOf(this, wxHeight, 40);
223 m_ctrlText->SetConstraints(c);
224
225 // Lower text control
226 c = new wxLayoutConstraints;
227 c->left.SameAs (this, wxLeft);
228 c->right.SameAs (this, wxRight);
229 c->height.PercentOf(this, wxHeight, 40);
230 c->top.SameAs(m_ctrlText, wxBottom);
231 m_ctrlLog->SetConstraints(c);
232
233 SetAutoLayout(TRUE);
234 }
235
236 void DnDFrame::OnQuit(wxCommandEvent& /* event */)
237 {
238 Close(TRUE);
239 }
240
241 void DnDFrame::OnPaint(wxPaintEvent& /*event*/)
242 {
243 int w = 0;
244 int h = 0;
245 GetClientSize( &w, &h );
246
247 wxPaintDC dc(this);
248 dc.SetFont( wxFont( 24, wxDECORATIVE, wxNORMAL, wxNORMAL, FALSE, "charter" ) );
249 dc.DrawText( "Drag text from here!", 20, h-35 );
250 }
251
252 void DnDFrame::OnDrag(wxCommandEvent& /* event */)
253 {
254 wxString strText = wxGetTextFromUser
255 (
256 "After you enter text in this dialog, press any mouse\n"
257 "button in the bottom (empty) part of the frame and \n"
258 "drag it anywhere - you will be in fact dragging the\n"
259 "text object containing this text",
260 "Please enter some text", m_strText, this
261 );
262
263 m_strText = strText;
264 }
265
266 void DnDFrame::OnAbout(wxCommandEvent& /* event */)
267 {
268 wxMessageDialog dialog(this,
269 "Drag-&-Drop Demo\n"
270 "Please see \"Help|Help...\" for details\n"
271 "Copyright (c) 1998 Vadim Zeitlin",
272 "About wxDnD");
273
274 dialog.ShowModal();
275 }
276
277 void DnDFrame::OnHelp(wxCommandEvent& /* event */)
278 {
279 wxMessageDialog dialog(this,
280 "This small program demonstrates drag & drop support in wxWindows. The program window\n"
281 "consists of 3 parts: the bottom pane is for debug messages, so that you can see what's\n"
282 "going on inside. The top part is split into 2 listboxes, the left one accepts files\n"
283 "and the right one accepts text.\n"
284 "\n"
285 "To test wxDropTarget: open wordpad (write.exe), select some text in it and drag it to\n"
286 "the right listbox (you'll notice the usual visual feedback, i.e. the cursor will change).\n"
287 "Also, try dragging some files (you can select several at once) from Windows Explorer (or \n"
288 "File Manager) to the left pane. Hold down Ctrl/Shift keys when you drop text (doesn't \n"
289 "work with files) and see what changes.\n"
290 "\n"
291 "To test wxDropSource: just press any mouse button on the empty zone of the window and drag\n"
292 "it to wordpad or any other droptarget accepting text (and of course you can just drag it\n"
293 "to the right pane). Due to a lot of trace messages, the cursor might take some time to \n"
294 "change, don't release the mouse button until it does. You can change the string being\n"
295 "dragged in in \"File|Test drag...\" dialog.\n"
296 "\n"
297 "\n"
298 "Please send all questions/bug reports/suggestions &c to \n"
299 "Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>",
300 "wxDnD Help");
301
302 dialog.ShowModal();
303 }
304
305 void DnDFrame::OnLogClear(wxCommandEvent& /* event */ )
306 {
307 m_ctrlLog->Clear();
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, wxIcon(mondrian_xpm) );
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( wxDropPointCoord, wxDropPointCoord, const wxChar *psz )
360 {
361 m_pOwner->Append(psz);
362
363 return TRUE;
364 }
365
366 bool DnDFile::OnDropFiles( wxDropPointCoord, wxDropPointCoord, size_t nFiles,
367 const wxChar* const aszFiles[])
368 {
369 wxString str;
370 str.Printf( _T("%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 }