KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > retouche > editor > GsfFormatter


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.modules.retouche.editor;
20
21 import java.io.IOException JavaDoc;
22 import java.io.Writer JavaDoc;
23 import javax.swing.text.BadLocationException JavaDoc;
24 import javax.swing.text.Document JavaDoc;
25 import javax.swing.text.JTextComponent JavaDoc;
26 import org.netbeans.api.gsf.FormattingPreferences;
27 import org.netbeans.api.gsf.FormattingPreferences;
28 import org.netbeans.editor.BaseDocument;
29 import org.netbeans.editor.SettingsChangeEvent;
30 import org.netbeans.editor.SettingsDefaults;
31 import org.netbeans.editor.SettingsNames;
32 import org.netbeans.editor.SettingsUtil;
33 import org.netbeans.editor.Syntax;
34 import org.netbeans.editor.TokenItem;
35 import org.netbeans.editor.TokenItem;
36 import org.netbeans.editor.Utilities;
37 import org.netbeans.editor.ext.AbstractFormatLayer;
38 import org.netbeans.editor.ext.ExtFormatter;
39 import org.netbeans.editor.ext.FormatSupport;
40 import org.netbeans.editor.ext.FormatTokenPosition;
41 import org.netbeans.editor.ext.FormatWriter;
42 import org.netbeans.modules.gsf.GsfEditorKitFactory;
43 import org.netbeans.modules.gsf.Language;
44 import org.openide.filesystems.FileObject;
45 import org.openide.loaders.DataObject;
46
47
48 /**
49  * Formatter used to reformat AND reindent code.
50  * Originally based on GsfFormatter by Miloslav Metelka.
51  *
52  * @author Tor Norbye
53  */

