PageRenderTime 60ms CodeModel.GetById 16ms app.highlight 38ms RepoModel.GetById 1ms app.codeStats 0ms

/jEdit/tags/jedit-4-1-pre5/org/gjt/sp/jedit/buffer/UndoManager.java

#
Java | 383 lines | 277 code | 48 blank | 58 comment | 61 complexity | 274782df1c14eae0040edadca08c1f35 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, 2002 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.ArrayList;
 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 ArrayList(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.clear();
 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.get(--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.get(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 == 0)
103		{
104			Log.log(Log.WARNING,this,new Exception("Unbalanced begin/endCompoundEdit()"));
105			return;
106		}
107		else if(compoundEditCount == 1)
108		{
109			switch(compoundEdit.undos.size())
110			{
111			case 0:
112				/* nothing done between begin/end calls */;
113				break;
114			case 1:
115				addEdit((Edit)compoundEdit.undos.get(0));
116				break;
117			default:
118				addEdit(compoundEdit);
119			}
120
121			compoundEdit = null;
122		}
123
124		compoundEditCount--;
125	} //}}}
126
127	//{{{ insideCompoundEdit() method
128	public boolean insideCompoundEdit()
129	{
130		return compoundEditCount != 0;
131	} //}}}
132
133	//{{{ contentInserted() method
134	public void contentInserted(int offset, int length, String text, boolean clearDirty)
135	{
136		Edit toMerge = getLastEdit();
137
138		if(!clearDirty && toMerge instanceof Insert)
139		{
140			Insert ins = (Insert)toMerge;
141			if(ins.offset == offset)
142			{
143				ins.str = text.concat(ins.str);
144				ins.length += length;
145				return;
146			}
147			else if(ins.offset + ins.length == offset)
148			{
149				ins.str = ins.str.concat(text);
150				ins.length += length;
151				return;
152			}
153		}
154
155		Insert ins = new Insert(offset,length,text,clearDirty);
156		if(clearDirty)
157		{
158			if(clearDirtyEdit != null)
159				clearDirtyEdit.clearDirty = false;
160			clearDirtyEdit = ins;
161		}
162
163		if(compoundEdit != null)
164			compoundEdit.undos.add(ins);
165		else
166			addEdit(ins);
167	} //}}}
168
169	//{{{ contentRemoved() method
170	public void contentRemoved(int offset, int length, String text, boolean clearDirty)
171	{
172		Edit toMerge = getLastEdit();
173
174		if(!clearDirty && toMerge instanceof Remove)
175		{
176			Remove rem = (Remove)toMerge;
177			if(rem.offset == offset)
178			{
179				rem.str = rem.str.concat(text);
180				rem.length += length;
181				return;
182			}
183			else if(offset + length == rem.offset)
184			{
185				rem.str = text.concat(rem.str);
186				rem.length += length;
187				rem.offset = offset;
188				return;
189			}
190		}
191
192		Remove rem = new Remove(offset,length,text,clearDirty);
193		if(clearDirty)
194		{
195			if(clearDirtyEdit != null)
196				clearDirtyEdit.clearDirty = false;
197			clearDirtyEdit = rem;
198		}
199
200		if(compoundEdit != null)
201			compoundEdit.undos.add(rem);
202		else
203			addEdit(rem);
204	} //}}}
205
206	//{{{ bufferSaved() method
207	public void bufferSaved()
208	{
209		if(clearDirtyEdit != null)
210		{
211			clearDirtyEdit.clearDirty = false;
212			clearDirtyEdit = null;
213		}
214	} //}}}
215
216	//{{{ Private members
217
218	//{{{ Instance variables
219	private Buffer buffer;
220	private ArrayList undos;
221	private int limit;
222	private int undoPos;
223	private int undoCount;
224	private int compoundEditCount;
225	private CompoundEdit compoundEdit;
226	private Edit clearDirtyEdit;
227	//}}}
228
229	//{{{ addEdit() method
230	private void addEdit(Edit edit)
231	{
232		undos.add(undoPos++,edit);
233
234		if(undos.size() > limit)
235		{
236			undos.remove(0);
237			undoPos--;
238		}
239
240		undoCount = undoPos;
241	} //}}}
242
243	//{{{ getLastEdit() method
244	private Edit getLastEdit()
245	{
246		if(compoundEdit != null)
247		{
248			int size = compoundEdit.undos.size();
249			if(size != 0)
250				return (Edit)compoundEdit.undos.get(size - 1);
251			else
252				return null;
253		}
254		else if(undoCount != 0 && undoPos != 0)
255		{
256			Edit e = (Edit)undos.get(undoPos - 1);
257			if(e instanceof CompoundEdit)
258			{
259				CompoundEdit c = (CompoundEdit)e;
260				return (Edit)c.undos.get(c.undos.size() - 1);
261			}
262		}
263
264		if(undoPos != 0)
265			return (Edit)undos.get(undoPos - 1);
266		else
267			return null;
268	} //}}}
269
270	//}}}
271
272	//{{{ Inner classes
273
274	//{{{ Edit interface
275	abstract class Edit
276	{
277		//{{{ undo() method
278		abstract int undo();
279		//}}}
280
281		//{{{ redo() method
282		abstract int redo();
283		//}}}
284
285		boolean clearDirty;
286	} //}}}
287
288	//{{{ Insert class
289	class Insert extends Edit
290	{
291		//{{{ Insert constructor
292		Insert(int offset, int length, String str, boolean clearDirty)
293		{
294			this.offset = offset;
295			this.length = length;
296			this.str = str;
297			this.clearDirty = clearDirty;
298		} //}}}
299
300		//{{{ undo() method
301		int undo()
302		{
303			buffer.remove(offset,length);
304			if(clearDirty)
305				buffer.setDirty(false);
306			return offset;
307		} //}}}
308
309		//{{{ redo() method
310		int redo()
311		{
312			buffer.insert(offset,str);
313			return offset + length;
314		} //}}}
315
316		int offset;
317		int length;
318		String str;
319	} //}}}
320
321	//{{{ Remove class
322	class Remove extends Edit
323	{
324		//{{{ Remove constructor
325		Remove(int offset, int length, String str, boolean clearDirty)
326		{
327			this.offset = offset;
328			this.length = length;
329			this.str = str;
330			this.clearDirty = clearDirty;
331		} //}}}
332
333		//{{{ undo() method
334		int undo()
335		{
336			buffer.insert(offset,str);
337			if(clearDirty)
338				buffer.setDirty(false);
339			return offset + length;
340		} //}}}
341
342		//{{{ redo() method
343		int redo()
344		{
345			buffer.remove(offset,length);
346			return offset;
347		} //}}}
348
349		int offset;
350		int length;
351		String str;
352	} //}}}
353
354	//{{{ CompoundEdit class
355	class CompoundEdit extends Edit
356	{
357		//{{{ undo() method
358		public int undo()
359		{
360			int retVal = -1;
361			for(int i = undos.size() - 1; i >= 0; i--)
362			{
363				retVal = ((Edit)undos.get(i)).undo();
364			}
365			return retVal;
366		} //}}}
367
368		//{{{ redo() method
369		public int redo()
370		{
371			int retVal = -1;
372			for(int i = 0; i < undos.size(); i++)
373			{
374				retVal = ((Edit)undos.get(i)).redo();
375			}
376			return retVal;
377		} //}}}
378
379		ArrayList undos = new ArrayList();
380	} //}}}
381
382	//}}}
383}