KickJava   Java API By Example, From Geeks To Geeks.

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


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.Set JavaDoc;
23 import org.netbeans.api.languages.ASTEvaluator;
24 import org.netbeans.api.languages.ASTToken;
25 import org.netbeans.api.languages.LanguagesManager;
26 import org.netbeans.api.languages.ParseException;
27 import org.netbeans.api.languages.ASTPath;
28 import org.netbeans.api.languages.ParserManager.State;
29 import org.netbeans.api.languages.SyntaxContext;
30 import org.netbeans.api.editor.fold.Fold;
31 import org.netbeans.api.editor.fold.FoldHierarchy;
32 import org.netbeans.api.editor.fold.FoldType;
33 import org.netbeans.api.languages.SyntaxContext;
34 import org.netbeans.api.languages.ASTNode;
35 import org.netbeans.api.languages.ASTItem;
36 import org.netbeans.api.languages.ParseException;
37 import org.netbeans.api.lexer.Token;
38 import org.netbeans.api.lexer.TokenSequence;
39 import org.netbeans.modules.languages.Feature;
40 import org.netbeans.spi.editor.fold.FoldHierarchyTransaction;
41 import org.netbeans.spi.editor.fold.FoldManager;
42 import org.netbeans.spi.editor.fold.FoldManagerFactory;
43 import org.netbeans.spi.editor.fold.FoldOperation;
44 import org.openide.text.NbDocument;
45 import org.netbeans.modules.editor.NbEditorDocument;
46 import org.netbeans.modules.languages.Language;
47 import org.netbeans.modules.languages.LanguagesManagerImpl;
48 import org.netbeans.modules.languages.ParserManagerImpl;
49 import java.util.ArrayList JavaDoc;
50 import javax.swing.SwingUtilities JavaDoc;
51 import javax.swing.text.Document JavaDoc;
52 import javax.swing.event.DocumentEvent JavaDoc;
53 import javax.swing.text.BadLocationException JavaDoc;
54 import java.util.Iterator JavaDoc;
55 import java.util.List JavaDoc;
56 import org.netbeans.api.lexer.TokenHierarchy;
57
58
59 /**
60  *
61  * @author Jan Jancura
62  */

