0
votes

This is the error picture:

enter image description here

My class is a subclass of NSTextView, it supports dragging. but When I drag text to former location, there will be a sticked inserting point.

Then I click elsewhere ,the normal insertion point appears at the end of text(which is correct),

but the first point did not disappear automatically, even though I delete the whole string.

there are only 3 method or property in NSTextView related to insertion point.

@property (readonly) BOOL shouldDrawInsertionPoint;
@property (copy) NSColor *insertionPointColor;

- (void)updateInsertionPointStateAndRestartTimer:(BOOL)restartFlag;
- (void)drawInsertionPointInRect:(NSRect)rect color:(NSColor *)color turnedOn:(BOOL)flag;

The first one is readonly, I tried the second one ,I set white color, when dragging and original color after dragActionEnded. I did not work.

Waiting for your resolution. Thanks!

The following is the drag delegate code I wrote. #pragma mark - Destination Operations

- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender

{ /------------------------------------------------------ method called whenever a drag enters our drop zone --------------------------------------------------------/

// Check if the pasteboard contains image data and source/user wants it copied
if ([sender draggingSourceOperationMask] & NSDragOperationCopy )
{
    //accept data as a copy operation
    return NSDragOperationCopy;
}

return NSDragOperationNone;

}

- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender

{

//check to see if we can accept the data
NSURL *fileURL=[NSURL URLFromPasteboard: [sender draggingPasteboard]];
if (fileURL == nil) {
return NO;}
NSString *filePathAndName = [[NSString alloc] initWithUTF8String:[fileURL fileSystemRepresentation]];
if (filePathAndName == nil)
{
    return NO;
}

NSString *fileExtension = [[filePathAndName pathExtension] uppercaseString];
if (fileExtension == nil)
{
    return NO;
}

if ([fileExtension isEqualToString:@"JPG"] ||
    [fileExtension isEqualToString:@"JPEG"] ||
    [fileExtension isEqualToString:@"PNG"] ||
    [fileExtension isEqualToString:@"GIF"] ||
    [fileExtension isEqualToString:@"BMP"])
{
    return YES;
}
else
{
    return NO;
}

}

- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender{

if ( [sender draggingSource] != self )
{
    
if ( [[[sender draggingPasteboard] types] containsObject:NSFilenamesPboardType] ) {
NSURL* fileURL=[NSURL URLFromPasteboard: [sender draggingPasteboard]];
        NSArray *files = [[sender draggingPasteboard] propertyListForType:NSFilenamesPboardType];
        [[NSNotificationCenter defaultCenter] postNotificationName:ZayhuSendPicToPeer object:self userInfo:@{@"filesArray":files}];
    }
}

return YES;

}

- (NSString *)preferredPasteboardTypeFromArray:(NSArray *)availableTypes restrictedToTypesFromArray:(NSArray *)allowedTypes{
if ([availableTypes containsObject:NSPasteboardTypeString])
{
    return NSPasteboardTypeString;
}
return [super preferredPasteboardTypeFromArray:availableTypes restrictedToTypesFromArray:allowedTypes];

}

2
I tried your code. I get an exception and drag & drop of text doesn't work. Fix it and the inserting point will be ok.Willeke
if (fileURL == nil) { return NO; } sorry,I did not check it ,Now, I add this line. It will work,but the problem is still there.Tianyeye田野野
Does drag & drop work?Willeke
drag is OK, drop is prohibited by file types.Tianyeye田野野

2 Answers

0
votes

I have encountered your problem.

My way to solve this problem is not subclassing NSTextView to do all drag and drop tasks but put NSTextView on a custom view and let the custom view do the main part of the job.

If i subclassed NSTextView to be the drag destination, i encountered some other UI problems such as disappearing insertion point when the textview is backed by a CALayer.

The following code are written in Swift, but it stills convey the idea for the solution.

First of all, for text drag & drop. You can subclass NSTextView and just override acceptableDragTypes

    override var acceptableDragTypes : [String] {
        return [NSStringPboardType]
    }

For other types of drag & drop, let the custom view deal with them. Take dragging files as example,

class MyCustomView: NSView {

    override init(frame frameRect: NSRect) {
        super.init(frame: frameRect)
        commonInit()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }

    func commonInit() {
        registerForDraggedTypes([NSFilenamesPboardType])
    }

    override func draggingEntered(sender: NSDraggingInfo) -> NSDragOperation {
        if sender.draggingSource() === self {
            return .None
        }
        return sender.draggingSourceOperationMask()
    }

    override func prepareForDragOperation(sender: NSDraggingInfo) -> Bool {
        //add your custom logic here
        return true
    }

    override func performDragOperation(sender: NSDraggingInfo) -> Bool {
        //add your custom logic here
        return true
    }

 }  
0
votes

I had need of subclassing a NSTextView for some other reasons and needed to add some custom object dragging. I ran into the same things you did with the insertion point weirdness.

In my case, instead of adding another view to handle the custom object logic I did override the performDragOperation and just called the super in the case that it wasn't my specific type. This seemed to work perfectly.

This allowed the default handling the String case in its natural way and the insertion UI stuff all cleared up.