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 "TrackPanel.h"
20
21#if wxUSE_DRAG_AND_DROP
22class FileObject final : public wxFileDataObject
23{
24public:
25 FileObject()
26 {
27 }
28
29 bool IsSupportedFormat(const wxDataFormat & format, Direction WXUNUSED(dir = Get)) const
30 // PRL: This function does NOT override any inherited virtual! What does it do?
31 {
32 if (format.GetType() == wxDF_FILENAME) {
33 return true;
34 }
35
36#if defined(__WXMAC__)
37#if !wxCHECK_VERSION(3, 0, 0)
38 if (format.GetFormatId() == kDragPromisedFlavorFindFile) {
39 return true;
40 }
41#endif
42#endif
43
44 return false;
45 }
46};
47
48class DropTarget final : public wxFileDropTarget
49{
50public:
51 DropTarget(AudacityProject *proj)
52 {
53 mProject = proj;
54
55 // SetDataObject takes ownership
56 SetDataObject(safenew FileObject());
57 }
58
59 ~DropTarget()
60 {
61 }
62
63#if defined(__WXMAC__)
64#if !wxCHECK_VERSION(3, 0, 0)
65 bool GetData() override
66 {
67 bool foundSupported = false;
68 bool firstFileAdded = false;
69 OSErr result;
70
71 UInt16 items = 0;
72 CountDragItems((DragReference)m_currentDrag, &items);
73
74 for (UInt16 index = 1; index <= items; index++) {
75
76 DragItemRef theItem = 0;
77 GetDragItemReferenceNumber((DragReference)m_currentDrag, index, &theItem);
78
79 UInt16 flavors = 0;
80 CountDragItemFlavors((DragReference)m_currentDrag, theItem , &flavors ) ;
81
82 for (UInt16 flavor = 1 ;flavor <= flavors; flavor++) {
83
84 FlavorType theType = 0;
85 result = GetFlavorType((DragReference)m_currentDrag, theItem, flavor, &theType);
86 if (theType != kDragPromisedFlavorFindFile && theType != kDragFlavorTypeHFS) {
87 continue;
88 }
89 foundSupported = true;
90
91 Size dataSize = 0;
92 GetFlavorDataSize((DragReference)m_currentDrag, theItem, theType, &dataSize);
93
94 ArrayOf<char> theData{ dataSize };
95 GetFlavorData((DragReference)m_currentDrag, theItem, theType, (void*) theData.get(), &dataSize, 0L);
96
97 wxString name;
98 if (theType == kDragPromisedFlavorFindFile) {
99 name = wxMacFSSpec2MacFilename((FSSpec *)theData.get());
100 }
101 else if (theType == kDragFlavorTypeHFS) {
102 name = wxMacFSSpec2MacFilename(&((HFSFlavor *)theData.get())->fileSpec);
103 }
104
105 if (!firstFileAdded) {
106 // reset file list
107 ((wxFileDataObject*)GetDataObject())->SetData(0, "");
108 firstFileAdded = true;
109 }
110
111 ((wxFileDataObject*)GetDataObject())->AddFile(name);
112
113 // We only want to process one flavor
114 break;
115 }
116 }
117 return foundSupported;
118 }
119#endif
120
121 bool OnDrop(wxCoord x, wxCoord y) override
122 {
123 // bool foundSupported = false;
124#if !wxCHECK_VERSION(3, 0, 0)
125 bool firstFileAdded = false;
126 OSErr result;
127
128 UInt16 items = 0;
129 CountDragItems((DragReference)m_currentDrag, &items);
130
131 for (UInt16 index = 1; index <= items; index++) {
132
133 DragItemRef theItem = 0;
134 GetDragItemReferenceNumber((DragReference)m_currentDrag, index, &theItem);
135
136 UInt16 flavors = 0;
137 CountDragItemFlavors((DragReference)m_currentDrag, theItem , &flavors ) ;
138
139 for (UInt16 flavor = 1 ;flavor <= flavors; flavor++) {
140
141 FlavorType theType = 0;
142 result = GetFlavorType((DragReference)m_currentDrag, theItem, flavor, &theType);
143 if (theType != kDragPromisedFlavorFindFile && theType != kDragFlavorTypeHFS) {
144 continue;
145 }
146 return true;
147 }
148 }
149#endif
150 return CurrentDragHasSupportedFormat();
151 }
152
153#endif
154
155 bool OnDropFiles(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y), const wxArrayString& filenames) override
156 {
157 // Experiment shows that this function can be reached while there is no
158 // catch block above in wxWidgets. So stop all exceptions here.
159 return GuardedCall<bool>(
160 [&] { return ProjectFileManager::Get(*mProject).Import(filenames); });
161 }
162
163private:
164 AudacityProject *mProject;
165};
166
167// Hook the construction of projects
170 // We can import now, so become a drag target
171 // SetDropTarget(safenew AudacityDropTarget(this));
172 // mTrackPanel->SetDropTarget(safenew AudacityDropTarget(this));
173
175 .SetDropTarget(
176 // SetDropTarget takes ownership
177 safenew DropTarget( &project ) );
178 return nullptr;
179 }
180};
181#endif
Declare abstract class AudacityException, some often-used subclasses, and GuardedCall.
#define safenew
Definition: MemoryX.h:10
static const AudacityProject::AttachedObjects::RegisteredFactory key
wxString name
Definition: TagsEditor.cpp:166
const auto project
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:275
bool Import(const FilePath &fileName, bool addToHistory=true)
static ProjectFileManager & Get(AudacityProject &project)
static TrackPanel & Get(AudacityProject &project)
Definition: TrackPanel.cpp:234
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
Definition: BasicUI.cpp:202
SizeType< float > Size
Alias for SizeType<float>
Definition: Size.h:174