Audacity 3.2.0
DropTarget.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 @file DropTarget.cpp
6 @brief Inject drag-and-drop importation of files
7
8 Paul Licameli split from ProjectManager.cpp
9
10**********************************************************************/
11
12#include <wx/dataobj.h>
13#include <wx/dnd.h>
14
15#include "AudacityException.h"
16#include "FileNames.h"
17#include "Project.h"
18#include "ProjectFileManager.h"
19#include "ProjectWindow.h"
20#include "TrackPanel.h"
21#include "import/Import.h"
22#include "import/ImportMIDI.h"
23
24#if wxUSE_DRAG_AND_DROP
25class FileObject final : public wxFileDataObject
26{
27public:
28 FileObject()
29 {
30 }
31
32 bool IsSupportedFormat(const wxDataFormat & format, Direction WXUNUSED(dir = Get)) const
33 // PRL: This function does NOT override any inherited virtual! What does it do?
34 {
35 if (format.GetType() == wxDF_FILENAME) {
36 return true;
37 }
38
39#if defined(__WXMAC__)
40#if !wxCHECK_VERSION(3, 0, 0)
41 if (format.GetFormatId() == kDragPromisedFlavorFindFile) {
42 return true;
43 }
44#endif
45#endif
46
47 return false;
48 }
49};
50
51class DropTarget final : public wxFileDropTarget
52{
53public:
54 DropTarget(AudacityProject *proj)
55 {
56 mProject = proj;
57
58 // SetDataObject takes ownership
59 SetDataObject(safenew FileObject());
60 }
61
62 ~DropTarget()
63 {
64 }
65
66#if defined(__WXMAC__)
67#if !wxCHECK_VERSION(3, 0, 0)
68 bool GetData() override
69 {
70 bool foundSupported = false;
71 bool firstFileAdded = false;
72 OSErr result;
73
74 UInt16 items = 0;
75 CountDragItems((DragReference)m_currentDrag, &items);
76
77 for (UInt16 index = 1; index <= items; index++) {
78
79 DragItemRef theItem = 0;
80 GetDragItemReferenceNumber((DragReference)m_currentDrag, index, &theItem);
81
82 UInt16 flavors = 0;
83 CountDragItemFlavors((DragReference)m_currentDrag, theItem , &flavors ) ;
84
85 for (UInt16 flavor = 1 ;flavor <= flavors; flavor++) {
86
87 FlavorType theType = 0;
88 result = GetFlavorType((DragReference)m_currentDrag, theItem, flavor, &theType);
89 if (theType != kDragPromisedFlavorFindFile && theType != kDragFlavorTypeHFS) {
90 continue;
91 }
92 foundSupported = true;
93
94 Size dataSize = 0;
95 GetFlavorDataSize((DragReference)m_currentDrag, theItem, theType, &dataSize);
96
97 ArrayOf<char> theData{ dataSize };
98 GetFlavorData((DragReference)m_currentDrag, theItem, theType, (void*) theData.get(), &dataSize, 0L);
99
100 wxString name;
101 if (theType == kDragPromisedFlavorFindFile) {
102 name = wxMacFSSpec2MacFilename((FSSpec *)theData.get());
103 }
104 else if (theType == kDragFlavorTypeHFS) {
105 name = wxMacFSSpec2MacFilename(&((HFSFlavor *)theData.get())->fileSpec);
106 }
107
108 if (!firstFileAdded) {
109 // reset file list
110 ((wxFileDataObject*)GetDataObject())->SetData(0, "");
111 firstFileAdded = true;
112 }
113
114 ((wxFileDataObject*)GetDataObject())->AddFile(name);
115
116 // We only want to process one flavor
117 break;
118 }
119 }
120 return foundSupported;
121 }
122#endif
123
124 bool OnDrop(wxCoord x, wxCoord y) override
125 {
126 // bool foundSupported = false;
127#if !wxCHECK_VERSION(3, 0, 0)
128 bool firstFileAdded = false;
129 OSErr result;
130
131 UInt16 items = 0;
132 CountDragItems((DragReference)m_currentDrag, &items);
133
134 for (UInt16 index = 1; index <= items; index++) {
135
136 DragItemRef theItem = 0;
137 GetDragItemReferenceNumber((DragReference)m_currentDrag, index, &theItem);
138
139 UInt16 flavors = 0;
140 CountDragItemFlavors((DragReference)m_currentDrag, theItem , &flavors ) ;
141
142 for (UInt16 flavor = 1 ;flavor <= flavors; flavor++) {
143
144 FlavorType theType = 0;
145 result = GetFlavorType((DragReference)m_currentDrag, theItem, flavor, &theType);
146 if (theType != kDragPromisedFlavorFindFile && theType != kDragFlavorTypeHFS) {
147 continue;
148 }
149 return true;
150 }
151 }
152#endif
153 return CurrentDragHasSupportedFormat();
154 }
155
156#endif
157
158 bool OnDropFiles(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), const wxArrayString& filenames) override
159 {
160 // Experiment shows that this function can be reached while there is no
161 // catch block above in wxWidgets. So stop all exceptions here.
162 return GuardedCall< bool > ( [&] {
163 wxArrayString sortednames(filenames);
164 sortednames.Sort(FileNames::CompareNoCase);
165
166 auto cleanup = finally( [&] {
167 ProjectWindow::Get( *mProject ).HandleResize(); // Adjust scrollers for NEW track sizes.
168 } );
169
170 for (const auto &name : sortednames) {
171#ifdef USE_MIDI
173 DoImportMIDI( *mProject, name );
174 else
175#endif
176 ProjectFileManager::Get( *mProject ).Import(name);
177 }
178
179 auto &window = ProjectWindow::Get( *mProject );
180 window.ZoomAfterImport(nullptr);
181
182 return true;
183 } );
184 }
185
186private:
187 AudacityProject *mProject;
188};
189
190// Hook the construction of projects
192 [](AudacityProject &project) {
193 // We can import now, so become a drag target
194 // SetDropTarget(safenew AudacityDropTarget(this));
195 // mTrackPanel->SetDropTarget(safenew AudacityDropTarget(this));
196
197 TrackPanel::Get( project )
198 .SetDropTarget(
199 // SetDropTarget takes ownership
200 safenew DropTarget( &project ) );
201 return nullptr;
202 }
203};
204#endif
Declare abstract class AudacityException, some often-used subclasses, and GuardedCall.
static const AudacityProject::AttachedObjects::RegisteredFactory key
const TranslatableString name
Definition: Distortion.cpp:74
int format
Definition: ExportPCM.cpp:53
bool DoImportMIDI(AudacityProject &project, const FilePath &fileName)
Definition: ImportMIDI.cpp:39
#define safenew
Definition: MemoryX.h:10
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Definition: Project.h:90
Client code makes static instance from a factory of attachments; passes it to Get or Find as a retrie...
Definition: ClientData.h:266
bool Import(const FilePath &fileName, bool addToHistory=true)
static ProjectFileManager & Get(AudacityProject &project)
static ProjectWindow & Get(AudacityProject &project)
static TrackPanel & Get(AudacityProject &project)
Definition: TrackPanel.cpp:230
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
Definition: BasicUI.cpp:194
FILES_API bool IsMidi(const FilePath &fName)
FILES_API int CompareNoCase(const wxString &first, const wxString &second)