mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Added support for drag and drop of text on OSX, via DragAndDropContainer::shouldDropTextWhenDraggedExternally
This commit is contained in:
parent
b1d3069464
commit
dd13702684
3 changed files with 135 additions and 42 deletions
|
|
@ -300,12 +300,17 @@ private:
|
|||
: files (f), canMoveFiles (canMove)
|
||||
{}
|
||||
|
||||
ExternalDragAndDropMessage (const String& t) : text (t), canMoveFiles() {}
|
||||
|
||||
void messageCallback() override
|
||||
{
|
||||
DragAndDropContainer::performExternalDragDropOfFiles (files, canMoveFiles);
|
||||
if (text.isEmpty())
|
||||
DragAndDropContainer::performExternalDragDropOfFiles (files, canMoveFiles);
|
||||
else
|
||||
DragAndDropContainer::performExternalDragDropOfText (text);
|
||||
}
|
||||
|
||||
private:
|
||||
String text;
|
||||
StringArray files;
|
||||
bool canMoveFiles;
|
||||
};
|
||||
|
|
@ -318,14 +323,21 @@ private:
|
|||
{
|
||||
hasCheckedForExternalDrag = true;
|
||||
StringArray files;
|
||||
String text;
|
||||
bool canMoveFiles = false;
|
||||
|
||||
if (owner.shouldDropFilesWhenDraggedExternally (details, files, canMoveFiles)
|
||||
&& files.size() > 0
|
||||
&& ModifierKeys::getCurrentModifiersRealtime().isAnyMouseButtonDown())
|
||||
if (ModifierKeys::getCurrentModifiersRealtime().isAnyMouseButtonDown())
|
||||
{
|
||||
(new ExternalDragAndDropMessage (files, canMoveFiles))->post();
|
||||
deleteSelf();
|
||||
if (owner.shouldDropFilesWhenDraggedExternally (details, files, canMoveFiles) && ! files.isEmpty())
|
||||
{
|
||||
(new ExternalDragAndDropMessage (files, canMoveFiles))->post();
|
||||
deleteSelf();
|
||||
}
|
||||
else if (owner.shouldDropTextWhenDraggedExternally (details, text) && text.isNotEmpty())
|
||||
{
|
||||
(new ExternalDragAndDropMessage (text))->post();
|
||||
deleteSelf();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -500,6 +512,11 @@ bool DragAndDropContainer::shouldDropFilesWhenDraggedExternally (const DragAndDr
|
|||
return false;
|
||||
}
|
||||
|
||||
bool DragAndDropContainer::shouldDropTextWhenDraggedExternally (const DragAndDropTarget::SourceDetails&, String&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void DragAndDropContainer::dragOperationStarted (const DragAndDropTarget::SourceDetails&) {}
|
||||
void DragAndDropContainer::dragOperationEnded (const DragAndDropTarget::SourceDetails&) {}
|
||||
|
||||
|
|
|
|||
|
|
@ -152,10 +152,10 @@ public:
|
|||
static bool performExternalDragDropOfText (const String& text);
|
||||
|
||||
protected:
|
||||
/** Override this if you want to be able to perform an external drag a set of files
|
||||
/** Override this if you want to be able to perform an external drag of a set of files
|
||||
when the user drags outside of this container component.
|
||||
|
||||
This method will be called when a drag operation moves outside the Juce-based window,
|
||||
This method will be called when a drag operation moves outside the JUCE window,
|
||||
and if you want it to then perform a file drag-and-drop, add the filenames you want
|
||||
to the array passed in, and return true.
|
||||
|
||||
|
|
@ -163,16 +163,30 @@ protected:
|
|||
@param files on return, the filenames you want to drag
|
||||
@param canMoveFiles on return, true if it's ok for the receiver to move the files; false if
|
||||
it must make a copy of them (see the performExternalDragDropOfFiles() method)
|
||||
@see performExternalDragDropOfFiles
|
||||
@see performExternalDragDropOfFiles, shouldDropTextWhenDraggedExternally
|
||||
*/
|
||||
virtual bool shouldDropFilesWhenDraggedExternally (const DragAndDropTarget::SourceDetails& sourceDetails,
|
||||
StringArray& files, bool& canMoveFiles);
|
||||
|
||||
/** Override this if you want to be able to perform an external drag of text
|
||||
when the user drags outside of this container component.
|
||||
|
||||
This method will be called when a drag operation moves outside the JUCE window,
|
||||
and if you want it to then perform a text drag-and-drop, copy the text you want to
|
||||
be dragged into the argument provided and return true.
|
||||
|
||||
@param sourceDetails information about the source of the drag operation
|
||||
@param text on return, the text you want to drag
|
||||
@see shouldDropFilesWhenDraggedExternally
|
||||
*/
|
||||
virtual bool shouldDropTextWhenDraggedExternally (const DragAndDropTarget::SourceDetails& sourceDetails,
|
||||
String& text);
|
||||
|
||||
/** Subclasses can override this to be told when a drag starts. */
|
||||
virtual void dragOperationStarted (const DragAndDropTarget::SourceDetails& sourceDetails);
|
||||
virtual void dragOperationStarted (const DragAndDropTarget::SourceDetails&);
|
||||
|
||||
/** Subclasses can override this to be told when a drag finishes. */
|
||||
virtual void dragOperationEnded (const DragAndDropTarget::SourceDetails& sourceDetails);
|
||||
virtual void dragOperationEnded (const DragAndDropTarget::SourceDetails&);
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -142,46 +142,86 @@ int JUCE_CALLTYPE NativeMessageBox::showYesNoCancelBox (AlertWindow::AlertIconTy
|
|||
|
||||
|
||||
//==============================================================================
|
||||
bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray& files, const bool /*canMoveFiles*/)
|
||||
static NSRect getDragRect (NSView* view, NSEvent* event)
|
||||
{
|
||||
if (files.size() == 0)
|
||||
return false;
|
||||
auto eventPos = [event locationInWindow];
|
||||
|
||||
MouseInputSource* draggingSource = Desktop::getInstance().getDraggingMouseSource(0);
|
||||
return [view convertRect: NSMakeRect (eventPos.x - 16.0f, eventPos.y - 16.0f, 32.0f, 32.0f)
|
||||
fromView: nil];
|
||||
}
|
||||
|
||||
if (draggingSource == nullptr)
|
||||
NSView* getNSViewForDragEvent()
|
||||
{
|
||||
if (auto* draggingSource = Desktop::getInstance().getDraggingMouseSource(0))
|
||||
if (auto* sourceComp = draggingSource->getComponentUnderMouse())
|
||||
return (NSView*) sourceComp->getWindowHandle();
|
||||
|
||||
jassertfalse; // This method must be called in response to a component's mouseDown or mouseDrag event!
|
||||
return nil;
|
||||
}
|
||||
|
||||
struct TextDragDataProviderClass : public ObjCClass<NSObject>
|
||||
{
|
||||
TextDragDataProviderClass() : ObjCClass<NSObject> ("JUCE_NSTextDragDataProvider_")
|
||||
{
|
||||
jassertfalse; // This method must be called in response to a component's mouseDown or mouseDrag event!
|
||||
return false;
|
||||
addIvar<String*> ("text");
|
||||
addMethod (@selector (dealloc), dealloc, "v@:");
|
||||
addMethod (@selector (pasteboard:item:provideDataForType:), provideDataForType, "v@:@@@");
|
||||
addProtocol (@protocol (NSPasteboardItemDataProvider));
|
||||
registerClass();
|
||||
}
|
||||
|
||||
Component* sourceComp = draggingSource->getComponentUnderMouse();
|
||||
|
||||
if (sourceComp == nullptr)
|
||||
static void setText (id self, const String& text)
|
||||
{
|
||||
jassertfalse; // This method must be called in response to a component's mouseDown or mouseDrag event!
|
||||
return false;
|
||||
object_setInstanceVariable (self, "text", new String (text));
|
||||
}
|
||||
|
||||
JUCE_AUTORELEASEPOOL
|
||||
private:
|
||||
static void dealloc (id self, SEL)
|
||||
{
|
||||
if (NSView* view = (NSView*) sourceComp->getWindowHandle())
|
||||
delete getIvar<String*> (self, "text");
|
||||
sendSuperclassMessage (self, @selector (dealloc));
|
||||
}
|
||||
|
||||
static void provideDataForType (id self, SEL, NSPasteboard* sender, NSPasteboardItem*, NSString* type)
|
||||
{
|
||||
if ([type compare: NSPasteboardTypeString] == NSOrderedSame)
|
||||
if (auto* text = getIvar<String*> (self, "text"))
|
||||
[sender setData: [juceStringToNS (*text) dataUsingEncoding: NSUTF8StringEncoding]
|
||||
forType: NSPasteboardTypeString];
|
||||
}
|
||||
};
|
||||
|
||||
bool DragAndDropContainer::performExternalDragDropOfText (const String& text)
|
||||
{
|
||||
if (text.isEmpty())
|
||||
return false;
|
||||
|
||||
if (auto* view = getNSViewForDragEvent())
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
if (NSEvent* event = [[view window] currentEvent])
|
||||
if (auto* event = [[view window] currentEvent])
|
||||
{
|
||||
NSPoint eventPos = [event locationInWindow];
|
||||
NSRect dragRect = [view convertRect: NSMakeRect (eventPos.x - 16.0f, eventPos.y - 16.0f, 32.0f, 32.0f)
|
||||
fromView: nil];
|
||||
static TextDragDataProviderClass dataProviderClass;
|
||||
id delegate = [dataProviderClass.createInstance() init];
|
||||
TextDragDataProviderClass::setText (delegate, text);
|
||||
|
||||
for (int i = 0; i < files.size(); ++i)
|
||||
{
|
||||
if (! [view dragFile: juceStringToNS (files[i])
|
||||
fromRect: dragRect
|
||||
slideBack: YES
|
||||
event: event])
|
||||
return false;
|
||||
}
|
||||
auto* pasteboardItem = [[NSPasteboardItem new] autorelease];
|
||||
[pasteboardItem setDataProvider: delegate
|
||||
forTypes: [NSArray arrayWithObjects: NSPasteboardTypeString, nil]];
|
||||
|
||||
auto* dragItem = [[[NSDraggingItem alloc] initWithPasteboardWriter: pasteboardItem] autorelease];
|
||||
|
||||
NSImage* image = [[NSWorkspace sharedWorkspace] iconForFile: nsEmptyString()];
|
||||
[dragItem setDraggingFrame: getDragRect (view, event) contents: image];
|
||||
|
||||
auto* draggingSession = [view beginDraggingSessionWithItems: [NSArray arrayWithObject: dragItem]
|
||||
event: event
|
||||
source: delegate];
|
||||
|
||||
draggingSession.animatesToStartingPositionsOnCancelOrFail = YES;
|
||||
draggingSession.draggingFormation = NSDraggingFormationNone;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -190,9 +230,31 @@ bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray& fi
|
|||
return false;
|
||||
}
|
||||
|
||||
bool DragAndDropContainer::performExternalDragDropOfText (const String& /*text*/)
|
||||
bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray& files, bool /*canMoveFiles*/)
|
||||
{
|
||||
jassertfalse; // not implemented!
|
||||
if (files.isEmpty())
|
||||
return false;
|
||||
|
||||
if (auto* view = getNSViewForDragEvent())
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
if (auto* event = [[view window] currentEvent])
|
||||
{
|
||||
auto dragRect = getDragRect (view, event);
|
||||
|
||||
for (int i = 0; i < files.size(); ++i)
|
||||
if (! [view dragFile: juceStringToNS (files[i])
|
||||
fromRect: dragRect
|
||||
slideBack: YES
|
||||
event: event])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -206,8 +268,8 @@ Point<float> MouseInputSource::getCurrentRawMousePosition()
|
|||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
const NSPoint p ([NSEvent mouseLocation]);
|
||||
return Point<float> ((float) p.x, (float) (getMainScreenHeight() - p.y));
|
||||
auto p = [NSEvent mouseLocation];
|
||||
return { (float) p.x, (float) (getMainScreenHeight() - p.y) };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue