KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > code_folding > CodeFoldingTest


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 code_folding;
21
22 import java.awt.event.KeyEvent JavaDoc;
23 import javax.swing.text.AbstractDocument JavaDoc;
24 import javax.swing.text.BadLocationException JavaDoc;
25 import javax.swing.text.JTextComponent JavaDoc;
26 import org.netbeans.jellytools.Bundle;
27 import org.netbeans.jellytools.EditorOperator;
28 import org.netbeans.jellytools.EditorWindowOperator;
29 import lib.EditorTestCase;
30 import org.netbeans.api.editor.fold.Fold;
31 import org.netbeans.api.editor.fold.FoldHierarchy;
32 import org.netbeans.api.editor.fold.FoldUtilities;
33 import org.netbeans.jemmy.operators.JEditorPaneOperator;
34 import org.netbeans.jemmy.operators.JTextComponentOperator;
35
36 /**
37  * Basic Code Folding Test class.
38  * It contains basic folding functionality methods.
39  *
40  *
41  * @author Martin Roskanin
42  */

43   public class CodeFoldingTest extends EditorTestCase {
44       
45     private final int COLLAPSE_EXPAND_DELAY = 200;
46       
47     /** Creates a new instance of Main */
48     public CodeFoldingTest(String JavaDoc testMethodName) {
49         super(testMethodName);
50     }
51
52     protected static void appendSpaces(StringBuffer JavaDoc sb, int spaces) {
53         while (--spaces >= 0) {
54             sb.append(' ');
55         }
56     }
57     
58     protected static String JavaDoc foldToStringChildren(Fold fold, int indent) {
59         indent += 4;
60         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
61         sb.append(fold);
62         sb.append('\n');
63         int foldCount = fold.getFoldCount();
64         for (int i = 0; i < foldCount; i++) {
65             appendSpaces(sb, indent);
66             sb.append('[');
67             sb.append(i);
68             sb.append("]: "); // NOI18N
69
sb.append(foldToStringChildren(fold.getFold(i), indent));
70         }
71         
72         return sb.toString();
73     }
74
75     
76     public static String JavaDoc foldHierarchyToString(JTextComponent JavaDoc target){
77         String JavaDoc ret = "";
78         AbstractDocument JavaDoc adoc = (AbstractDocument JavaDoc)target.getDocument();
79
80         // Dump fold hierarchy
81
FoldHierarchy hierarchy = FoldHierarchy.get(target);
82         adoc.readLock();
83         try {
84             hierarchy.lock();
85             try {
86                 Fold root = hierarchy.getRootFold();
87                 ret = (root == null) ? "root is null" : foldToStringChildren(root, 0); //NOI18N
88
} finally {
89                 hierarchy.unlock();
90             }
91         } finally {
92             adoc.readUnlock();
93         }
94         return ret;
95     }
96     
97     protected void waitForFolding(JTextComponent JavaDoc target, int maxMiliSeconds){
98         //wait for parser and folding hierarchy creation
99
int time = (int) maxMiliSeconds / 100;
100         
101         AbstractDocument JavaDoc adoc = (AbstractDocument JavaDoc)target.getDocument();
102         
103         // Dump fold hierarchy
104
FoldHierarchy hierarchy = FoldHierarchy.get(target);
105         int foldCount = 0;
106         while (foldCount==0 && time > 0) {
107             
108             adoc.readLock();
109             try {
110                 hierarchy.lock();
111                 try {
112                     foldCount = hierarchy.getRootFold().getFoldCount();
113                 } finally {
114                     hierarchy.unlock();
115                 }
116             } finally {
117                 adoc.readUnlock();
118             }
119             
120             try {
121                 Thread.currentThread().sleep(100);
122             } catch (InterruptedException JavaDoc ex) {
123                 time=0;
124             }
125             time--;
126             
127         }
128             
129     }
130     
131     private ValueResolver getResolver(final JTextComponent JavaDoc target){
132         
133         ValueResolver foldValueResolver = new ValueResolver(){
134             public Object JavaDoc getValue(){
135                 FoldHierarchy hierarchy = FoldHierarchy.get(target);
136                 int dot = target.getCaret().getDot();
137                 hierarchy.lock();
138                 try{
139                     try{
140                         int rowStart = javax.swing.text.Utilities.getRowStart(target, dot);
141                         int rowEnd = javax.swing.text.Utilities.getRowEnd(target, dot);
142                         Fold fold = getLineFold(hierarchy, dot, rowStart, rowEnd);
143                         if (fold!=null){
144                             return Boolean.valueOf(fold.isCollapsed());
145                         }else{
146                             return null;
147                         }
148                     }catch(BadLocationException JavaDoc ble){
149                         ble.printStackTrace();
150                     }
151                 }finally {
152                     hierarchy.unlock();
153                 }
154                 return null;
155             }
156         };
157         
158         return foldValueResolver;
159     }
160     
161     protected void collapseFoldAtCaretPosition(EditorOperator editor, int line, int column){
162         // 1. move to adequate place
163
editor.setCaretPosition(line, column);
164
165         // 2. hit CTRL -
166
JEditorPaneOperator txtOper = editor.txtEditorPane();
167         txtOper.pushKey(KeyEvent.VK_SUBTRACT, KeyEvent.CTRL_DOWN_MASK);
168
169         JTextComponentOperator text = new JTextComponentOperator(editor);
170         JTextComponent JavaDoc target = (JTextComponent JavaDoc)text.getSource();
171
172         // give max 500 milis to fold to collapse
173
waitMaxMilisForValue(500, getResolver(target), Boolean.TRUE);
174        
175     }
176
177     protected void expandFoldAtCaretPosition(EditorOperator editor, int line, int column){
178         // 1. move to adequate place
179
editor.setCaretPosition(line, column);
180
181         // 2. hit CTRL +
182
JEditorPaneOperator txtOper = editor.txtEditorPane();
183         txtOper.pushKey(KeyEvent.VK_ADD, KeyEvent.CTRL_DOWN_MASK);
184         
185         JTextComponentOperator text = new JTextComponentOperator(editor);
186         JTextComponent JavaDoc target = (JTextComponent JavaDoc)text.getSource();
187         
188         // give max 500 milis to fold to expand
189
waitMaxMilisForValue(500, getResolver(target), Boolean.FALSE);
190     }
191     
192     protected void collapseAllFolds(EditorOperator editor){
193         // hit CTRL Shift -
194
JEditorPaneOperator txtOper = editor.txtEditorPane();
195         txtOper.pushKey(KeyEvent.VK_SUBTRACT, KeyEvent.CTRL_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK);
196         
197         // wait a while
198
try {
199             Thread.currentThread().sleep(COLLAPSE_EXPAND_DELAY);
200         } catch (InterruptedException JavaDoc ex) {
201         }
202     }
203
204     protected void expandAllFolds(EditorOperator editor){
205         // hit CTRL Shift +
206
JEditorPaneOperator txtOper = editor.txtEditorPane();
207         txtOper.pushKey(KeyEvent.VK_ADD, KeyEvent.CTRL_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK);
208         
209         // wait a while
210
try {
211             Thread.currentThread().sleep(COLLAPSE_EXPAND_DELAY);
212         } catch (InterruptedException JavaDoc ex) {
213         }
214     }
215
216     /** Returns the fold that should be collapsed/expanded in the caret row
217      * @param hierarchy hierarchy under which all folds should be collapsed/expanded.
218      * @param dot caret position offset
219      * @param lineStart offset of the start of line
220      * @param lineEnd offset of the end of line
221      * @return the fold that meet common criteria in accordance with the caret position
222      */

223     private static Fold getLineFold(FoldHierarchy hierarchy, int dot, int lineStart, int lineEnd){
224         Fold caretOffsetFold = FoldUtilities.findOffsetFold(hierarchy, dot);
225
226         // beginning searching from the lineStart
227
Fold fold = FoldUtilities.findNearestFold(hierarchy, lineStart);
228         
229         while (fold!=null &&
230                   (fold.getEndOffset()<=dot || // find next available fold if the 'fold' is one-line
231
// or it has children and the caret is in the fold body
232
// i.e. class A{ |public void method foo(){}}
233
(!fold.isCollapsed() && fold.getFoldCount() > 0 && fold.getStartOffset()+1<dot)
234                    )
235                ){
236
237                    // look for next fold in forward direction
238
Fold nextFold = FoldUtilities.findNearestFold(hierarchy,
239                        (fold.getFoldCount()>0) ? fold.getStartOffset()+1 : fold.getEndOffset());
240                    if (nextFold!=null && nextFold.getStartOffset()<lineEnd){
241                        if (nextFold == fold) return fold;
242                        fold = nextFold;
243                    }else{
244                        break;
245                    }
246         }
247
248         
249         // a fold on the next line was found, returning fold at offset (in most cases inner class)
250
if (fold == null || fold.getStartOffset()>lineEnd) {
251
252             // in the case:
253
// class A{
254
// } |
255
// try to find an offset fold on the offset of the line beginning
256
if (caretOffsetFold == null){
257                 caretOffsetFold = FoldUtilities.findOffsetFold(hierarchy, lineStart);
258             }
259             
260             return caretOffsetFold;
261         }
262         
263         // no fold at offset found, in this case return the fold
264
if (caretOffsetFold == null) return fold;
265         
266         // skip possible inner class members validating if the innerclass fold is collapsed
267
if (caretOffsetFold.isCollapsed()) return caretOffsetFold;
268         
269         // in the case:
270
// class A{
271
// public vo|id foo(){} }
272
// 'fold' (in this case fold of the method foo) will be returned
273
if ( caretOffsetFold.getEndOffset()>fold.getEndOffset() &&
274              fold.getEndOffset()>dot){
275             return fold;
276         }
277         
278         // class A{
279
// |} public void method foo(){}
280
// inner class fold will be returned
281
if (fold.getStartOffset()>caretOffsetFold.getEndOffset()) return caretOffsetFold;
282         
283         // class A{
284
// public void foo(){} |}
285
// returning innerclass fold
286
if (fold.getEndOffset()<dot) return caretOffsetFold;
287         
288         return fold;
289     }
290     
291 }
292
Popular Tags