Re: Undo and the text widget
- From: Christopher Blizzard <blizzard redhat com>
- To: Havoc Pennington <hp redhat com>
- Cc: gtk-devel-list gnome org, darin eazel com
- Subject: Re: Undo and the text widget
- Date: Tue, 28 Nov 2000 16:16:32 -0500
Havoc Pennington wrote:
I'm hoping people can give me some input on the text widget and
implementing an "undo" facility.
What I've done at the moment is that the "insert_text" and
"delete_text" signals have an "interactive" flag, that indicates
whether the insertion or deletion is the result of user action.
The problem with this is that one user action can result in multiple
signals. e.g. say you select a range of text that includes uneditable
text and press delete, only the possibly discontiguous editable chunks
will be deleted. Or the way meta-space works is that it deletes all
spaces, then inserts one space.
An alternative to the flag indicating whether an insertion or deletion
is interactive might be:
void gtk_text_buffer_begin_user_action (GtkTextBuffer *buffer);
void gtk_text_buffer_end_user_action (GtkTextBuffer *buffer);
int gtk_text_buffer_get_user_action_serial (GtkTextBuffer *buffer);
The idea is that each user action is identified by a serial number.
To implement meta-space for example, you'd do:
During the delete/insert, the user action serial number would be the
same. If no user action is pending, the current user action serial
number would be 0.
begin_user_action() checks whether there is currently a user action
pending. If so, it just increments a counter for "depth of user action
nesting" and does nothing else. If not, it sets a new user action
end_user_action() decrements the "depth of user actions" counter, and
if the counter reaches 0, resets the serial number to 0.
This allows you to compose a single user action out of smaller user
actions. For example, a search-and-replace could make all the replaces
be the same action. The outermost begin/end pair defines the active
So, to implement undo, in your insert_text or delete_text signal
handler, you'd see whether the current user action serial is
nonzero. If the current serial matches the serial of the topmost
item on the undo stack, you add the insert or delete to the topmost
undo item. If it's different, you create a new undo item and push it
on the undo stack.
Anyone see any problems with this approach?
You might want to consider breaking the undo and the text widget into
seperate components instead of making the transaction management part of
the editor's api.
Is it possible to break the text widget's actions down into chunks that
you can play forward and back? That way you would get redo and undo.
You could pass in something like:
"Add" "Type" <char code> "Offset"
"Delete" "Cut" <char code> "Offset"
You could also use that to build macroified text actions - it lends
itself to scriptability. You could build the transaction manager around
it instead of as a part of the editor. You could also hook up to the
key signals in the editor widget and build your own transactions from
that instead of having a hard coded transaction behaviour in the editor
Sorry if this sounds a little disjointed, I'm in a meeting. :)
] [Thread Prev