001: /*
002: * Sun Public License Notice
003: *
004: * The contents of this file are subject to the Sun Public License
005: * Version 1.0 (the "License"). You may not use this file except in
006: * compliance with the License. A copy of the License is available at
007: * http://www.sun.com/
008: *
009: * The Original Code is NetBeans. The Initial Developer of the Original
010: * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun
011: * Microsystems, Inc. All Rights Reserved.
012: */
013:
014: package org.netbeans.editor;
015:
016: import java.lang.ref.WeakReference;
017:
018: /**
019: * Various marks are located here
020: *
021: * @author Miloslav Metelka
022: * @version 1.00
023: */
024:
025: public class MarkFactory {
026:
027: private MarkFactory() {
028: // no instantiation
029: }
030:
031: /**
032: * Syntax mark holds info about scan state of syntax scanner. This helps in
033: * redraws because reparsing after insert/delete is done only from nearest
034: * left syntax mark. Moreover rescaning is done only until there are marks
035: * with different scan state. As soon as mark is found with same parsing
036: * info as rescanning scanner has, parsing ends.
037: */
038: public static class SyntaxMark extends Mark {
039:
040: /** Syntax mark state info */
041: private Syntax.StateInfo stateInfo;
042:
043: private TokenItem tokenItem;
044:
045: /** Get state info of this mark */
046: public Syntax.StateInfo getStateInfo() {
047: return stateInfo;
048: }
049:
050: public void updateStateInfo(Syntax syntax) {
051: if (stateInfo == null) {
052: stateInfo = syntax.createStateInfo();
053: }
054: syntax.storeState(stateInfo);
055: }
056:
057: void setStateInfo(Syntax.StateInfo stateInfo) {
058: this .stateInfo = stateInfo;
059: }
060:
061: public TokenItem getTokenItem() {
062: return tokenItem;
063: }
064:
065: void setTokenItem(TokenItem tokenItem) {
066: this .tokenItem = tokenItem;
067: }
068:
069: /** When removal occurs */
070: protected void removeUpdateAction(int pos, int len) {
071: try {
072: remove();
073: } catch (InvalidMarkException e) {
074: // shouldn't happen
075: }
076: }
077:
078: }
079:
080: /** Mark that can have its position updated by where it's located */
081: public static class ContextMark extends Mark {
082:
083: /** Stay at all times at the begining of the line */
084: boolean stayBOL;
085:
086: public ContextMark(boolean stayBOL) {
087: this (false, stayBOL);
088: }
089:
090: public ContextMark(boolean insertAfter, boolean stayBOL) {
091: super (insertAfter);
092: this .stayBOL = stayBOL;
093: }
094:
095: }
096:
097: /**
098: * Activation mark for particular layer. When layer is not active its
099: * updateContext() method is not called.
100: */
101: public static class DrawMark extends ContextMark {
102:
103: /** Activation flag means either activate layer or deactivate it */
104: protected boolean activateLayer;
105:
106: /** Reference to draw layer this mark belogns to */
107: String layerName;
108:
109: /**
110: * Reference to extended UI if this draw mark is info-specific or null
111: * if it's document-wide.
112: */
113: WeakReference editorUIRef;
114:
115: public DrawMark(String layerName, EditorUI editorUI) {
116: super (false);
117: this .layerName = layerName;
118: setEditorUI(editorUI);
119: }
120:
121: public boolean isDocumentMark() {
122: return (editorUIRef == null);
123: }
124:
125: public EditorUI getEditorUI() {
126: if (editorUIRef != null) {
127: return (EditorUI) editorUIRef.get();
128: }
129: return null;
130: }
131:
132: public void setEditorUI(EditorUI editorUI) {
133: this .editorUIRef = (editorUI != null) ? new WeakReference(
134: editorUI) : null;
135: }
136:
137: public boolean isValidUI() {
138: return !(editorUIRef != null && editorUIRef.get() == null);
139: }
140:
141: public void setActivateLayer(boolean activateLayer) {
142: this .activateLayer = activateLayer;
143: }
144:
145: public boolean getActivateLayer() {
146: return activateLayer;
147: }
148:
149: public boolean removeInvalid() {
150: if (!isValidUI()) {
151: try {
152: this .remove();
153: } catch (InvalidMarkException e) {
154: }
155: return true; // invalid and removed
156: }
157: return false; // valid
158: }
159:
160: public String toString() {
161: try {
162: return "pos=" + getOffset() + ", line=" + getLine(); // NOI18N
163: } catch (InvalidMarkException e) {
164: return "mark not valid"; // NOI18N
165: }
166: }
167:
168: }
169:
170: /** Support for draw marks chained in double linked list */
171: public static class ChainDrawMark extends DrawMark {
172:
173: /** Next mark in chain */
174: protected ChainDrawMark next;
175:
176: /** Previous mark in chain */
177: protected ChainDrawMark prev;
178:
179: public ChainDrawMark(String layerName, EditorUI editorUI) {
180: super (layerName, editorUI);
181: }
182:
183: public final ChainDrawMark getNext() {
184: return next;
185: }
186:
187: public final void setNext(ChainDrawMark mark) {
188: next = mark;
189: }
190:
191: /** Set next mark in chain */
192: public void setNextChain(ChainDrawMark mark) {
193: this .next = mark;
194: if (mark != null) {
195: mark.prev = this ;
196: }
197: }
198:
199: public final ChainDrawMark getPrev() {
200: return prev;
201: }
202:
203: public final void setPrev(ChainDrawMark mark) {
204: prev = mark;
205: }
206:
207: /** Set previous mark in chain */
208: public void setPrevChain(ChainDrawMark mark) {
209: this .prev = mark;
210: if (mark != null) {
211: mark.next = this ;
212: }
213: }
214:
215: /**
216: * Insert mark before this one in chain
217: *
218: * @return inserted mark
219: */
220: public ChainDrawMark insertChain(ChainDrawMark mark) {
221: ChainDrawMark this Prev = this .prev;
222: mark.prev = this Prev;
223: mark.next = this ;
224: if (this Prev != null) {
225: this Prev.next = mark;
226: }
227: this .prev = mark;
228: return mark;
229: }
230:
231: /**
232: * Remove this mark from the chain
233: *
234: * @return next chain member or null for end of chain
235: */
236: public ChainDrawMark removeChain() {
237: ChainDrawMark this Next = this .next;
238: ChainDrawMark this Prev = this .prev;
239: if (this Prev != null) { // not the first
240: this Prev.next = this Next;
241: this .prev = null;
242: }
243: if (this Next != null) { // not the last
244: this Next.prev = this Prev;
245: this .next = null;
246: }
247: try {
248: this .remove(); // remove the mark from DocMarks
249: } catch (InvalidMarkException e) {
250: // already removed
251: }
252: return this Next;
253: }
254:
255: public String toStringChain() {
256: return toString()
257: + (next != null ? "\n" + next.toStringChain() : ""); // NOI18N
258: }
259:
260: public String toString() {
261: return super .toString()
262: + ", " // NOI18N
263: + ((prev != null) ? ((next != null) ? "chain member" // NOI18N
264: : "last member")
265: : ((next != null) ? "first member" // NOI18N
266: : "standalone member")); // NOI18N
267: }
268:
269: }
270:
271: /**
272: * Special mark for caret. Its signature is used in Analyzer not to move
273: * this mark when initial read is performed.
274: */
275: static class CaretMark extends DrawMark {
276:
277: CaretMark() {
278: super (DrawLayerFactory.CARET_LAYER_NAME, null);
279: }
280:
281: }
282:
283: /** Mark for creating line elements */
284: static class LineMark extends Mark {
285:
286: /** Weak reference to line element */
287: BaseDocument.LineElement lineElemRef; // non-weak ref due to #17351
288:
289: public LineMark() {
290: super (true);
291: }
292:
293: }
294:
295: }
|