KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > gjt > sp > jedit > textarea > BufferHandler


1 /*
2  * BufferHandler.java
3  * :tabSize=8:indentSize=8:noTabs=false:
4  * :folding=explicit:collapseFolds=1:
5  *
6  * Copyright (C) 2001, 2005 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
23 package org.gjt.sp.jedit.textarea;
24
25 import java.util.Iterator JavaDoc;
26 import org.gjt.sp.jedit.buffer.*;
27 import org.gjt.sp.jedit.Debug;
28
29 /**
30  * Note that in this class we take great care to defer complicated
31  * calculations to the end of the current transaction if the buffer
32  * informs us a compound edit is in progress
33  * (<code>isTransactionInProgress()</code>).
34  *
35  * This greatly speeds up replace all for example, by only doing certain
36  * things once, particularly in <code>moveCaretPosition()</code>.
37  *
38  * Try doing a replace all in a large file, for example. It is very slow
39  * in 3.2, faster in 4.0 (where the transaction optimization was
40  * introduced) and faster still in 4.1 (where it was further improved).
41  *
42  * There is still work to do; see TODO.txt.
43  */

44 class BufferHandler implements BufferListener
45 {
46     private DisplayManager displayManager;
47     private TextArea textArea;
48     private JEditBuffer buffer;
49
50     boolean delayedUpdate;
51     boolean delayedMultilineUpdate;
52     int delayedUpdateStart;
53     int delayedUpdateEnd;
54
55     //{{{ BufferChangeHandler constructor
56
BufferHandler(DisplayManager displayManager,
57         TextArea textArea,
58         JEditBuffer buffer)
59     {
60         this.displayManager = displayManager;
61         this.textArea = textArea;
62         this.buffer = buffer;
63     } //}}}
64

65     //{{{ bufferLoaded() method
66
public void bufferLoaded(JEditBuffer buffer)
67     {
68         displayManager.bufferLoaded();
69     } //}}}
70

71     //{{{ foldHandlerChanged() method
72
public void foldHandlerChanged(JEditBuffer buffer)
73     {
74         displayManager.foldHandlerChanged();
75     } //}}}
76

77     //{{{ foldLevelChanged() method
78
public void foldLevelChanged(JEditBuffer buffer, int start, int end)
79     {
80         //System.err.println("foldLevelChanged " + (start-1) + " to " + textArea.getLastPhysicalLine() + "," + end);
81

82         if(textArea.getDisplayManager() == displayManager
83             && end != 0 && !buffer.isLoading())
84         {
85             textArea.invalidateLineRange(start - 1,
86                 textArea.getLastPhysicalLine());
87         }
88     } //}}}
89

90     //{{{ contentInserted() method
91
public void contentInserted(JEditBuffer buffer, int startLine,
92         int offset, int numLines, int length)
93     {
94         if(buffer.isLoading())
95             return;
96
97         displayManager.screenLineMgr.contentInserted(startLine,numLines);
98
99         int endLine = startLine + numLines;
100
101         if(numLines != 0)
102             delayedMultilineUpdate = true;
103
104         displayManager.folds.contentInserted(startLine,numLines);
105
106         FirstLine firstLine = displayManager.firstLine;
107         ScrollLineCount scrollLineCount = displayManager.scrollLineCount;
108
109         if(textArea.getDisplayManager() == displayManager)
110         {
111             if(numLines != 0)
112             {
113                 firstLine.contentInserted(startLine,numLines);
114                 scrollLineCount.contentInserted(startLine,numLines);
115             }
116
117             if(delayedUpdateEnd >= startLine)
118                 delayedUpdateEnd += numLines;
119             delayUpdate(startLine,endLine);
120
121             //{{{ resize selections if necessary
122
Iterator JavaDoc iter = textArea.getSelectionIterator();
123             while(iter.hasNext())
124             {
125                 Selection s = (Selection)iter.next();
126
127                 if(s.contentInserted(buffer,startLine,offset,
128                     numLines,length))
129                 {
130                     delayUpdate(s.startLine,s.endLine);
131                 }
132             } //}}}
133

134             int caret = textArea.getCaretPosition();
135             if(caret >= offset)
136             {
137                 int scrollMode = (textArea.caretAutoScroll()
138                     ? TextArea.ELECTRIC_SCROLL
139                     : TextArea.NO_SCROLL);
140                 textArea.moveCaretPosition(
141                     caret + length,scrollMode);
142             }
143             else
144             {
145                 int scrollMode = (textArea.caretAutoScroll()
146                     ? TextArea.NORMAL_SCROLL
147                     : TextArea.NO_SCROLL);
148                 textArea.moveCaretPosition(
149                     caret,scrollMode);
150             }
151         }
152         else
153         {
154             firstLine.callReset = true;
155             scrollLineCount.callReset = true;
156         }
157     } //}}}
158

159     //{{{ preContentRemoved() method
160
public void preContentRemoved(JEditBuffer buffer, int startLine,
161         int offset, int numLines, int length)
162     {
163         if(buffer.isLoading())
164             return;
165
166         FirstLine firstLine = displayManager.firstLine;
167         ScrollLineCount scrollLineCount = displayManager.scrollLineCount;
168
169         if(textArea.getDisplayManager() == displayManager)
170         {
171             if(numLines != 0)
172             {
173                 firstLine.preContentRemoved(startLine,numLines);
174                 scrollLineCount.preContentRemoved(startLine,numLines);
175             }
176
177             if(delayedUpdateEnd >= startLine)
178                 delayedUpdateEnd -= numLines;
179             delayUpdate(startLine,startLine);
180         }
181         else
182         {
183             firstLine.callReset = true;
184             scrollLineCount.callReset = true;
185         }
186
187         displayManager.screenLineMgr.contentRemoved(startLine,numLines);
188
189         if(numLines == 0)
190             return;
191
192         delayedMultilineUpdate = true;
193
194         if(displayManager.folds.preContentRemoved(startLine,numLines))
195         {
196             displayManager.folds.reset(buffer.getLineCount());
197             firstLine.callReset = true;
198             scrollLineCount.callReset = true;
199         }
200
201         if(firstLine.physicalLine
202             > displayManager.getLastVisibleLine()
203             || firstLine.physicalLine
204             < displayManager.getFirstVisibleLine())
205         {
206             // will be handled later.
207
// see comments at the end of
208
// transactionComplete().
209
}
210         // very subtle... if we leave this for
211
// ensurePhysicalLineIsVisible(), an
212
// extra line will be added to the
213
// scroll line count.
214
else if(!displayManager.isLineVisible(
215             firstLine.physicalLine))
216         {
217             firstLine.physicalLine =
218                 displayManager.getNextVisibleLine(
219                 firstLine.physicalLine);
220         }
221     } //}}}
222

223     //{{{ contentRemoved() method
224
public void contentRemoved(JEditBuffer buffer, int startLine,
225         int start, int numLines, int length)
226     {
227         if(buffer.isLoading())
228             return;
229
230         if(textArea.getDisplayManager() == displayManager)
231         {
232             //{{{ resize selections if necessary
233
Iterator JavaDoc iter = textArea.getSelectionIterator();
234             while(iter.hasNext())
235             {
236                 Selection s = (Selection)iter.next();
237
238                 if(s.contentRemoved(buffer,startLine,
239                     start,numLines,length))
240                 {
241                     delayUpdate(s.startLine,s.endLine);
242                     if(s.start == s.end)
243                         iter.remove();
244                 }
245             } //}}}
246

247             int caret = textArea.getCaretPosition();
248
249             if(caret >= start + length)
250             {
251                 int scrollMode = (textArea.caretAutoScroll()
252                     ? TextArea.ELECTRIC_SCROLL
253                     : TextArea.NO_SCROLL);
254                 textArea.moveCaretPosition(
255                     caret - length,
256                     scrollMode);
257             }
258             else if(caret >= start)
259             {
260                 int scrollMode = (textArea.caretAutoScroll()
261                     ? TextArea.ELECTRIC_SCROLL
262                     : TextArea.NO_SCROLL);
263                 textArea.moveCaretPosition(
264                     start,scrollMode);
265             }
266             else
267             {
268                 int scrollMode = (textArea.caretAutoScroll()
269                     ? TextArea.NORMAL_SCROLL
270                     : TextArea.NO_SCROLL);
271                 textArea.moveCaretPosition(caret,scrollMode);
272             }
273         }
274     }
275     //}}}
276

277     //{{{ transactionComplete() method
278
public void transactionComplete(JEditBuffer buffer)
279     {
280         if(textArea.getDisplayManager() != displayManager)
281         {
282             delayedUpdate = false;
283             return;
284         }
285
286         if(delayedUpdate)
287             doDelayedUpdate();
288
289         textArea._finishCaretUpdate();
290
291         delayedUpdate = false;
292
293         //{{{ Debug code
294
if(Debug.SCROLL_VERIFY)
295         {
296             int scrollLineCount = 0;
297             int line = delayedUpdateStart;
298             if(!displayManager.isLineVisible(line))
299                 line = displayManager.getNextVisibleLine(line);
300             System.err.println(delayedUpdateStart + ":" + delayedUpdateEnd + ":" + textArea.getLineCount());
301             while(line != -1 && line <= delayedUpdateEnd)
302             {
303                 scrollLineCount += displayManager.getScreenLineCount(line);
304                 line = displayManager.getNextVisibleLine(line);
305             }
306
307             if(scrollLineCount != displayManager.getScrollLineCount())
308             {
309                 throw new InternalError JavaDoc(scrollLineCount
310                     + " != "
311                     + displayManager.getScrollLineCount());
312             }
313         } //}}}
314
} //}}}
315

316     //{{{ doDelayedUpdate() method
317
private void doDelayedUpdate()
318     {
319         // must update screen line counts before we call
320
// notifyScreenLineChanges() since that calls
321
// updateScrollBar() which needs valid info
322
int line = delayedUpdateStart;
323         if(!displayManager.isLineVisible(line))
324             line = displayManager.getNextVisibleLine(line);
325         while(line != -1 && line <= delayedUpdateEnd)
326         {
327             displayManager.updateScreenLineCount(line);
328             line = displayManager.getNextVisibleLine(line);
329         }
330
331         // must be before the below call
332
// so that the chunk cache is not
333
// updated with an invisible first
334
// line (see above)
335
displayManager.notifyScreenLineChanges();
336
337         if(delayedMultilineUpdate)
338         {
339             textArea.invalidateScreenLineRange(
340                 textArea.chunkCache
341                 .getScreenLineOfOffset(
342                 delayedUpdateStart,0),
343                 textArea.getVisibleLines());
344             delayedMultilineUpdate = false;
345         }
346         else
347         {
348             textArea.invalidateLineRange(
349                 delayedUpdateStart,
350                 delayedUpdateEnd);
351         }
352
353         // update visible lines
354
int visibleLines = textArea.getVisibleLines();
355         if(visibleLines != 0)
356         {
357             textArea.chunkCache.getLineInfo(
358                 visibleLines - 1);
359         }
360
361         // force the fold levels to be
362
// updated.
363

364         // when painting the last line of
365
// a buffer, Buffer.isFoldStart()
366
// doesn't call getFoldLevel(),
367
// hence the foldLevelChanged()
368
// event might not be sent for the
369
// previous line.
370

371         buffer.getFoldLevel(delayedUpdateEnd);
372     } //}}}
373

374     //{{{ delayUpdate() method
375
private void delayUpdate(int startLine, int endLine)
376     {
377         textArea.chunkCache.invalidateChunksFromPhys(startLine);
378         textArea.repaintMgr.setFastScroll(false);
379
380         if(!delayedUpdate)
381         {
382             delayedUpdateStart = startLine;
383             delayedUpdateEnd = endLine;
384             delayedUpdate = true;
385         }
386         else
387         {
388             delayedUpdateStart = Math.min(
389                 delayedUpdateStart,
390                 startLine);
391             delayedUpdateEnd = Math.max(
392                 delayedUpdateEnd,
393                 endLine);
394         }
395     } //}}}
396
}
397
Popular Tags