KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > text > DefaultDocumentAdapter


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jface.text;
12
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import java.util.List JavaDoc;
17
18 import org.eclipse.swt.SWT;
19 import org.eclipse.swt.custom.TextChangeListener;
20 import org.eclipse.swt.custom.TextChangedEvent;
21 import org.eclipse.swt.custom.TextChangingEvent;
22
23 import org.eclipse.core.runtime.Assert;
24
25
26 /**
27  * Default implementation of {@link org.eclipse.jface.text.IDocumentAdapter}.
28  * <p>
29  * <strong>Note:</strong> This adapter does not work if the widget auto-wraps the text.
30  * </p>
31  */

32 class DefaultDocumentAdapter implements IDocumentAdapter, IDocumentListener, IDocumentAdapterExtension {
33
34     /** The adapted document. */
35     private IDocument fDocument;
36     /** The document clone for the non-forwarding case. */
37     private IDocument fDocumentClone;
38     /** The original content */
39     private String JavaDoc fOriginalContent;
40     /** The original line delimiters */
41     private String JavaDoc[] fOriginalLineDelimiters;
42     /** The registered text change listeners */
43     private List JavaDoc fTextChangeListeners= new ArrayList JavaDoc(1);
44     /**
45      * The remembered document event
46      * @since 2.0
47      */

48     private DocumentEvent fEvent;
49     /** The line delimiter */
50     private String JavaDoc fLineDelimiter= null;
51     /**
52      * Indicates whether this adapter is forwarding document changes
53      * @since 2.0
54      */

55     private boolean fIsForwarding= true;
56     /**
57      * Length of document at receipt of <code>documentAboutToBeChanged</code>
58      * @since 2.1
59      */

60     private int fRememberedLengthOfDocument;
61     /**
62      * Length of first document line at receipt of <code>documentAboutToBeChanged</code>
63      * @since 2.1
64      */

65     private int fRememberedLengthOfFirstLine;
66     /**
67      * The data of the event at receipt of <code>documentAboutToBeChanged</code>
68      * @since 2.1
69      */

70     private DocumentEvent fOriginalEvent= new DocumentEvent();
71
72
73     /**
74      * Creates a new document adapter which is initially not connected to
75      * any document.
76      */

77     public DefaultDocumentAdapter() {
78     }
79
80     /**
81      * Sets the given document as the document to be adapted.
82      *
83      * @param document the document to be adapted or <code>null</code> if there is no document
84      */

85     public void setDocument(IDocument document) {
86
87         if (fDocument != null)
88             fDocument.removePrenotifiedDocumentListener(this);
89
90         fDocument= document;
91         fLineDelimiter= null;
92
93         if (!fIsForwarding) {
94             fDocumentClone= null;
95             if (fDocument != null) {
96                 fOriginalContent= fDocument.get();
97                 fOriginalLineDelimiters= fDocument.getLegalLineDelimiters();
98             } else {
99                 fOriginalContent= null;
100                 fOriginalLineDelimiters= null;
101             }
102         }
103
104         if (fDocument != null)
105             fDocument.addPrenotifiedDocumentListener(this);
106     }
107
108     /*
109      * @see StyledTextContent#addTextChangeListener(TextChangeListener)
110      */

111     public void addTextChangeListener(TextChangeListener listener) {
112         Assert.isNotNull(listener);
113         if (! fTextChangeListeners.contains(listener))
114             fTextChangeListeners.add(listener);
115     }
116
117     /*
118      * @see StyledTextContent#removeTextChangeListener(TextChangeListener)
119      */

120     public void removeTextChangeListener(TextChangeListener listener) {
121         Assert.isNotNull(listener);
122         fTextChangeListeners.remove(listener);
123     }
124
125     /**
126      * Tries to repair the line information.
127      *
128      * @param document the document
129      * @see IRepairableDocument#repairLineInformation()
130      * @since 3.0
131      */

132     private void repairLineInformation(IDocument document) {
133         if (document instanceof IRepairableDocument) {
134             IRepairableDocument repairable= (IRepairableDocument) document;
135             repairable.repairLineInformation();
136         }
137     }
138
139     /**
140      * Returns the line for the given line number.
141      *
142      * @param document the document
143      * @param line the line number
144      * @return the content of the line of the given number in the given document
145      * @throws BadLocationException if the line number is invalid for the adapted document
146      * @since 3.0
147      */

148     private String JavaDoc doGetLine(IDocument document, int line) throws BadLocationException {
149         IRegion r= document.getLineInformation(line);
150         return document.get(r.getOffset(), r.getLength());
151     }
152
153     private IDocument getDocumentForRead() {
154         if (!fIsForwarding) {
155             if (fDocumentClone == null) {
156                 String JavaDoc content= fOriginalContent == null ? "" : fOriginalContent; //$NON-NLS-1$
157
String JavaDoc[] delims= fOriginalLineDelimiters == null ? DefaultLineTracker.DELIMITERS : fOriginalLineDelimiters;
158                 fDocumentClone= new DocumentClone(content, delims);
159             }
160             return fDocumentClone;
161         }
162
163         return fDocument;
164     }
165
166     /*
167      * @see StyledTextContent#getLine(int)
168      */

169     public String JavaDoc getLine(int line) {
170
171         IDocument document= getDocumentForRead();
172         try {
173             return doGetLine(document, line);
174         } catch (BadLocationException x) {
175             repairLineInformation(document);
176             try {
177                 return doGetLine(document, line);
178             } catch (BadLocationException x2) {
179             }
180         }
181
182         SWT.error(SWT.ERROR_INVALID_ARGUMENT);
183         return null;
184     }
185
186     /*
187      * @see StyledTextContent#getLineAtOffset(int)
188      */

189     public int getLineAtOffset(int offset) {
190         IDocument document= getDocumentForRead();
191         try {
192             return document.getLineOfOffset(offset);
193         } catch (BadLocationException x) {
194             repairLineInformation(document);
195             try {
196                 return document.getLineOfOffset(offset);
197             } catch (BadLocationException x2) {
198             }
199         }
200
201         SWT.error(SWT.ERROR_INVALID_ARGUMENT);
202         return -1;
203     }
204
205     /*
206      * @see StyledTextContent#getLineCount()
207      */

208     public int getLineCount() {
209         return getDocumentForRead().getNumberOfLines();
210     }
211
212     /*
213      * @see StyledTextContent#getOffsetAtLine(int)
214      */

215     public int getOffsetAtLine(int line) {
216         IDocument document= getDocumentForRead();
217         try {
218             return document.getLineOffset(line);
219         } catch (BadLocationException x) {
220             repairLineInformation(document);
221             try {
222                 return document.getLineOffset(line);
223             } catch (BadLocationException x2) {
224             }
225         }
226
227         SWT.error(SWT.ERROR_INVALID_ARGUMENT);
228         return -1;
229     }
230
231     /*
232      * @see StyledTextContent#getTextRange(int, int)
233      */

234     public String JavaDoc getTextRange(int offset, int length) {
235         try {
236             return getDocumentForRead().get(offset, length);
237         } catch (BadLocationException x) {
238             SWT.error(SWT.ERROR_INVALID_ARGUMENT);
239             return null;
240         }
241     }
242
243     /*
244      * @see StyledTextContent#replaceTextRange(int, int, String)
245      */

246     public void replaceTextRange(int pos, int length, String JavaDoc text) {
247         try {
248             fDocument.replace(pos, length, text);
249         } catch (BadLocationException x) {
250             SWT.error(SWT.ERROR_INVALID_ARGUMENT);
251         }
252     }
253
254     /*
255      * @see StyledTextContent#setText(String)
256      */

257     public void setText(String JavaDoc text) {
258         fDocument.set(text);
259     }
260
261     /*
262      * @see StyledTextContent#getCharCount()
263      */

264     public int getCharCount() {
265         return getDocumentForRead().getLength();
266     }
267
268     /*
269      * @see StyledTextContent#getLineDelimiter()
270      */

271     public String JavaDoc getLineDelimiter() {
272         if (fLineDelimiter == null)
273             fLineDelimiter= TextUtilities.getDefaultLineDelimiter(fDocument);
274         return fLineDelimiter;
275     }
276
277     /*
278      * @see IDocumentListener#documentChanged(DocumentEvent)
279      */

280     public void documentChanged(DocumentEvent event) {
281         // check whether the given event is the one which was remembered
282
if (fEvent == null || event != fEvent)
283             return;
284
285         if (isPatchedEvent(event) || (event.getOffset() == 0 && event.getLength() == fRememberedLengthOfDocument)) {
286             fLineDelimiter= null;
287             fireTextSet();
288         } else {
289             if (event.getOffset() < fRememberedLengthOfFirstLine)
290                 fLineDelimiter= null;
291             fireTextChanged();
292         }
293     }
294
295     /*
296      * @see IDocumentListener#documentAboutToBeChanged(DocumentEvent)
297      */

298     public void documentAboutToBeChanged(DocumentEvent event) {
299
300         fRememberedLengthOfDocument= fDocument.getLength();
301         try {
302             fRememberedLengthOfFirstLine= fDocument.getLineLength(0);
303         } catch (BadLocationException e) {
304             fRememberedLengthOfFirstLine= -1;
305         }
306
307         fEvent= event;
308         rememberEventData(fEvent);
309         fireTextChanging();
310     }
311
312     /**
313      * Checks whether this event has been changed between <code>documentAboutToBeChanged</code> and
314      * <code>documentChanged</code>.
315      *
316      * @param event the event to be checked
317      * @return <code>true</code> if the event has been changed, <code>false</code> otherwise
318      */

319     private boolean isPatchedEvent(DocumentEvent event) {
320         return fOriginalEvent.fOffset != event.fOffset || fOriginalEvent.fLength != event.fLength || fOriginalEvent.fText != event.fText;
321     }
322
323     /**
324      * Makes a copy of the given event and remembers it.
325      *
326      * @param event the event to be copied
327      */

328     private void rememberEventData(DocumentEvent event) {
329         fOriginalEvent.fOffset= event.fOffset;
330         fOriginalEvent.fLength= event.fLength;
331         fOriginalEvent.fText= event.fText;
332     }
333
334     /**
335      * Sends a text changed event to all registered listeners.
336      */

337     private void fireTextChanged() {
338
339         if (!fIsForwarding)
340             return;
341
342         TextChangedEvent event= new TextChangedEvent(this);
343
344         if (fTextChangeListeners != null && fTextChangeListeners.size() > 0) {
345             Iterator JavaDoc e= new ArrayList JavaDoc(fTextChangeListeners).iterator();
346             while (e.hasNext())
347                 ((TextChangeListener) e.next()).textChanged(event);
348         }
349     }
350
351     /**
352      * Sends a text set event to all registered listeners.
353      */

354     private void fireTextSet() {
355
356         if (!fIsForwarding)
357             return;
358
359         TextChangedEvent event = new TextChangedEvent(this);
360
361         if (fTextChangeListeners != null && fTextChangeListeners.size() > 0) {
362             Iterator JavaDoc e= new ArrayList JavaDoc(fTextChangeListeners).iterator();
363             while (e.hasNext())
364                 ((TextChangeListener) e.next()).textSet(event);
365         }
366     }
367
368     /**
369      * Sends the text changing event to all registered listeners.
370      */

371     private void fireTextChanging() {
372
373         if (!fIsForwarding)
374             return;
375
376         try {
377             IDocument document= fEvent.getDocument();
378             if (document == null)
379                 return;
380
381             TextChangingEvent event= new TextChangingEvent(this);
382             event.start= fEvent.fOffset;
383             event.replaceCharCount= fEvent.fLength;
384             event.replaceLineCount= document.getNumberOfLines(fEvent.fOffset, fEvent.fLength) - 1;
385             event.newText= fEvent.fText;
386             event.newCharCount= (fEvent.fText == null ? 0 : fEvent.fText.length());
387             event.newLineCount= (fEvent.fText == null ? 0 : document.computeNumberOfLines(fEvent.fText));
388
389             if (fTextChangeListeners != null && fTextChangeListeners.size() > 0) {
390                 Iterator JavaDoc e= new ArrayList JavaDoc(fTextChangeListeners).iterator();
391                 while (e.hasNext())
392                      ((TextChangeListener) e.next()).textChanging(event);
393             }
394
395         } catch (BadLocationException e) {
396         }
397     }
398
399     /*
400      * @see IDocumentAdapterExtension#resumeForwardingDocumentChanges()
401      * @since 2.0
402      */

403     public void resumeForwardingDocumentChanges() {
404         fIsForwarding= true;
405         fDocumentClone= null;
406         fOriginalContent= null;
407         fOriginalLineDelimiters= null;
408         fireTextSet();
409     }
410
411     /*
412      * @see IDocumentAdapterExtension#stopForwardingDocumentChanges()
413      * @since 2.0
414      */

415     public void stopForwardingDocumentChanges() {
416         fDocumentClone= null;
417         fOriginalContent= fDocument.get();
418         fOriginalLineDelimiters= fDocument.getLegalLineDelimiters();
419         fIsForwarding= false;
420     }
421 }
422
Popular Tags