summaryrefslogtreecommitdiffstats
path: root/devel-docs/undo.txt
diff options
context:
space:
mode:
Diffstat (limited to 'devel-docs/undo.txt')
-rw-r--r--devel-docs/undo.txt73
1 files changed, 73 insertions, 0 deletions
diff --git a/devel-docs/undo.txt b/devel-docs/undo.txt
new file mode 100644
index 0000000..03457a3
--- /dev/null
+++ b/devel-docs/undo.txt
@@ -0,0 +1,73 @@
+A quick overview of the undo system
+-----------------------------------
+
+Actions on the image by the user are pushed onto an undo stack. Each
+action object includes all the information needed to undo or redo an
+operation, plus an UndoType. The type can be converted to text to
+show to the user. Actions may be run forwards (UndoState == REDO) or
+backwards (UndoState == UNDO). As the action is run, it swaps the
+image's current state and the recorded state. A run action is moved
+from the undo stack to the redo stack (or vice-versa if UndoState ==
+REDO). Pushing something onto the undo stack causes the redo stack to
+be cleared, since the actions on the redo stack may depend on the
+image being in a particular state (eg consider: layer add, rename,
+undo rename, layer delete. If the redo stack weren't cleared on undo,
+then there would still be a "rename" operation on the redo stack which
+could be run on a non-existent layer. Bad news.)
+
+Undo groups
+-----------
+In order to group many basic operations together into a more useful
+whole, code can push group start and end markers. A group is treated
+as a single action for the purposes of the undo and redo user
+commands. It is legal to nest groups, in which case the outermost
+group is the only user-visible one.
+
+Groups boundaries used to be implemented by pushing a NULL pointer on
+the undo (or redo) stack. Now they are a special action which has the
+"group_boundary" bit set. This allows the group boundaries to include
+the undo type associated with the whole group. The individual actions
+need to preserve their own undo type since the undo_free_* functions
+sometimes need to know which action is being freed.
+
+Undo events
+-----------
+Images emit UNDO_EVENT signals, to say that the user has performed an
+undo or redo action on that image. This allows interested parties to
+track image mutation actions. So far, only the undo history dialog
+uses this feature. The other way to discover the undo status of an
+image is to use the iterator functions undo_map_over_undo_stack() and
+undo_map_over_redo_stack(). These call your function on each action
+(or group) on the stack. There is also undo_get_undo_name() and
+undo_get_redo_name() to peek at the top items on each stack. This
+could be used (eg) to change the undo/redo menu strings to something
+more meaningful, but currently lack synchronisation.
+
+Dirtying images
+---------------
+NOTE about the gimage->dirty counter:
+ If 0, then the image is clean (ie, copy on disk is the same as the one
+ in memory).
+ If positive, then that's the number of dirtying operations done
+ on the image since the last save.
+ If negative, then user has hit undo and gone back in time prior
+ to the saved copy. Hitting redo will eventually come back to
+ the saved copy.
+ The image is dirty (ie, needs saving) if counter is non-zero.
+ If the counter is around 10000, this is due to undo-ing back
+ before a saved version, then mutating the image (thus destroying
+ the redo stack). Once this has happened, it's impossible to get
+ the image back to the state on disk, since the redo info has been
+ freed. See undo.c for the gorey details.
+
+NEVER CALL gimp_image_dirty() directly!
+
+If your code has just dirtied the image, push an undo instead.
+Failing that, push the trivial undo which tells the user the
+command is not undoable: undo_push_cantundo() (But really, it would
+be best to push a proper undo). If you just dirty the image
+without pushing an undo then the dirty count is increased, but
+popping that many undo actions won't lead to a clean image.
+
+Austin
+