-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathUndoer.rb
152 lines (134 loc) · 3.66 KB
/
Undoer.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
module Yoshied
class Undoer
include javax.swing.event.UndoableEditListener
def initialize
@undoAction = UndoAction.new(self)
@redoAction = RedoAction.new(self)
@undoManager = UndoManager.new
@inReplace = false
end
attr_reader :undoAction, :redoAction, :undoManager
attr_writer :inReplace
def resetUndo
@undoManager.discardAllEdits
@undoAction.updateUndoState(@undoManager)
@redoAction.updateRedoState(@undoManager)
end
def undo
begin
@undoManager.undo
rescue
$stderr.puts($!)
$stderr.puts($!.backtrace)
end
@undoAction.updateUndoState(@undoManager)
@redoAction.updateRedoState(@undoManager)
end
def redo
begin
@undoManager.redo
rescue
$stderr.puts($!)
$stderr.puts($!.backtrace)
end
@redoAction.updateRedoState(@undoManager)
@undoAction.updateUndoState(@undoManager)
end
def undoableEditHappened(undoableEditEvent)
edit = undoableEditEvent.getEdit
seq = SequentialEdit.new
seq.addEdit(edit)
seq.editType = toEditType(edit)
last = @undoManager.lastEdit
last and differentEditType?(last, edit) and last.end
@undoManager.addEdit(seq)
@undoAction.updateUndoState(@undoManager)
@redoAction.updateRedoState(@undoManager)
end
def differentEditType?(lastSeq, undoableEdit)
!lastSeq and return false
lastSeq.editType == :change and return true
editType = toEditType(undoableEdit)
lastSeq.editType != editType and !@inReplace
end
def toEditType(undoableEdit)
return case undoableEdit.getType
when DocumentEvent::EventType::CHANGE
:change
when DocumentEvent::EventType::INSERT
:insert
when DocumentEvent::EventType::REMOVE
:remove
else
:unknown
end
end
def lastEditEnd
last = @undoManager.lastEdit
!last and return
last.end
end
end
class UndoAction < AbstractAction
def initialize(undoer)
super("Undo")
@undoer = undoer
setEnabled(false)
end
def actionPerformed(e)
@undoer.undo
end
def updateUndoState(undo)
if undo.canUndo
setEnabled(true)
putValue(Action::NAME, undo.getUndoPresentationName)
else
setEnabled(false)
putValue(Action::NAME, "Undo")
end
end
end
class RedoAction < AbstractAction
def initialize(undoer)
super("Redo")
@undoer = undoer
setEnabled(false)
end
def actionPerformed(e)
@undoer.redo
end
def updateRedoState(undo)
if undo.canRedo
setEnabled(true)
putValue(Action::NAME, undo.getRedoPresentationName)
else
setEnabled(false)
putValue(Action::NAME, "Redo")
end
end
end
class SequentialEdit < CompoundEdit
def initialize
@super
@editType = nil
end
attr_accessor :editType
def isInProgress
return false
end
end
class EndUndoSequenceAction < TextAction
def initialize(undoer, textAction)
super(textAction.getValue(Action::NAME))
@undoer = undoer
@textAction = textAction
end
def actionPerformed(actionEvent)
editor = actionEvent.getSource
before = editor.getCaretPosition
@textAction.actionPerformed(actionEvent)
after = editor.getCaretPosition
before != after and @undoer.lastEditEnd
end
end
end