Make DnD follow mouse pointer in text view

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@21038 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-Macdonald 2005-04-03 10:39:32 +00:00
parent 508987f93b
commit c55a8d1a73
3 changed files with 101 additions and 21 deletions

View file

@ -1,3 +1,11 @@
2005-04-03 Richard Frith-Macdonald <rfm@gnu.org>
* Headers/AppKit/NSTextView.h: Keep track of whether we are acting
as a target for a DnD operation, and what the selected range was
before the operation began.
* Source/NSTextView.m: Display insertion point during DnD operation
Fixes bug #9788
2005-04-02 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSTableView.m: ([-mouseDown:]) tweak vertical image

View file

@ -123,6 +123,8 @@ therefore be stored in the NSLayoutManager to avoid problems.
/* YES if delegate responds to
`textView:willChangeSelectionFromCharacterRange:toCharacterRange:' */
unsigned delegate_responds_to_will_change_sel:1;
/* YES if a DnD operation is in progress with this as the target view */
unsigned isDragTarget:1;
} _tf;
@ -201,6 +203,10 @@ therefore be stored in the NSLayoutManager to avoid problems.
*/
int _currentInsertionPointMovementDirection;
/* Ivar to store the original range so it can be restored after a DnD
* operation is cancelled (the mouse moves back out of the view).
*/
NSRange _dragTargetSelectionRange;
/*
TODO:
Still need to figure out what "proper behavior" is when moving between two

View file

@ -3050,8 +3050,15 @@ Figure out how the additional layout stuff is supposed to work.
{
if (!_layoutManager)
return NO;
return (_layoutManager->_selected_range.length == 0) && _tf.is_editable
&& [_window isKeyWindow] && ([_window firstResponder] == self);
if (_layoutManager->_selected_range.length != 0)
return NO;
if (_tf.is_editable == NO)
return NO;
if (_tf.isDragTarget == YES)
return YES;
if ([_window isKeyWindow] == YES && [_window firstResponder] == self)
return YES;
return NO;
}
/*
@ -3889,7 +3896,7 @@ right.)
{
// get default types, what are they?
NSMutableArray *ret = [NSMutableArray arrayWithObjects: NSRulerPboardType,
NSColorPboardType, NSFontPboardType, nil];
NSColorPboardType, NSFontPboardType, nil];
if (_tf.imports_graphics)
{
@ -3898,8 +3905,9 @@ right.)
[ret addObject: NSFileContentsPboardType];
}
if (_tf.is_rich_text)
[ret addObject: NSRTFPboardType];
{
[ret addObject: NSRTFPboardType];
}
[ret addObject: NSStringPboardType];
return ret;
@ -4044,26 +4052,80 @@ other than copy/paste or dragging. */
// dragging of text, colors and files
- (unsigned int) draggingEntered: (id <NSDraggingInfo>)sender
{
NSPasteboard *pboard = [sender draggingPasteboard];
NSString *type = [self preferredPasteboardTypeFromArray: [pboard types]
restrictedToTypesFromArray: [self readablePasteboardTypes]];
NSPasteboard *pboard = [sender draggingPasteboard];
NSArray *types = [self readablePasteboardTypes];
NSString *type = [self preferredPasteboardTypeFromArray: [pboard types]
restrictedToTypesFromArray: types];
unsigned int flags = [self dragOperationForDraggingInfo: sender type: type];
return [self dragOperationForDraggingInfo: sender
type: type];
if (flags != NSDragOperationNone)
{
NSPoint dragPoint;
unsigned dragIndex;
NSRange dragRange;
NSRange range;
if (_tf.isDragTarget == NO)
{
_tf.isDragTarget = YES;
_dragTargetSelectionRange = [self selectedRange];
}
dragPoint = [sender draggingLocation];
dragPoint = [self convertPoint: dragPoint fromView: nil];
dragIndex = [self characterIndexForPoint: dragPoint];
dragRange = NSMakeRange (dragIndex, 0);
range = [self selectionRangeForProposedRange: dragRange
granularity: NSSelectByCharacter];
[self setSelectedRange: range];
[self displayIfNeeded];
}
return flags;
}
- (unsigned int) draggingUpdated: (id <NSDraggingInfo>)sender
{
NSPasteboard *pboard = [sender draggingPasteboard];
NSString *type = [self preferredPasteboardTypeFromArray: [pboard types]
restrictedToTypesFromArray: [self readablePasteboardTypes]];
NSPasteboard *pboard = [sender draggingPasteboard];
NSArray *types = [self readablePasteboardTypes];
NSString *type = [self preferredPasteboardTypeFromArray: [pboard types]
restrictedToTypesFromArray: types];
unsigned int flags = [self dragOperationForDraggingInfo: sender type: type];
return [self dragOperationForDraggingInfo: sender
type: type];
if (flags != NSDragOperationNone)
{
NSPoint dragPoint;
unsigned dragIndex;
NSRange dragRange;
NSRange range;
if (_tf.isDragTarget == NO)
{
_tf.isDragTarget = YES;
_dragTargetSelectionRange = [self selectedRange];
}
dragPoint = [sender draggingLocation];
dragPoint = [self convertPoint: dragPoint fromView: nil];
dragIndex = [self characterIndexForPoint: dragPoint];
dragRange = NSMakeRange (dragIndex, 0);
range = [self selectionRangeForProposedRange: dragRange
granularity: NSSelectByCharacter];
[self setSelectedRange: range];
[self displayIfNeeded];
}
return flags;
}
- (void) draggingExited: (id <NSDraggingInfo>)sender
{
if (_tf.isDragTarget == YES)
{
_tf.isDragTarget = NO;
[self setSelectedRange: _dragTargetSelectionRange];
[self displayIfNeeded];
}
}
- (BOOL) prepareForDragOperation: (id <NSDraggingInfo>)sender
@ -4073,11 +4135,13 @@ other than copy/paste or dragging. */
- (BOOL) performDragOperation: (id <NSDraggingInfo>)sender
{
_tf.isDragTarget = NO;
return [self readSelectionFromPasteboard: [sender draggingPasteboard]];
}
- (void) concludeDragOperation: (id <NSDraggingInfo>)sender
{
_tf.isDragTarget = NO;
}
- (void) cleanUpAfterDragOperation
@ -4166,11 +4230,13 @@ other than copy/paste or dragging. */
granularity = _layoutManager->_selectionGranularity;
/* Compute the new selection */
proposedRange = NSMakeRange (startIndex, 0);
proposedRange = NSUnionRange (_layoutManager->_selected_range, proposedRange);
proposedRange = NSUnionRange (_layoutManager->_selected_range,
proposedRange);
proposedRange = [self selectionRangeForProposedRange: proposedRange
granularity: granularity];
granularity: granularity];
/* Merge it with the old one */
proposedRange = NSUnionRange (_layoutManager->_selected_range, proposedRange);
proposedRange = NSUnionRange (_layoutManager->_selected_range,
proposedRange);
/* Now decide what happens if the user shift-drags. The range
will be based in startIndex, so we need to adjust it. */
if (startIndex <= _layoutManager->_selected_range.location)
@ -4309,9 +4375,9 @@ other than copy/paste or dragging. */
while (currentEvent && [currentEvent type] != NSLeftMouseUp)
{
if ([currentEvent type] == NSPeriodic)
{
gotPeriodic = YES;
}
{
gotPeriodic = YES;
}
else
lastEvent = currentEvent;
currentEvent = [_window nextEventMatchingMask: mask