+ // frame icon and status bar
+ SetIcon(wxICON(mondrian));
+
+ CreateStatusBar();
+
+ // construct menu
+ wxMenu *file_menu = new wxMenu;
+ file_menu->Append(Menu_Drag, "&Test drag...");
+ file_menu->AppendSeparator();
+ file_menu->Append(Menu_NewFrame, "&New frame\tCtrl-N");
+ file_menu->AppendSeparator();
+ file_menu->Append(Menu_Quit, "E&xit");
+
+ wxMenu *log_menu = new wxMenu;
+ log_menu->Append(Menu_Clear, "Clear\tCtrl-L");
+
+ wxMenu *help_menu = new wxMenu;
+ help_menu->Append(Menu_Help, "&Help...");
+ help_menu->AppendSeparator();
+ help_menu->Append(Menu_About, "&About");
+
+ wxMenu *clip_menu = new wxMenu;
+ clip_menu->Append(Menu_Copy, "&Copy text\tCtrl+C");
+ clip_menu->Append(Menu_Paste, "&Paste text\tCtrl+V");
+ clip_menu->AppendSeparator();
+ clip_menu->Append(Menu_CopyBitmap, "&Copy bitmap\tAlt+C");
+ clip_menu->Append(Menu_PasteBitmap, "&Paste bitmap\tAlt+V");
+ clip_menu->AppendSeparator();
+ clip_menu->Append(Menu_CopyFiles, "&Copy files\tCtrl+F");
+
+ wxMenuBar *menu_bar = new wxMenuBar;
+ menu_bar->Append(file_menu, "&File");
+ menu_bar->Append(log_menu, "&Log");
+ menu_bar->Append(clip_menu, "&Clipboard");
+ menu_bar->Append(help_menu, "&Help");
+
+ SetMenuBar(menu_bar);
+
+ // make a panel with 3 subwindows
+ wxPoint pos(0, 0);
+ wxSize size(400, 200);
+
+ wxString strFile("Drop files here!"), strText("Drop text on me");
+
+ m_ctrlFile = new wxListBox(this, -1, pos, size, 1, &strFile,
+ wxLB_HSCROLL | wxLB_ALWAYS_SB );
+ m_ctrlText = new wxListBox(this, -1, pos, size, 1, &strText,
+ wxLB_HSCROLL | wxLB_ALWAYS_SB );
+
+ m_ctrlLog = new wxTextCtrl(this, -1, "", pos, size,
+ wxTE_MULTILINE | wxTE_READONLY |
+ wxSUNKEN_BORDER );
+
+ // redirect log messages to the text window
+ m_pLog = new wxLogTextCtrl(m_ctrlLog);
+ m_pLogPrev = wxLog::SetActiveTarget(m_pLog);
+
+ // associate drop targets with 2 text controls
+ m_ctrlFile->SetDropTarget(new DnDFile(m_ctrlFile));
+ m_ctrlText->SetDropTarget(new DnDText(m_ctrlText));
+
+ wxLayoutConstraints *c;
+
+ // Top-left listbox
+ c = new wxLayoutConstraints;
+ c->left.SameAs(this, wxLeft);
+ c->top.SameAs(this, wxTop);
+ c->right.PercentOf(this, wxRight, 50);
+ c->height.PercentOf(this, wxHeight, 30);
+ m_ctrlFile->SetConstraints(c);
+
+ // Top-right listbox
+ c = new wxLayoutConstraints;
+ c->left.SameAs (m_ctrlFile, wxRight);
+ c->top.SameAs (this, wxTop);
+ c->right.SameAs (this, wxRight);
+ c->height.PercentOf(this, wxHeight, 30);
+ m_ctrlText->SetConstraints(c);
+
+ // Lower text control
+ c = new wxLayoutConstraints;
+ c->left.SameAs (this, wxLeft);
+ c->right.SameAs (this, wxRight);
+ c->height.PercentOf(this, wxHeight, 50);
+ c->top.SameAs(m_ctrlText, wxBottom);
+ m_ctrlLog->SetConstraints(c);
+
+ SetAutoLayout(TRUE);
+}
+
+void DnDFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
+{
+ Close(TRUE);
+}
+
+void DnDFrame::OnPaint(wxPaintEvent& WXUNUSED(event))
+{
+ int w = 0;
+ int h = 0;
+ GetClientSize( &w, &h );
+
+ wxPaintDC dc(this);
+ dc.SetFont( wxFont( 24, wxDECORATIVE, wxNORMAL, wxNORMAL, FALSE, "charter" ) );
+ dc.DrawText( "Drag text from here!", 20, h-50 );
+
+ if ( m_bitmap.Ok() )
+ {
+ // 4/5 is 80% taken by other windows, 20 is arbitrary margin
+ dc.DrawBitmap(m_bitmap,
+ w - m_bitmap.GetWidth() - 20,
+ (4*h)/5 + 20);
+ }
+}
+
+void DnDFrame::OnUpdateUIPasteText(wxUpdateUIEvent& event)
+{
+#ifdef __WXDEBUG__
+ // too many trace messages if we don't do it - this function is called
+ // very often
+ wxLogNull nolog;
+#endif
+
+ event.Enable( wxTheClipboard->IsSupported(wxDF_TEXT) );
+}
+
+void DnDFrame::OnUpdateUIPasteBitmap(wxUpdateUIEvent& event)
+{
+#ifdef __WXDEBUG__
+ // too many trace messages if we don't do it - this function is called
+ // very often
+ wxLogNull nolog;
+#endif
+
+ event.Enable( wxTheClipboard->IsSupported(wxDF_BITMAP) );
+}
+
+void DnDFrame::OnNewFrame(wxCommandEvent& WXUNUSED(event))
+{
+ (new DnDShapeFrame(this))->Show(TRUE);
+
+ wxLogStatus(this, "Double click the new frame to select a shape for it");
+}
+
+void DnDFrame::OnDrag(wxCommandEvent& WXUNUSED(event))
+{
+ wxString strText = wxGetTextFromUser
+ (
+ "After you enter text in this dialog, press any mouse\n"
+ "button in the bottom (empty) part of the frame and \n"
+ "drag it anywhere - you will be in fact dragging the\n"
+ "text object containing this text",
+ "Please enter some text", m_strText, this
+ );
+
+ m_strText = strText;
+}
+
+void DnDFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
+{
+ wxMessageBox("Drag-&-Drop Demo\n"
+ "Please see \"Help|Help...\" for details\n"
+ "Copyright (c) 1998 Vadim Zeitlin",
+ "About wxDnD",
+ wxICON_INFORMATION | wxOK,
+ this);
+}
+
+void DnDFrame::OnHelp(wxCommandEvent& /* event */)
+{
+ wxMessageDialog dialog(this,
+ "This small program demonstrates drag & drop support in wxWindows. The program window\n"
+ "consists of 3 parts: the bottom pane is for debug messages, so that you can see what's\n"
+ "going on inside. The top part is split into 2 listboxes, the left one accepts files\n"
+ "and the right one accepts text.\n"
+ "\n"
+ "To test wxDropTarget: open wordpad (write.exe), select some text in it and drag it to\n"
+ "the right listbox (you'll notice the usual visual feedback, i.e. the cursor will change).\n"
+ "Also, try dragging some files (you can select several at once) from Windows Explorer (or \n"
+ "File Manager) to the left pane. Hold down Ctrl/Shift keys when you drop text (doesn't \n"
+ "work with files) and see what changes.\n"
+ "\n"
+ "To test wxDropSource: just press any mouse button on the empty zone of the window and drag\n"
+ "it to wordpad or any other droptarget accepting text (and of course you can just drag it\n"
+ "to the right pane). Due to a lot of trace messages, the cursor might take some time to \n"
+ "change, don't release the mouse button until it does. You can change the string being\n"
+ "dragged in in \"File|Test drag...\" dialog.\n"
+ "\n"
+ "\n"
+ "Please send all questions/bug reports/suggestions &c to \n"
+ "Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>",
+ "wxDnD Help");
+
+ dialog.ShowModal();
+}
+
+void DnDFrame::OnLogClear(wxCommandEvent& /* event */ )
+{
+ m_ctrlLog->Clear();
+ m_ctrlText->Clear();
+ m_ctrlFile->Clear();
+}
+
+void DnDFrame::OnLeftDown(wxMouseEvent &WXUNUSED(event) )
+{
+ if ( !m_strText.IsEmpty() )
+ {
+ // start drag operation
+ wxTextDataObject textData(m_strText);
+/*
+ wxFileDataObject textData;
+ textData.AddFile( "/file1.txt" );
+ textData.AddFile( "/file2.txt" );
+*/
+ wxDropSource source(textData, this
+
+#ifdef __WXMSW__
+ ,wxCURSOR_PENCIL, // for copy
+ wxCURSOR_SPRAYCAN, // for move
+ wxCURSOR_QUESTION_ARROW // for nothing
+#endif
+ );
+
+ const char *pc;
+
+ switch ( source.DoDragDrop(TRUE) )
+ {
+ case wxDragError: pc = "Error!"; break;
+ case wxDragNone: pc = "Nothing"; break;
+ case wxDragCopy: pc = "Copied"; break;
+ case wxDragMove: pc = "Moved"; break;
+ case wxDragCancel: pc = "Cancelled"; break;
+ default: pc = "Huh?"; break;
+ }
+
+ SetStatusText(wxString("Drag result: ") + pc);
+ }
+}
+
+void DnDFrame::OnRightDown(wxMouseEvent &event )
+{
+ wxMenu menu("Dnd sample menu");
+
+ menu.Append(Menu_Drag, "&Test drag...");
+ menu.AppendSeparator();
+ menu.Append(Menu_About, "&About");
+
+ PopupMenu( &menu, event.GetX(), event.GetY() );
+}
+
+DnDFrame::~DnDFrame()
+{
+ if ( m_pLog != NULL ) {
+ if ( wxLog::SetActiveTarget(m_pLogPrev) == m_pLog )
+ delete m_pLog;
+ }
+}
+
+// ---------------------------------------------------------------------------
+// bitmap clipboard
+// ---------------------------------------------------------------------------