Add timed undo

This commit is contained in:
Zachary Yedidia 2016-04-01 09:54:10 -04:00
parent 28c0ee3510
commit b7447c82ca
3 changed files with 70 additions and 0 deletions

View file

@ -94,24 +94,85 @@ func (eh *EventHandler) Execute(t *TextEvent) {
// Undo the first event in the undo stack
func (eh *EventHandler) Undo() {
t := eh.undo.Peek()
if t == nil {
return
}
te := t.(*TextEvent)
startTime := t.(*TextEvent).time.UnixNano() / int64(time.Millisecond)
eh.UndoOneEvent()
for {
t = eh.undo.Peek()
if t == nil {
return
}
te = t.(*TextEvent)
if startTime-(te.time.UnixNano()/int64(time.Millisecond)) > undoThreshold {
return
}
eh.UndoOneEvent()
}
}
// UndoOneEvent undoes one event
func (eh *EventHandler) UndoOneEvent() {
// This event should be undone
// Pop it off the stack
t := eh.undo.Pop()
if t == nil {
return
}
te := t.(*TextEvent)
// Undo it
// Modifies the text event
UndoTextEvent(te)
// Set the cursor in the right place
teCursor := te.c
te.c = eh.v.cursor
eh.v.cursor = teCursor
// Push it to the redo stack
eh.redo.Push(te)
}
// Redo the first event in the redo stack
func (eh *EventHandler) Redo() {
t := eh.redo.Peek()
if t == nil {
return
}
te := t.(*TextEvent)
startTime := t.(*TextEvent).time.UnixNano() / int64(time.Millisecond)
eh.RedoOneEvent()
for {
t = eh.redo.Peek()
if t == nil {
return
}
te = t.(*TextEvent)
if (te.time.UnixNano()/int64(time.Millisecond))-startTime > undoThreshold {
return
}
eh.RedoOneEvent()
}
}
// RedoOneEvent redoes one event
func (eh *EventHandler) RedoOneEvent() {
t := eh.redo.Pop()
if t == nil {
return

View file

@ -13,6 +13,7 @@ const (
synLinesUp = 75 // How many lines up to look to do syntax highlighting
synLinesDown = 75 // How many lines down to look to do syntax highlighting
doubleClickThreshold = 400 // How many milliseconds to wait before a second click is not a double click
undoThreshold = 500 // If two events are less than n milliseconds apart, undo both of them
)
// The main screen

View file

@ -33,3 +33,11 @@ func (s *Stack) Pop() (value interface{}) {
}
return nil
}
// Peek returns the top element of the stack without removing it
func (s *Stack) Peek() interface{} {
if s.size > 0 {
return s.top.value
}
return nil
}