This is the main page which describes what are Changes, why are they needed, how to use them and also concepts related with them.
Overview
An important part of the core layer of Sophie is formed by the ProLib. The ProLib is intended to be used as the bottom layer for most actions in Sophie.
One important concept is that when some action happens in Sophie, it is translated into basic ProLib operations. Thus, if all ProLib operations get "logged" some how, then everything which happens in Sophie would also get "logged".
Based on this information and automatic undo/redo logic can be implemented at this core ProLib layer, thus providing automatic undo/redo logic for the whole Sophie platform.
The way to "log" actions in Sophie are the Changes.
For further info on the ProLib see PRO_LIB_CORE_TUTORIAL.
Change
- Hierarchy
- Change
Change is the base interface for all changes that need to be tracked and respectively undone, redone and skipped in Sophie.
Changes can be composed via GroupChanges and actually in Sophie, each more complex action is represented by a GroupChange and thus form a tree of GroupChanges, having internal nodes form the tree structure and leaves being just GroupChanges with a single ProChange in it.
- Change
- Top-level Changes
Top-level Changes are changes cause by a user actions like creating a frame, changing the background color, etc.
Each top-level Change is represented as a GroupChange and most likely has side-effect Changes.
Top-level Changes can be undoed, redoed and skipped by the UndoManager.
- Side-effect Changes
Side-effect Changes are Changes which are caused to happen due to a top-level Change.
Side-effect Changes are represented as subChanges of the GroupChanges which represents the top-level Change which caused them.
- Significance of Changes
- Main Changes
- ProChange
A ProChange is a Change to a single Pro. It is meant to be the lowest level Change in the hierarchy.
- ProChange
- GroupChange
GroupChanges are used to implement composing of simpler Changes in one bigger Change and thus capsulate a complex action in one Change.
With their help we can implement hierarchical representation of each action which is to be treated as a Change. Further details at PRO_CHANGE_COMPOSING_R0.
- AutoChange
AutoChanges are meant to be used by the developer when he wants some group of actions to be treated atomically by the UndoManager and thus either all of them get undone, redone or skipped in one transaction.
In contrast with other Changes, which are used internally by the ProLib, this Change is used by the developer and simply produces a GroupChange from all the described actions, thus this is the user way of creating a GroupChange.
- Special Changes
- UndoChange
UndoChange is a Change which wraps an undo command issued by the UndoManager.
It cancels the effect of the last Change in the History it's associated with.
- UndoChange
- RedoChange
RedoChange is a Change which wraps a redo command issued by the UndoManager.
It is only valid if the last Change the History it's associated with is an UndoChange in which case it cancels its effect.
- SkipChange
SkipChange is a Change which wraps a skip command issued by the UndoManager.
It accepts one parameter which is the id of a Change in the History it's associated with and cancels its effect.
- CreateChange
Creating ProObjects is an important special event which couldn't be handled in the standard manner and thus is wrapped in a CreateChange.
- DestroyChange
Same applies to destroying ProObjects.
- UnmanagedChange
UnmanagedChange is a Change which is meant to wrap actions which need special handling of their undo logic.
Since the Change mechanism in Sophie should handle changes related with ProObjects and Immutables automatically, the UnmanagedChange is designed to handle other actions like writing to the filesystem, for instance.
History
- Euler traversal
Further info at PRO_CHANGE_MANAGER_R0 (previously Histories were known as ChangeManagers but were later renamed and thus the naming discrepancies occurred).
ChangeManager
ChangeManager is an interface which everyone interested in custom handling of fired Changes should implement. For instance, all Resources are ChangeManagers. Since each Resource is associated one-to-one with a History, kept in its ResourceSpace, the Resource is able to apply logging in its History or don't do anything if it doesn't need logging.
When a Change is fired, there is a ChangeManager which is responsible for the Change, and it handles it.
A ChangeManager is responsible for grouping incoming Changes into GroupChanges and also provides the possibility of overriding the registering of each fired Change to allow custom handling.
- DefaultChangeManager
This is a sample implementation of the ChangeManager interface, which simply executes the incoming Change without logging it or doing any other handling.
UndoManager
Sophie should provide an UndoManager to the user and with its help he or she will be able to undo, redo or skip a given top-level change of the current Resource.
The UndoManager is a singleton instance of an entity which performs undo/redo/skip logic on the current Resource. It provides to the end-user of Sophie a view on the History of the current Resource and allows him to undo/redo the last Change there or skip any of the top-level Changes of which this History is consisted.
Further info at PRO_CHANGE_UNDO_MANAGER_R0.
ProLib Change primitives
Further info at PRO_CHANGE_PRIMITIVES_R0.