KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > languages > features > IndentAction


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
20 package org.netbeans.modules.languages.features;
21
22 import java.util.ArrayList JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.HashSet JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.List JavaDoc;
27 import java.util.List JavaDoc;
28 import java.util.Map JavaDoc;
29 import java.util.Set JavaDoc;
30 import java.util.WeakHashMap JavaDoc;
31 import java.util.regex.Pattern JavaDoc;
32 import javax.swing.text.BadLocationException JavaDoc;
33 import javax.swing.text.Caret JavaDoc;
34 import javax.swing.text.Document JavaDoc;
35 import javax.swing.text.JTextComponent JavaDoc;
36 import javax.swing.text.StyledDocument JavaDoc;
37 import org.netbeans.api.languages.Context;
38 import org.netbeans.api.languages.LanguagesManager;
39 import org.netbeans.api.lexer.Token;
40 import org.netbeans.api.lexer.TokenHierarchy;
41 import org.netbeans.api.lexer.TokenSequence;
42 import org.netbeans.editor.BaseDocument;
43 import org.netbeans.editor.BaseKit.InsertBreakAction;
44 import org.netbeans.modules.languages.Feature;
45 import org.netbeans.modules.languages.Feature.Type;
46 import org.netbeans.modules.languages.Language;
47 import org.netbeans.modules.languages.LanguagesManagerImpl;
48 import org.openide.ErrorManager;
49 import org.openide.text.NbDocument;
50
51
52 /**
53  *
54  * @author Jan Jancura
55  */

