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