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 of this
34  	 * document up into tokens. May return null if this document is not to be
35  	 * 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 this document
44  	 * up into tokens. May throw an exception if this is not supported for this
45  	 * type of document.
46  	 * 
47  	 * @param tm
48  	 *           The new token marker
49  	 */
50  	public void setTokenMarker( TokenMarker tm )
51  	{
52  		tokenMarker = tm;
53  		if( tm == null )
54  			return;
55  		tokenMarker.insertLines( 0, getDefaultRootElement().getElementCount() );
56  		tokenizeLines();
57  	}
58  
59  	/***
60  	 * Reparses the document, by passing all lines to the token marker. This
61  	 * should be called after the document is first 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 token marker.
70  	 * This should be called after a large quantity of text is first inserted.
71  	 * 
72  	 * @param start
73  	 *           The first line to parse
74  	 * @param len
75  	 *           The number of lines, after the first one to parse
76  	 */
77  	public void tokenizeLines( int start, int len )
78  	{
79  		if( tokenMarker == null || !tokenMarker.supportsMultilineTokens() )
80  			return;
81  
82  		Segment lineSegment = new Segment();
83  		Element map = getDefaultRootElement();
84  
85  		len += start;
86  
87  		try
88  		{
89  			for( int i = start; i < len; i++ )
90  			{
91  				Element lineElement = map.getElement( i );
92  				int lineStart = lineElement.getStartOffset();
93  				getText( lineStart, lineElement.getEndOffset() - lineStart - 1, lineSegment );
94  				tokenMarker.markTokens( lineSegment, i );
95  			}
96  		}
97  		catch( BadLocationException bl )
98  		{
99  			SoapUI.logError( bl );
100 		}
101 	}
102 
103 	/***
104 	 * Starts a compound edit that can be undone in one operation. Subclasses
105 	 * that implement undo should override this method; this class has no undo
106 	 * functionality so this method is empty.
107 	 */
108 	public void beginCompoundEdit()
109 	{
110 	}
111 
112 	/***
113 	 * Ends a compound edit that can be undone in one operation. Subclasses that
114 	 * implement undo should override this method; this class has no undo
115 	 * functionality so this method is empty.
116 	 */
117 	public void endCompoundEdit()
118 	{
119 	}
120 
121 	/***
122 	 * Adds an undoable edit to this document's undo list. The edit should be
123 	 * ignored if something is currently being undone.
124 	 * 
125 	 * @param edit
126 	 *           The undoable edit
127 	 * 
128 	 * @since jEdit 2.2pre1
129 	 */
130 	public void addUndoableEdit( UndoableEdit edit )
131 	{
132 	}
133 
134 	// protected members
135 	protected TokenMarker tokenMarker;
136 
137 	/***
138 	 * We overwrite this method to update the token marker state immediately so
139 	 * that any event listeners get a consistent token marker.
140 	 */
141 	protected void fireInsertUpdate( DocumentEvent evt )
142 	{
143 		if( tokenMarker != null )
144 		{
145 			DocumentEvent.ElementChange ch = evt.getChange( getDefaultRootElement() );
146 			if( ch != null )
147 			{
148 				tokenMarker.insertLines( ch.getIndex() + 1, ch.getChildrenAdded().length - ch.getChildrenRemoved().length );
149 			}
150 		}
151 
152 		super.fireInsertUpdate( evt );
153 	}
154 
155 	/***
156 	 * We overwrite this method to update the token marker state immediately so
157 	 * that any event listeners get a consistent token marker.
158 	 */
159 	protected void fireRemoveUpdate( DocumentEvent evt )
160 	{
161 		if( tokenMarker != null )
162 		{
163 			DocumentEvent.ElementChange ch = evt.getChange( getDefaultRootElement() );
164 			if( ch != null )
165 			{
166 				tokenMarker.deleteLines( ch.getIndex() + 1, ch.getChildrenRemoved().length - ch.getChildrenAdded().length );
167 			}
168 		}
169 
170 		super.fireRemoveUpdate( evt );
171 	}
172 }