diff options
Diffstat (limited to 'shared/dragAndDrop.cpp')
-rw-r--r-- | shared/dragAndDrop.cpp | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/shared/dragAndDrop.cpp b/shared/dragAndDrop.cpp new file mode 100644 index 00000000..9261d604 --- /dev/null +++ b/shared/dragAndDrop.cpp @@ -0,0 +1,216 @@ +#include "dragAndDrop.h" +#include <wx/dnd.h> +#include <wx/window.h> +#include <wx/combobox.h> +#include <wx/textctrl.h> +#include <wx/filepicker.h> +#include <wx/filename.h> + + +//define new event type +const wxEventType FFS_DROP_FILE_EVENT = wxNewEventType(); + +typedef void (wxEvtHandler::*FFSFileDropEventFunction)(FFSFileDropEvent&); + +#define FFSFileDropEventHandler(func) \ + (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(FFSFileDropEventFunction, &func) + +class FFSFileDropEvent : public wxCommandEvent +{ +public: + FFSFileDropEvent(const wxString& nameDropped, const wxWindow* dropWindow) : + wxCommandEvent(FFS_DROP_FILE_EVENT), + nameDropped_(nameDropped), + dropWindow_(dropWindow) {} + + virtual wxEvent* Clone() const + { + return new FFSFileDropEvent(nameDropped_, dropWindow_); + } + + const wxString nameDropped_; + const wxWindow* dropWindow_; +}; + +//############################################################################################################## + + +class WindowDropTarget : public wxFileDropTarget +{ +public: + WindowDropTarget(wxWindow* dropWindow) : + dropWindow_(dropWindow) {} + + virtual bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames) + { + if (!filenames.IsEmpty()) + { + const wxString droppedFileName = filenames[0]; + + //create a custom event on drop window: execute event after file dropping is completed! (e.g. after mouse is released) + FFSFileDropEvent evt(droppedFileName, dropWindow_); + dropWindow_->AddPendingEvent(evt); + } + return false; + } + +private: + wxWindow* dropWindow_; +}; + + + +//############################################################################################################## + +using FreeFileSync::DragDropOnMainDlg; + +DragDropOnMainDlg::DragDropOnMainDlg(wxWindow* dropWindow1, + wxWindow* dropWindow2, + wxDirPickerCtrl* dirPicker, + wxComboBox* dirName) : + dropWindow1_(dropWindow1), + dropWindow2_(dropWindow2), + dirPicker_(dirPicker), + dirName_(dirName) +{ + //prepare drag & drop + dropWindow1->SetDropTarget(new WindowDropTarget(dropWindow1)); //takes ownership + dropWindow2->SetDropTarget(new WindowDropTarget(dropWindow2)); //takes ownership + + //redirect drag & drop event back to this class + dropWindow1->Connect(FFS_DROP_FILE_EVENT, FFSFileDropEventHandler(DragDropOnMainDlg::OnFilesDropped), NULL, this); + dropWindow2->Connect(FFS_DROP_FILE_EVENT, FFSFileDropEventHandler(DragDropOnMainDlg::OnFilesDropped), NULL, this); + + //keep dirPicker and dirName synchronous + dirName->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DragDropOnMainDlg::OnWriteDirManually ), NULL, this ); + dirPicker->Connect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( DragDropOnMainDlg::OnDirSelected ), NULL, this ); +} + + +void DragDropOnMainDlg::OnFilesDropped(FFSFileDropEvent& event) +{ + if ( this->dropWindow1_ == event.dropWindow_ || //file may be dropped on window 1 or 2 + this->dropWindow2_ == event.dropWindow_) + { + if (AcceptDrop(event.nameDropped_)) + { + wxString fileName = event.nameDropped_; + if (wxDirExists(fileName)) + { + dirName_->SetSelection(wxNOT_FOUND); + dirName_->SetValue(fileName); + dirPicker_->SetPath(fileName); + } + else + { + fileName = wxFileName(fileName).GetPath(); + if (wxDirExists(fileName)) + { + dirName_->SetSelection(wxNOT_FOUND); + dirName_->SetValue(fileName); + dirPicker_->SetPath(fileName); + } + } + } + } + else //should never be reached + event.Skip(); +}; + + +wxString formatDirectory(const wxString& dirname) +{ + wxString dirnameTmp = dirname; + dirnameTmp.Trim(true); //remove whitespace characters from right + dirnameTmp.Trim(false); //remove whitespace characters from left + + return dirnameTmp; +} + + +void DragDropOnMainDlg::OnWriteDirManually(wxCommandEvent& event) +{ + const wxString newDir = formatDirectory(event.GetString()); + if (wxDirExists(newDir)) + dirPicker_->SetPath(newDir); + + event.Skip(); +} + + +void DragDropOnMainDlg::OnDirSelected(wxFileDirPickerEvent& event) +{ + const wxString newPath = event.GetPath(); + dirName_->SetSelection(wxNOT_FOUND); + dirName_->SetValue(newPath); + + event.Skip(); +} + +//############################################################################################################## + + +using FreeFileSync::DragDropOnDlg; + +DragDropOnDlg::DragDropOnDlg(wxWindow* dropWindow, + wxDirPickerCtrl* dirPicker, + wxTextCtrl* dirName) : + dropWindow_(dropWindow), + dirPicker_(dirPicker), + dirName_(dirName) +{ + //prepare drag & drop + dropWindow->SetDropTarget(new WindowDropTarget(dropWindow)); //takes ownership + + //redirect drag & drop event back to this class + dropWindow->Connect(FFS_DROP_FILE_EVENT, FFSFileDropEventHandler(DragDropOnDlg::OnFilesDropped), NULL, this); + + //keep dirPicker and dirName synchronous + dirName->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( DragDropOnDlg::OnWriteDirManually ), NULL, this ); + dirPicker->Connect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( DragDropOnDlg::OnDirSelected ), NULL, this ); +} + + +void DragDropOnDlg::OnFilesDropped(FFSFileDropEvent& event) +{ + if (this->dropWindow_ == event.dropWindow_) + { + wxString fileName = event.nameDropped_; + if (wxDirExists(fileName)) + { + dirName_->SetValue(fileName); + dirPicker_->SetPath(fileName); + } + else + { + fileName = wxFileName(fileName).GetPath(); + if (wxDirExists(fileName)) + { + dirName_->SetValue(fileName); + dirPicker_->SetPath(fileName); + } + } + } + else //should never be reached + event.Skip(); +}; + + +void DragDropOnDlg::OnWriteDirManually(wxCommandEvent& event) +{ + const wxString newDir = formatDirectory(event.GetString()); + if (wxDirExists(newDir)) + dirPicker_->SetPath(newDir); + + event.Skip(); +} + + +void DragDropOnDlg::OnDirSelected(wxFileDirPickerEvent& event) +{ + const wxString newPath = event.GetPath(); + dirName_->SetValue(newPath); + + event.Skip(); +} + |