Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

267 lines
14KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2022 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 7 End-User License
  8. Agreement and JUCE Privacy Policy.
  9. End User License Agreement: www.juce.com/juce-7-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. namespace juce
  19. {
  20. //==============================================================================
  21. /**
  22. Enables drag-and-drop behaviour for a component and all its sub-components.
  23. For a component to be able to make or receive drag-and-drop events, one of its parent
  24. components must derive from this class. It's probably best for the top-level
  25. component to implement it.
  26. Then to start a drag operation, any sub-component can just call the startDragging()
  27. method, and this object will take over, tracking the mouse and sending appropriate
  28. callbacks to any child components derived from DragAndDropTarget which the mouse
  29. moves over.
  30. Note: If all that you need to do is to respond to files being drag-and-dropped from
  31. the operating system onto your component, you don't need any of these classes: you can do this
  32. simply by overriding FileDragAndDropTarget::filesDropped().
  33. @see DragAndDropTarget
  34. @tags{GUI}
  35. */
  36. class JUCE_API DragAndDropContainer
  37. {
  38. public:
  39. //==============================================================================
  40. /** Creates a DragAndDropContainer.
  41. The object that derives from this class must also be a Component.
  42. */
  43. DragAndDropContainer();
  44. /** Destructor. */
  45. virtual ~DragAndDropContainer();
  46. //==============================================================================
  47. /** Begins a drag-and-drop operation.
  48. This starts a drag-and-drop operation - call it when the user drags the
  49. mouse in your drag-source component, and this object will track mouse
  50. movements until the user lets go of the mouse button, and will send
  51. appropriate messages to DragAndDropTarget objects that the mouse moves
  52. over.
  53. findParentDragContainerFor() is a handy method to call to find the
  54. drag container to use for a component.
  55. @param sourceDescription a string or value to use as the description of the thing being dragged -
  56. this will be passed to the objects that might be dropped-onto so they can
  57. decide whether they want to handle it
  58. @param sourceComponent the component that is being dragged
  59. @param dragImage the image to drag around underneath the mouse. If this is a null image,
  60. a snapshot of the sourceComponent will be used instead.
  61. @param allowDraggingToOtherJuceWindows if true, the dragged component will appear as a desktop
  62. window, and can be dragged to DragAndDropTargets that are the
  63. children of components other than this one.
  64. @param imageOffsetFromMouse if an image has been passed-in, this specifies the offset
  65. at which the image should be drawn from the mouse. If it isn't
  66. specified, then the image will be centred around the mouse. If
  67. an image hasn't been passed-in, this will be ignored.
  68. @param inputSourceCausingDrag the mouse input source which started the drag. When calling
  69. from within a mouseDown or mouseDrag event, you can pass
  70. MouseEvent::source to this method. If this param is nullptr then JUCE
  71. will use the mouse input source which is currently dragging. If there
  72. are several dragging mouse input sources (which can often occur on mobile)
  73. then JUCE will use the mouseInputSource which is closest to the sourceComponent.
  74. */
  75. void startDragging (const var& sourceDescription,
  76. Component* sourceComponent,
  77. const ScaledImage& dragImage = ScaledImage(),
  78. bool allowDraggingToOtherJuceWindows = false,
  79. const Point<int>* imageOffsetFromMouse = nullptr,
  80. const MouseInputSource* inputSourceCausingDrag = nullptr);
  81. [[deprecated ("This overload does not allow the image's scale to be specified. Use the other overload of startDragging instead.")]]
  82. void startDragging (const var& sourceDescription,
  83. Component* sourceComponent,
  84. Image dragImage,
  85. bool allowDraggingToOtherJuceWindows = false,
  86. const Point<int>* imageOffsetFromMouse = nullptr,
  87. const MouseInputSource* inputSourceCausingDrag = nullptr)
  88. {
  89. startDragging (sourceDescription,
  90. sourceComponent,
  91. ScaledImage (dragImage),
  92. allowDraggingToOtherJuceWindows,
  93. imageOffsetFromMouse,
  94. inputSourceCausingDrag);
  95. }
  96. /** Returns true if something is currently being dragged. */
  97. bool isDragAndDropActive() const;
  98. /** Returns the number of things currently being dragged. */
  99. int getNumCurrentDrags() const;
  100. /** Returns the description of the thing that's currently being dragged.
  101. If nothing's being dragged, this will return a null var, otherwise it'll return
  102. the var that was passed into startDragging().
  103. If you are using drag and drop in a multi-touch environment then you should use the
  104. getDragDescriptionForIndex() method instead which takes a touch index parameter.
  105. @see startDragging, getDragDescriptionForIndex
  106. */
  107. var getCurrentDragDescription() const;
  108. /** Same as the getCurrentDragDescription() method but takes a touch index parameter.
  109. @see getCurrentDragDescription
  110. */
  111. var getDragDescriptionForIndex (int index) const;
  112. /** If a drag is in progress, this allows the image being shown to be dynamically updated.
  113. If you are using drag and drop in a multi-touch environment then you should use the
  114. setDragImageForIndex() method instead which takes a touch index parameter.
  115. @see setDragImageForIndex
  116. */
  117. void setCurrentDragImage (const ScaledImage& newImage);
  118. [[deprecated ("This overload does not allow the image's scale to be specified. Use the other overload of setCurrentDragImage instead.")]]
  119. void setCurrentDragImage (const Image& newImage) { setCurrentDragImage (ScaledImage (newImage)); }
  120. /** Same as the setCurrentDragImage() method but takes a touch index parameter.
  121. @see setCurrentDragImage
  122. */
  123. void setDragImageForIndex (int index, const ScaledImage& newImage);
  124. [[deprecated ("This overload does not allow the image's scale to be specified. Use the other overload of setDragImageForIndex instead.")]]
  125. void setDragImageForIndex (int index, const Image& newImage) { setDragImageForIndex (index, ScaledImage (newImage)); }
  126. /** Utility to find the DragAndDropContainer for a given Component.
  127. This will search up this component's parent hierarchy looking for the first
  128. parent component which is a DragAndDropContainer.
  129. It's useful when a component wants to call startDragging but doesn't know
  130. the DragAndDropContainer it should to use.
  131. Obviously this may return nullptr if it doesn't find a suitable component.
  132. */
  133. static DragAndDropContainer* findParentDragContainerFor (Component* childComponent);
  134. //==============================================================================
  135. /** This performs an asynchronous drag-and-drop of a set of files to some external
  136. application.
  137. You can call this function in response to a mouseDrag callback, and it will
  138. use a native operating system drag-and-drop operation to move or copy some
  139. files to another application.
  140. @param files a list of filenames to drag
  141. @param canMoveFiles if true, the app that receives the files is allowed to move the files to a new location
  142. (if this is appropriate). If false, the receiver is expected to make a copy of them.
  143. @param sourceComponent normally, JUCE will assume that the component under the mouse is the source component
  144. of the drag, but you can use this parameter to override this.
  145. @param callback an optional completion callback that will be called when the operation has ended.
  146. @returns true if the drag operation was successfully started, or false if it failed for some reason
  147. @see performExternalDragDropOfText
  148. */
  149. static bool performExternalDragDropOfFiles (const StringArray& files, bool canMoveFiles,
  150. Component* sourceComponent = nullptr,
  151. std::function<void()> callback = nullptr);
  152. /** This performs an asynchronous drag-and-drop of a block of text to some external
  153. application.
  154. You can call this function in response to a mouseDrag callback, and it will
  155. use a native operating system drag-and-drop operation to move or copy some
  156. text to another application.
  157. @param text the text to copy
  158. @param sourceComponent Normally, JUCE will assume that the component under the mouse is the source component
  159. of the drag, but you can use this parameter to override this.
  160. @param callback an optional completion callback that will be called when the operation has ended.
  161. @returns true if the drag operation was successfully started, or false if it failed for some reason
  162. @see performExternalDragDropOfFiles
  163. */
  164. static bool performExternalDragDropOfText (const String& text, Component* sourceComponent = nullptr,
  165. std::function<void()> callback = nullptr);
  166. protected:
  167. /** Override this if you want to be able to perform an external drag of a set of files
  168. when the user drags outside of this container component.
  169. This method will be called when a drag operation moves outside the JUCE window,
  170. and if you want it to then perform a file drag-and-drop, add the filenames you want
  171. to the array passed in, and return true.
  172. @param sourceDetails information about the source of the drag operation
  173. @param files on return, the filenames you want to drag
  174. @param canMoveFiles on return, true if it's ok for the receiver to move the files; false if
  175. it must make a copy of them (see the performExternalDragDropOfFiles() method)
  176. @see performExternalDragDropOfFiles, shouldDropTextWhenDraggedExternally
  177. */
  178. virtual bool shouldDropFilesWhenDraggedExternally (const DragAndDropTarget::SourceDetails& sourceDetails,
  179. StringArray& files, bool& canMoveFiles);
  180. /** Override this if you want to be able to perform an external drag of text
  181. when the user drags outside of this container component.
  182. This method will be called when a drag operation moves outside the JUCE window,
  183. and if you want it to then perform a text drag-and-drop, copy the text you want to
  184. be dragged into the argument provided and return true.
  185. @param sourceDetails information about the source of the drag operation
  186. @param text on return, the text you want to drag
  187. @see shouldDropFilesWhenDraggedExternally
  188. */
  189. virtual bool shouldDropTextWhenDraggedExternally (const DragAndDropTarget::SourceDetails& sourceDetails,
  190. String& text);
  191. /** Subclasses can override this to be told when a drag starts. */
  192. virtual void dragOperationStarted (const DragAndDropTarget::SourceDetails&);
  193. /** Subclasses can override this to be told when a drag finishes. */
  194. virtual void dragOperationEnded (const DragAndDropTarget::SourceDetails&);
  195. private:
  196. //==============================================================================
  197. class DragImageComponent;
  198. OwnedArray<DragImageComponent> dragImageComponents;
  199. const MouseInputSource* getMouseInputSourceForDrag (Component* sourceComponent, const MouseInputSource* inputSourceCausingDrag);
  200. bool isAlreadyDragging (Component* sourceComponent) const noexcept;
  201. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DragAndDropContainer)
  202. };
  203. } // namespace juce