diff --git a/extras/Introjucer/Builds/MacOSX/The Introjucer.xcodeproj/project.pbxproj b/extras/Introjucer/Builds/MacOSX/The Introjucer.xcodeproj/project.pbxproj index 79e2b4ab3e..3033efd4bd 100644 --- a/extras/Introjucer/Builds/MacOSX/The Introjucer.xcodeproj/project.pbxproj +++ b/extras/Introjucer/Builds/MacOSX/The Introjucer.xcodeproj/project.pbxproj @@ -206,6 +206,7 @@ 3419904525A3F1FF0CC50687 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_FileBasedDocument.cpp"; path = "../../../../modules/juce_gui_extra/documents/juce_FileBasedDocument.cpp"; sourceTree = "SOURCE_ROOT"; }; 352DA3794CAAE2400AE8F2E0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_data_structures.h"; path = "../../../../modules/juce_data_structures/juce_data_structures.h"; sourceTree = "SOURCE_ROOT"; }; 35AF9D5F0603CF6CE2D355A1 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_RelativeCoordinatePositioner.cpp"; path = "../../../../modules/juce_gui_basics/positioning/juce_RelativeCoordinatePositioner.cpp"; sourceTree = "SOURCE_ROOT"; }; + 35BF11530EF0D771FD94ABDC = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_TextDragAndDropTarget.h"; path = "../../../../modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h"; sourceTree = "SOURCE_ROOT"; }; 35CB48D497F35BF3F6998F5D = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "jucer_ProjectExporter.h"; path = "../../Source/Project Saving/jucer_ProjectExporter.h"; sourceTree = "SOURCE_ROOT"; }; 364D1A9B113320407A7E57B9 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = JuceHeader.h; path = ../../JuceLibraryCode/JuceHeader.h; sourceTree = "SOURCE_ROOT"; }; 37A0A38C2B5825B9A302879C = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ReferenceCountedArray.h"; path = "../../../../modules/juce_core/containers/juce_ReferenceCountedArray.h"; sourceTree = "SOURCE_ROOT"; }; @@ -1256,6 +1257,7 @@ 199722DD9BA0E30C0506941E, 2FBA1138907F4DE651870008, B20A5F49C7E6342B71770D18, + 35BF11530EF0D771FD94ABDC, BDEBB0AC32DDA8C16FFE6011 ); name = mouse; sourceTree = ""; }; A186EF5D092D513F30A4FE23 = { isa = PBXGroup; children = ( 148FC834CE2CAE18477AB708, diff --git a/extras/Introjucer/Builds/VisualStudio2005/The Introjucer.vcproj b/extras/Introjucer/Builds/VisualStudio2005/The Introjucer.vcproj index 3b83d0f1d8..a294a4dd7d 100644 --- a/extras/Introjucer/Builds/VisualStudio2005/The Introjucer.vcproj +++ b/extras/Introjucer/Builds/VisualStudio2005/The Introjucer.vcproj @@ -2060,6 +2060,7 @@ + diff --git a/extras/Introjucer/Builds/VisualStudio2008/The Introjucer.vcproj b/extras/Introjucer/Builds/VisualStudio2008/The Introjucer.vcproj index d9b75c4f38..c6b25f9879 100644 --- a/extras/Introjucer/Builds/VisualStudio2008/The Introjucer.vcproj +++ b/extras/Introjucer/Builds/VisualStudio2008/The Introjucer.vcproj @@ -2060,6 +2060,7 @@ + diff --git a/extras/Introjucer/Builds/VisualStudio2010/The Introjucer.vcxproj b/extras/Introjucer/Builds/VisualStudio2010/The Introjucer.vcxproj index b885702ebd..b9b3bcb069 100644 --- a/extras/Introjucer/Builds/VisualStudio2010/The Introjucer.vcxproj +++ b/extras/Introjucer/Builds/VisualStudio2010/The Introjucer.vcxproj @@ -1196,6 +1196,7 @@ + diff --git a/extras/Introjucer/Builds/VisualStudio2010/The Introjucer.vcxproj.filters b/extras/Introjucer/Builds/VisualStudio2010/The Introjucer.vcxproj.filters index 26b6bd9eaf..c46b73eaba 100644 --- a/extras/Introjucer/Builds/VisualStudio2010/The Introjucer.vcxproj.filters +++ b/extras/Introjucer/Builds/VisualStudio2010/The Introjucer.vcxproj.filters @@ -1887,6 +1887,9 @@ Juce Modules\juce_gui_basics\mouse + + Juce Modules\juce_gui_basics\mouse + Juce Modules\juce_gui_basics\mouse diff --git a/extras/JuceDemo/Builds/MacOSX/Juce Demo.xcodeproj/project.pbxproj b/extras/JuceDemo/Builds/MacOSX/Juce Demo.xcodeproj/project.pbxproj index f51c15cf5f..fef50459d9 100644 --- a/extras/JuceDemo/Builds/MacOSX/Juce Demo.xcodeproj/project.pbxproj +++ b/extras/JuceDemo/Builds/MacOSX/Juce Demo.xcodeproj/project.pbxproj @@ -828,6 +828,7 @@ DEB23C98FEC261260F63B6A4 = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; DED6D04CFED991C5924B78F0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_MD5.h"; path = "../../../../modules/juce_cryptography/hashing/juce_MD5.h"; sourceTree = "SOURCE_ROOT"; }; DF2D86EEA8031481C1FD08B2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_FileTreeComponent.cpp"; path = "../../../../modules/juce_gui_basics/filebrowser/juce_FileTreeComponent.cpp"; sourceTree = "SOURCE_ROOT"; }; + DF3B7E1BC0AF0C826C47745B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ResizableWindow.h"; path = "../../../../modules/juce_gui_basics/windows/juce_ResizableWindow.h"; sourceTree = "SOURCE_ROOT"; }; DF47E8197FF5A9309C062C61 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Justification.cpp"; path = "../../../../modules/juce_graphics/placement/juce_Justification.cpp"; sourceTree = "SOURCE_ROOT"; }; DF590CD70352A30FA3BD9835 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_linux_SystemTrayIcon.cpp"; path = "../../../../modules/juce_gui_extra/native/juce_linux_SystemTrayIcon.cpp"; sourceTree = "SOURCE_ROOT"; }; E0AE248F52C70AA1DEA1A5A1 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_MidiOutput.h"; path = "../../../../modules/juce_audio_devices/midi_io/juce_MidiOutput.h"; sourceTree = "SOURCE_ROOT"; }; @@ -840,7 +841,6 @@ E6448B3F03DD2B41519DF93D = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DiscRecording.framework; path = System/Library/Frameworks/DiscRecording.framework; sourceTree = SDKROOT; }; D119A3871626EC2B8EFCB0D4 = { isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JuceDemo.app; sourceTree = "BUILT_PRODUCTS_DIR"; }; DEE1FC30E2FBB97921616CA9 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Font.cpp"; path = "../../../../modules/juce_graphics/fonts/juce_Font.cpp"; sourceTree = "SOURCE_ROOT"; }; - DF3B7E1BC0AF0C826C47745B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ResizableWindow.h"; path = "../../../../modules/juce_gui_basics/windows/juce_ResizableWindow.h"; sourceTree = "SOURCE_ROOT"; }; DFEAB699C98B89FF0B85F557 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_win32_DirectWriteTypeLayout.cpp"; path = "../../../../modules/juce_graphics/native/juce_win32_DirectWriteTypeLayout.cpp"; sourceTree = "SOURCE_ROOT"; }; DFF6BF0BB64714A494A25E93 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_RSAKey.h"; path = "../../../../modules/juce_cryptography/encryption/juce_RSAKey.h"; sourceTree = "SOURCE_ROOT"; }; E15F577E82B2E12597447472 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ApplicationBase.h"; path = "../../../../modules/juce_events/messages/juce_ApplicationBase.h"; sourceTree = "SOURCE_ROOT"; }; @@ -898,6 +898,7 @@ F664E58A0B3899FB98CF8E1C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ComponentAnimator.cpp"; path = "../../../../modules/juce_gui_basics/layout/juce_ComponentAnimator.cpp"; sourceTree = "SOURCE_ROOT"; }; F6AE140F7CE1B08B52A8C8AF = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_TextPropertyComponent.cpp"; path = "../../../../modules/juce_gui_basics/properties/juce_TextPropertyComponent.cpp"; sourceTree = "SOURCE_ROOT"; }; F6D1D5FD437BF40AC208AA2E = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_FileChooser.cpp"; path = "../../../../modules/juce_gui_basics/filebrowser/juce_FileChooser.cpp"; sourceTree = "SOURCE_ROOT"; }; + F7310246639A5CB75EFF7E7A = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_TextDragAndDropTarget.h"; path = "../../../../modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h"; sourceTree = "SOURCE_ROOT"; }; F76944FF282DB2FB4FB1B229 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Time.h"; path = "../../../../modules/juce_core/time/juce_Time.h"; sourceTree = "SOURCE_ROOT"; }; F796E49F8209912C1E8E0ADC = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ButtonPropertyComponent.cpp"; path = "../../../../modules/juce_gui_basics/properties/juce_ButtonPropertyComponent.cpp"; sourceTree = "SOURCE_ROOT"; }; F7BA444D0130F3613252D00D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_mac_AudioCDReader.mm"; path = "../../../../modules/juce_audio_devices/native/juce_mac_AudioCDReader.mm"; sourceTree = "SOURCE_ROOT"; }; @@ -1587,6 +1588,7 @@ EDDDD60231231B8221711145, 6E0DA76710F31FA13F5168B3, A18C61D2206141C03B24BF9B, + F7310246639A5CB75EFF7E7A, E963816786695359C91EF35D ); name = mouse; sourceTree = ""; }; FDFB0903CA0E73107353483F = { isa = PBXGroup; children = ( 1FC2BD9784C0FCB1D259C006, diff --git a/extras/JuceDemo/Builds/VisualStudio2005/Juce Demo.vcproj b/extras/JuceDemo/Builds/VisualStudio2005/Juce Demo.vcproj index b30f4dc69d..4f30603beb 100644 --- a/extras/JuceDemo/Builds/VisualStudio2005/Juce Demo.vcproj +++ b/extras/JuceDemo/Builds/VisualStudio2005/Juce Demo.vcproj @@ -2827,6 +2827,7 @@ + diff --git a/extras/JuceDemo/Builds/VisualStudio2008/Juce Demo.vcproj b/extras/JuceDemo/Builds/VisualStudio2008/Juce Demo.vcproj index 1d1e38b520..2b528d69eb 100644 --- a/extras/JuceDemo/Builds/VisualStudio2008/Juce Demo.vcproj +++ b/extras/JuceDemo/Builds/VisualStudio2008/Juce Demo.vcproj @@ -2827,6 +2827,7 @@ + diff --git a/extras/JuceDemo/Builds/VisualStudio2010/Juce Demo.vcxproj b/extras/JuceDemo/Builds/VisualStudio2010/Juce Demo.vcxproj index 6ec5a37c2c..27f5ce4b00 100644 --- a/extras/JuceDemo/Builds/VisualStudio2010/Juce Demo.vcxproj +++ b/extras/JuceDemo/Builds/VisualStudio2010/Juce Demo.vcxproj @@ -1473,6 +1473,7 @@ + diff --git a/extras/JuceDemo/Builds/VisualStudio2010/Juce Demo.vcxproj.filters b/extras/JuceDemo/Builds/VisualStudio2010/Juce Demo.vcxproj.filters index d94a9618e1..4c687e482e 100644 --- a/extras/JuceDemo/Builds/VisualStudio2010/Juce Demo.vcxproj.filters +++ b/extras/JuceDemo/Builds/VisualStudio2010/Juce Demo.vcxproj.filters @@ -2352,6 +2352,9 @@ Juce Modules\juce_gui_basics\mouse + + Juce Modules\juce_gui_basics\mouse + Juce Modules\juce_gui_basics\mouse diff --git a/extras/JuceDemo/Builds/iOS/Juce Demo.xcodeproj/project.pbxproj b/extras/JuceDemo/Builds/iOS/Juce Demo.xcodeproj/project.pbxproj index f5d9c8cde7..ba28bc1c31 100644 --- a/extras/JuceDemo/Builds/iOS/Juce Demo.xcodeproj/project.pbxproj +++ b/extras/JuceDemo/Builds/iOS/Juce Demo.xcodeproj/project.pbxproj @@ -816,7 +816,6 @@ DEE1FC30E2FBB97921616CA9 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Font.cpp"; path = "../../../../modules/juce_graphics/fonts/juce_Font.cpp"; sourceTree = "SOURCE_ROOT"; }; DF2D86EEA8031481C1FD08B2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_FileTreeComponent.cpp"; path = "../../../../modules/juce_gui_basics/filebrowser/juce_FileTreeComponent.cpp"; sourceTree = "SOURCE_ROOT"; }; DF47E8197FF5A9309C062C61 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Justification.cpp"; path = "../../../../modules/juce_graphics/placement/juce_Justification.cpp"; sourceTree = "SOURCE_ROOT"; }; - DF590CD70352A30FA3BD9835 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_linux_SystemTrayIcon.cpp"; path = "../../../../modules/juce_gui_extra/native/juce_linux_SystemTrayIcon.cpp"; sourceTree = "SOURCE_ROOT"; }; DFF6BF0BB64714A494A25E93 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_RSAKey.h"; path = "../../../../modules/juce_cryptography/encryption/juce_RSAKey.h"; sourceTree = "SOURCE_ROOT"; }; E0AE248F52C70AA1DEA1A5A1 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_MidiOutput.h"; path = "../../../../modules/juce_audio_devices/midi_io/juce_MidiOutput.h"; sourceTree = "SOURCE_ROOT"; }; E15F577E82B2E12597447472 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ApplicationBase.h"; path = "../../../../modules/juce_events/messages/juce_ApplicationBase.h"; sourceTree = "SOURCE_ROOT"; }; @@ -834,6 +833,7 @@ DB507A1F7BB7489344FF90A9 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Range.h"; path = "../../../../modules/juce_core/maths/juce_Range.h"; sourceTree = "SOURCE_ROOT"; }; DE80C724F35B1464853FDE9E = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_SubregionStream.h"; path = "../../../../modules/juce_core/streams/juce_SubregionStream.h"; sourceTree = "SOURCE_ROOT"; }; DF3B7E1BC0AF0C826C47745B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ResizableWindow.h"; path = "../../../../modules/juce_gui_basics/windows/juce_ResizableWindow.h"; sourceTree = "SOURCE_ROOT"; }; + DF590CD70352A30FA3BD9835 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_linux_SystemTrayIcon.cpp"; path = "../../../../modules/juce_gui_extra/native/juce_linux_SystemTrayIcon.cpp"; sourceTree = "SOURCE_ROOT"; }; DFEAB699C98B89FF0B85F557 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_win32_DirectWriteTypeLayout.cpp"; path = "../../../../modules/juce_graphics/native/juce_win32_DirectWriteTypeLayout.cpp"; sourceTree = "SOURCE_ROOT"; }; E26E3AC933F70B56B7B83EFA = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_MACAddress.cpp"; path = "../../../../modules/juce_core/network/juce_MACAddress.cpp"; sourceTree = "SOURCE_ROOT"; }; E2732267CD7C0C3BDB17456A = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_BooleanPropertyComponent.h"; path = "../../../../modules/juce_gui_basics/properties/juce_BooleanPropertyComponent.h"; sourceTree = "SOURCE_ROOT"; }; @@ -890,6 +890,7 @@ F664E58A0B3899FB98CF8E1C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ComponentAnimator.cpp"; path = "../../../../modules/juce_gui_basics/layout/juce_ComponentAnimator.cpp"; sourceTree = "SOURCE_ROOT"; }; F6AE140F7CE1B08B52A8C8AF = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_TextPropertyComponent.cpp"; path = "../../../../modules/juce_gui_basics/properties/juce_TextPropertyComponent.cpp"; sourceTree = "SOURCE_ROOT"; }; F6D1D5FD437BF40AC208AA2E = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_FileChooser.cpp"; path = "../../../../modules/juce_gui_basics/filebrowser/juce_FileChooser.cpp"; sourceTree = "SOURCE_ROOT"; }; + F7310246639A5CB75EFF7E7A = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_TextDragAndDropTarget.h"; path = "../../../../modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h"; sourceTree = "SOURCE_ROOT"; }; F76944FF282DB2FB4FB1B229 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Time.h"; path = "../../../../modules/juce_core/time/juce_Time.h"; sourceTree = "SOURCE_ROOT"; }; F796E49F8209912C1E8E0ADC = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ButtonPropertyComponent.cpp"; path = "../../../../modules/juce_gui_basics/properties/juce_ButtonPropertyComponent.cpp"; sourceTree = "SOURCE_ROOT"; }; F7BA444D0130F3613252D00D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_mac_AudioCDReader.mm"; path = "../../../../modules/juce_audio_devices/native/juce_mac_AudioCDReader.mm"; sourceTree = "SOURCE_ROOT"; }; @@ -1579,6 +1580,7 @@ EDDDD60231231B8221711145, 6E0DA76710F31FA13F5168B3, A18C61D2206141C03B24BF9B, + F7310246639A5CB75EFF7E7A, E963816786695359C91EF35D ); name = mouse; sourceTree = ""; }; FDFB0903CA0E73107353483F = { isa = PBXGroup; children = ( 1FC2BD9784C0FCB1D259C006, diff --git a/extras/JuceDemo/Source/demos/DragAndDropDemo.cpp b/extras/JuceDemo/Source/demos/DragAndDropDemo.cpp index f7c9fd2b72..b4777855fc 100644 --- a/extras/JuceDemo/Source/demos/DragAndDropDemo.cpp +++ b/extras/JuceDemo/Source/demos/DragAndDropDemo.cpp @@ -97,7 +97,8 @@ public: class DragAndDropDemoTarget : public Component, public DragAndDropTarget, - public FileDragAndDropTarget + public FileDragAndDropTarget, + public TextDragAndDropTarget { public: //============================================================================== @@ -201,6 +202,38 @@ public: repaint(); } + // These methods implement the TextDragAndDropTarget interface, and allow our component + // to accept drag-and-drop of text.. + + bool isInterestedInTextDrag (const String& /*text*/) + { + return true; + } + + void textDragEnter (const String& /*text*/, int /*x*/, int /*y*/) + { + somethingIsBeingDraggedOver = true; + repaint(); + } + + void textDragMove (const String& /*text*/, int /*x*/, int /*y*/) + { + } + + void textDragExit (const String& /*text*/) + { + somethingIsBeingDraggedOver = false; + repaint(); + } + + void textDropped (const String& text, int /*x*/, int /*y*/) + { + message = "text dropped:\n" + text; + + somethingIsBeingDraggedOver = false; + repaint(); + } + private: String message; bool somethingIsBeingDraggedOver; diff --git a/extras/audio plugin host/Builds/VisualStudio2005/Plugin Host.vcproj b/extras/audio plugin host/Builds/VisualStudio2005/Plugin Host.vcproj index 1037dd36f1..f0b01806d3 100644 --- a/extras/audio plugin host/Builds/VisualStudio2005/Plugin Host.vcproj +++ b/extras/audio plugin host/Builds/VisualStudio2005/Plugin Host.vcproj @@ -2750,6 +2750,7 @@ + diff --git a/extras/audio plugin host/Builds/VisualStudio2008/Plugin Host.vcproj b/extras/audio plugin host/Builds/VisualStudio2008/Plugin Host.vcproj index 67772787bb..09401de4be 100644 --- a/extras/audio plugin host/Builds/VisualStudio2008/Plugin Host.vcproj +++ b/extras/audio plugin host/Builds/VisualStudio2008/Plugin Host.vcproj @@ -2750,6 +2750,7 @@ + diff --git a/extras/example projects/Builds/VisualStudio2005/HelloWorld.vcproj b/extras/example projects/Builds/VisualStudio2005/HelloWorld.vcproj index 6542d5176f..a780bf2b6e 100644 --- a/extras/example projects/Builds/VisualStudio2005/HelloWorld.vcproj +++ b/extras/example projects/Builds/VisualStudio2005/HelloWorld.vcproj @@ -1788,6 +1788,7 @@ + diff --git a/extras/example projects/Builds/VisualStudio2008/HelloWorld.vcproj b/extras/example projects/Builds/VisualStudio2008/HelloWorld.vcproj index e7fef18cbc..c05728fea1 100644 --- a/extras/example projects/Builds/VisualStudio2008/HelloWorld.vcproj +++ b/extras/example projects/Builds/VisualStudio2008/HelloWorld.vcproj @@ -1788,6 +1788,7 @@ + diff --git a/extras/static library/Builds/VisualStudio2008/juce.vcproj b/extras/static library/Builds/VisualStudio2008/juce.vcproj index ef0db7438d..75633beade 100644 --- a/extras/static library/Builds/VisualStudio2008/juce.vcproj +++ b/extras/static library/Builds/VisualStudio2008/juce.vcproj @@ -2712,6 +2712,7 @@ + diff --git a/extras/static library/Builds/VisualStudio2010/juce.vcxproj b/extras/static library/Builds/VisualStudio2010/juce.vcxproj index 35a620e1f5..6f8cd95c3d 100644 --- a/extras/static library/Builds/VisualStudio2010/juce.vcxproj +++ b/extras/static library/Builds/VisualStudio2010/juce.vcxproj @@ -1441,6 +1441,7 @@ + diff --git a/extras/static library/Builds/VisualStudio2010/juce.vcxproj.filters b/extras/static library/Builds/VisualStudio2010/juce.vcxproj.filters index ce295db162..3a86e69fd6 100644 --- a/extras/static library/Builds/VisualStudio2010/juce.vcxproj.filters +++ b/extras/static library/Builds/VisualStudio2010/juce.vcxproj.filters @@ -2253,6 +2253,9 @@ Juce Modules\juce_gui_basics\mouse + + Juce Modules\juce_gui_basics\mouse + Juce Modules\juce_gui_basics\mouse diff --git a/extras/the jucer/Builds/MacOSX/Jucer.xcodeproj/project.pbxproj b/extras/the jucer/Builds/MacOSX/Jucer.xcodeproj/project.pbxproj index 8756c19c1e..06c80200a8 100644 --- a/extras/the jucer/Builds/MacOSX/Jucer.xcodeproj/project.pbxproj +++ b/extras/the jucer/Builds/MacOSX/Jucer.xcodeproj/project.pbxproj @@ -411,6 +411,7 @@ 7CC66B40D5C3739D0A284D20 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ChildProcess.h"; path = "../../../../modules/juce_core/threads/juce_ChildProcess.h"; sourceTree = "SOURCE_ROOT"; }; 7D3624000CAB22908F768E79 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_FileChooserDialogBox.h"; path = "../../../../modules/juce_gui_basics/filebrowser/juce_FileChooserDialogBox.h"; sourceTree = "SOURCE_ROOT"; }; 7D756488BD3EA6FA4B592B32 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_RelativePointPath.cpp"; path = "../../../../modules/juce_gui_basics/positioning/juce_RelativePointPath.cpp"; sourceTree = "SOURCE_ROOT"; }; + 7E1102808EC2A1A3DA676E74 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_TextDragAndDropTarget.h"; path = "../../../../modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h"; sourceTree = "SOURCE_ROOT"; }; 7E1C9DDB7A06CE9F25FABB17 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ActionBroadcaster.cpp"; path = "../../../../modules/juce_events/broadcasters/juce_ActionBroadcaster.cpp"; sourceTree = "SOURCE_ROOT"; }; 7E3F55C0299155E2BF10C89A = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Slider.cpp"; path = "../../../../modules/juce_gui_basics/widgets/juce_Slider.cpp"; sourceTree = "SOURCE_ROOT"; }; 7E9461652B3F35C68CD213CE = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ChangeBroadcaster.h"; path = "../../../../modules/juce_events/broadcasters/juce_ChangeBroadcaster.h"; sourceTree = "SOURCE_ROOT"; }; @@ -1301,6 +1302,7 @@ B2F268461E72BFE4B9B6642A, 57D8E4D78A4E8B8EC8466B98, DB4BB79021DBB8BE1847787E, + 7E1102808EC2A1A3DA676E74, E9FA21969B0983F69D4FC6F8 ); name = mouse; sourceTree = ""; }; DBD798D7F4C2E66D303CD10D = { isa = PBXGroup; children = ( 3CAF4F225FB95CF2C0580DB5, diff --git a/extras/the jucer/Builds/VisualStudio2008/Jucer.vcproj b/extras/the jucer/Builds/VisualStudio2008/Jucer.vcproj index d5b26ea135..f626fd75c3 100644 --- a/extras/the jucer/Builds/VisualStudio2008/Jucer.vcproj +++ b/extras/the jucer/Builds/VisualStudio2008/Jucer.vcproj @@ -1955,6 +1955,7 @@ + diff --git a/extras/the jucer/Builds/VisualStudio2010/Jucer.vcxproj b/extras/the jucer/Builds/VisualStudio2010/Jucer.vcxproj index 16978d73c5..5f5a858fe0 100644 --- a/extras/the jucer/Builds/VisualStudio2010/Jucer.vcxproj +++ b/extras/the jucer/Builds/VisualStudio2010/Jucer.vcxproj @@ -1193,6 +1193,7 @@ + diff --git a/extras/the jucer/Builds/VisualStudio2010/Jucer.vcxproj.filters b/extras/the jucer/Builds/VisualStudio2010/Jucer.vcxproj.filters index 28ccbc1eda..e93fb7a34f 100644 --- a/extras/the jucer/Builds/VisualStudio2010/Jucer.vcxproj.filters +++ b/extras/the jucer/Builds/VisualStudio2010/Jucer.vcxproj.filters @@ -1941,6 +1941,9 @@ Juce Modules\juce_gui_basics\mouse + + Juce Modules\juce_gui_basics\mouse + Juce Modules\juce_gui_basics\mouse diff --git a/modules/juce_gui_basics/juce_gui_basics.h b/modules/juce_gui_basics/juce_gui_basics.h index 6b2bfd70f9..2b1943b81f 100644 --- a/modules/juce_gui_basics/juce_gui_basics.h +++ b/modules/juce_gui_basics/juce_gui_basics.h @@ -103,6 +103,9 @@ namespace juce #ifndef __JUCE_FILEDRAGANDDROPTARGET_JUCEHEADER__ #include "mouse/juce_FileDragAndDropTarget.h" #endif +#ifndef __JUCE_TEXTDRAGANDDROPTARGET_JUCEHEADER__ + #include "mouse/juce_TextDragAndDropTarget.h" +#endif #ifndef __JUCE_LASSOCOMPONENT_JUCEHEADER__ #include "mouse/juce_LassoComponent.h" #endif diff --git a/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp b/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp index 706df074c7..0bc81254a8 100644 --- a/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp +++ b/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp @@ -441,3 +441,7 @@ bool DragAndDropTarget::shouldDrawDragImageWhenOver() { return true; } void FileDragAndDropTarget::fileDragEnter (const StringArray&, int, int) {} void FileDragAndDropTarget::fileDragMove (const StringArray&, int, int) {} void FileDragAndDropTarget::fileDragExit (const StringArray&) {} + +void TextDragAndDropTarget::textDragEnter (const String&, int, int) {} +void TextDragAndDropTarget::textDragMove (const String&, int, int) {} +void TextDragAndDropTarget::textDragExit (const String&) {} \ No newline at end of file diff --git a/modules/juce_gui_basics/mouse/juce_FileDragAndDropTarget.h b/modules/juce_gui_basics/mouse/juce_FileDragAndDropTarget.h index 93cd11eab6..200775aacf 100644 --- a/modules/juce_gui_basics/mouse/juce_FileDragAndDropTarget.h +++ b/modules/juce_gui_basics/mouse/juce_FileDragAndDropTarget.h @@ -26,10 +26,6 @@ #ifndef __JUCE_FILEDRAGANDDROPTARGET_JUCEHEADER__ #define __JUCE_FILEDRAGANDDROPTARGET_JUCEHEADER__ -#include "../components/juce_Component.h" - - -//============================================================================== /** Components derived from this class can have files dropped onto them by an external application. diff --git a/modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h b/modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h new file mode 100644 index 0000000000..51055212a3 --- /dev/null +++ b/modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h @@ -0,0 +1,104 @@ +/* + ============================================================================== + + This file is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-11 by Raw Material Software Ltd. + + ------------------------------------------------------------------------------ + + JUCE can be redistributed and/or modified under the terms of the GNU General + Public License (Version 2), as published by the Free Software Foundation. + A copy of the license is included in the JUCE distribution, or can be found + online at www.gnu.org/licenses. + + JUCE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.rawmaterialsoftware.com/juce for more information. + + ============================================================================== +*/ + +#ifndef __JUCE_TEXTDRAGANDDROPTARGET_JUCEHEADER__ +#define __JUCE_TEXTDRAGANDDROPTARGET_JUCEHEADER__ + +/** + Components derived from this class can have text dropped onto them by an external application. + + @see DragAndDropContainer +*/ +class JUCE_API TextDragAndDropTarget +{ +public: + /** Destructor. */ + virtual ~TextDragAndDropTarget() {} + + /** Callback to check whether this target is interested in the set of text being offered. + + Note that this will be called repeatedly when the user is dragging the mouse around over your + component, so don't do anything time-consuming in here! + + @param text the text that the user is dragging + @returns true if this component wants to receive the other callbacks regarging this + type of object; if it returns false, no other callbacks will be made. + */ + virtual bool isInterestedInTextDrag (const String& text) = 0; + + /** Callback to indicate that some text is being dragged over this component. + + This gets called when the user moves the mouse into this component while dragging. + + Use this callback as a trigger to make your component repaint itself to give the + user feedback about whether the text can be dropped here or not. + + @param text the text that the user is dragging + @param x the mouse x position, relative to this component + @param y the mouse y position, relative to this component + */ + virtual void textDragEnter (const String& text, int x, int y); + + /** Callback to indicate that the user is dragging some text over this component. + + This gets called when the user moves the mouse over this component while dragging. + Normally overriding itemDragEnter() and itemDragExit() are enough, but + this lets you know what happens in-between. + + @param text the text that the user is dragging + @param x the mouse x position, relative to this component + @param y the mouse y position, relative to this component + */ + virtual void textDragMove (const String& text, int x, int y); + + /** Callback to indicate that the mouse has moved away from this component. + + This gets called when the user moves the mouse out of this component while dragging + the text. + + If you've used textDragEnter() to repaint your component and give feedback, use this + as a signal to repaint it in its normal state. + + @param text the text that the user is dragging + */ + virtual void textDragExit (const String& text); + + /** Callback to indicate that the user has dropped the text onto this component. + + When the user drops the text, this get called, and you can use the text in whatever + way is appropriate. + + Note that after this is called, the textDragExit method may not be called, so you should + clean up in here if there's anything you need to do when the drag finishes. + + @param text the text that the user is dragging + @param x the mouse x position, relative to this component + @param y the mouse y position, relative to this component + */ + virtual void textDropped (const String& text, int x, int y) = 0; +}; + + +#endif // __JTEXTDRAGANDDROPTARGET_JUCEHEADER__ diff --git a/modules/juce_gui_basics/native/juce_linux_Windowing.cpp b/modules/juce_gui_basics/native/juce_linux_Windowing.cpp index f077991103..d9acf5dbd3 100644 --- a/modules/juce_gui_basics/native/juce_linux_Windowing.cpp +++ b/modules/juce_gui_basics/native/juce_linux_Windowing.cpp @@ -2263,8 +2263,9 @@ private: //============================================================================== void resetDragAndDrop() { - dragAndDropFiles.clear(); - lastDropPos = Point (-1, -1); + dragInfo.files.clear(); + dragInfo.text = String::empty; + dragInfo.position = Point (-1, -1); dragAndDropCurrentMimeType = 0; dragAndDropSourceWindow = 0; srcMimeTypeAtomList.clear(); @@ -2312,10 +2313,10 @@ private: { sendDragAndDropLeave(); - if (dragAndDropFiles.size() > 0) - handleFileDragExit (dragAndDropFiles); + if (dragInfo.files.size() > 0) + handleDragExit (dragInfo); - dragAndDropFiles.clear(); + dragInfo.files.clear(); } } @@ -2330,10 +2331,9 @@ private: (int) clientMsg->data.l[2] & 0xffff); dropPos -= getScreenPosition(); - if (lastDropPos != dropPos) + if (dragInfo.position != dropPos) { - lastDropPos = dropPos; - dragAndDropTimestamp = clientMsg->data.l[3]; + dragInfo.position = dropPos; Atom targetAction = Atoms::XdndActionCopy; @@ -2348,32 +2348,31 @@ private: sendDragAndDropStatus (true, targetAction); - if (dragAndDropFiles.size() == 0) + if (dragInfo.files.size() == 0) updateDraggedFileList (clientMsg); - if (dragAndDropFiles.size() > 0) - handleFileDragMove (dragAndDropFiles, dropPos); + if (dragInfo.files.size() > 0) + handleDragMove (dragInfo); } } void handleDragAndDropDrop (const XClientMessageEvent* const clientMsg) { - if (dragAndDropFiles.size() == 0) + if (dragInfo.files.size() == 0) updateDraggedFileList (clientMsg); - const StringArray files (dragAndDropFiles); - const Point lastPos (lastDropPos); + DragInfo dragInfoCopy (dragInfo); sendDragAndDropFinish(); resetDragAndDrop(); - if (files.size() > 0) - handleFileDragDrop (files, lastPos); + if (dragInfoCopy.files.size() > 0) + handleDragDrop (dragInfoCopy); } void handleDragAndDropEnter (const XClientMessageEvent* const clientMsg) { - dragAndDropFiles.clear(); + dragInfo.files.clear(); srcMimeTypeAtomList.clear(); dragAndDropCurrentMimeType = 0; @@ -2437,7 +2436,7 @@ private: void handleDragAndDropSelection (const XEvent* const evt) { - dragAndDropFiles.clear(); + dragInfo.files.clear(); if (evt->xselection.property != 0) { @@ -2475,36 +2474,31 @@ private: } for (int i = 0; i < lines.size(); ++i) - dragAndDropFiles.add (URL::removeEscapeChars (lines[i].fromFirstOccurrenceOf ("file://", false, true))); + dragInfo.files.add (URL::removeEscapeChars (lines[i].fromFirstOccurrenceOf ("file://", false, true))); - dragAndDropFiles.trim(); - dragAndDropFiles.removeEmptyStrings(); + dragInfo.files.trim(); + dragInfo.files.removeEmptyStrings(); } } void updateDraggedFileList (const XClientMessageEvent* const clientMsg) { - dragAndDropFiles.clear(); + dragInfo.files.clear(); if (dragAndDropSourceWindow != None && dragAndDropCurrentMimeType != 0) { - dragAndDropTimestamp = clientMsg->data.l[2]; - ScopedXLock xlock; XConvertSelection (display, Atoms::XdndSelection, dragAndDropCurrentMimeType, Atoms::getCreating ("JXSelectionWindowProperty"), windowH, - dragAndDropTimestamp); + clientMsg->data.l[2]); } } - StringArray dragAndDropFiles; - int dragAndDropTimestamp; - Point lastDropPos; - + DragInfo dragInfo; Atom dragAndDropCurrentMimeType; Window dragAndDropSourceWindow; diff --git a/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm b/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm index 565dca62c8..4143bb6c38 100644 --- a/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm +++ b/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm @@ -209,8 +209,6 @@ public: virtual bool redirectPerformKeyEquivalent (NSEvent* ev); #endif - virtual BOOL sendDragCallback (int type, id sender); - virtual bool isOpaque(); virtual void drawRect (NSRect r); @@ -289,6 +287,79 @@ public: return style; } + virtual BOOL sendDragCallback (const int type, id sender) + { + NSPasteboard* pasteboard = [sender draggingPasteboard]; + NSString* contentType = [pasteboard availableTypeFromArray: [view getSupportedDragTypes]]; + + if (contentType == nil) + return false; + + NSPoint p = [view convertPoint: [sender draggingLocation] fromView: nil]; + ComponentPeer::DragInfo dragInfo; + dragInfo.position.setXY ((int) p.x, (int) ([view frame].size.height - p.y)); + + if (contentType == NSStringPboardType) + dragInfo.text = nsStringToJuce ([pasteboard stringForType: NSStringPboardType]); + else + dragInfo.files = getDroppedFiles (pasteboard, contentType); + + if (dragInfo.files.size() > 0 || dragInfo.text.isNotEmpty()) + { + switch (type) + { + case 0: return handleDragMove (dragInfo); + case 1: return handleDragExit (dragInfo); + case 2: return handleDragDrop (dragInfo); + default: jassertfalse; break; + } + } + + return false; + } + + StringArray getDroppedFiles (NSPasteboard* pasteboard, NSString* contentType) + { + StringArray files; + NSString* iTunesPasteboardType = nsStringLiteral ("CorePasteboardFlavorType 0x6974756E"); // 'itun' + + if (contentType == NSFilesPromisePboardType + && [[pasteboard types] containsObject: iTunesPasteboardType]) + { + id list = [pasteboard propertyListForType: iTunesPasteboardType]; + + if ([list isKindOfClass: [NSDictionary class]]) + { + NSDictionary* iTunesDictionary = (NSDictionary*) list; + NSArray* tracks = [iTunesDictionary valueForKey: nsStringLiteral ("Tracks")]; + NSEnumerator* enumerator = [tracks objectEnumerator]; + NSDictionary* track; + + while ((track = [enumerator nextObject]) != nil) + { + NSURL* url = [NSURL URLWithString: [track valueForKey: nsStringLiteral ("Location")]]; + + if ([url isFileURL]) + files.add (nsStringToJuce ([url path])); + } + } + } + else + { + id list = [pasteboard propertyListForType: NSFilenamesPboardType]; + + if ([list isKindOfClass: [NSArray class]]) + { + NSArray* items = (NSArray*) [pasteboard propertyListForType: NSFilenamesPboardType]; + + for (unsigned int i = 0; i < [items count]; ++i) + files.add (nsStringToJuce ((NSString*) [items objectAtIndex: i])); + } + } + + return files; + } + //============================================================================== virtual void viewFocusGain(); virtual void viewFocusLoss(); @@ -713,7 +784,7 @@ private: //============================================================================== - (NSArray*) getSupportedDragTypes { - return [NSArray arrayWithObjects: NSFilenamesPboardType, NSFilesPromisePboardType, /* NSStringPboardType,*/ nil]; + return [NSArray arrayWithObjects: NSFilenamesPboardType, NSFilesPromisePboardType, NSStringPboardType, nil]; } - (BOOL) sendDragCallback: (int) type sender: (id ) sender @@ -1553,70 +1624,6 @@ void NSViewComponentPeer::showArrowCursorIfNeeded() } //============================================================================== -BOOL NSViewComponentPeer::sendDragCallback (const int type, id sender) -{ - NSString* bestType - = [[sender draggingPasteboard] availableTypeFromArray: [view getSupportedDragTypes]]; - - if (bestType == nil) - return false; - - NSPoint p = [view convertPoint: [sender draggingLocation] fromView: nil]; - const Point pos ((int) p.x, (int) ([view frame].size.height - p.y)); - - NSPasteboard* pasteBoard = [sender draggingPasteboard]; - StringArray files; - - NSString* iTunesPasteboardType = nsStringLiteral ("CorePasteboardFlavorType 0x6974756E"); // 'itun' - - if (bestType == NSFilesPromisePboardType - && [[pasteBoard types] containsObject: iTunesPasteboardType]) - { - id list = [pasteBoard propertyListForType: iTunesPasteboardType]; - - if ([list isKindOfClass: [NSDictionary class]]) - { - NSDictionary* iTunesDictionary = (NSDictionary*) list; - NSArray* tracks = [iTunesDictionary valueForKey: nsStringLiteral ("Tracks")]; - NSEnumerator* enumerator = [tracks objectEnumerator]; - NSDictionary* track; - - while ((track = [enumerator nextObject]) != nil) - { - NSURL* url = [NSURL URLWithString: [track valueForKey: nsStringLiteral ("Location")]]; - - if ([url isFileURL]) - files.add (nsStringToJuce ([url path])); - } - } - } - else - { - id list = [pasteBoard propertyListForType: NSFilenamesPboardType]; - - if ([list isKindOfClass: [NSArray class]]) - { - NSArray* items = (NSArray*) [pasteBoard propertyListForType: NSFilenamesPboardType]; - - for (unsigned int i = 0; i < [items count]; ++i) - files.add (nsStringToJuce ((NSString*) [items objectAtIndex: i])); - } - } - - if (files.size() > 0) - { - switch (type) - { - case 0: return handleFileDragMove (files, pos); - case 1: return handleFileDragExit (files); - case 2: return handleFileDragDrop (files, pos); - default: jassertfalse; break; - } - } - - return false; -} - bool NSViewComponentPeer::isOpaque() { return component == nullptr || component->isOpaque(); diff --git a/modules/juce_gui_basics/native/juce_win32_Windowing.cpp b/modules/juce_gui_basics/native/juce_win32_Windowing.cpp index 77351f85d8..b59fbf5807 100644 --- a/modules/juce_gui_basics/native/juce_win32_Windowing.cpp +++ b/modules/juce_gui_basics/native/juce_win32_Windowing.cpp @@ -920,7 +920,7 @@ public: if (ownerInfo == nullptr) return S_FALSE; - ownerInfo->owner.handleFileDragExit (ownerInfo->files); + ownerInfo->owner.handleDragExit (ownerInfo->dragInfo); return S_OK; } @@ -929,7 +929,8 @@ public: if (ownerInfo == nullptr) return S_FALSE; - const bool wasWanted = ownerInfo->owner.handleFileDragMove (ownerInfo->files, ownerInfo->getMousePos (mousePos)); + ownerInfo->dragInfo.position = ownerInfo->getMousePos (mousePos); + const bool wasWanted = ownerInfo->owner.handleDragMove (ownerInfo->dragInfo); *pdwEffect = wasWanted ? (DWORD) DROPEFFECT_COPY : (DWORD) DROPEFFECT_NONE; return S_OK; } @@ -939,7 +940,8 @@ public: HRESULT hr = updateFileList (pDataObject); if (SUCCEEDED (hr)) { - const bool wasWanted = ownerInfo->owner.handleFileDragDrop (ownerInfo->files, ownerInfo->getMousePos (mousePos)); + ownerInfo->dragInfo.position = ownerInfo->getMousePos (mousePos); + const bool wasWanted = ownerInfo->owner.handleDragDrop (ownerInfo->dragInfo); *pdwEffect = wasWanted ? (DWORD) DROPEFFECT_COPY : (DWORD) DROPEFFECT_NONE; hr = S_OK; } @@ -971,46 +973,83 @@ public: if (len == 0) break; - files.add (String (names + i, len)); + dragInfo.files.add (String (names + i, len)); i += len + 1; } } HWNDComponentPeer& owner; - StringArray files; + ComponentPeer::DragInfo dragInfo; JUCE_DECLARE_NON_COPYABLE (OwnerInfo); }; ScopedPointer ownerInfo; - HRESULT updateFileList (IDataObject* const pDataObject) + struct DroppedData + { + DroppedData (IDataObject* const dataObject, const CLIPFORMAT type) + : data (nullptr) + { + FORMATETC format = { type, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + STGMEDIUM resetMedium = { TYMED_HGLOBAL, { 0 }, 0 }; + medium = resetMedium; + + if (SUCCEEDED (error = dataObject->GetData (&format, &medium))) + { + dataSize = GlobalSize (medium.hGlobal); + data = GlobalLock (medium.hGlobal); + } + } + + ~DroppedData() + { + if (data != nullptr) + GlobalUnlock (medium.hGlobal); + } + + HRESULT error; + STGMEDIUM medium; + void* data; + SIZE_T dataSize; + }; + + HRESULT updateFileList (IDataObject* const dataObject) { if (ownerInfo == nullptr) return S_FALSE; - ownerInfo->files.clear(); - - FORMATETC format = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; - STGMEDIUM medium = { TYMED_HGLOBAL, { 0 }, 0 }; + ownerInfo->dragInfo.files.clear(); + ownerInfo->dragInfo.text = String::empty; - HRESULT hr = pDataObject->GetData (&format, &medium); + DroppedData textData (dataObject, CF_UNICODETEXT); - if (SUCCEEDED (hr)) + if (SUCCEEDED (textData.error)) + { + ownerInfo->dragInfo.text = String (CharPointer_UTF16 ((LPCWCHAR) textData.data), + CharPointer_UTF16 ((LPCWCHAR) addBytesToPointer (textData.data, textData.dataSize))); + } + else { - const SIZE_T totalLen = GlobalSize (medium.hGlobal); - const LPDROPFILES dropFiles = (const LPDROPFILES) GlobalLock (medium.hGlobal); - const void* const names = addBytesToPointer (dropFiles, sizeof (DROPFILES)); + DroppedData fileData (dataObject, CF_HDROP); - if (dropFiles->fWide) - ownerInfo->parseFileList (static_cast (names), totalLen); - else - ownerInfo->parseFileList (static_cast (names), totalLen); + if (SUCCEEDED (fileData.error)) + { + const LPDROPFILES dropFiles = static_cast (fileData.data); + const void* const names = addBytesToPointer (dropFiles, sizeof (DROPFILES)); - GlobalUnlock (medium.hGlobal); + if (dropFiles->fWide) + ownerInfo->parseFileList (static_cast (names), fileData.dataSize); + else + ownerInfo->parseFileList (static_cast (names), fileData.dataSize); + } + else + { + return fileData.error; + } } - return hr; + return S_OK; } JUCE_DECLARE_NON_COPYABLE (JuceDropTarget); diff --git a/modules/juce_gui_basics/windows/juce_ComponentPeer.cpp b/modules/juce_gui_basics/windows/juce_ComponentPeer.cpp index ae91a39c96..e1a9246559 100644 --- a/modules/juce_gui_basics/windows/juce_ComponentPeer.cpp +++ b/modules/juce_gui_basics/windows/juce_ComponentPeer.cpp @@ -409,54 +409,97 @@ Rectangle ComponentPeer::globalToLocal (const Rectangle& screenPositio } //============================================================================== -namespace ComponentPeerHelpers +namespace DragHelpers { - static FileDragAndDropTarget* findDragAndDropTarget (Component* c, - const StringArray& files, - FileDragAndDropTarget* const lastOne) + static bool isFileDrag (const ComponentPeer::DragInfo& info) { - while (c != nullptr) - { - FileDragAndDropTarget* const t = dynamic_cast (c); + return info.files.size() > 0; + } - if (t != nullptr && (t == lastOne || t->isInterestedInFileDrag (files))) - return t; + static bool isSuitableTarget (const ComponentPeer::DragInfo& info, Component* target) + { + return isFileDrag (info) ? dynamic_cast (target) != nullptr + : dynamic_cast (target) != nullptr; + } - c = c->getParentComponent(); - } + static bool isInterested (const ComponentPeer::DragInfo& info, Component* target) + { + return isFileDrag (info) ? dynamic_cast (target)->isInterestedInFileDrag (info.files) + : dynamic_cast (target)->isInterestedInTextDrag (info.text); + } + + static Component* findDragAndDropTarget (Component* c, const ComponentPeer::DragInfo& info, Component* lastOne) + { + for (; c != nullptr; c = c->getParentComponent()) + if (isSuitableTarget (info, c) && (c == lastOne || isInterested (info, c))) + return c; return nullptr; } + + // We'll use an async message to deliver the drop, because if the target decides + // to run a modal loop, it can gum-up the operating system.. + class AsyncDropMessage : public CallbackMessage + { + public: + AsyncDropMessage (Component* target_, const ComponentPeer::DragInfo& info_) + : target (target_), info (info_) + {} + + void messageCallback() + { + if (target.get() != nullptr) + { + if (isFileDrag (info)) + dynamic_cast (target.get())->filesDropped (info.files, info.position.x, info.position.y); + else + dynamic_cast (target.get())->textDropped (info.text, info.position.x, info.position.y); + } + } + + private: + WeakReference target; + const ComponentPeer::DragInfo info; + + JUCE_DECLARE_NON_COPYABLE (AsyncDropMessage); + }; } -bool ComponentPeer::handleFileDragMove (const StringArray& files, const Point& position) +bool ComponentPeer::handleDragMove (const ComponentPeer::DragInfo& info) { updateCurrentModifiers(); - FileDragAndDropTarget* lastTarget - = dynamic_cast (dragAndDropTargetComponent.get()); - - FileDragAndDropTarget* newTarget = nullptr; + Component* const compUnderMouse = component->getComponentAt (info.position); - Component* const compUnderMouse = component->getComponentAt (position); + Component* const lastTarget = dragAndDropTargetComponent.get(); + Component* newTarget = nullptr; if (compUnderMouse != lastDragAndDropCompUnderMouse) { lastDragAndDropCompUnderMouse = compUnderMouse; - newTarget = ComponentPeerHelpers::findDragAndDropTarget (compUnderMouse, files, lastTarget); + newTarget = DragHelpers::findDragAndDropTarget (compUnderMouse, info, lastTarget); if (newTarget != lastTarget) { if (lastTarget != nullptr) - lastTarget->fileDragExit (files); + { + if (DragHelpers::isFileDrag (info)) + dynamic_cast (lastTarget)->fileDragExit (info.files); + else + dynamic_cast (lastTarget)->textDragExit (info.text); + } dragAndDropTargetComponent = nullptr; - if (newTarget != nullptr) + if (DragHelpers::isSuitableTarget (info, newTarget)) { - dragAndDropTargetComponent = dynamic_cast (newTarget); - const Point pos (dragAndDropTargetComponent->getLocalPoint (component, position)); - newTarget->fileDragEnter (files, pos.getX(), pos.getY()); + dragAndDropTargetComponent = newTarget; + const Point pos (newTarget->getLocalPoint (component, info.position)); + + if (DragHelpers::isFileDrag (info)) + dynamic_cast (newTarget)->fileDragEnter (info.files, pos.x, pos.y); + else + dynamic_cast (newTarget)->textDragEnter (info.text, pos.x, pos.y); } } } @@ -465,62 +508,42 @@ bool ComponentPeer::handleFileDragMove (const StringArray& files, const Point pos (dragAndDropTargetComponent->getLocalPoint (component, position)); - newTarget->fileDragMove (files, pos.getX(), pos.getY()); + const Point pos (newTarget->getLocalPoint (component, info.position)); + + if (DragHelpers::isFileDrag (info)) + dynamic_cast (newTarget)->fileDragMove (info.files, pos.x, pos.y); + else + dynamic_cast (newTarget)->textDragMove (info.text, pos.x, pos.y); + return true; } -bool ComponentPeer::handleFileDragExit (const StringArray& files) +bool ComponentPeer::handleDragExit (const ComponentPeer::DragInfo& info) { - const bool used = handleFileDragMove (files, Point (-1, -1)); + DragInfo info2 (info); + info2.position.setXY (-1, -1); + const bool used = handleDragMove (info2); jassert (dragAndDropTargetComponent == nullptr); lastDragAndDropCompUnderMouse = nullptr; return used; } -// We'll use an async message to deliver the drop, because if the target decides -// to run a modal loop, it can gum-up the operating system.. -class AsyncFileDropMessage : public CallbackMessage +bool ComponentPeer::handleDragDrop (const ComponentPeer::DragInfo& info) { -public: - AsyncFileDropMessage (Component* target_, FileDragAndDropTarget* dropTarget_, - const Point& position_, const StringArray& files_) - : target (target_), dropTarget (dropTarget_), position (position_), files (files_) - { - } - - void messageCallback() - { - if (target.get() != nullptr) - dropTarget->filesDropped (files, position.getX(), position.getY()); - } + handleDragMove (info); -private: - WeakReference target; - FileDragAndDropTarget* const dropTarget; - const Point position; - const StringArray files; + Component* const targetComp = dragAndDropTargetComponent; - JUCE_DECLARE_NON_COPYABLE (AsyncFileDropMessage); -}; - -bool ComponentPeer::handleFileDragDrop (const StringArray& files, const Point& position) -{ - handleFileDragMove (files, position); - - if (dragAndDropTargetComponent != nullptr) + if (targetComp != nullptr) { - Component* const targetComp = dragAndDropTargetComponent; - FileDragAndDropTarget* const target = dynamic_cast (targetComp); - dragAndDropTargetComponent = nullptr; lastDragAndDropCompUnderMouse = nullptr; - if (target != nullptr) + if (DragHelpers::isSuitableTarget (info, targetComp)) { if (targetComp->isCurrentlyBlockedByAnotherModalComponent()) { @@ -530,7 +553,7 @@ bool ComponentPeer::handleFileDragDrop (const StringArray& files, const PointgetLocalPoint (component, position), files))->post(); + (new DragHelpers::AsyncDropMessage (targetComp, info))->post(); return true; } } diff --git a/modules/juce_gui_basics/windows/juce_ComponentPeer.h b/modules/juce_gui_basics/windows/juce_ComponentPeer.h index 8cc0461a3d..17e9b445e9 100644 --- a/modules/juce_gui_basics/windows/juce_ComponentPeer.h +++ b/modules/juce_gui_basics/windows/juce_ComponentPeer.h @@ -311,9 +311,16 @@ public: void handleUserClosingWindow(); - bool handleFileDragMove (const StringArray& files, const Point& position); - bool handleFileDragExit (const StringArray& files); - bool handleFileDragDrop (const StringArray& files, const Point& position); + struct DragInfo + { + StringArray files; + String text; + Point position; + }; + + bool handleDragMove (const DragInfo&); + bool handleDragExit (const DragInfo&); + bool handleDragDrop (const DragInfo&); //============================================================================== /** Resets the masking region. @@ -384,6 +391,7 @@ private: static ComponentPeer* getPeerFor (const Component* component) noexcept; void setLastDragDropTarget (Component* comp); + bool finishDrag (bool); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ComponentPeer); };