mirror of
https://github.com/gnustep/libs-base.git
synced 2025-04-25 09:41:15 +00:00
* Headers/gnustep/base/NSUndoManager.h: Add
NSUndoCloseGroupingRunLoopOrdering enum. Replace instance variables _registeredUndo with _runLoopGroupingPending and _actionName with _unused1. * Source/NSUndoManager.m: Added documentation. Added actionName instance variable to PrivateUndoGroup. (-[PrivateUndoGroup actionName]): New method. (-[PrivateUndoGroup setActionName]): Ditto. (-[PrivateUndoGroup dealloc]): Release new instance variable. (-[PrivateUndoGroup initWithParent:]): Initialize actionName. (-[NSUndoManager forwardInvocation]): Implicitly call beginUndoGrouping if group has not been setup and we are grouping by events. Register _loop: invocation if none is already pending and if we are grouping by event. (-[NSUndoManager registerUndoWithTarget:selector:object]): Ditto. (-[NSUndoManager methodSignatureForSelector:]): Overriden to forward request to target supplied by -prepareWithInvocationTarget: if available. (-[NSUndoManager _loop:]): Set flag to determine pending _loop: processing. (-[NSUndoManager init]): Removed access to _actionName. Have receiver default to group by event. (-[NSUndoManager dealloc]): Ditto. (-[NSUndoManager enableUndoRegistration]): Remove access to _registeredUndo. (-[NSUndoManager redo]): Simplified implementation. (-[NSUndoManager redoActionName:]: Retrieve action name from first grouping of the redo stack. (-[NSUndoManager redoMenuTitleForUndoActionName:]): Add comment about localization. (-[NSUndoManager undoMenuTitleForUndoActionName:]): Ditto. (-[NSUndoManager setActionName:]): Forward call to current grouping. (-[NSUndoManager undoActionName:]: Retrieve action name from first grouping of the undo stack. (-[NSUndoManager setRunLoopModes:]): Use correct run loop ordering and set flag for pending _loop: invocation. (-[NSUndoManager undoNestedGroup]): Removed special case handling of _registeredUndo. Raise NSInternalInconsistencyException if grouping is still in progress. Simplified implementation. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@17221 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
910415ea46
commit
f65f0ffe09
3 changed files with 414 additions and 48 deletions
43
ChangeLog
43
ChangeLog
|
@ -1,3 +1,46 @@
|
||||||
|
2003-07-15 David Ayers <d.ayers@inode.at>
|
||||||
|
|
||||||
|
* Headers/gnustep/base/NSUndoManager.h: Add
|
||||||
|
NSUndoCloseGroupingRunLoopOrdering enum. Replace instance
|
||||||
|
variables _registeredUndo with _runLoopGroupingPending and
|
||||||
|
_actionName with _unused1.
|
||||||
|
* Source/NSUndoManager.m: Added documentation.
|
||||||
|
Added actionName instance variable to PrivateUndoGroup.
|
||||||
|
(-[PrivateUndoGroup actionName]): New method.
|
||||||
|
(-[PrivateUndoGroup setActionName]): Ditto.
|
||||||
|
(-[PrivateUndoGroup dealloc]): Release new instance variable.
|
||||||
|
(-[PrivateUndoGroup initWithParent:]): Initialize actionName.
|
||||||
|
(-[NSUndoManager forwardInvocation]): Implicitly call
|
||||||
|
beginUndoGrouping if group has not been setup and we are grouping
|
||||||
|
by events. Register _loop: invocation if none is already pending
|
||||||
|
and if we are grouping by event.
|
||||||
|
(-[NSUndoManager registerUndoWithTarget:selector:object]): Ditto.
|
||||||
|
(-[NSUndoManager methodSignatureForSelector:]): Overriden to
|
||||||
|
forward request to target supplied by
|
||||||
|
-prepareWithInvocationTarget: if available.
|
||||||
|
(-[NSUndoManager _loop:]): Set flag to determine pending _loop:
|
||||||
|
processing.
|
||||||
|
(-[NSUndoManager init]): Removed access to _actionName. Have
|
||||||
|
receiver default to group by event.
|
||||||
|
(-[NSUndoManager dealloc]): Ditto.
|
||||||
|
(-[NSUndoManager enableUndoRegistration]): Remove access to
|
||||||
|
_registeredUndo.
|
||||||
|
(-[NSUndoManager redo]): Simplified implementation.
|
||||||
|
(-[NSUndoManager redoActionName:]: Retrieve action name from first
|
||||||
|
grouping of the redo stack.
|
||||||
|
(-[NSUndoManager redoMenuTitleForUndoActionName:]): Add comment
|
||||||
|
about localization.
|
||||||
|
(-[NSUndoManager undoMenuTitleForUndoActionName:]): Ditto.
|
||||||
|
(-[NSUndoManager setActionName:]): Forward call to current
|
||||||
|
grouping.
|
||||||
|
(-[NSUndoManager undoActionName:]: Retrieve action name from first
|
||||||
|
grouping of the undo stack.
|
||||||
|
(-[NSUndoManager setRunLoopModes:]): Use correct run loop ordering
|
||||||
|
and set flag for pending _loop: invocation.
|
||||||
|
(-[NSUndoManager undoNestedGroup]): Removed special case handling
|
||||||
|
of _registeredUndo. Raise NSInternalInconsistencyException if
|
||||||
|
grouping is still in progress. Simplified implementation.
|
||||||
|
|
||||||
2003-07-15 Alexander Malmberg <alexander@malmberg.org>
|
2003-07-15 Alexander Malmberg <alexander@malmberg.org>
|
||||||
|
|
||||||
* Source/NSConnection.m: When creating new connection with registered
|
* Source/NSConnection.m: When creating new connection with registered
|
||||||
|
|
|
@ -30,6 +30,11 @@
|
||||||
@class NSMutableArray;
|
@class NSMutableArray;
|
||||||
@class NSInvocation;
|
@class NSInvocation;
|
||||||
|
|
||||||
|
/** Defines run loop ordering for closing undo groupings. */
|
||||||
|
enum {
|
||||||
|
NSUndoCloseGroupingRunLoopOrdering = 350000
|
||||||
|
};
|
||||||
|
|
||||||
/* Public notification */
|
/* Public notification */
|
||||||
GS_EXPORT NSString *NSUndoManagerCheckpointNotification;
|
GS_EXPORT NSString *NSUndoManagerCheckpointNotification;
|
||||||
GS_EXPORT NSString *NSUndoManagerDidOpenUndoGroupNotification;
|
GS_EXPORT NSString *NSUndoManagerDidOpenUndoGroupNotification;
|
||||||
|
@ -44,14 +49,14 @@ GS_EXPORT NSString *NSUndoManagerWillUndoChangeNotification;
|
||||||
@private
|
@private
|
||||||
NSMutableArray *_redoStack;
|
NSMutableArray *_redoStack;
|
||||||
NSMutableArray *_undoStack;
|
NSMutableArray *_undoStack;
|
||||||
NSString *_actionName;
|
id *_unused1;
|
||||||
id _group;
|
id _group;
|
||||||
id _nextTarget;
|
id _nextTarget;
|
||||||
NSArray *_modes;
|
NSArray *_modes;
|
||||||
BOOL _isRedoing;
|
BOOL _isRedoing;
|
||||||
BOOL _isUndoing;
|
BOOL _isUndoing;
|
||||||
BOOL _groupsByEvent;
|
BOOL _groupsByEvent;
|
||||||
BOOL _registeredUndo;
|
BOOL _runLoopGroupingPending;
|
||||||
unsigned _disableCount;
|
unsigned _disableCount;
|
||||||
unsigned _levelsOfUndo;
|
unsigned _levelsOfUndo;
|
||||||
}
|
}
|
||||||
|
@ -73,7 +78,7 @@ GS_EXPORT NSString *NSUndoManagerWillUndoChangeNotification;
|
||||||
- (void) redo;
|
- (void) redo;
|
||||||
- (NSString*) redoActionName;
|
- (NSString*) redoActionName;
|
||||||
- (NSString*) redoMenuItemTitle;
|
- (NSString*) redoMenuItemTitle;
|
||||||
- (NSString*) redoMenuTitleForUndoActionName: (NSString*)name;
|
- (NSString*) redoMenuTitleForUndoActionName: (NSString*)actionName;
|
||||||
- (void) registerUndoWithTarget: (id)target
|
- (void) registerUndoWithTarget: (id)target
|
||||||
selector: (SEL)aSelector
|
selector: (SEL)aSelector
|
||||||
object: (id)anObject;
|
object: (id)anObject;
|
||||||
|
@ -87,7 +92,7 @@ GS_EXPORT NSString *NSUndoManagerWillUndoChangeNotification;
|
||||||
- (void) undo;
|
- (void) undo;
|
||||||
- (NSString*) undoActionName;
|
- (NSString*) undoActionName;
|
||||||
- (NSString*) undoMenuItemTitle;
|
- (NSString*) undoMenuItemTitle;
|
||||||
- (NSString*) undoMenuTitleForUndoActionName: (NSString*)name;
|
- (NSString*) undoMenuTitleForUndoActionName: (NSString*)actionName;
|
||||||
- (void) undoNestedGroup;
|
- (void) undoNestedGroup;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -55,16 +55,20 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
*/
|
*/
|
||||||
@interface PrivateUndoGroup : NSObject
|
@interface PrivateUndoGroup : NSObject
|
||||||
{
|
{
|
||||||
PrivateUndoGroup *parent;
|
PrivateUndoGroup *parent;
|
||||||
NSMutableArray *actions;
|
NSMutableArray *actions;
|
||||||
|
NSString *actionName;
|
||||||
}
|
}
|
||||||
- (NSMutableArray*) actions;
|
- (NSMutableArray*) actions;
|
||||||
|
|
||||||
|
- (NSString*) actionName;
|
||||||
- (void) addInvocation: (NSInvocation*)inv;
|
- (void) addInvocation: (NSInvocation*)inv;
|
||||||
- (id) initWithParent: (PrivateUndoGroup*)parent;
|
- (id) initWithParent: (PrivateUndoGroup*)parent;
|
||||||
- (void) orphan;
|
- (void) orphan;
|
||||||
- (PrivateUndoGroup*) parent;
|
- (PrivateUndoGroup*) parent;
|
||||||
- (void) perform;
|
- (void) perform;
|
||||||
- (BOOL) removeActionsForTarget: (id)target;
|
- (BOOL) removeActionsForTarget: (id)target;
|
||||||
|
- (void) setActionName: (NSString*)name;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation PrivateUndoGroup
|
@implementation PrivateUndoGroup
|
||||||
|
@ -74,6 +78,11 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSString*) actionName
|
||||||
|
{
|
||||||
|
return actionName;
|
||||||
|
}
|
||||||
|
|
||||||
- (void) addInvocation: (NSInvocation*)inv
|
- (void) addInvocation: (NSInvocation*)inv
|
||||||
{
|
{
|
||||||
if (actions == nil)
|
if (actions == nil)
|
||||||
|
@ -87,6 +96,7 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
{
|
{
|
||||||
RELEASE(actions);
|
RELEASE(actions);
|
||||||
RELEASE(parent);
|
RELEASE(parent);
|
||||||
|
RELEASE(actionName);
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,6 +107,7 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
{
|
{
|
||||||
parent = RETAIN(p);
|
parent = RETAIN(p);
|
||||||
actions = nil;
|
actions = nil;
|
||||||
|
actionName = @"";
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
@ -147,6 +158,11 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) setActionName: (NSString *)name
|
||||||
|
{
|
||||||
|
ASSIGNCOPY(actionName,name);
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@ -169,6 +185,7 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
}
|
}
|
||||||
[self beginUndoGrouping];
|
[self beginUndoGrouping];
|
||||||
}
|
}
|
||||||
|
_runLoopGroupingPending = NO;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@ -179,6 +196,13 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
*/
|
*/
|
||||||
@implementation NSUndoManager
|
@implementation NSUndoManager
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts a new grouping of undo actions which can be
|
||||||
|
* atomically undone by an [-undo] invovation.
|
||||||
|
* This method posts an NSUndoManagerCheckpointNotification
|
||||||
|
* unless an undo is currently in progress. It posts an
|
||||||
|
* NSUndoManagerDidOpenUndoGroupNotification upon creating the grouping.
|
||||||
|
*/
|
||||||
- (void) beginUndoGrouping
|
- (void) beginUndoGrouping
|
||||||
{
|
{
|
||||||
PrivateUndoGroup *parent;
|
PrivateUndoGroup *parent;
|
||||||
|
@ -207,6 +231,10 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the receiver can service redo requests and
|
||||||
|
* posts a NSUndoManagerCheckpointNotification.
|
||||||
|
*/
|
||||||
- (BOOL) canRedo
|
- (BOOL) canRedo
|
||||||
{
|
{
|
||||||
[[NSNotificationCenter defaultCenter]
|
[[NSNotificationCenter defaultCenter]
|
||||||
|
@ -222,6 +250,13 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the receiver has any action groupings
|
||||||
|
* on the stack to undo. It does not imply, that the
|
||||||
|
* receiver is currently in a state to service an undo
|
||||||
|
* request. Make sure [-endEndGrouping] is invoked before
|
||||||
|
* requesting either an [-undo] or an [-undoNestedGroup].
|
||||||
|
*/
|
||||||
- (BOOL) canUndo
|
- (BOOL) canUndo
|
||||||
{
|
{
|
||||||
if ([_undoStack count] > 0)
|
if ([_undoStack count] > 0)
|
||||||
|
@ -242,23 +277,37 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
argument: nil];
|
argument: nil];
|
||||||
RELEASE(_redoStack);
|
RELEASE(_redoStack);
|
||||||
RELEASE(_undoStack);
|
RELEASE(_undoStack);
|
||||||
RELEASE(_actionName);
|
|
||||||
RELEASE(_group);
|
RELEASE(_group);
|
||||||
RELEASE(_modes);
|
RELEASE(_modes);
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables the registration of operations with with either
|
||||||
|
* [-registerUndoWithTarget:selector:object:] or
|
||||||
|
* [-forwardInvocation:]. This method may be called multiple
|
||||||
|
* times. Each will need to be paired to a call of
|
||||||
|
* [-enableUndoRegistration] before registration is actually
|
||||||
|
* reenabled.
|
||||||
|
*/
|
||||||
- (void) disableUndoRegistration
|
- (void) disableUndoRegistration
|
||||||
{
|
{
|
||||||
_disableCount++;
|
_disableCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches previous calls of to [-disableUndoRegistration].
|
||||||
|
* Only call this method to that end. Once all are matched,
|
||||||
|
* the registration of [-registerUndoWithTarget:selector:object:]
|
||||||
|
* and [-forwardInvocation:] are reenabled. If this method is
|
||||||
|
* called without a matching -disableUndoRegistration,
|
||||||
|
* it will raise an NSInternalInconsistencyException.
|
||||||
|
*/
|
||||||
- (void) enableUndoRegistration
|
- (void) enableUndoRegistration
|
||||||
{
|
{
|
||||||
if (_disableCount > 0)
|
if (_disableCount > 0)
|
||||||
{
|
{
|
||||||
_disableCount--;
|
_disableCount--;
|
||||||
_registeredUndo = NO; /* No operations since registration enabled. */
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -267,6 +316,14 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches previous calls of to [-beginUndoGrouping] and
|
||||||
|
* puts the group on the undo stack. This method posts
|
||||||
|
* an NSUndoManagerCheckpointNotification and
|
||||||
|
* a NSUndoManagerWillCloseUndoGroupNotification.
|
||||||
|
* If there was no matching call to -beginUndoGrouping,
|
||||||
|
* this method will raise an NSInternalInconsistencyException.
|
||||||
|
*/
|
||||||
- (void) endUndoGrouping
|
- (void) endUndoGrouping
|
||||||
{
|
{
|
||||||
PrivateUndoGroup *g;
|
PrivateUndoGroup *g;
|
||||||
|
@ -319,6 +376,32 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
RELEASE(g);
|
RELEASE(g);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the invocation with the current undo grouping.
|
||||||
|
* This method is part of the NSInvocation-based undo registration
|
||||||
|
* as opposed to the simpler [-registerUndoWithTarget:selector:object:]
|
||||||
|
* technique. <br/>
|
||||||
|
* You generally never invoke this method directly.
|
||||||
|
* Instead invoke [-prepareWithInvocationTarget:] with the target of the
|
||||||
|
* undo action and then invoke the targets method to undo the action
|
||||||
|
* on the return value of -prepareWithInvocationTarget:
|
||||||
|
* which actually is the undo manager.
|
||||||
|
* The runtime will then fallback to -forwardInvocation: to do the actual
|
||||||
|
* registration of the invocation.
|
||||||
|
* The invocation will added to the current grouping.<br/>
|
||||||
|
* If the registrations have been disabled through [-disableUndoRegistration],
|
||||||
|
* this method does nothing.<br/>
|
||||||
|
* Unless the reciever implicitly
|
||||||
|
* groups operations by event, the this method must have been preceeded
|
||||||
|
* with a [-beginUndoGrouping] message. Otherwise it will raise an
|
||||||
|
* NSInternalInconsistencyException. <br/>
|
||||||
|
* Unless this method is invoked as part of a [-undo] or [-undoNestedGroup]
|
||||||
|
* processing, the redo stack is cleared.<br/>
|
||||||
|
* If the reciever [-groupsByEvents] and this is the first call to this
|
||||||
|
* method since the last run loop processing, this method sets up
|
||||||
|
* the reciever to process the [-endUndoGrouping] at the
|
||||||
|
* end of the event loop.
|
||||||
|
*/
|
||||||
- (void) forwardInvocation: (NSInvocation*)anInvocation
|
- (void) forwardInvocation: (NSInvocation*)anInvocation
|
||||||
{
|
{
|
||||||
if (_disableCount == 0)
|
if (_disableCount == 0)
|
||||||
|
@ -330,8 +413,15 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
}
|
}
|
||||||
if (_group == nil)
|
if (_group == nil)
|
||||||
{
|
{
|
||||||
[NSException raise: NSInternalInconsistencyException
|
if ([self groupsByEvent])
|
||||||
format: @"forwardInvocation without beginUndoGrouping"];
|
{
|
||||||
|
[self beginUndoGrouping];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[NSException raise: NSInternalInconsistencyException
|
||||||
|
format: @"forwardInvocation without beginUndoGrouping"];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
[anInvocation setTarget: _nextTarget];
|
[anInvocation setTarget: _nextTarget];
|
||||||
_nextTarget = nil;
|
_nextTarget = nil;
|
||||||
|
@ -340,10 +430,45 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
{
|
{
|
||||||
[_redoStack removeAllObjects];
|
[_redoStack removeAllObjects];
|
||||||
}
|
}
|
||||||
_registeredUndo = YES;
|
if ((_runLoopGroupingPending == NO) && ([self groupsByEvent] == YES))
|
||||||
|
{
|
||||||
|
[[NSRunLoop currentRunLoop] performSelector: @selector(_loop:)
|
||||||
|
target: self
|
||||||
|
argument: nil
|
||||||
|
order: NSUndoCloseGroupingRunLoopOrdering
|
||||||
|
modes: _modes];
|
||||||
|
_runLoopGroupingPending = YES;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the reciever was sent a [-prepareWithInvocationTarget:] and
|
||||||
|
* the target's method hasn't been invoked on the reciever yet, this
|
||||||
|
* method forwards the request to the target.
|
||||||
|
* Otherwise or if the target didn't return a signature, the message
|
||||||
|
* is sent to super.
|
||||||
|
*/
|
||||||
|
- (NSMethodSignature*) methodSignatureForSelector: (SEL)selector
|
||||||
|
{
|
||||||
|
NSMethodSignature *sig = nil;
|
||||||
|
|
||||||
|
if (_nextTarget != nil)
|
||||||
|
{
|
||||||
|
sig = [_nextTarget methodSignatureForSelector: selector];
|
||||||
|
}
|
||||||
|
if (sig == nil)
|
||||||
|
{
|
||||||
|
sig = [super methodSignatureForSelector: selector];
|
||||||
|
}
|
||||||
|
return sig;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current number of groupings. These are the current
|
||||||
|
* groupings which can be nested, not the number of of groups on either
|
||||||
|
* the undo or redo stack.
|
||||||
|
*/
|
||||||
- (int) groupingLevel
|
- (int) groupingLevel
|
||||||
{
|
{
|
||||||
PrivateUndoGroup *g = (PrivateUndoGroup*)_group;
|
PrivateUndoGroup *g = (PrivateUndoGroup*)_group;
|
||||||
|
@ -357,6 +482,14 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
return level;
|
return level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the receiver currently groups undo
|
||||||
|
* operations by events. When it does, so it implicitly
|
||||||
|
* invokes [-beginUndoGrouping] upon registration of undo
|
||||||
|
* operations and registers an internal call to insure
|
||||||
|
* the invocation of [-endUndoGrouping] at the end of the
|
||||||
|
* run loop.
|
||||||
|
*/
|
||||||
- (BOOL) groupsByEvent
|
- (BOOL) groupsByEvent
|
||||||
{
|
{
|
||||||
return _groupsByEvent;
|
return _groupsByEvent;
|
||||||
|
@ -367,25 +500,34 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if (self)
|
if (self)
|
||||||
{
|
{
|
||||||
_actionName = @"";
|
|
||||||
_redoStack = [[NSMutableArray alloc] initWithCapacity: 16];
|
_redoStack = [[NSMutableArray alloc] initWithCapacity: 16];
|
||||||
_undoStack = [[NSMutableArray alloc] initWithCapacity: 16];
|
_undoStack = [[NSMutableArray alloc] initWithCapacity: 16];
|
||||||
|
_groupsByEvent = YES;
|
||||||
[self setRunLoopModes:
|
[self setRunLoopModes:
|
||||||
[NSArray arrayWithObjects: NSDefaultRunLoopMode, nil]];
|
[NSArray arrayWithObjects: NSDefaultRunLoopMode, nil]];
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the receiver is currently processing a redo.
|
||||||
|
*/
|
||||||
- (BOOL) isRedoing
|
- (BOOL) isRedoing
|
||||||
{
|
{
|
||||||
return _isRedoing;
|
return _isRedoing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the receiver is currently processing an undo.
|
||||||
|
*/
|
||||||
- (BOOL) isUndoing
|
- (BOOL) isUndoing
|
||||||
{
|
{
|
||||||
return _isUndoing;
|
return _isUndoing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the receiver will currently register undo operations.
|
||||||
|
*/
|
||||||
- (BOOL) isUndoRegistrationEnabled
|
- (BOOL) isUndoRegistrationEnabled
|
||||||
{
|
{
|
||||||
if (_disableCount == 0)
|
if (_disableCount == 0)
|
||||||
|
@ -398,17 +540,44 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the maximium number of undo groupings the reciever will maintain.
|
||||||
|
* The default value is 0 meaning the number is only limited by
|
||||||
|
* memory availability.
|
||||||
|
*/
|
||||||
- (unsigned int) levelsOfUndo
|
- (unsigned int) levelsOfUndo
|
||||||
{
|
{
|
||||||
return _levelsOfUndo;
|
return _levelsOfUndo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares the receiver to registers an invocation-based undo operation.
|
||||||
|
* This method is part of the NSInvocation-based undo registration
|
||||||
|
* as opposed to the simpler [-registerUndoWithTarget:selector:object:]
|
||||||
|
* technique. <br/>
|
||||||
|
* You invoke this method with the target of the
|
||||||
|
* undo action and then invoke the targets method to undo the action
|
||||||
|
* on the return value of this invocation
|
||||||
|
* which actually is the undo manager.
|
||||||
|
* The runtime will then fallback to [-forwardInvocation:] to do the actual
|
||||||
|
* registration of the invocation.
|
||||||
|
*/
|
||||||
- (id) prepareWithInvocationTarget: (id)target
|
- (id) prepareWithInvocationTarget: (id)target
|
||||||
{
|
{
|
||||||
_nextTarget = target;
|
_nextTarget = target;
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a redo of previous undo request by taking the top grouping
|
||||||
|
* from the redo stack and invoking them. This method posts an
|
||||||
|
* NSUndoManagerCheckpointNotification notification to allow the client
|
||||||
|
* to porcess any pending changes before proceding. If there are groupings
|
||||||
|
* on the redo stack, the top object is poped of the stack and invoked
|
||||||
|
* within a nested [-beginUndoGrouping]/[-endUndoGrouping]. During this
|
||||||
|
* pocessing, the operations registered for undo are recorded on the undo
|
||||||
|
* stack again.<br\>
|
||||||
|
*/
|
||||||
- (void) redo
|
- (void) redo
|
||||||
{
|
{
|
||||||
if (_isUndoing || _isRedoing)
|
if (_isUndoing || _isRedoing)
|
||||||
|
@ -427,54 +596,103 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
[[NSNotificationCenter defaultCenter]
|
[[NSNotificationCenter defaultCenter]
|
||||||
postNotificationName: NSUndoManagerWillRedoChangeNotification
|
postNotificationName: NSUndoManagerWillRedoChangeNotification
|
||||||
object: self];
|
object: self];
|
||||||
groupToRedo = [_redoStack objectAtIndex: [_redoStack count] - 1];
|
|
||||||
IF_NO_GC([groupToRedo retain]);
|
groupToRedo = RETAIN([_redoStack lastObject]);
|
||||||
[_redoStack removeObjectAtIndex: [_redoStack count] - 1];
|
[_redoStack removeLastObject];
|
||||||
|
|
||||||
oldGroup = _group;
|
oldGroup = _group;
|
||||||
_group = nil;
|
_group = nil;
|
||||||
_isRedoing = YES;
|
_isRedoing = YES;
|
||||||
|
|
||||||
[self beginUndoGrouping];
|
[self beginUndoGrouping];
|
||||||
[groupToRedo perform];
|
[groupToRedo perform];
|
||||||
RELEASE(groupToRedo);
|
RELEASE(groupToRedo);
|
||||||
[self endUndoGrouping];
|
[self endUndoGrouping];
|
||||||
|
|
||||||
_isRedoing = NO;
|
_isRedoing = NO;
|
||||||
_group = oldGroup;
|
_group = oldGroup;
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter]
|
[[NSNotificationCenter defaultCenter]
|
||||||
postNotificationName: NSUndoManagerDidRedoChangeNotification
|
postNotificationName: NSUndoManagerDidRedoChangeNotification
|
||||||
object: self];
|
object: self];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the receiver can preform a redo, this method returns
|
||||||
|
* the action name previously associated with the top grouping with
|
||||||
|
* [-setActionName:]. This name should identify the action to be redone.
|
||||||
|
* If there are no items on the redo stack this method returns nil.
|
||||||
|
* If no action name hs been set, this method returns an empty string.
|
||||||
|
*/
|
||||||
- (NSString*) redoActionName
|
- (NSString*) redoActionName
|
||||||
{
|
{
|
||||||
if ([self canRedo] == NO)
|
if ([self canRedo] == NO)
|
||||||
{
|
{
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
return _actionName;
|
return [[_redoStack lastObject] actionName];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the full localized title of the actions to be displayed
|
||||||
|
* as a menu item. This method first invokes [-redoActionName] and
|
||||||
|
* passes it to [-redoMenuTitelForUndoActionName:] and returns the result.
|
||||||
|
*/
|
||||||
- (NSString*) redoMenuItemTitle
|
- (NSString*) redoMenuItemTitle
|
||||||
{
|
{
|
||||||
return [self redoMenuTitleForUndoActionName: [self redoActionName]];
|
return [self redoMenuTitleForUndoActionName: [self redoActionName]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString*) redoMenuTitleForUndoActionName: (NSString*)name
|
/**
|
||||||
|
* Returns the localized title of the actions to be displayed
|
||||||
|
* as a menu item identified by actionName, by appending a
|
||||||
|
* localized command string like @"Redo <localized(actionName)>".
|
||||||
|
*/
|
||||||
|
- (NSString*) redoMenuTitleForUndoActionName: (NSString*)actionName
|
||||||
{
|
{
|
||||||
if (name)
|
/*
|
||||||
|
* FIXME: The terms @"Redo" and @"Redo %@" should be localized.
|
||||||
|
* Possibly with the introduction of GSBaseLocalizedString() private
|
||||||
|
* the the library.
|
||||||
|
*/
|
||||||
|
if (actionName)
|
||||||
{
|
{
|
||||||
if ([name isEqual: @""])
|
if ([actionName isEqual: @""])
|
||||||
{
|
{
|
||||||
return @"Redo";
|
return @"Redo";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return [NSString stringWithFormat: @"Redo %@", name];
|
return [NSString stringWithFormat: @"Redo %@", actionName];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return name;
|
return actionName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers an undo operation.
|
||||||
|
* This method is the simple target-action-based undo registration
|
||||||
|
* as opposed to the sophisticated [-forwardInvocation:]
|
||||||
|
* mechanism. <br/>
|
||||||
|
* You invoke this method with the target of the
|
||||||
|
* undo action providing the selector which can perform the undo with
|
||||||
|
* the provided object. The object is often a dictionary of the
|
||||||
|
* identifying the attribute and thier values before the change.
|
||||||
|
* The invocation will added to the current grouping.<br/>
|
||||||
|
* If the registrations have been disabled through [-disableUndoRegistration],
|
||||||
|
* this method does nothing.<br/>
|
||||||
|
* Unless the reciever implicitly
|
||||||
|
* groups operations by event, the this method must have been preceeded
|
||||||
|
* with a [-beginUndoGrouping] message. Otherwise it will raise an
|
||||||
|
* NSInternalInconsistencyException. <br/>
|
||||||
|
* Unless this method is invoked as part of a [-undo] or [-undoNestedGroup]
|
||||||
|
* processing, the redo stack is cleared.<br/>
|
||||||
|
* If the reciever [-groupsByEvents] and this is the first call to this
|
||||||
|
* method since the last run loop processing, this method sets up
|
||||||
|
* the reciever to process the [-endUndoGrouping] at the
|
||||||
|
* end of the event loop.
|
||||||
|
*/
|
||||||
- (void) registerUndoWithTarget: (id)target
|
- (void) registerUndoWithTarget: (id)target
|
||||||
selector: (SEL)aSelector
|
selector: (SEL)aSelector
|
||||||
object: (id)anObject
|
object: (id)anObject
|
||||||
|
@ -487,8 +705,15 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
|
|
||||||
if (_group == nil)
|
if (_group == nil)
|
||||||
{
|
{
|
||||||
[NSException raise: NSInternalInconsistencyException
|
if ([self groupsByEvent])
|
||||||
format: @"registerUndo without beginUndoGrouping"];
|
{
|
||||||
|
[self beginUndoGrouping];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[NSException raise: NSInternalInconsistencyException
|
||||||
|
format: @"registerUndo without beginUndoGrouping"];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
g = _group;
|
g = _group;
|
||||||
sig = [target methodSignatureForSelector: aSelector];
|
sig = [target methodSignatureForSelector: aSelector];
|
||||||
|
@ -501,10 +726,26 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
{
|
{
|
||||||
[_redoStack removeAllObjects];
|
[_redoStack removeAllObjects];
|
||||||
}
|
}
|
||||||
_registeredUndo = YES;
|
if ((_runLoopGroupingPending == NO) && ([self groupsByEvent] == YES))
|
||||||
|
{
|
||||||
|
[[NSRunLoop currentRunLoop] performSelector: @selector(_loop:)
|
||||||
|
target: self
|
||||||
|
argument: nil
|
||||||
|
order: NSUndoCloseGroupingRunLoopOrdering
|
||||||
|
modes: _modes];
|
||||||
|
_runLoopGroupingPending = YES;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all grouping stored in the receiver. This clears the both
|
||||||
|
* the undo and the redo stacks. This method is if the sole client
|
||||||
|
* of the undo manager will be unable to service any undo or redo events.
|
||||||
|
* The client can call this method in its -dealloc method, unless the
|
||||||
|
* undo manager has several clients, in which case
|
||||||
|
* [-removeAllActionsWithTarget:] is more apropriate.
|
||||||
|
*/
|
||||||
- (void) removeAllActions
|
- (void) removeAllActions
|
||||||
{
|
{
|
||||||
[_redoStack removeAllObjects];
|
[_redoStack removeAllObjects];
|
||||||
|
@ -514,6 +755,13 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
_disableCount = 0;
|
_disableCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all actions recorded for the given target. This method is
|
||||||
|
* is useful when a client of the undo manager will be unable to
|
||||||
|
* service any undo or redo events. Clients should call this method
|
||||||
|
* in thier dealloc method, unless they are the sole client of the
|
||||||
|
* undo manager in which case [-removeAllActions] is more apropriate.
|
||||||
|
*/
|
||||||
- (void) removeAllActionsWithTarget: (id)target
|
- (void) removeAllActionsWithTarget: (id)target
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
@ -542,19 +790,36 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the run loop modes in which the receiver registers
|
||||||
|
* the [-endUndoGroup] processing when it [-groupsByEvent].
|
||||||
|
*/
|
||||||
- (NSArray*) runLoopModes
|
- (NSArray*) runLoopModes
|
||||||
{
|
{
|
||||||
return _modes;
|
return _modes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the name associated with the actions of the current group.
|
||||||
|
* Typically you can call this method while registering the actions
|
||||||
|
* for the current group. This name will be used to determine the
|
||||||
|
* name in the [-undoMenuTitleForUndoActionName:] and
|
||||||
|
* [-redoMenuTitleForUndoActionName:] names typically displayed
|
||||||
|
* in the menu.
|
||||||
|
*/
|
||||||
- (void) setActionName: (NSString*)name
|
- (void) setActionName: (NSString*)name
|
||||||
{
|
{
|
||||||
if (name != nil && _actionName != name)
|
if ((name != nil) && (_group != nil))
|
||||||
{
|
{
|
||||||
ASSIGNCOPY(_actionName, name);
|
[_group setActionName: name];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the receiver should implicitly call [-beginUndoGrouping] when
|
||||||
|
* necessary and register a call to invoke [-endUndoGrouping] at the end
|
||||||
|
* of the current event loop. The grouping is tunred on by default.
|
||||||
|
*/
|
||||||
- (void) setGroupsByEvent: (BOOL)flag
|
- (void) setGroupsByEvent: (BOOL)flag
|
||||||
{
|
{
|
||||||
if (_groupsByEvent != flag)
|
if (_groupsByEvent != flag)
|
||||||
|
@ -563,6 +828,13 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the maximum number of groups in either the undo or redo stack.
|
||||||
|
* Use this method to limit memory usage if you either expect very many
|
||||||
|
* actions to be recorded or the recorded objects require a lot of memory.
|
||||||
|
* When set to 0 the stack size is limited by the range of a unsigned int,
|
||||||
|
* available memory.
|
||||||
|
*/
|
||||||
- (void) setLevelsOfUndo: (unsigned)num
|
- (void) setLevelsOfUndo: (unsigned)num
|
||||||
{
|
{
|
||||||
_levelsOfUndo = num;
|
_levelsOfUndo = num;
|
||||||
|
@ -579,6 +851,13 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the modes in which the reciever registers the calls
|
||||||
|
* with the current run loop to invoke
|
||||||
|
* [-endUndoGroup] when it [-groupsByEvents]. This method
|
||||||
|
* first cancels any pending registrations in the old modes and
|
||||||
|
* registers the invokation in the new modes.
|
||||||
|
*/
|
||||||
- (void) setRunLoopModes: (NSArray*)newModes
|
- (void) setRunLoopModes: (NSArray*)newModes
|
||||||
{
|
{
|
||||||
if (_modes != newModes)
|
if (_modes != newModes)
|
||||||
|
@ -590,11 +869,18 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
[[NSRunLoop currentRunLoop] performSelector: @selector(_loop:)
|
[[NSRunLoop currentRunLoop] performSelector: @selector(_loop:)
|
||||||
target: self
|
target: self
|
||||||
argument: nil
|
argument: nil
|
||||||
order: 0
|
order: NSUndoCloseGroupingRunLoopOrdering
|
||||||
modes: _modes];
|
modes: _modes];
|
||||||
|
_runLoopGroupingPending = YES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method performs an undo by invoking [-undoNestedGroup].
|
||||||
|
* If current group of the reciever is the top group this method first
|
||||||
|
* calls [-endUndoGrouping]. This method may only be called on the top
|
||||||
|
* level group, otherwise it will raise an NSInternalInconsistencyException.
|
||||||
|
*/
|
||||||
- (void) undo
|
- (void) undo
|
||||||
{
|
{
|
||||||
if ([self groupingLevel] == 1)
|
if ([self groupingLevel] == 1)
|
||||||
|
@ -609,36 +895,68 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
[self undoNestedGroup];
|
[self undoNestedGroup];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the receiver can preform an undo, this method returns
|
||||||
|
* the action name previously associated with the top grouping with
|
||||||
|
* [-setActionName:]. This name should identify the action to be undone.
|
||||||
|
* If there are no items on the undo stack this method returns nil.
|
||||||
|
* If no action name hs been set, this method returns an empty string.
|
||||||
|
*/
|
||||||
- (NSString*) undoActionName
|
- (NSString*) undoActionName
|
||||||
{
|
{
|
||||||
if ([self canUndo] == NO)
|
if ([self canUndo] == NO)
|
||||||
{
|
{
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
return _actionName;
|
return [[_undoStack lastObject] actionName];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the full localized title of the actions to be displayed
|
||||||
|
* as a menu item. This method first invokes [-undoActionName] and
|
||||||
|
* passes it to [-undoMenuTitelForUndoActionName:] and returns the result.
|
||||||
|
*/
|
||||||
- (NSString*) undoMenuItemTitle
|
- (NSString*) undoMenuItemTitle
|
||||||
{
|
{
|
||||||
return [self undoMenuTitleForUndoActionName: [self undoActionName]];
|
return [self undoMenuTitleForUndoActionName: [self undoActionName]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString*) undoMenuTitleForUndoActionName: (NSString*)name
|
/**
|
||||||
|
* Returns the localized title of the actions to be displayed
|
||||||
|
* as a menu item identified by actionName, by appending a
|
||||||
|
* localized command string like @"Undo <localized(actionName)>".
|
||||||
|
*/
|
||||||
|
- (NSString*) undoMenuTitleForUndoActionName: (NSString*)actionName
|
||||||
{
|
{
|
||||||
if (name)
|
/*
|
||||||
|
* FIXME: The terms @"Undo" and @"Undo %@" should be localized.
|
||||||
|
* Possibly with the introduction of GSBaseLocalizedString() private
|
||||||
|
* the the library.
|
||||||
|
*/
|
||||||
|
if (actionName)
|
||||||
{
|
{
|
||||||
if ([name isEqual: @""])
|
if ([actionName isEqual: @""])
|
||||||
{
|
{
|
||||||
return @"Undo";
|
return @"Undo";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return [NSString stringWithFormat: @"Undo %@", name];
|
return [NSString stringWithFormat: @"Undo %@", actionName];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return name;
|
return actionName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs an undo by taking the top grouping
|
||||||
|
* from the undo stack and invoking them. This method posts an
|
||||||
|
* NSUndoManagerCheckpointNotification notification to allow the client
|
||||||
|
* to porcess any pending changes before proceding. If there are groupings
|
||||||
|
* on the undo stack, the top object is poped of the stack and invoked
|
||||||
|
* within a nested beginUndoGrouping/endUndoGrouping. During this
|
||||||
|
* pocessing, the undo operations registered for undo are recorded on the redo
|
||||||
|
* stack.<br\>
|
||||||
|
*/
|
||||||
- (void) undoNestedGroup
|
- (void) undoNestedGroup
|
||||||
{
|
{
|
||||||
PrivateUndoGroup *oldGroup;
|
PrivateUndoGroup *oldGroup;
|
||||||
|
@ -647,34 +965,32 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
[[NSNotificationCenter defaultCenter]
|
[[NSNotificationCenter defaultCenter]
|
||||||
postNotificationName: NSUndoManagerCheckpointNotification
|
postNotificationName: NSUndoManagerCheckpointNotification
|
||||||
object: self];
|
object: self];
|
||||||
#if 0
|
|
||||||
/*
|
if (_group != nil)
|
||||||
* The documentation says we should raise an exception - but I can't
|
|
||||||
* make sense of it - raising an exception seems to break everything.
|
|
||||||
* It would make more sense to raise an exception if NO undo operations
|
|
||||||
* had been registered.
|
|
||||||
*/
|
|
||||||
if (_registeredUndo)
|
|
||||||
{
|
{
|
||||||
[NSException raise: NSInternalInconsistencyException
|
[NSException raise: NSInternalInconsistencyException
|
||||||
format: @"undoNestedGroup with registered undo ops"];
|
format: @"undoNestedGroup before endUndoGrouping"];
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (_isUndoing || _isRedoing)
|
if (_isUndoing || _isRedoing)
|
||||||
{
|
{
|
||||||
[NSException raise: NSInternalInconsistencyException
|
[NSException raise: NSInternalInconsistencyException
|
||||||
format: @"undoNestedGroup while undoing or redoing"];
|
format: @"undoNestedGroup while undoing or redoing"];
|
||||||
}
|
}
|
||||||
if (_group != nil && [_undoStack count] == 0)
|
|
||||||
|
if ([_undoStack count] == 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter]
|
[[NSNotificationCenter defaultCenter]
|
||||||
postNotificationName: NSUndoManagerWillUndoChangeNotification
|
postNotificationName: NSUndoManagerWillUndoChangeNotification
|
||||||
object: self];
|
object: self];
|
||||||
|
|
||||||
oldGroup = _group;
|
oldGroup = _group;
|
||||||
_group = nil;
|
_group = nil;
|
||||||
_isUndoing = YES;
|
_isUndoing = YES;
|
||||||
|
|
||||||
if (oldGroup)
|
if (oldGroup)
|
||||||
{
|
{
|
||||||
groupToUndo = oldGroup;
|
groupToUndo = oldGroup;
|
||||||
|
@ -684,16 +1000,18 @@ NSString *NSUndoManagerWillUndoChangeNotification =
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
groupToUndo = [_undoStack objectAtIndex: [_undoStack count] - 1];
|
groupToUndo = RETAIN([_undoStack lastObject]);
|
||||||
IF_NO_GC([groupToUndo retain]);
|
[_undoStack removeLastObject];
|
||||||
[_undoStack removeObjectAtIndex: [_undoStack count] - 1];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[self beginUndoGrouping];
|
[self beginUndoGrouping];
|
||||||
[groupToUndo perform];
|
[groupToUndo perform];
|
||||||
RELEASE(groupToUndo);
|
RELEASE(groupToUndo);
|
||||||
[self endUndoGrouping];
|
[self endUndoGrouping];
|
||||||
|
|
||||||
_isUndoing = NO;
|
_isUndoing = NO;
|
||||||
_group = oldGroup;
|
_group = oldGroup;
|
||||||
|
|
||||||
[[NSNotificationCenter defaultCenter]
|
[[NSNotificationCenter defaultCenter]
|
||||||
postNotificationName: NSUndoManagerDidUndoChangeNotification
|
postNotificationName: NSUndoManagerDidUndoChangeNotification
|
||||||
object: self];
|
object: self];
|
||||||
|
|
Loading…
Reference in a new issue