4 # GtkSourceBuffer is a subclass of GtkTextBuffer which provides extra
5 # features. We'll use it if it's available, or GtkTextBuffer if not.
8 _parentClass
= gtksourceview
.SourceBuffer
11 _parentClass
= g
.TextBuffer
12 have_sourceview
= False
18 # As operations are performed, they are added to 'in_progress'.
19 # When complete, the whole group is added to undo_buffer.
21 class Buffer(_parentClass
):
22 "A buffer that deals with undo/redo."
28 _parentClass
.__init
__(self
)
29 self
.set_max_undo_levels(1000)
31 _parentClass
.__init
__(self
, None)
33 self
.in_progress
= None
35 self
.redo_buffer
= [] # Will be None during undo or redo
38 self
.lm
= gtksourceview
.SourceLanguagesManager()
39 self
.set_data('languages-manager', self
.lm
)
41 def set_type(self
, mime_type
):
42 """Set up syntax highlighting, if available"""
44 if not have_sourceview
: return
45 if not mime_type
: return
47 language
= self
.lm
.get_language_from_mime_type(mime_type
.media
+ '/' + mime_type
.subtype
)
49 self
.set_highlight(True)
50 self
.set_language(language
)
51 self
.language
= language
.get_name()
53 #print 'No language found for mime type "%s"' % mime_type
54 self
.set_highlight(False)
56 def start_undo_history(self
):
57 if have_sourceview
: return
59 self
.action_nest_level
+= 1
60 if self
.action_nest_level
== 1:
61 assert self
.in_progress
is None
64 self
.connect('begin-user-action', begin
)
65 def end_action(buffer):
66 self
.action_nest_level
-= 1
67 assert self
.action_nest_level
>= 0
68 if self
.action_nest_level
== 0:
69 assert self
.in_progress
is not None
71 self
.undo_buffer
.append(self
.in_progress
)
72 self
.in_progress
= None
73 self
.connect('end-user-action', end_action
)
74 self
.connect('delete-range', self
.delete_range
)
75 self
.connect('insert-text', self
.insert_text
)
77 def delete_range(self
, buffer, start
, end
):
78 self
.in_progress
.append((INSERT
,
80 buffer.get_slice(start
, end
, True)))
84 def insert_text(self
, buffer, where
, text
, len):
85 text
= text
[:len] # PyGtk bug?
86 start
= where
.get_offset()
87 self
.in_progress
.append((DELETE
,
88 start
, start
+ len, text
))
93 g
.TextBuffer(None).insert_at_cursor('hello')
95 # Old version of pygtk
96 def insert(self
, iter, text
):
97 g
.TextBuffer
.insert(self
, iter, text
, -1)
98 def insert_at_cursor(self
, text
):
99 g
.TextBuffer
.insert_at_cursor(self
, text
, -1)
101 def do_action(self
, op
):
103 start
= self
.get_iter_at_offset(op
[1])
104 end
= self
.get_iter_at_offset(op
[2])
105 self
.delete(start
, end
)
106 elif op
[0] == INSERT
:
107 start
= self
.get_iter_at_offset(op
[1])
108 self
.insert(start
, op
[2])
110 rox
.alert('Unknown entry in undo buffer!\n' + `op`
)
112 def undo(self
, hist
= None):
115 _parentClass
.undo(self
)
118 if hist
is None: hist
= self
.undo_buffer
122 return # Nothing to undo/redo
124 assert not self
.in_progress
126 # List of actions to perform
129 old_redo
, self
.redo_buffer
= self
.redo_buffer
, None
132 self
.begin_user_action()
135 self
.do_action(action
)
137 self
.redo_buffer
= old_redo
138 if hist
is self
.undo_buffer
:
139 self
.redo_buffer
.append(self
.in_progress
)
141 self
.undo_buffer
.append(self
.in_progress
)
142 self
.in_progress
= []
144 self
.end_user_action()
148 _parentClass
.redo(self
)
150 self
.undo(hist
= self
.redo_buffer
)
153 def begin_not_undoable_action(self
):
155 _parentClass
.begin_not_undoable_action(self
)
157 def end_not_undoable_action(self
):
159 _parentClass
.end_not_undoable_action(self
)