54 public class GsfFormatter extends ExtFormatter {
55     private Language language;
56     private Document JavaDoc doc;
57     private boolean inited;
58     private boolean customSpacesPerTab;
59     private int spacesPerTab;
60
61
62     // Temporarily disabled
63
// public class StripEndWhitespaceLayer extends AbstractFormatLayer {
64
//
65
// public StripEndWhitespaceLayer() {
66
// super("java-strip-whitespace-at-line-end"); // NOI18N
67
// }
68
//
69
// protected FormatSupport createFormatSupport(FormatWriter fw) {
70
// return new GsfFormatSupport(fw, language, doc);
71
// }
72
//
73
// public void format(FormatWriter fw) {
74
// GsfFormatSupport jfs = (GsfFormatSupport)createFormatSupport(fw);
75
//
76
// FormatTokenPosition pos = jfs.getFormatStartPosition();
77
// if (jfs.isIndentOnly()) { // don't do anything
78
//
79
// } else { // remove end-line whitespace
80
// while (pos.getToken() != null) {
81
// FormatTokenPosition startPos = pos;
82
// pos = jfs.removeLineEndWhitespace(pos);
83
// if (pos.getToken() != null) {
84
// pos = jfs.getNextPosition(pos);
85
// }
86
// // fix for issue 14725
87
// // this is more hack than correct fix. It happens that
88
// // jfs.removeLineEndWhitespace() does not move to next
89
// // position. The reason is that token from which the
90
// // endline whitespaces must be removed is not 'modifiable' -
91
// // FormatWritter.canModifyToken() returns false in
92
// // FormatWritter.remove. I don't dare to fix this problem
93
// // in ExtFormatSupport and so I'm patching this
94
// // loop to check whether we are still on the same position
95
// // and if we are, let's do break. If similar problem reappear
96
// // we will have to find better fix. Hopefully, with the planned
97
// // conversion of indentation engines to new lexel module
98
// // all this code will be replaced in next verison.
99
// if (startPos.equals(pos)) {
100
// break;
101
// }
102
// }
103
// }
104
// }
105
//
106
// }
107
private int formatStartOffset;
108     private int formatEndOffset;
109
110     public GsfFormatter(Class JavaDoc kitClass, Language language, Document JavaDoc doc) {
111         super(kitClass);
112         assert doc != null;
113         this.language = language;
114         this.doc = doc;
115     }
116
117     protected boolean acceptSyntax(Syntax syntax) {
118         //return (syntax instanceof GenericSyntax);
119
return true;
120     }
121
122     @Override JavaDoc
123     public int[] getReformatBlock(JTextComponent JavaDoc target, String JavaDoc typedText) {
124         int[] ret = null;
125
126         // XXX This is bogus - java specific
127
// TODO - allow plugins to do something specific here
128
BaseDocument doc = Utilities.getDocument(target);
129         int dotPos = target.getCaret().getDot();
130
131         if (doc != null) {
132             /* Check whether the user has written the ending 'e'
133              * of the first 'else' on the line.
134              */

135             if ("e".equals(typedText)) { // NOI18N
136

137                 try {
138                     int fnw = Utilities.getRowFirstNonWhite(doc, dotPos);
139
140                     if ((fnw >= 0) && ((fnw + 4) == dotPos) &&
141                             "else".equals(doc.getText(fnw, 4)) // NOI18N
142
) {
143                         ret = new int[] { fnw, fnw + 4 };
144                     }
145                 } catch (BadLocationException JavaDoc e) {
146                 }
147             } else if (":".equals(typedText)) { // NOI18N
148

149                 try {
150                     int fnw = Utilities.getRowFirstNonWhite(doc, dotPos);
151
152                     if ((fnw >= 0) && ((fnw + 4) <= doc.getLength()) &&
153                             "case".equals(doc.getText(fnw, 4)) // NOI18N
154
) {
155                         ret = new int[] { fnw, fnw + 4 };
156                     } else {
157                         if (((fnw >= 0) & ((fnw + 7) <= doc.getLength())) &&
158                                 "default".equals(doc.getText(fnw, 7)) // NOI18N
159
) {
160                             ret = new int[] { fnw, fnw + 7 };
161                         }
162                     }
163                 } catch (BadLocationException JavaDoc e) {
164                 }
165             } else {
166                 ret = super.getReformatBlock(target, typedText);
167             }
168         }
169
170         return ret;
171     }
172
173     protected void initFormatLayers() {
174         // addFormatLayer(new StripEndWhitespaceLayer());
175
addFormatLayer(new GsfLayer());
176     }
177
178     public FormatSupport createFormatSupport(FormatWriter fw) {
179         assert doc != null;
180
181         return new GsfFormatSupport(fw, language, doc);
182     }
183
184     @Override JavaDoc
185     public Writer JavaDoc reformat(BaseDocument doc, int startOffset, int endOffset, boolean indentOnly)
186         throws BadLocationException JavaDoc, IOException JavaDoc {
187         this.formatStartOffset = formatStartOffset;
188         this.formatEndOffset = formatEndOffset;
189
190         return super.reformat(doc, startOffset, endOffset, indentOnly);
191     }
192     
193     public void settingsChange(SettingsChangeEvent evt) {
194         String JavaDoc settingName = (evt != null) ? evt.getSettingName() : null;
195         if (!inited || settingName == null || SettingsNames.SPACES_PER_TAB.equals(settingName)) {
196             if (!customSpacesPerTab) {
197                 int deflt = SettingsDefaults.defaultSpacesPerTab;
198                 if (language.getFormatter() != null) {
199                     deflt = language.getFormatter().indentSize();
200                 }
201                 int spacesPerTab = SettingsUtil.getInteger(GsfEditorKitFactory.GsfEditorKit.class, SettingsNames.SPACES_PER_TAB,
202                                                       deflt);
203                 setSpacesPerTab(spacesPerTab);
204             }
205         }
206
207         inited = true;
208
209         super.settingsChange(evt);
210     }
211
212     /** Get the number of spaces that should be inserted into the document
213     * instead of one typed tab.
214     */

215     public int getSpacesPerTab() {
216         if (!customSpacesPerTab && !inited) {
217             settingsChange(null);
218         }
219
220         return spacesPerTab;
221     }
222
223     public void setSpacesPerTab(int spacesPerTab) {
224         customSpacesPerTab = true;
225         this.spacesPerTab = spacesPerTab;
226         super.setSpacesPerTab(spacesPerTab);
227     }
228
229     public static class GenericFormattingPreferences extends FormattingPreferences {
230         private int indentSize;
231         
232         public GenericFormattingPreferences(int indentSize) {
233             this.indentSize = indentSize;
234         }
235         
236         public int getIndentation() {
237             return indentSize;
238         }
239     }
240
241     public class GsfLayer extends AbstractFormatLayer {
242         public GsfLayer() {
243             super("gsf-layer"); // NOI18N
244
}
245
246         protected FormatSupport createFormatSupport(FormatWriter fw) {
247             assert GsfFormatter.this.doc != null;
248
249             return new GsfFormatSupport(fw, language, GsfFormatter.this.doc);
250         }
251
252         private FileObject getFileObject(Document JavaDoc doc) {
253             DataObject od = (DataObject)doc.getProperty(Document.StreamDescriptionProperty);
254
255             return (od != null) ? od.getPrimaryFile() : null;
256         }
257
258         public void format(FormatWriter fw) {
259             try {
260                 if (language.getFormatter() != null) {
261                     // Just reindent?
262
if (fw.isIndentOnly()) {
263                         int indentSize = language.getFormatter().indentSize();
264                         FormattingPreferences preferences = new GenericFormattingPreferences(indentSize);
265                         GsfFormatSupport jfs = (GsfFormatSupport)createFormatSupport(fw);
266                         int offset = fw.getOffset();
267                         int indent =
268                             language.getFormatter().getLineIndent(doc, offset, preferences);
269                         FormatTokenPosition pos = jfs.getFormatStartPosition();
270                         jfs.changeLineIndent(pos, indent);
271                     } else {
272                         //int startOffset = fw.getOffset();
273
//int endOffset = fw.get
274
final int startOffset = formatStartOffset;
275                         final int endOffset = formatEndOffset == 0 ? doc.getLength() : formatEndOffset;
276                         
277                         FormattingPreferences preferences = new GenericFormattingPreferences(language.getFormatter().indentSize());
278                         language.getFormatter().reindent(doc, startOffset, endOffset, null/* controller*/, preferences);
279                         
280                         return;
281                         
282                         //final Writer writer = fw;
283

284                         // Not yet implemented
285
// try {
286
// final FileObject fo = getFileObject(doc);
287
// if (fo != null) {
288
//
289
// Source js = Source.forFileObject(fo);
290
// final String[] result = new String[1];
291
//
292
// js.runUserActionTask(new CancellableTask<CompilationController>() {
293
// public void cancel() {
294
// }
295
//
296
// public void run(CompilationController controller)
297
// throws Exception {
298
// if (controller.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0) {
299
// return;
300
// }
301
//
302
// Language language = controller.getLanguage();
303
// FormattingPreferences preferences = new GenericFormattingPreferences();
304
// language.getFormatter().reformat(writer, doc, startOffset, endOffset, controller, preferences);
305
// }
306
// }, true);
307
// }
308
// } catch (IOException ioe) {
309
// throw new IllegalStateException(ioe);
310
// }
311
//
312
// return;
313
}
314                 }
315
316                 // Old style formatting... Does not work right because the offsets are obviously
317
// not right - the idea is for offsets to be computed on the fly here
318
GsfFormatSupport jfs = (GsfFormatSupport)createFormatSupport(fw);
319
320                 FormatTokenPosition pos = jfs.getFormatStartPosition();
321
322                 if (jfs.isIndentOnly()) { // create indentation only
323
jfs.indentLine(pos);
324                 } else { // regular formatting
325

326                     while (pos != null) {
327                         // Indent the current line
328
jfs.indentLine(pos);
329
330                         // Format the line by additional rules
331
formatLine(jfs, pos);
332
333                         // Goto next line
334
FormatTokenPosition pos2 = jfs.findLineEnd(pos);
335
336                         if ((pos2 == null) || (pos2.getToken() == null)) {
337                             break; // the last line was processed
338
}
339
340                         pos = jfs.getNextPosition(pos2, javax.swing.text.Position.Bias.Forward);
341
342                         if (pos == pos2) {
343                             break; // in case there is no next position
344
}
345
346                         if ((pos == null) || (pos.getToken() == null)) {
347                             break; // there is nothing after the end of line
348
}
349
350                         FormatTokenPosition fnw = jfs.findLineFirstNonWhitespace(pos);
351
352                         if (fnw != null) {
353                             pos = fnw;
354                         } else { // no non-whitespace char on the line
355
pos = jfs.findLineStart(pos);
356                         }
357                     }
358                 }
359             } catch (IllegalStateException JavaDoc e) {
360             }
361         }
362
363         protected void formatLine(GsfFormatSupport jfs, FormatTokenPosition pos) {
364             TokenItem token = jfs.findLineStart(pos).getToken();
365
366             while (token != null) {
367                 // TODO - allow plugins to customize line formatting here - newlines before else, etc.
368
token = token.getNext();
369             }
370         }
371     }
372 }
373
Popular Tags