]> git.lizzy.rs Git - micro.git/blob - eventhandler.go
Add undo/redo stack
[micro.git] / eventhandler.go
1 package main
2
3 import (
4         "time"
5 )
6
7 const (
8         // TextEventInsert repreasents an insertion event
9         TextEventInsert = 1
10         // TextEventRemove represents a deletion event
11         TextEventRemove = -1
12 )
13
14 // TextEvent holds data for a manipulation on some text that can be undone
15 type TextEvent struct {
16         c Cursor
17
18         eventType int
19         text      string
20         start     int
21         end       int
22         buf       *Buffer
23         time      time.Time
24 }
25
26 // ExecuteTextEvent runs a text event
27 func ExecuteTextEvent(t *TextEvent) {
28         if t.eventType == TextEventInsert {
29                 t.buf.Insert(t.start, t.text)
30         } else if t.eventType == TextEventRemove {
31                 t.text = t.buf.Remove(t.start, t.end)
32         }
33 }
34
35 // UndoTextEvent undoes a text event
36 func UndoTextEvent(t *TextEvent) {
37         t.eventType = -t.eventType
38         ExecuteTextEvent(t)
39 }
40
41 // EventHandler executes text manipulations and allows undoing and redoing
42 type EventHandler struct {
43         v    *View
44         undo *Stack
45         redo *Stack
46 }
47
48 // NewEventHandler returns a new EventHandler
49 func NewEventHandler(v *View) *EventHandler {
50         eh := new(EventHandler)
51         eh.undo = new(Stack)
52         eh.redo = new(Stack)
53         eh.v = v
54         return eh
55 }
56
57 // Insert creates an insert text event and executes it
58 func (eh *EventHandler) Insert(start int, text string) {
59         e := &TextEvent{
60                 c:         eh.v.cursor,
61                 eventType: TextEventInsert,
62                 text:      text,
63                 start:     start,
64                 end:       start + len(text),
65                 buf:       eh.v.buf,
66                 time:      time.Now(),
67         }
68         eh.Execute(e)
69 }
70
71 // Remove creates a remove text event and executes it
72 func (eh *EventHandler) Remove(start, end int) {
73         e := &TextEvent{
74                 c:         eh.v.cursor,
75                 eventType: TextEventRemove,
76                 start:     start,
77                 end:       end,
78                 buf:       eh.v.buf,
79                 time:      time.Now(),
80         }
81         eh.Execute(e)
82 }
83
84 // Execute a textevent and add it to the undo stack
85 func (eh *EventHandler) Execute(t *TextEvent) {
86         eh.undo.Push(t)
87         ExecuteTextEvent(t)
88 }
89
90 // Undo the first event in the undo stack
91 func (eh *EventHandler) Undo() {
92         t := eh.undo.Pop()
93         if t == nil {
94                 return
95         }
96
97         te := t.(*TextEvent)
98         // Modifies the text event
99         UndoTextEvent(te)
100         eh.redo.Push(t)
101
102         eh.v.cursor = te.c
103 }
104
105 // Redo the first event in the redo stack
106 func (eh *EventHandler) Redo() {
107         t := eh.redo.Pop()
108         if t == nil {
109                 return
110         }
111
112         te := t.(*TextEvent)
113         // Modifies the text event
114         UndoTextEvent(te)
115         eh.undo.Push(t)
116         eh.v.cursor = te.c
117 }