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 accepts_glyph_info:1;
unsigned allows_document_background_color_change:1;
unsigned isAutoCompleting:2;
} _tf;

View file

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

View file

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