PageRenderTime 14ms CodeModel.GetById 1ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/jEdit/tags/jedit-4-0-pre3/org/gjt/sp/jedit/buffer/UndoManager.java

#
Java | 379 lines | 273 code | 47 blank | 59 comment | 63 complexity | 575fc29236447883a2fc163bfb03c279 MD5 | raw file
  1/*
  2 * UndoManager.java - Buffer undo manager
  3 * :tabSize=8:indentSize=8:noTabs=false:
  4 * :folding=explicit:collapseFolds=1:
  5 *
  6 * Copyright (C) 2001 Slava Pestov
  7 *
  8 * This program is free software; you can redistribute it and/or
  9 * modify it under the terms of the GNU General Public License
 10 * as published by the Free Software Foundation; either version 2
 11 * of the License, or any later version.
 12 *
 13 * This program is distributed in the hope that it will be useful,
 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 16 * GNU General Public License for more details.
 17 *
 18 * You should have received a copy of the GNU General Public License
 19 * along with this program; if not, write to the Free Software
 20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 21 */
 22
 23package org.gjt.sp.jedit.buffer;
 24
 25//{{{ Imports
 26import java.util.Vector;
 27import org.gjt.sp.jedit.textarea.JEditTextArea;
 28import org.gjt.sp.jedit.Buffer;
 29import org.gjt.sp.util.Log;
 30//}}}
 31
 32public class UndoManager
 33{
 34	//{{{ UndoManager constructor
 35	public UndoManager(Buffer buffer)
 36	{
 37		this.buffer = buffer;
 38		undos = new Vector(100);
 39	} //}}}
 40
 41	//{{{ setLimit() method
 42	public void setLimit(int limit)
 43	{
 44		this.limit = limit;
 45	} //}}}
 46
 47	//{{{ clear() method
 48	public void clear()
 49	{
 50		undos.removeAllElements();
 51		undoPos = undoCount = 0;
 52	} //}}}
 53
 54	//{{{ undo() method
 55	public boolean undo(JEditTextArea textArea)
 56	{
 57		if(insideCompoundEdit())
 58			throw new InternalError("Unbalanced begin/endCompoundEdit()");
 59
 60		if(undoPos == 0)
 61			return false;
 62		else
 63		{
 64			Edit edit = (Edit)undos.elementAt(--undoPos);
 65			int caret = edit.undo();
 66			if(caret != -1)
 67				textArea.setCaretPosition(caret);
 68			return true;
 69		}
 70	} //}}}
 71
 72	//{{{ redo() method
 73	public boolean redo(JEditTextArea textArea)
 74	{
 75		if(insideCompoundEdit())
 76			throw new InternalError("Unbalanced begin/endCompoundEdit()");
 77
 78		if(undoPos == undoCount)
 79			return false;
 80		else
 81		{
 82			Edit edit = (Edit)undos.elementAt(undoPos++);
 83			int caret = edit.redo();
 84			if(caret != -1)
 85				textArea.setCaretPosition(caret);
 86			return true;
 87		}
 88	} //}}}
 89
 90	//{{{ beginCompoundEdit() method
 91	public void beginCompoundEdit()
 92	{
 93		if(compoundEditCount == 0)
 94			compoundEdit = new CompoundEdit();
 95
 96		compoundEditCount++;
 97	} //}}}
 98
 99	//{{{ endCompoundEdit() method
100	public void endCompoundEdit()
101	{
102		if(compoundEditCount == 1)
103		{
104			if(compoundEdit.getSize() != 0)
105				addEdit(compoundEdit);
106			compoundEdit = null;
107		}
108		else if(compoundEditCount == 0)
109		{
110			Log.log(Log.WARNING,this,new Exception("Unbalanced begin/endCompoundEdit()"));
111			return;
112		}
113
114		compoundEditCount--;
115	} //}}}
116
117	//{{{ insideCompoundEdit() method
118	public boolean insideCompoundEdit()
119	{
120		return compoundEditCount != 0;
121	} //}}}
122
123	//{{{ contentInserted() method
124	public void contentInserted(int offset, int length, String text, boolean clearDirty)
125	{
126		Edit toMerge = null;
127		if(compoundEdit != null)
128		{
129			int size = compoundEdit.getSize();
130			if(size != 0)
131				toMerge = (Edit)compoundEdit.undos.elementAt(size - 1);
132		}
133		else
134		{
135			if(undoPos != 0)
136				toMerge = (Edit)undos.elementAt(undoPos - 1);
137		}
138
139		if(!clearDirty && toMerge instanceof Insert)
140		{
141			Insert ins = (Insert)toMerge;
142			if(ins.offset == offset)
143			{
144				ins.str = text.concat(ins.str);
145				ins.length += length;
146				return;
147			}
148			else if(ins.offset + ins.length == offset)
149			{
150				ins.str = ins.str.concat(text);
151				ins.length += length;
152				return;
153			}
154		}
155
156		Insert ins = new Insert(offset,length,text,clearDirty);
157		if(clearDirty)
158		{
159			if(clearDirtyEdit != null)
160				clearDirtyEdit.clearDirty = false;
161			clearDirtyEdit = ins;
162		}
163
164		if(compoundEdit != null)
165			compoundEdit.addEdit(ins);
166		else
167			addEdit(ins);
168	} //}}}
169
170	//{{{ contentRemoved() method
171	public void contentRemoved(int offset, int length, String text, boolean clearDirty)
172	{
173		Edit toMerge = null;
174		if(compoundEdit != null)
175		{
176			int size = compoundEdit.getSize();
177			if(size != 0)
178				toMerge = (Edit)compoundEdit.undos.elementAt(size - 1);
179		}
180		else
181		{
182			if(undoPos != 0)
183				toMerge = (Edit)undos.elementAt(undoPos - 1);
184		}
185
186		if(!clearDirty && toMerge instanceof Remove)
187		{
188			Remove rem = (Remove)toMerge;
189			if(rem.offset == offset)
190			{
191				rem.str = rem.str.concat(text);
192				rem.length += length;
193				return;
194			}
195			else if(rem.offset + rem.length == offset)
196			{
197				rem.str = text.concat(rem.str);
198				rem.length += length;
199				return;
200			}
201		}
202
203		Remove rem = new Remove(offset,length,text,clearDirty);
204		if(clearDirty)
205		{
206			if(clearDirtyEdit != null)
207				clearDirtyEdit.clearDirty = false;
208			clearDirtyEdit = rem;
209		}
210
211		if(compoundEdit != null)
212			compoundEdit.addEdit(rem);
213		else
214			addEdit(rem);
215	} //}}}
216
217	//{{{ bufferSaved() method
218	public void bufferSaved()
219	{
220		if(clearDirtyEdit != null)
221		{
222			clearDirtyEdit.clearDirty = false;
223			clearDirtyEdit = null;
224		}
225	} //}}}
226
227	//{{{ Private members
228
229	//{{{ Instance variables
230	private Buffer buffer;
231	private Vector undos;
232	private int limit;
233	private int undoPos;
234	private int undoCount;
235	private int compoundEditCount;
236	private CompoundEdit compoundEdit;
237	private Edit clearDirtyEdit;
238	//}}}
239
240	//{{{ addEdit() method
241	private void addEdit(Edit edit)
242	{
243		undos.insertElementAt(edit,undoPos++);
244
245		if(undos.size() > limit)
246		{
247			undos.removeElementAt(0);
248			undoPos--;
249		}
250
251		undoCount = undoPos;
252	} //}}}
253
254	//}}}
255
256	//{{{ Inner classes
257
258	//{{{ Edit interface
259	abstract class Edit
260	{
261		//{{{ undo() method
262		abstract int undo();
263		//}}}
264
265		//{{{ redo() method
266		abstract int redo();
267		//}}}
268
269		boolean clearDirty;
270	} //}}}
271
272	//{{{ Insert class
273	class Insert extends Edit
274	{
275		//{{{ Insert constructor
276		Insert(int offset, int length, String str, boolean clearDirty)
277		{
278			this.offset = offset;
279			this.length = length;
280			this.str = str;
281			this.clearDirty = clearDirty;
282		} //}}}
283
284		//{{{ undo() method
285		int undo()
286		{
287			buffer.remove(offset,length);
288			if(clearDirty)
289				buffer.setDirty(false);
290			return offset;
291		} //}}}
292
293		//{{{ redo() method
294		int redo()
295		{
296			buffer.insert(offset,str);
297			return offset + length;
298		} //}}}
299
300		int offset;
301		int length;
302		String str;
303	} //}}}
304
305	//{{{ Remove class
306	class Remove extends Edit
307	{
308		//{{{ Remove constructor
309		Remove(int offset, int length, String str, boolean clearDirty)
310		{
311			this.offset = offset;
312			this.length = length;
313			this.str = str;
314			this.clearDirty = clearDirty;
315		} //}}}
316
317		//{{{ undo() method
318		int undo()
319		{
320			buffer.insert(offset,str);
321			if(clearDirty)
322				buffer.setDirty(false);
323			return offset + length;
324		} //}}}
325
326		//{{{ redo() method
327		int redo()
328		{
329			buffer.remove(offset,length);
330			return offset;
331		} //}}}
332
333		int offset;
334		int length;
335		String str;
336	} //}}}
337
338	//{{{ CompoundEdit class
339	class CompoundEdit extends Edit
340	{
341		//{{{ undo() method
342		public int undo()
343		{
344			int retVal = -1;
345			for(int i = undos.size() - 1; i >= 0; i--)
346			{
347				retVal = ((Edit)undos.elementAt(i)).undo();
348			}
349			return retVal;
350		} //}}}
351
352		//{{{ redo() method
353		public int redo()
354		{
355			int retVal = -1;
356			for(int i = 0; i < undos.size(); i++)
357			{
358				retVal = ((Edit)undos.elementAt(i)).redo();
359			}
360			return retVal;
361		} //}}}
362
363		//{{{ addEdit() method
364		public void addEdit(Edit edit)
365		{
366			undos.addElement(edit);
367		} //}}}
368
369		//{{{ getSize() method
370		public int getSize()
371		{
372			return undos.size();
373		} //}}}
374
375		Vector undos = new Vector();
376	} //}}}
377
378	//}}}
379}