Save undo sequences for only LAST auto-completion selected or UNDO on cancelled auto-completion

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/branches/gnustep_testplant_branch@37051 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Marcian Lytwyn 2013-09-09 01:54:02 +00:00
parent 2929f8aed8
commit a9e4f72f54
3 changed files with 99 additions and 83 deletions

View file

@ -153,6 +153,7 @@ therefore be stored in the NSLayoutManager to avoid problems.
unsigned uses_find_panel:1; unsigned uses_find_panel:1;
unsigned accepts_glyph_info:1; unsigned accepts_glyph_info:1;
unsigned allows_document_background_color_change:1; unsigned allows_document_background_color_change:1;
unsigned isAutoCompleting:2;
} _tf; } _tf;

View file

@ -26,6 +26,7 @@
#import <Foundation/NSAutoreleasePool.h> #import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSRunLoop.h> #import <Foundation/NSRunLoop.h>
#import <Foundation/NSNotification.h> #import <Foundation/NSNotification.h>
#import "Foundation/NSUndoManager.h"
#import "AppKit/NSApplication.h" #import "AppKit/NSApplication.h"
#import "AppKit/NSBox.h" #import "AppKit/NSBox.h"
#import "AppKit/NSEvent.h" #import "AppKit/NSEvent.h"
@ -316,7 +317,7 @@ static GSAutocompleteWindow *gsWindow = nil;
if ([event window] != self) if ([event window] != self)
{ {
[self updateTextViewWithMovement: NSCancelTextMovement [self updateTextViewWithMovement: NSCancelTextMovement
isFinal: NO]; isFinal: YES];
break; break;
} }
else else
@ -352,7 +353,7 @@ static GSAutocompleteWindow *gsWindow = nil;
key == NSLeftArrowFunctionKey) key == NSLeftArrowFunctionKey)
{ {
[self updateTextViewWithMovement: NSCancelTextMovement [self updateTextViewWithMovement: NSCancelTextMovement
isFinal: NO]; isFinal: YES];
break; break;
} }
else else
@ -382,7 +383,7 @@ static GSAutocompleteWindow *gsWindow = nil;
{ {
_stopped = YES; _stopped = YES;
[self updateTextViewWithMovement: NSCancelTextMovement [self updateTextViewWithMovement: NSCancelTextMovement
isFinal: NO]; isFinal: YES];
} }
- (void) reloadData - (void) reloadData
@ -431,25 +432,28 @@ static GSAutocompleteWindow *gsWindow = nil;
{ {
NSString *word; NSString *word;
if (movement != NSCancelTextMovement) // If this is a cancelling request...
if (movement == NSCancelTextMovement)
{ {
NSInteger rowIndex = [_tableView selectedRow]; // Invocation with flag==YES indicates we've inserted at least once
word = [[_words objectAtIndex: rowIndex] description]; // causing text view to push an undo sequence that we need to undo
// here...
if (flag)
[[_textView undoManager] undo];
} }
else else
{ {
word = _originalWord; NSInteger rowIndex = [_tableView selectedRow];
word = [[_words objectAtIndex: rowIndex] description];
[_textView insertCompletion: word
forPartialWordRange: _range
movement: movement
isFinal: flag];
} }
[_textView insertCompletion: word
forPartialWordRange: _range
movement: movement
isFinal: flag];
// Release _words and _originalWords if // Release _words and _originalWords if
// autocomplete is final or canceled. // autocomplete is final or canceled.
if ( (flag) || if ((flag) || (movement == NSCancelTextMovement) )
(movement == NSCancelTextMovement) )
{ {
ASSIGN(_originalWord, nil); ASSIGN(_originalWord, nil);
ASSIGN(_words, nil); ASSIGN(_words, nil);

View file

@ -2658,27 +2658,27 @@ TextDidEndEditing notification _without_ asking the delegate
return NO; return NO;
/* /*
We need to send the textShouldBeginEditing: / We need to send the textShouldBeginEditing: /
textDidBeginEditingNotification only once. textDidBeginEditingNotification only once.
*/ */
if (BEGAN_EDITING == NO) if (BEGAN_EDITING == NO)
{ {
if (([_delegate respondsToSelector: @selector(textShouldBeginEditing:)]) if (([_delegate respondsToSelector: @selector(textShouldBeginEditing:)])
&& ([_delegate textShouldBeginEditing: _notifObject] == NO)) && ([_delegate textShouldBeginEditing: _notifObject] == NO))
return NO; return NO;
SET_BEGAN_EDITING(YES); SET_BEGAN_EDITING(YES);
[notificationCenter postNotificationName: NSTextDidBeginEditingNotification [notificationCenter postNotificationName: NSTextDidBeginEditingNotification
object: _notifObject]; object: _notifObject];
} }
if (_tf.delegate_responds_to_should_change) if (_tf.delegate_responds_to_should_change)
{ {
result = [_delegate textView: self result = [_delegate textView: self
shouldChangeTextInRange: affectedCharRange shouldChangeTextInRange: affectedCharRange
replacementString: replacementString]; replacementString: replacementString];
} }
if (result && [self allowsUndo]) if (result && [self allowsUndo])
@ -2692,54 +2692,61 @@ TextDidEndEditing notification _without_ asking the delegate
static BOOL undoManagerCanCoalesce = NO; static BOOL undoManagerCanCoalesce = NO;
{ {
// FIXME This code (together with undoManagerCanCoalesce) is a // FIXME This code (together with undoManagerCanCoalesce) is a
// temporary workaround to allow using an out of date version of // temporary workaround to allow using an out of date version of
// base. Removed this upon the next release of base. // base. Removed this upon the next release of base.
static BOOL didCheck = NO; static BOOL didCheck = NO;
if (!didCheck) if (!didCheck)
{ {
undoManagerCanCoalesce = undoManagerCanCoalesce =
[NSUndoManager instancesRespondToSelector: [NSUndoManager instancesRespondToSelector:
@selector(_canCoalesceUndoWithTarget:selector:object:)]; @selector(_canCoalesceUndoWithTarget:selector:object:)];
if (!undoManagerCanCoalesce) if (!undoManagerCanCoalesce)
{ {
NSLog(@"This version of NSUndoManager does not\n" NSLog(@"This version of NSUndoManager does not\n"
@"support coalescing undo operations. " @"support coalescing undo operations. "
@"Upgrade gnustep-base to r29163 or newer to\n" @"Upgrade gnustep-base to r29163 or newer to\n"
@"get rid of this one-time warning."); @"get rid of this one-time warning.");
} }
didCheck = YES; didCheck = YES;
} }
} }
undo = [self undoManager]; undo = [self undoManager];
/* Coalesce consecutive typing events into a single undo action using /* Coalesce consecutive typing events into a single undo action using
currently private undo manager functionality. An event is considered currently private undo manager functionality. An event is considered
a typing event if it is a keyboard event and the event's characters a typing event if it is a keyboard event and the event's characters
match our replacement string. match our replacement string.
Note: Typing events are coalesced only when the previous action was Note: Typing events are coalesced only when the previous action was
a typing event too and the current character follows the previous one a typing event too and the current character follows the previous one
immediately. We never coalesce actions when the current selection is immediately. We never coalesce actions when the current selection is
not empty. */ not empty. */
event = [NSApp currentEvent]; event = [NSApp currentEvent];
isTyping = [event type] == NSKeyDown isTyping = (([event type] == NSKeyDown) &&
&& [[event characters] isEqualToString: replacementString]; ([[event characters] isEqualToString: replacementString]));
if (undoManagerCanCoalesce && _undoObject) if (undoManagerCanCoalesce && _undoObject)
{ {
undoRange = [_undoObject range]; if ([undo _canCoalesceUndoWithTarget: _textStorage
if (isTyping && selector: @selector(_undoTextChange:)
NSMaxRange(undoRange) == affectedCharRange.location && object: _undoObject])
affectedCharRange.length == 0 && {
[undo _canCoalesceUndoWithTarget: _textStorage undoRange = [_undoObject range];
selector: @selector(_undoTextChange:) if (isTyping &&
object: _undoObject]) NSMaxRange(undoRange) == affectedCharRange.location &&
{ affectedCharRange.length == 0)
undoRange.length += [replacementString length]; {
[_undoObject setRange: undoRange]; undoRange.length += [replacementString length];
return result; [_undoObject setRange: undoRange];
} return result;
DESTROY(_undoObject); }
else if (_tf.isAutoCompleting == 2)
{
[_undoObject setRange: affectedCharRange];
return result;
}
DESTROY(_undoObject);
}
} }
// The length of the undoRange is the length of the replacement, if any. // The length of the undoRange is the length of the replacement, if any.
@ -2755,15 +2762,17 @@ TextDidEndEditing notification _without_ asking the delegate
undoString = [self attributedSubstringFromRange: affectedCharRange]; undoString = [self attributedSubstringFromRange: affectedCharRange];
undoObject = undoObject =
[[NSTextViewUndoObject alloc] initWithRange: undoRange [[NSTextViewUndoObject alloc] initWithRange: undoRange
attributedString: undoString]; attributedString: undoString];
[undo registerUndoWithTarget: _textStorage [undo registerUndoWithTarget: _textStorage
selector: @selector(_undoTextChange:) selector: @selector(_undoTextChange:)
object: undoObject]; object: undoObject];
if (isTyping) if (isTyping || _tf.isAutoCompleting)
_undoObject = undoObject; _undoObject = undoObject;
else else
RELEASE(undoObject); RELEASE(undoObject);
if (_tf.isAutoCompleting == 1)
_tf.isAutoCompleting = 2;
} }
return result; return result;
@ -6022,7 +6031,9 @@ configuation! */
range.location != NSNotFound && range.length != 0) range.location != NSNotFound && range.length != 0)
{ {
GSAutocompleteWindow *window = [GSAutocompleteWindow defaultWindow]; GSAutocompleteWindow *window = [GSAutocompleteWindow defaultWindow];
_tf.isAutoCompleting = 1;
[window displayForTextView: self]; [window displayForTextView: self];
_tf.isAutoCompleting = 0;
} }
} }