56 public class IndentAction extends InsertBreakAction {
57
58     protected void afterBreak (
59         JTextComponent JavaDoc target,
60         BaseDocument doc,
61         Caret JavaDoc caret,
62         Object JavaDoc cookie
63     ) {
64         try {
65             TokenHierarchy th = TokenHierarchy.get (doc);
66             TokenSequence ts = th.tokenSequence ();
67             ts.move (caret.getDot ());
68             if (ts.moveNext ())
69                 while (ts.embedded () != null) {
70                     ts = ts.embedded ();
71                     ts.move (caret.getDot ());
72                     if (!ts.moveNext ()) break;
73                 }
74             Language l = ((LanguagesManagerImpl) LanguagesManager.getDefault ()).getLanguage (ts.language ().mimeType ());
75             Token token = ts.token ();
76             Object JavaDoc indentValue = getIndentProperties (l);
77
78             if (indentValue == null) return;
79             if (indentValue instanceof Object JavaDoc[]) {
80                 Object JavaDoc[] params = (Object JavaDoc[]) indentValue;
81                 int ln = NbDocument.findLineNumber ((StyledDocument JavaDoc) doc, caret.getDot () - 1);
82                 int start = NbDocument.findLineOffset ((StyledDocument JavaDoc) doc, ln);
83                 int end = NbDocument.findLineOffset ((StyledDocument JavaDoc) doc, ln + 1);
84                 String JavaDoc line = doc.getText (start, end - start);
85                 int indent = getIndent (line);
86                 ts.move (start);
87                 ts.moveNext ();
88                 int ni = getIndent (line, ts, end, params);
89                 if (ni > 0)
90                     indent += 4;
91                 else
92                 if (ni == 0 && ln > 0) {
93                     int start1 = NbDocument.findLineOffset ((StyledDocument JavaDoc) doc, ln - 1);
94                     line = doc.getText (start1, start - start1);
95                     ts.move (start1);
96                     ts.moveNext ();
97                     ni = getIndent (line, ts, start, params);
98                     if (ni == 2)
99                         indent -= 4;
100                 }
101                 try {
102                     start = NbDocument.findLineOffset ((StyledDocument JavaDoc) doc, ln + 1);
103                     end = NbDocument.findLineOffset ((StyledDocument JavaDoc) doc, ln + 2);
104                     line = doc.getText (start, end - start);
105                 } catch (IndexOutOfBoundsException JavaDoc ex) {
106                     line = null;
107                 }
108                 indent (doc, caret.getDot (), indent);
109                 if ( line != null &&
110                      ((Set JavaDoc) params [2]).contains (line.trim ())
111                 ) {
112                     indent -= 4;
113                     int offset = caret.getDot ();
114                     doc.insertString (offset, "\n", null);
115                     indent (doc, caret.getDot (), indent);
116                     caret.setDot (offset);
117                 }
118             } else
119             if (indentValue instanceof Feature) {
120                 Feature m = (Feature) indentValue;
121                 m.getValue (Context.create (doc, ts));
122             }
123         } catch (Exception JavaDoc ex) {
124             ErrorManager.getDefault ().notify (ex);
125         }
126     }
127
128     private static int getIndent (String JavaDoc line) {
129         int i = 0, k = line.length () - 1;
130         while (i < k && Character.isWhitespace (line.charAt (i)))
131             i++;
132         return i;
133     }
134
135     private static int getIndent (
136         String JavaDoc line,
137         TokenSequence ts,
138         int end,
139         Object JavaDoc[] params
140     ) {
141         Map JavaDoc p = new HashMap JavaDoc ();
142         do {
143             Token t = ts.token ();
144             String JavaDoc id = t.text ().toString ();
145             if (((Set JavaDoc) params [1]).contains (id)) {
146                 Integer JavaDoc i = (Integer JavaDoc) p.get (id);
147                 if (i == null) {
148                     i = Integer.valueOf (1);
149                 } else
150                     i = Integer.valueOf (i.intValue () + 1);
151                 p.put (id, i);
152             }
153             if (((Set JavaDoc) params [2]).contains (t.text ().toString ())) {
154                 id = (String JavaDoc) ((Map JavaDoc) params [3]).get (id);
155                 Integer JavaDoc i = (Integer JavaDoc) p.get (id);
156                 if (i == null) {
157                     i = Integer.valueOf (-1);
158                 } else
159                     i = Integer.valueOf (i.intValue () - 1);
160                 p.put (id, i);
161             }
162             if (!ts.moveNext ()) break;
163         } while (ts.offset () < end);
164         Iterator JavaDoc it = p.values ().iterator ();
165         while (it.hasNext ()) {
166             int i = ((Integer JavaDoc) it.next ()).intValue ();
167             if (i > 0) return 1;
168             if (i < 0) return -1;
169         }
170         it = ((List JavaDoc) params [0]).iterator ();
171         while (it.hasNext ()) {
172             Pattern JavaDoc pattern = (Pattern JavaDoc) it.next ();
173             if (pattern.matcher (line).matches ())
174                 return 2;
175         }
176         return 0;
177     }
178
179     private static void indent (Document JavaDoc doc, int offset, int i) {
180         StringBuilder JavaDoc sb = new StringBuilder JavaDoc ();
181         while (i > 0) {
182             sb.append (' ');i--;
183         }
184         try {
185             doc.insertString (offset, sb.toString (), null);
186         } catch (BadLocationException JavaDoc ex) {
187             ErrorManager.getDefault ().notify (ex);
188         }
189     }
190     
191     private static Map JavaDoc indentProperties = new WeakHashMap JavaDoc ();
192     
193     private static Object JavaDoc getIndentProperties (Language l) {
194         if (!indentProperties.containsKey (l)) {
195             List JavaDoc<Pattern JavaDoc> patterns = new ArrayList JavaDoc<Pattern JavaDoc> ();
196             Set JavaDoc<String JavaDoc> start = new HashSet JavaDoc<String JavaDoc> ();
197             Set JavaDoc<String JavaDoc> end = new HashSet JavaDoc<String JavaDoc> ();
198             Map JavaDoc<String JavaDoc,String JavaDoc> endToStart = new HashMap JavaDoc<String JavaDoc,String JavaDoc> ();
199             
200             List JavaDoc<Feature> indents = l.getFeatures ("INDENT");
201             Iterator JavaDoc<Feature> it = indents.iterator ();
202             while (it.hasNext ()) {
203                 Feature indent = it.next ();
204                 if (indent.getType () == Type.METHOD_CALL) {
205                     return indent;
206                 }
207                 String JavaDoc s = (String JavaDoc) indent.getValue ();
208                 int i = s.indexOf (':');
209                 if (i < 1) {
210                     patterns.add (Pattern.compile (c (s)));
211                     continue;
212                 }
213                 start.add (s.substring (0, i));
214                 end.add (s.substring (i + 1));
215                 endToStart.put (s.substring (i + 1), s.substring (0, i));
216             }
217             indentProperties.put (
218                 l,
219                 new Object JavaDoc[] {patterns, start, end, endToStart}
220             );
221         }
222         return indentProperties.get (l);
223     }
224     
225     private static String JavaDoc c (String JavaDoc s) {
226         s = s.replace ("\\n", "\n");
227         s = s.replace ("\\r", "\r");
228         s = s.replace ("\\t", "\t");
229         s = s.replace ("\\\"", "\"");
230         s = s.replace ("\\\'", "\'");
231         s = s.replace ("\\\\", "\\");
232         return s;
233     }
234 }
235
Popular Tags