def __init__(self, textbuffer): self.undo_stack = UndoStack(MAX_UNDOS) self._next_action = None self._buffer = textbuffer self.after_changed = Listeners()
class UndoHandler(object): """TextBuffer Handler that provides undo/redo functionality""" def __init__(self, textbuffer): self.undo_stack = UndoStack(MAX_UNDOS) self._next_action = None self._buffer = textbuffer self.after_changed = Listeners() def on_insert_text(self, textbuffer, it, text, length): """Callback for text insert""" # NOTE: GTK does not give us a proper UTF string, so fix it text = unicode(text, "utf_8") length = len(text) # setup next action offset = it.get_offset() self._next_action = InsertAction( textbuffer, offset, text, length, cursor_insert=(offset == textbuffer.get_iter_at_mark( textbuffer.get_insert()).get_offset())) def on_delete_range(self, textbuffer, start, end): """Callback for delete range""" # setup next action self._next_action = DeleteAction( textbuffer, start.get_offset(), end.get_offset(), start.get_slice(end), textbuffer.get_iter_at_mark(textbuffer.get_insert()).get_offset()) def on_insert_pixbuf(self, textbuffer, it, pixbuf): """Callback for inserting a pixbuf""" pass def on_insert_child_anchor(self, textbuffer, it, anchor): """Callback for inserting a child anchor""" # setup next action self._next_action = InsertChildAction(textbuffer, it.get_offset(), anchor) def on_apply_tag(self, textbuffer, tag, start, end): """Callback for tag apply""" if not isinstance(tag, RichTextTag): # do not process tags that are not rich text # i.e. gtkspell tags (ignored by undo/redo) return action = TagAction(textbuffer, tag, start.get_offset(), end.get_offset(), True) self.undo_stack.do(action.do, action.undo, False) textbuffer.set_modified(True) def on_remove_tag(self, textbuffer, tag, start, end): """Callback for tag remove""" if not isinstance(tag, RichTextTag): # do not process tags that are not rich text # i.e. gtkspell tags (ignored by undo/redo) return action = TagAction(textbuffer, tag, start.get_offset(), end.get_offset(), False) self.undo_stack.do(action.do, action.undo, False) textbuffer.set_modified(True) def on_changed(self, textbuffer): """Callback for buffer change""" # process actions that have changed the buffer if not self._next_action: return textbuffer.begin_user_action() # add action to undo stack action = self._next_action self._next_action = None self.undo_stack.do(action.do, action.undo, False) # perfrom additional "clean-up" actions # note: only if undo/redo is not currently in progress if not self.undo_stack.is_in_progress(): self.after_changed.notify(action) textbuffer.end_user_action()
class UndoHandler(object): """TextBuffer Handler that provides undo/redo functionality""" def __init__(self, textbuffer): self.undo_stack = UndoStack(MAX_UNDOS) self._next_action = None self._buffer = textbuffer self.after_changed = Listeners() def on_insert_text(self, textbuffer, it, text, length): """Callback for text insert""" # NOTE: GTK does not give us a proper UTF string, so fix it text = unicode(text, "utf_8") length = len(text) # setup next action offset = it.get_offset() self._next_action = InsertAction( textbuffer, offset, text, length, cursor_insert=(offset == textbuffer.get_iter_at_mark(textbuffer.get_insert()).get_offset()), ) def on_delete_range(self, textbuffer, start, end): """Callback for delete range""" # setup next action self._next_action = DeleteAction( textbuffer, start.get_offset(), end.get_offset(), start.get_slice(end), textbuffer.get_iter_at_mark(textbuffer.get_insert()).get_offset(), ) def on_insert_pixbuf(self, textbuffer, it, pixbuf): """Callback for inserting a pixbuf""" pass def on_insert_child_anchor(self, textbuffer, it, anchor): """Callback for inserting a child anchor""" # setup next action self._next_action = InsertChildAction(textbuffer, it.get_offset(), anchor) def on_apply_tag(self, textbuffer, tag, start, end): """Callback for tag apply""" if not isinstance(tag, RichTextTag): # do not process tags that are not rich text # i.e. gtkspell tags (ignored by undo/redo) return action = TagAction(textbuffer, tag, start.get_offset(), end.get_offset(), True) self.undo_stack.do(action.do, action.undo, False) textbuffer.set_modified(True) def on_remove_tag(self, textbuffer, tag, start, end): """Callback for tag remove""" if not isinstance(tag, RichTextTag): # do not process tags that are not rich text # i.e. gtkspell tags (ignored by undo/redo) return action = TagAction(textbuffer, tag, start.get_offset(), end.get_offset(), False) self.undo_stack.do(action.do, action.undo, False) textbuffer.set_modified(True) def on_changed(self, textbuffer): """Callback for buffer change""" # process actions that have changed the buffer if not self._next_action: return textbuffer.begin_user_action() # add action to undo stack action = self._next_action self._next_action = None self.undo_stack.do(action.do, action.undo, False) # perfrom additional "clean-up" actions # note: only if undo/redo is not currently in progress if not self.undo_stack.is_in_progress(): self.after_changed.notify(action) textbuffer.end_user_action()