use gtksourceview 2.x
[rox-edit.git] / buffer.py
blobcd5af783d14b930e049277f5f85526cad0ff78d8
1 import rox
2 from rox import g
4 # GtkSourceBuffer is a subclass of GtkTextBuffer which provides extra
5 # features. We'll use it if it's available, or GtkTextBuffer if not.
6 try:
7 import gtksourceview2 as gtksourceview
8 _parentClass = gtksourceview.Buffer
9 have_sourceview = True
10 except:
11 _parentClass = g.TextBuffer
12 have_sourceview = False
15 DELETE = 1
16 INSERT = 2
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."
24 action_nest_level = 0
26 def __init__(self):
27 if have_sourceview:
28 _parentClass.__init__(self)
29 self.set_max_undo_levels(1000)
30 else:
31 _parentClass.__init__(self, None)
33 self.in_progress = None
34 self.undo_buffer = []
35 self.redo_buffer = [] # Will be None during undo or redo
37 if have_sourceview:
38 self.lm = gtksourceview.LanguageManager()
39 self.set_data('languages-manager', self.lm)
41 def set_type(self, mime_type):
42 """Set up syntax highlighting, if available"""
43 self.language = None
44 if not have_sourceview: return
45 if not mime_type: return
47 language = self.lm.guess_language(content_type=mime_type.media + '/' + mime_type.subtype)
48 if language:
49 self.set_highlight_syntax(True)
50 self.set_language(language)
51 self.language = language.get_name()
52 else:
53 #print 'No language found for mime type "%s"' % mime_type
54 self.set_highlight_syntax(False)
56 def start_undo_history(self):
57 if have_sourceview: return
58 def begin(buffer):
59 self.action_nest_level += 1
60 if self.action_nest_level == 1:
61 assert self.in_progress is None
62 self.in_progress = []
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
70 if self.in_progress:
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,
79 start.get_offset(),
80 buffer.get_slice(start, end, True)))
81 if self.redo_buffer:
82 self.redo_buffer = []
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))
89 if self.redo_buffer:
90 self.redo_buffer = []
92 try:
93 g.TextBuffer(None).insert_at_cursor('hello')
94 except:
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):
102 if op[0] == DELETE:
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])
109 else:
110 rox.alert('Unknown entry in undo buffer!\n' + `op`)
112 def undo(self, hist = None):
113 if have_sourceview:
114 if self.can_undo():
115 _parentClass.undo(self)
116 return
118 if hist is None: hist = self.undo_buffer
120 if not hist:
121 g.gdk.beep()
122 return # Nothing to undo/redo
124 assert not self.in_progress
126 # List of actions to perform
127 group = hist.pop()
129 old_redo, self.redo_buffer = self.redo_buffer, None
131 try:
132 self.begin_user_action()
133 group.reverse()
134 for action in group:
135 self.do_action(action)
136 finally:
137 self.redo_buffer = old_redo
138 if hist is self.undo_buffer:
139 self.redo_buffer.append(self.in_progress)
140 else:
141 self.undo_buffer.append(self.in_progress)
142 self.in_progress = []
144 self.end_user_action()
146 def redo(self):
147 if have_sourceview:
148 _parentClass.redo(self)
149 else:
150 self.undo(hist = self.redo_buffer)
153 def begin_not_undoable_action(self):
154 if have_sourceview:
155 _parentClass.begin_not_undoable_action(self)
157 def end_not_undoable_action(self):
158 if have_sourceview:
159 _parentClass.end_not_undoable_action(self)