63 public class LanguagesFoldManager extends ASTEvaluator implements FoldManager {
64     
65     private FoldOperation operation;
66     private NbEditorDocument doc;
67     
68     
69     /** Creates a new instance of JavaFoldManager */
70     public LanguagesFoldManager () {
71     }
72     
73     /**
74      * Initialize this manager.
75      *
76      * @param operation fold hierarchy operation dedicated to the fold manager.
77      */

78     public void init (FoldOperation operation) {
79         Document d = operation.getHierarchy ().getComponent ().getDocument ();
80         if (d instanceof NbEditorDocument) {
81             this.operation = operation;
82             doc = (NbEditorDocument) d;
83             ParserManagerImpl.get (doc).addASTEvaluator (this);
84         }
85     }
86     
87     /**
88      * Initialize the folds provided by this manager.
89      * <br>
90      * The fold manager should create initial set of folds here
91      * if it does not require too much resource consumption.
92      * <br>
93      * As this method is by default called at the file opening time
94      * then it may be better to schedule the initial fold computations
95      * for later time and do nothing here.
96      *
97      * <p>
98      * Any listeners necessary for the maintenance of the folds
99      * can be attached here.
100      * <br>
101      * Generally there should be just weak listeners used
102      * to not prevent the GC of the text component.
103      *
104      * @param transaction transaction in terms of which the intial
105      * fold changes can be performed.
106      */

107     public void initFolds (FoldHierarchyTransaction transaction) {
108     }
109     
110     /**
111      * Called by hierarchy upon the insertion to the underlying document.
112      * <br>
113      * If there would be any fold modifications required they may be added
114      * to the given transaction.
115      *
116      * @param evt document event describing the document modification.
117      * @param transaction open transaction to which the manager can add
118      * the fold changes.
119      */

120     public void insertUpdate (DocumentEvent JavaDoc evt, FoldHierarchyTransaction transaction) {
121     }
122     
123     /**
124      * Called by hierarchy upon the removal in the underlying document.
125      * <br>
126      * If there would be any fold modifications required they may be added
127      * to the given transaction.
128      *
129      * @param evt document event describing the document modification.
130      * @param transaction open transaction to which the manager can add
131      * the fold changes.
132      */

133     public void removeUpdate (DocumentEvent JavaDoc evt, FoldHierarchyTransaction transaction) {
134     }
135     
136     /**
137      * Called by hierarchy upon the change in the underlying document.
138      * <br>
139      * If there would be any fold modifications required they may be added
140      * to the given transaction.
141      *
142      * @param evt document event describing the document change.
143      * @param transaction open transaction to which the manager can add
144      * the fold changes.
145      */

146     public void changedUpdate (DocumentEvent JavaDoc evt, FoldHierarchyTransaction transaction) {
147     }
148     
149     /**
150      * Notify that the fold was removed from hierarchy automatically
151      * by fold hierarchy infrastructure processing
152      * because it became empty (by a document modification).
153      */

154     public void removeEmptyNotify (Fold epmtyFold) {
155     }
156     
157     /**
158      * Notify that the fold was removed from hierarchy automatically
159      * by fold hierarchy infrastructure processing
160      * because it was damaged by a document modification.
161      */

162     public void removeDamagedNotify (Fold damagedFold) {
163     }
164     
165     /**
166      * Notify that the fold was expanded automatically
167      * by fold hierarchy infrastructure processing
168      * because its <code>isExpandNecessary()</code>
169      * return true.
170      */

171     public void expandNotify (Fold expandedFold) {
172     }
173
174     /**
175      * Notification that this manager will no longer be used by the hierarchy.
176      * <br>
177      * The folds that it maintains are still valid but after this method
178      * finishes they will be removed from the hierarchy.
179      *
180      * <p>
181      * This method is not guaranteed to be called. Therefore the manager
182      * must only listen weekly on the related information providers
183      * so that it does not block the hierarchy from being garbage collected.
184      */

185     public void release () {
186         //S ystem.out.println("release " + mimeType + " : " + operation + " : " + this);
187
if (doc != null)
188             ParserManagerImpl.get (doc).removeASTEvaluator (this);
189     }
190
191     
192     // ASTEvaluator methods ....................................................
193

194
195     private static FoldType defaultFoldType = new FoldType ("default");
196     private List JavaDoc<FoldItem> folds;
197     
198     public void beforeEvaluation (State state, ASTNode root) {
199         folds = new ArrayList JavaDoc<FoldItem> ();
200     }
201
202     public void afterEvaluation (State state, ASTNode root) {
203         SwingUtilities.invokeLater (new Runnable JavaDoc () {
204             public void run () {
205                 FoldHierarchy hierarchy = operation.getHierarchy ();
206                 FoldHierarchyTransaction transaction = operation.openTransaction ();
207                 try {
208                     Fold fold = operation.getHierarchy ().getRootFold ();
209                     List JavaDoc<Fold> l = new ArrayList JavaDoc<Fold> (fold.getFoldCount ());
210                     int i, k = fold.getFoldCount ();
211                     for (i = 0; i < k; i++)
212                         l.add (fold.getFold (i));
213                     for (i = 0; i < k; i++)
214                         operation.removeFromHierarchy (l.get (i), transaction);
215                     Iterator JavaDoc<FoldItem> it = folds.iterator ();
216                     while (it.hasNext ()) {
217                         FoldItem f = it.next ();
218                         operation.addToHierarchy (
219                             f.type, f.foldName, false, f.start, f.end, 0, 0,
220                             hierarchy, transaction
221                         );
222                     }
223                 } catch (BadLocationException JavaDoc ex) {
224                     ex.printStackTrace ();
225                 } finally {
226                     transaction.commit ();
227                 }
228             }
229         });
230     }
231
232     public void evaluate (State state, ASTPath path) {
233         try {
234             ASTItem item = path.getLeaf ();
235             int s = item.getOffset (),
236                 e = item.getEndOffset ();
237             int sln = NbDocument.findLineNumber (doc, s),
238                 eln = NbDocument.findLineNumber (doc, e);
239             if (sln == eln) return;
240             String JavaDoc mimeType = item.getMimeType ();
241             Language language = ((LanguagesManagerImpl) LanguagesManager.getDefault ()).
242                 getLanguage (mimeType);
243             List JavaDoc<Feature> fls = language.getFeatures (Language.FOLD, path);
244             if (fls == null || fls.isEmpty()) {
245                 return;
246             }
247             Feature fold = fls.get(0);
248             boolean isTokenFold = (fls.size() == 1 && (item instanceof ASTToken) &&
249                         fold == language.getFeature(Language.FOLD, ((ASTToken) item).getType()));
250             if (!isTokenFold) {
251                 TokenHierarchy th = TokenHierarchy.get (doc);
252                 TokenSequence ts = th.tokenSequence ();
253                 ts.move (e - 1);
254                 if (!ts.moveNext ()) return;
255                 while (!ts.language ().mimeType ().equals (mimeType)) {
256                     ts = ts.embedded ();
257                     if (ts == null) return;
258                     ts.move (e - 1);
259                     if (!ts.moveNext ()) return;
260                 }
261                 Token t = ts.token ();
262                 Set JavaDoc<String JavaDoc> skip = language.getSkipTokenTypes ();
263                 while (skip.contains (t.id ().name ())) {
264                     if (!ts.movePrevious ()) break;
265                     t = ts.token ();
266                 }
267                 ts.moveNext ();
268                 e = ts.offset ();
269                 sln = NbDocument.findLineNumber (doc, s);
270                 eln = NbDocument.findLineNumber (doc, e);
271                 if (eln - sln < 1) return;
272             }
273                 
274             if (fold.hasSingleValue ()) {
275                 String JavaDoc foldName = (String JavaDoc) fold.getValue (SyntaxContext.create (doc, path));
276                 if (foldName == null) return;
277                 folds.add (new FoldItem(foldName, s, e, defaultFoldType));
278                 return;
279             }
280             String JavaDoc foldName = (String JavaDoc) fold.getValue ("fold_display_name", SyntaxContext.create (doc, path));
281             if (foldName == null) foldName = "...";
282             String JavaDoc foldType = (String JavaDoc) fold.getValue ("collapse_type_action_name");
283             folds.add (new FoldItem (foldName, s, e, Folds.getFoldType (foldType)));
284         } catch (ParseException ex) {
285         }
286     }
287     
288     
289     // innerclasses ............................................................
290

291     private static final class FoldItem {
292         String JavaDoc foldName;
293         int start;
294         int end;
295         FoldType type;
296         
297         FoldItem (String JavaDoc foldName, int start, int end, FoldType type) {
298             this.foldName = foldName;
299             this.start = start;
300             this.end = end;
301             this.type = type;
302         }
303     }
304
305     public static final class Factory implements FoldManagerFactory {
306         
307         public FoldManager createFoldManager () {
308             return new LanguagesFoldManager ();
309         }
310
311     }
312 }
313
Popular Tags