View Javadoc

1   /*
2    * SyntaxDocument.java - Document that can be tokenized
3    * Copyright (C) 1999 Slava Pestov
4    *
5    * You may use and modify this package for any purpose. Redistribution is
6    * permitted, in both source and binary form, provided that this notice
7    * remains intact in all source distributions of this package.
8    */
9   
10  package org.syntax.jedit;
11  
12  import javax.swing.event.DocumentEvent;
13  import javax.swing.text.BadLocationException;
14  import javax.swing.text.Element;
15  import javax.swing.text.PlainDocument;
16  import javax.swing.text.Segment;
17  import javax.swing.undo.UndoableEdit;
18  
19  import org.syntax.jedit.tokenmarker.TokenMarker;
20  
21  import com.eviware.soapui.SoapUI;
22  
23  /***
24   * A document implementation that can be tokenized by the syntax highlighting
25   * system.
26   *
27   * @author Slava Pestov
28   * @version $Id$
29   */
30  public class SyntaxDocument extends PlainDocument
31  {
32  	/***
33  	 * Returns the token marker that is to be used to split lines
34  	 * of this document up into tokens. May return null if this
35  	 * document is not to be colorized.
36  	 */
37  	public TokenMarker getTokenMarker()
38  	{
39  		return tokenMarker;
40  	}
41  
42  	/***
43  	 * Sets the token marker that is to be used to split lines of
44  	 * this document up into tokens. May throw an exception if
45  	 * this is not supported for this type of document.
46  	 * @param tm The new token marker
47  	 */
48  	public void setTokenMarker(TokenMarker tm)
49  	{
50  		tokenMarker = tm;
51  		if(tm == null)
52  			return;
53  		tokenMarker.insertLines(0,getDefaultRootElement()
54  			.getElementCount());
55  		tokenizeLines();
56  	}
57  
58  	/***
59  	 * Reparses the document, by passing all lines to the token
60  	 * marker. This should be called after the document is first
61  	 * loaded.
62  	 */
63  	public void tokenizeLines()
64  	{
65  		tokenizeLines(0,getDefaultRootElement().getElementCount());
66  	}
67  
68  	/***
69  	 * Reparses the document, by passing the specified lines to the
70  	 * token marker. This should be called after a large quantity of
71  	 * text is first inserted.
72  	 * @param start The first line to parse
73  	 * @param len The number of lines, after the first one to parse
74  	 */
75  	public void tokenizeLines(int start, int len)
76  	{
77  		if(tokenMarker == null || !tokenMarker.supportsMultilineTokens())
78  			return;
79  
80  		Segment lineSegment = new Segment();
81  		Element map = getDefaultRootElement();
82  
83  		len += start;
84  
85  		try
86  		{
87  			for(int i = start; i < len; i++)
88  			{
89  				Element lineElement = map.getElement(i);
90  				int lineStart = lineElement.getStartOffset();
91  				getText(lineStart,lineElement.getEndOffset()
92  					- lineStart - 1,lineSegment);
93  				tokenMarker.markTokens(lineSegment,i);
94  			}
95  		}
96  		catch(BadLocationException bl)
97  		{
98  			SoapUI.logError( bl );
99  		}
100 	}
101 
102 	/***
103 	 * Starts a compound edit that can be undone in one operation.
104 	 * Subclasses that implement undo should override this method;
105 	 * this class has no undo functionality so this method is
106 	 * empty.
107 	 */
108 	public void beginCompoundEdit() {}
109 
110 	/***
111 	 * Ends a compound edit that can be undone in one operation.
112 	 * Subclasses that implement undo should override this method;
113 	 * this class has no undo functionality so this method is
114 	 * empty.
115 	 */
116 	public void endCompoundEdit() {
117 	}
118 
119 	/***
120 	 * Adds an undoable edit to this document's undo list. The edit
121 	 * should be ignored if something is currently being undone.
122 	 * @param edit The undoable edit
123 	 *
124 	 * @since jEdit 2.2pre1
125 	 */
126 	public void addUndoableEdit(UndoableEdit edit) {}
127 
128 	// protected members
129 	protected TokenMarker tokenMarker;
130 
131 	/***
132 	 * We overwrite this method to update the token marker
133 	 * state immediately so that any event listeners get a
134 	 * consistent token marker.
135 	 */
136 	protected void fireInsertUpdate(DocumentEvent evt)
137 	{
138 		if(tokenMarker != null)
139 		{
140 			DocumentEvent.ElementChange ch = evt.getChange(
141 				getDefaultRootElement());
142 			if(ch != null)
143 			{
144 				tokenMarker.insertLines(ch.getIndex() + 1,
145 					ch.getChildrenAdded().length -
146 					ch.getChildrenRemoved().length);
147 			}
148 		}
149 
150 		super.fireInsertUpdate(evt);
151 	}
152 	
153 	/***
154 	 * We overwrite this method to update the token marker
155 	 * state immediately so that any event listeners get a
156 	 * consistent token marker.
157 	 */
158 	protected void fireRemoveUpdate(DocumentEvent evt)
159 	{
160 		if(tokenMarker != null)
161 		{
162 			DocumentEvent.ElementChange ch = evt.getChange(
163 				getDefaultRootElement());
164 			if(ch != null)
165 			{
166 				tokenMarker.deleteLines(ch.getIndex() + 1,
167 					ch.getChildrenRemoved().length -
168 					ch.getChildrenAdded().length);
169 			}
170 		}
171 
172 		super.fireRemoveUpdate(evt);
173 	}
174 }