|
WebObjects 5.2 | |||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: INNER | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object | +--com.webobjects.foundation.NSUndoManager
NSUndoManager is a general-purpose recorder of operations for undo and redo. You register an undo operation by specifying the object that's changing (or the owner of that object), along with a method to invoke to revert its state, and the arguments for that method. NSUndoManager groups all operations within a single cycle of the run loop, so that performing an undo reverts all changes that occurred during the loop. Also, when performing undo an NSUndoManager saves the operations reverted so that you can redo the undos.
NSUndoManager is implemented as a class of the Foundation framework because executables other than applications might want to revert changes to their states. For example, you might have an interactive command-line tool with undo and redo commands. However, users typically see undo and redo as application features. WebObjects applications can use NSUndoManagers to undo and redo user operations. Typically a session's editing context has an undo manager that provides undo and redo operations on enterprise objects. For more information, see the class specification for EOEditingContext (eocontrol package).
An undo operation is a method for reverting a change to an object, along with the arguments needed to revert the change (for example, its state before the change). Undo operations are typically collected in undo groups, which represent whole revertible actions, and are stored on a stack. Redo operations and groups are simply undo operations stored on a separate stack (described below). When an NSUndoManager performs undo or redo, it's actually undoing or redoing an entire group of operations. For example, a user could change the first name and the last name of an employee. An application might package both operations as a group, so when the user chooses Undo, both the first and last names are reverted. To undo a single operation, the operation must be packaged alone in a group.
NSUndoManager normally creates undo groups automatically during the run loop. The first
time it's asked to record an undo operation in the run loop, it creates a new group. Then,
at the end of the loop, it closes the group. You can create additional, nested undo groups
within these default groups using the beginUndoGrouping()
and enableUndoRegistration()
methods. You can also turn off the default grouping behavior using setGroupsByEvent(boolean)
.
Undo groups are stored on a stack, with the oldest groups at the bottom and the newest at the top.
The undo stack is unlimited by default, but you can restrict it to a maximum number of groups using
the setLevelsOfUndo(int)
method. When
the stack exceeds the maximum, the oldest undo groups are dropped from the bottom.
Initially, both stacks are empty. Recording undo operations adds to the undo stack, but the redo stack remains empty until an undo is performed. Performing an undo causes the reverting operations in the latest group to be applied to their objects. Since these operations cause changes to the objects' states, the objects presumably register new operations with the NSUndoManager, this time in the reverse direction from the original operations. Since the NSUndoManager is in the process of performing undo, it records these operations as redo operations on the redo stack. Consecutive undos add to the redo stack. Subsequent redo operations pull the operations off the redo stack, apply them to the objects, and push them back onto the undo stack.
The redo stack's contents last as long as undo and redo are performed successively. However,
because applying a new change to an object invalidates the previous changes, as soon as a new
undo operation is registered, the redo stack is cleared. This prevents redo from returning objects
to an inappropriate prior state. You can check for the ability to undo and redo with the
canUndo()
and canRedo()
methods.
To add an undo operation to the undo stack, you must register it with the object that will perform the undo operation. To register the undo operation you specify a selector with a single object argument. When an object changes, the object itself (or another object acting on its behalf) records its attributes prior to the change in the argument object. (This argument is frequently an NSDictionary object, but it can be any object.) Performing the undo then involves resetting the object with these attributes.
To record a simple undo operation, you need only invoke registerUndoWithTarget(java.lang.Object, com.webobjects.foundation.NSSelector, java.lang.Object)
,
giving the object to be sent the undo operation selector, the selector to invoke, and an argument
to pass with that message. The target object is usually not the actual object whose state is changing;
instead, it's the client object, a document or container that holds many undoable objects. The argument
is an object that captures the state of the object before the change is made. If you have multiple
arguments, use registerUndoWithTargetAndArguments(java.lang.Object, com.webobjects.foundation.NSSelector, java.lang.Object[])
.
In most applications a single instance of NSUndoManager belongs to an object that contains or manages other objects. This is particularly the case with document-based applications, where a single object is responsible for all undo and redo operations for a document. An object such as this is often called the NSUndoManager's client. Each client object has its own NSUndoManager. The client claims exclusive right to alter its undoable objects so that it can record undo operations for all changes. In the specific case of documents, this scheme keeps each pair of undo and redo stacks separate so that when an undo is performed, it applies to the focal document in the application (typically the one displayed in the key window). It also relieves the individual objects in a document from having to know the identity of their NSUndoManager or from having to track changes to themselves.
However, an object that is changed can have its own NSUndoManager and perform its own undo and redo operations. For example, you could have a custom view that displays images dragged into it; with each successful drag operation, it registers a new undo group. If the view is then selected (that is, made first responder) and the Undo command applied, the previously displayed image would be redisplayed.
Performing undo and redo is usually as simple as sending undo()
and redo()
messages
to the NSUndoManager. undo closes the last open undo group and then applies all the undo operations
in that group (recording any undo operations
as redo operations instead). redo likewise applies all the redo operations on the top redo group.
undo is intended for undoing top-level groups, and shouldn't be used for nested undo groups.
If any unclosed, nested undo groups are on the stack when undo is invoked, it throws an exception.
To undo nested groups, you must explicitly close the group with an
enableUndoRegistration()
message, then use undoNestedGroup()
to undo it.
Note also that if you turn off automatic grouping by event with
setGroupsByEvent(boolean)
, you must explicitly
close the current undo group with enableUndoRegistration()
before invoking either undo method.
An NSUndoManager regularly posts checkpoint notifications to synchronize the inclusion of undo
operations in undo groups. Objects sometimes delay performing changes, for various reasons. This
means they may also delay registering undo operations for those changes. Because NSUndoManager
collects individual operations into groups, it must be sure to synchronize its client with the
creation of these groups so that operations are entered into the proper undo groups. To this end,
whenever an NSUndoManager opens or closes a new undo group (except when it opens a top-level group),
it posts a CheckpointNotification
so observers can apply their pending undo
operations to the group in effect. The NSUndoManager's client should register itself as an observer
for this notification and record undo operations for all pending changes upon receiving it.
NSUndoManager also posts a number of other notifications at specific intervals: when a group is created, when a group is closed, and just before and just after both undo and redo operations. For more on notifications, see "Notifications".
CheckpointNotification
,
setGroupsByEvent(boolean)
,
beginUndoGrouping()
,
enableUndoRegistration()
,
setLevelsOfUndo(int)
,
canUndo()
,
canRedo()
,
registerUndoWithTarget(java.lang.Object, com.webobjects.foundation.NSSelector, java.lang.Object)
,
registerUndoWithTargetAndArguments(java.lang.Object, com.webobjects.foundation.NSSelector, java.lang.Object[])
,
redo()
,
undo()
,
undoNestedGroup()
Field Summary | |
static String |
CheckpointNotification
Posted whenever an NSUndoManager opens or closes an undo group (except when it opens a top-level group), and when an NSUndoManager checks the redo stack in canRedo . |
static String |
DidOpenUndoGroupNotification
Posted whenever an NSUndoManager opens an undo group, which occurs in an invocation of beginUndoGrouping. |
static String |
DidRedoChangeNotification
Posted just after an NSUndoManager performs a redo operation. |
static String |
DidUndoChangeNotification
Posted just after an NSUndoManager performs an undo operation. |
static int |
UndoCloseGroupingRunLoopOrdering
Specifies the priority for closing the current undo group compared to other operations in the delayed callback queue. |
static String |
WillCloseUndoGroupNotification
Posted whenever an NSUndoManager closes an undo group, which occurs in an invocation of endUndoGrouping . |
static String |
WillRedoChangeNotification
Posted just before an NSUndoManager performs a redo operation. |
static String |
WillUndoChangeNotification
Posted just before an NSUndoManager performs an undo operation. |
Constructor Summary | |
NSUndoManager()
Creates an NSUndoManager object. |
Method Summary | |
void |
beginUndoGrouping()
Marks the beginning of an undo group. |
boolean |
canRedo()
Returns true if this NSUndoManager has any actions to redo. |
boolean |
canUndo()
Returns true if this NSUndoManager has any actions to undo. |
void |
disableUndoRegistration()
Disables the recording of undo operations, whether by registerUndoWithTarget or by invocation-based undo. |
void |
dispose()
Conformance to NSDisposable. |
void |
enableUndoRegistration()
Enables the recording of undo operations. |
void |
endUndoGrouping()
Marks the end of an undo group. |
int |
groupingLevel()
Returns the number of nested undo groups in the current event loop. |
boolean |
groupsByEvent()
Returns true if this NSUndoManager automatically creates undo
groups around each pass of the run loop. |
boolean |
isRedoing()
Returns true if this NSUndoManager is in the process of
performing an redo operation. |
boolean |
isUndoing()
Returns true if this NSUndoManager is in the process of
performing an undo operation. |
boolean |
isUndoRegistrationEnabled()
Indicates whether the recording of undo operations is enabled. |
int |
levelsOfUndo()
Returns the maximum number of top-level undo groups this NSUndoManager will hold. |
void |
redo()
Performs the operations in the last group on the redo stack, if there are any, recording them on the undo stack as a single group. |
void |
registerUndoWithTarget(Object target,
NSSelector selector,
Object object)
Records a single undo operation for target , so that when undo is
performed it's sent selector with object as the sole
argument. |
void |
registerUndoWithTargetAndArguments(Object target,
NSSelector selector,
Object[] objects)
For undo operations dealing with multiple arguments you need to use registerUndoWithTargetAndArguments method giving the object
to be sent the undo operation selector, the selector to invoke, and
arguments to pass with that message. |
void |
removeAllActions()
Clears the undo and redo stacks and re-enables this NSUndoManager |
void |
removeAllActionsWithTarget(Object target)
Clears the undo and redo stacks of all operations involving target
as the recipient of the undo message. |
void |
setGroupsByEvent(boolean groupsByEvent)
Sets whether this NSUndoManager automatically groups undo operations during the run loop. |
void |
setLevelsOfUndo(int levels)
Sets the maximum number of top-level undo groups this NSUndoManager will hold to levels . |
void |
undo()
Closes the top-level undo group if necessary and invokes undoNestedGroup . |
void |
undoNestedGroup()
Performs the undo operations in the last undo group (whether top-level or nested), recording the operations on the redo stack as a single group. |
Methods inherited from class java.lang.Object |
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Field Detail |
public static final String CheckpointNotification
canRedo
. The notification contains:
null
canRedo()
public static final String DidOpenUndoGroupNotification
null
beginUndoGrouping()
public static final String DidRedoChangeNotification
null
redo()
public static final String DidUndoChangeNotification
undo
or undoNestedGroup
, this notification is
posted.
The notification contains:
null
undoNestedGroup()
,
undo()
public static final int UndoCloseGroupingRunLoopOrdering
public static final String WillCloseUndoGroupNotification
endUndoGrouping
. The notification contains:
null
endUndoGrouping()
public static final String WillRedoChangeNotification
null
redo()
public static final String WillUndoChangeNotification
undo
or undoNestedGroup
, this notification is
posted. The notification contains:
null
undo()
,
undoNestedGroup()
Constructor Detail |
public NSUndoManager()
Method Detail |
public void beginUndoGrouping()
endUndoGrouping
invocation are grouped together and reversed by
a later undo
invocation. By default, undo groups are begun automatically at
the start of the event loop, but you can begin undo groups
with this method, and nest them within other groups.
This method posts a CheckpointNotification
unless a top-level undo
is in progress. It posts a DidOpenUndoGroupNotification
if a new
group was successfully created.
CheckpointNotification
,
DidOpenUndoGroupNotification
,
endUndoGrouping()
,
undo()
public boolean canRedo()
true
if this NSUndoManager has any actions to redo.
Because any undo operation registered clears the redo stack, this
method posts a CheckpointNotification
to allow clients to apply
their pending operations before testing the redo stack.true
if this NSUndoManager has any actions to redoCheckpointNotification
public boolean canUndo()
true
if this NSUndoManager has any actions to undo.
To invoke undo
or undoNestedGroup
safely, undo groups
may have to close open first.true
if this NSUndoManager has any actions to undoundo()
,
undoNestedGroup()
,
enableUndoRegistration()
,
registerUndoWithTarget(java.lang.Object, com.webobjects.foundation.NSSelector, java.lang.Object)
public void disableUndoRegistration()
registerUndoWithTarget
or by invocation-based undo. This method can
be invoked multiple times by multiple clients. enableUndoRegistration
must be invoked an equal number of times to re-enable undo
registration.registerUndoWithTarget(Object target, NSSelector
aSelector, Object anObject)
,
enableUndoRegistration()
public void dispose()
dispose
in interface NSDisposable
public void enableUndoRegistration()
disableUndoRegistration
invocation. Undo registration
isn't actually re-enabled until an enable...
balances the last
disable...
in effect.IllegalStateException
- this method was invoked while
disableUndoRegistration
is not in effectdisableUndoRegistration()
public void endUndoGrouping()
beginUndoGrouping
invocation are grouped together and reversed by a
later undo
or undoNestedGroup
. Undo groups can be nested, thus
providing functionality similar to nested transactions.
This method posts a CheckpointNotification
and a
WillCloseUndoGroupNotification
just before the group is closed.
IllegalStateException
- if there's no beginUndoGrouping
in effectCheckpointNotification
,
WillCloseUndoGroupNotification
,
beginUndoGrouping()
,
undo()
,
undoNestedGroup()
,
levelsOfUndo()
public int groupingLevel()
redo
was last invoked) in the current event loop, 0
when
there is no open undo or redo grouplevelsOfUndo()
,
setLevelsOfUndo(int)
public boolean groupsByEvent()
true
if this NSUndoManager automatically creates undo
groups around each pass of the run loop. The default is true
.true
if this NSUndoManager automatically creates undo
groups around each pass of the run loopbeginUndoGrouping()
public boolean isRedoing()
true
if this NSUndoManager is in the process of
performing an redo operation.true
if this NSUndoManager is in the process of
performing its redo methodredo()
public boolean isUndoRegistrationEnabled()
true
if the recording of undo operations is enableddisableUndoRegistration()
,
enableUndoRegistration()
public boolean isUndoing()
true
if this NSUndoManager is in the process of
performing an undo operation.true
if this NSUndoManager is in the process of
performing an undo
or undoNestedGroup
undo()
,
undoNestedGroup()
public int levelsOfUndo()
0
indicates no limit, so old undo groups are never
dropped. The default is 0
.enableUndoRegistration()
,
setLevelsOfUndo(int)
public void redo()
This method posts a CheckpointNotification
and
WillRedoChangeNotification
before it performs the redo operation, and it posts
DidRedoChangeNotification
after it performs the redo operation.
IllegalStateException
- the method is invoked during
an undo operationCheckpointNotification
,
WillRedoChangeNotification
,
DidRedoChangeNotification
,
registerUndoWithTarget(java.lang.Object, com.webobjects.foundation.NSSelector, java.lang.Object)
public void registerUndoWithTarget(Object target, NSSelector selector, Object object)
target
, so that when undo is
performed it's sent selector
with object
as the sole
argument. Also clears the redo stack.
To record a simple undo operation, you need only invoke
registerUndoWithTarget
, giving the object to be sent the undo operation
selector, the selector to invoke, and an argument to pass with that
message. The target object is usually not the actual object whose state is
changing; instead, it's the client object, a document or container that
holds many undoable objects. The argument is an object that captures the
state of the object before the change is made. If you have multiple
arguments, use registerUndoWithTargetAndArguments
.
Undo groups are normally set by default, so it should rarely need to begin a top-level undo group explicitly.
target
- target object which captures the state
of the object before being changedselector
- undo operation selector which is to be invokedobject
- object to be sent the undo operation selectorIllegalStateException
- this method is invoked when no undo group
has been established using beginUndoGrouping
beginUndoGrouping()
,
undoNestedGroup()
,
groupingLevel()
,
registerUndoWithTarget(java.lang.Object, com.webobjects.foundation.NSSelector, java.lang.Object)
,
registerUndoWithTargetAndArguments(java.lang.Object, com.webobjects.foundation.NSSelector, java.lang.Object[])
public void registerUndoWithTargetAndArguments(Object target, NSSelector selector, Object[] objects)
registerUndoWithTargetAndArguments
method giving the object
to be sent the undo operation selector, the selector to invoke, and
arguments to pass with that message. The target object is usually not the
actual object whose state is changing; instead, it's the client object, a
document or container that holds many undoable objects. The argument is an
object that captures the state of the object before the change is made.target
- target object which captures the state
of the objects before being changedselector
- undo operation selector which is
to be invokedobjects
- arguments to be passed with selector's methodpublic void removeAllActions()
enableUndoRegistration()
,
removeAllActionsWithTarget(java.lang.Object)
public void removeAllActionsWithTarget(Object target)
target
as the recipient of the undo message. Doesn't re-enable this NSUndoManager
if it's disabled. An object that shares an NSUndoManager with other
clients should invoke this method in its implementation of
finalize
.target
- target as recipient of the undo messageenableUndoRegistration()
,
removeAllActions()
public void setGroupsByEvent(boolean groupsByEvent)
groupsByEvent
is true
,
this NSUndoManager creates undo groups around each pass through the run loop;
if groupsByEvent is false
it doesn't.
The default is true
.
If you turn automatic grouping off, you must close groups explicitly
before invoking either undo
or undoNestedGroup
.
groupsByEvent
- flag which indicates whether the method
automatically groups undo operations
during the run loopundo()
,
undoNestedGroup()
,
groupingLevel()
,
groupsByEvent()
public void setLevelsOfUndo(int levels)
levels
. When ending an undo group results in the number of groups
exceeding this limit, the oldest groups are dropped from the stack. A
limit of 0
indicates no limit, so that old undo groups are never
dropped. The default is 0
.
If invoked with a limit below the prior limit, old undo groups are immediately dropped.
levels
- specifies level of undo groupsenableUndoRegistration()
,
levelsOfUndo()
public void undo()
undoNestedGroup
.
It also invokes endUndoGrouping
if the nesting level is 1
.
This method posts a CheckpointNotification
.InternalInconsistencyException
- more than
one undo group is open (that is, if the last group isn't at the top level)CheckpointNotification
,
enableUndoRegistration()
,
groupingLevel()
public void undoNestedGroup()
This method posts a CheckpointNotification
and
WillUndoChangeNotification
before it performs the undo operation, and it
posts DidUndoChangeNotification
after it performs the
undo operation.
InternalInconsistencyException
- there are undo operations that have
been registered since the last enableUndoRegistration
invocationCheckpointNotification
,
WillUndoChangeNotification
,
DidUndoChangeNotification
,
undo()
,
enableUndoRegistration()
|
Last updated Fri Feb 21 13:15:00 PST 2003. | |||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
SUMMARY: INNER | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |