001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.openide.text;
042:
043: import org.openide.ServiceType;
044: import org.openide.util.HelpCtx;
045: import org.openide.util.Lookup;
046:
047: import java.io.Writer;
048:
049: import java.util.Collections;
050: import java.util.Enumeration;
051: import java.util.HashMap;
052: import java.util.Map;
053:
054: import javax.swing.text.*;
055:
056: /** Indentation engine for formating text in documents.
057: * Provides mapping between MIME types and engines, so anybody
058: * can find appropriate type of engine for type of document.
059: *
060: * @author Jaroslav Tulach
061: */
062: public abstract class IndentEngine extends ServiceType {
063: static final long serialVersionUID = -8548906260608507035L;
064:
065: /** hashtable mapping MIME type to engine */
066: private static Map<String, IndentEngine> map = new HashMap<String, IndentEngine>(
067: 7);
068: private static IndentEngine INSTANCE = null;
069:
070: public HelpCtx getHelpCtx() {
071: return HelpCtx.DEFAULT_HELP;
072: }
073:
074: /** Indents the current line. Should not effect any other
075: * lines.
076: * @param doc the document to work on
077: * @param offset the offset of a character on the line
078: * @return new offset of the original character
079: */
080: public abstract int indentLine(Document doc, int offset);
081:
082: /** Inserts new line at given position and indents the new line with
083: * spaces.
084: *
085: * @param doc the document to work on
086: * @param offset the offset of a character on the line
087: * @return new offset to place cursor to
088: */
089: public abstract int indentNewLine(Document doc, int offset);
090:
091: /** Creates writer that formats text that is inserted into it.
092: * The writer should not modify the document but use the
093: * provided writer to write to. Usually the underlaying writer
094: * will modify the document itself and optionally it can remember
095: * the current position in document. That is why the newly created
096: * writer should do no buffering.
097: * <P>
098: * The provided document and offset are only informational,
099: * should not be modified but only used to find correct indentation
100: * strategy.
101: *
102: * @param doc document
103: * @param offset position to begin inserts at
104: * @param writer writer to write to
105: * @return new writer that will format written text and pass it
106: * into the writer
107: */
108: public abstract Writer createWriter(Document doc, int offset,
109: Writer writer);
110:
111: /** Allow subclasses to decide whether they are suitable
112: * for the given mime-type or not.
113: * @param mime mime-type string
114: * @return true if this engine is suitable for the given mime-type.
115: */
116: protected boolean acceptMimeType(String mime) {
117: return false;
118: }
119:
120: /**
121: * @deprecated IndentEngine now is a ServiceType
122: */
123: @Deprecated
124: public synchronized static void register(String mime,
125: IndentEngine eng) {
126: map.put(mime, eng);
127: }
128:
129: /** Returns enumeration of all registered indentation engines.
130: * @return enumeration of IndentEngine
131: */
132: public static Enumeration<? extends IndentEngine> indentEngines() {
133: return Collections.enumeration(Lookup.getDefault().lookupAll(
134: IndentEngine.class));
135: }
136:
137: /** Finds engine associated with given mime type.
138: * If no engine is associated returns default one.
139: */
140: public synchronized static IndentEngine find(String mime) {
141: Enumeration<? extends IndentEngine> en = indentEngines();
142:
143: while (en.hasMoreElements()) {
144: IndentEngine eng = en.nextElement();
145:
146: if (eng.acceptMimeType(mime)) {
147: return eng;
148: }
149: }
150:
151: IndentEngine eng = map.get(mime);
152:
153: if (eng != null) {
154: return eng;
155: }
156:
157: return getDefault();
158: }
159:
160: /** Finds engine associated with given document.
161: * If no engine is associated returns default one.
162: */
163: public static IndentEngine find(Document doc) {
164: Object o = doc.getProperty("indentEngine"); // NOI18N
165:
166: if (o instanceof IndentEngine) {
167: return (IndentEngine) o;
168: } else {
169: o = doc.getProperty("mimeType"); // NOI18N
170:
171: String s = (o instanceof String) ? (String) o
172: : "text/plain"; // NOI18N
173:
174: return find(s);
175: }
176: }
177:
178: /** Returns a simple indentation engine that does no formatting. */
179: public static synchronized IndentEngine getDefault() {
180: if (INSTANCE == null) {
181: INSTANCE = new Default();
182: }
183:
184: return INSTANCE;
185: }
186:
187: /** Default indentation engine.
188: */
189: private static final class Default extends IndentEngine {
190: private static final long serialVersionUID = 4493180326470838469L;
191:
192: Default() {
193: }
194:
195: public int indentLine(Document doc, int offset) {
196: return offset;
197: }
198:
199: public int indentNewLine(Document doc, int offset) {
200: try {
201: doc.insertString(offset, "\n", null); // NOI18N
202: } catch (BadLocationException ex) {
203: // ignore
204: }
205:
206: return offset + 1;
207: }
208:
209: public Writer createWriter(Document doc, int offset,
210: Writer writer) {
211: return writer;
212: }
213:
214: protected boolean acceptMimeType(String mime) {
215: return true;
216: }
217:
218: public HelpCtx getHelpCtx() {
219: return new HelpCtx(Default.class);
220: }
221: }
222: }
|