001: package net.xoetrope.builder.editor.syntaxhighlight;
002:
003: /*
004: * SyntaxDocument.java - Document that can be tokenized
005: * Copyright (C) 1999 Slava Pestov
006: *
007: * You may use and modify this package for any purpose. Redistribution is
008: * permitted, in both source and binary form, provided that this notice
009: * remains intact in all source distributions of this package.
010: */
011:
012: import javax.swing.event.DocumentEvent;
013: import javax.swing.text.BadLocationException;
014: import javax.swing.text.Element;
015: import javax.swing.text.PlainDocument;
016: import javax.swing.text.Segment;
017: import javax.swing.undo.UndoableEdit;
018:
019: /**
020: * A document implementation that can be tokenized by the syntax highlighting
021: * system.
022: *
023: * @author Slava Pestov
024: * @version $Id: SyntaxDocument.java,v 1.22 2005/01/05 17:20:49 luano Exp $
025: */
026: public class SyntaxDocument extends PlainDocument {
027: /**
028: * Returns the token marker that is to be used to split lines
029: * of this document up into tokens. May return null if this
030: * document is not to be colorized.
031: */
032: public TokenMarker getTokenMarker() {
033: return tokenMarker;
034: }
035:
036: /**
037: * Sets the token marker that is to be used to split lines of
038: * this document up into tokens. May throw an exception if
039: * this is not supported for this type of document.
040: * @param tm The new token marker
041: */
042: public void setTokenMarker(TokenMarker tm) {
043: tokenMarker = tm;
044: if (tm == null)
045: return;
046: tokenMarker.insertLines(0, getDefaultRootElement()
047: .getElementCount());
048: tokenizeLines();
049: }
050:
051: /**
052: * Reparses the document, by passing all lines to the token
053: * marker. This should be called after the document is first
054: * loaded.
055: */
056: public void tokenizeLines() {
057: tokenizeLines(0, getDefaultRootElement().getElementCount());
058: }
059:
060: /**
061: * Reparses the document, by passing the specified lines to the
062: * token marker. This should be called after a large quantity of
063: * text is first inserted.
064: * @param start The first line to parse
065: * @param len The number of lines, after the first one to parse
066: */
067: public void tokenizeLines(int start, int len) {
068: if (tokenMarker == null
069: || !tokenMarker.supportsMultilineTokens())
070: return;
071:
072: Segment lineSegment = new Segment();
073: Element map = getDefaultRootElement();
074:
075: len += start;
076:
077: try {
078: for (int i = start; i < len; i++) {
079: Element lineElement = map.getElement(i);
080: int lineStart = lineElement.getStartOffset();
081: getText(lineStart, lineElement.getEndOffset()
082: - lineStart - 1, lineSegment);
083: tokenMarker.markTokens(lineSegment, i);
084: }
085: } catch (BadLocationException bl) {
086: bl.printStackTrace();
087: }
088: }
089:
090: /**
091: * Starts a compound edit that can be undone in one operation.
092: * Subclasses that implement undo should override this method;
093: * this class has no undo functionality so this method is
094: * empty.
095: */
096: public void beginCompoundEdit() {
097: }
098:
099: /**
100: * Ends a compound edit that can be undone in one operation.
101: * Subclasses that implement undo should override this method;
102: * this class has no undo functionality so this method is
103: * empty.
104: */
105: public void endCompoundEdit() {
106: }
107:
108: /**
109: * Adds an undoable edit to this document's undo list. The edit
110: * should be ignored if something is currently being undone.
111: * @param edit The undoable edit
112: *
113: * @since jEdit 2.2pre1
114: */
115: public void addUndoableEdit(UndoableEdit edit) {
116: }
117:
118: // protected members
119: protected TokenMarker tokenMarker;
120:
121: /**
122: * We overwrite this method to update the token marker
123: * state immediately so that any event listeners get a
124: * consistent token marker.
125: */
126: protected void fireInsertUpdate(DocumentEvent evt) {
127: if (tokenMarker != null) {
128: DocumentEvent.ElementChange ch = evt
129: .getChange(getDefaultRootElement());
130: if (ch != null) {
131: tokenMarker.insertLines(ch.getIndex() + 1, ch
132: .getChildrenAdded().length
133: - ch.getChildrenRemoved().length);
134: }
135: }
136:
137: super .fireInsertUpdate(evt);
138: }
139:
140: /**
141: * We overwrite this method to update the token marker
142: * state immediately so that any event listeners get a
143: * consistent token marker.
144: */
145: protected void fireRemoveUpdate(DocumentEvent evt) {
146: if (tokenMarker != null) {
147: DocumentEvent.ElementChange ch = evt
148: .getChange(getDefaultRootElement());
149: if (ch != null) {
150: tokenMarker.deleteLines(ch.getIndex() + 1, ch
151: .getChildrenRemoved().length
152: - ch.getChildrenAdded().length);
153: }
154: }
155:
156: super.fireRemoveUpdate(evt);
157: }
158: }
|