COTrack documentation

COTrack <ETCollection>

COTrack is a protocol to present changes on a timeline, manipulate them, and provide a custom view on the store history

AuthorsGenerated by qmathe
Declared inCOTrack.h


A track represents usually a revision or commit sequence, but it is up to the class adopting the protocol to decide about the sequence content (the track nodes). What constitutes a change from the track standpoint is thus under the track class responsability. COTrack requires the presented changes to be objects that conform to COTrackNode. All nodes on a track must also be of the same kind.

Built-in Tracks

In CoreObject, CORevision and COCommand conform to this track node protocol, and COBranch and COUndoTrack are track classes that present respectively revisions and commits as track nodes.


A track content can be persistent (e.g. a normal undo track or a branch) or lazily constructed (e.g. a pattern undo track, see +[COUndoTrack trackForPattern:withEditingContext:] ).

Track Node Collection

The track protocol is split in several parts, the core part implements the logic to navigate track node collection: -nodes , -nextNodeOnTrackFrom:backwards: , -currentNode and -setCurrentNode: .

You should implement these methods first, and then the other methods.

A track must also implement ETCollection support based on the core method listed above.

Basic Undo and Redo

Another part in the protocol is the basic Undo and Redo support that makes possible to move the current node accross the node collection, and interprets this move as an undo/redo action.

-undo and -redo should usually move the current node in a linear way, but there is no hard requirements on this point.

Selective Undo

All tracks must also implement -undoNode: and -redoNode: to support selective undo and redo, which usually move the current node in a non-linear way unlike -undo and -redo.

A selective undo means undoing a single action in the past, while keeping the more recent actions that depend on the undone one. A normal undo can be seen as a selective undo subcase where the undone action is the most recent one. The main difference lies in the fact, a selective undo usually requires to make a new commit that discards the undone changes while keeping the other changes that follow on the track. To compute this new commit, -undoNode: and -redoNode: can leverage the Diff API or some API built on top of it (e.g. -[COCommand inverse] ).

Accessing Track Nodes

- (NSArray *) nodes

Returns all the nodes on the track.

Calling this methods mean all the nodes will be loaded in memory. For tracks that can contain 10000 nodes or even more, there is a cost involved, so the track implementation should rely on -nextNodeOnTrackFrom:backwards: as much as possible.

    - (id <COTrackNode>) nextNodeOnTrackFrom: (id <COTrackNode>)aNode backwards: (BOOL)back

    Returns the node that follows aNode on the track when back is NO, otherwise when back is YES, returns the node that precedes aNode.

    See also -nodes.

      Changing Track Nodes

      - (id <COTrackNode>) currentNode

      The current node represents the change that was applied to arrive at the current state, or in other words, the change that will be undone if -undo is called.

      See also -setCurrentNode: .

        - (BOOL) setCurrentNode: (id <COTrackNode>)node

        Sets the current position in the the track timeline to match the track node.

        As a result, the receiver current state will correspond to the change represented by the given track node.

        See also -currentNode .

          Selective Undo

          - (void) undoNode: (id <COTrackNode>)aNode

          Does a selective undo to cancel the changes involved in the track node revision.

          How the track decides between selective undo vs normal undo/redo is up to the track subclass.

          See also -redoNode: and -undo.

            - (void) redoNode: (id <COTrackNode>)aNode

            Same as -undoNode: , but for redoing a node.

            See also -undoNode: and -redo.

              Undo and Redo

              - (BOOL) canUndo

              Returns whether an undo can be performed.

              See also -undo and -canRedo.

                - (BOOL) canRedo

                Returns whether a redo can be performed.

                See also -redo and -canUndo.

                  - (void) undo

                  Performs an undo. The meaning of undo is left up to subclasses.

                  See also -redo and -undoNode: .

                    - (void) redo

                    Performs a redo. The meaning of redo is left up to subclasses.

                    See also -undo and -redoNode: