Undo and the text widget



Hi,

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:

 begin_user_action ();
 delete_spaces_around_cursor ();
 insert_a_space ();
 end_user_action ();

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
serial number. 

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 
serial number.


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?

Havoc









[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]