KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > editor > fold > FoldChildren


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.editor.fold;
21
22 import org.netbeans.api.editor.fold.Fold;
23 import org.netbeans.modules.editor.fold.ApiPackageAccessor;
24 import org.netbeans.lib.editor.util.GapList;
25
26 //import org.netbeans.spi.lexer.util.GapObjectArray;
27

28 /**
29  * Manager of the children of a fold.
30  * <br>
31  *
32  * @author Miloslav Metelka
33  * @version 1.00
34  */

35
36 public final class FoldChildren extends GapList {
37
38     /**
39      * Initial size of the index gap.
40      */

41     private static final int INITIAL_INDEX_GAP_LENGTH
42         = Integer.MAX_VALUE >> 1;
43
44     /**
45      * Parent fold for the folds contained in this children instance.
46      */

47     Fold parent;
48
49    /**
50      * Index where the index gap resides.
51      */

52     private int indexGapIndex;
53
54     /**
55      * Length of the index gap in managed folds.
56      * <br>
57      * The initial gap length is chosen big enough
58      * so that it's never reached.
59      */

60     private int indexGapLength;
61
62     public FoldChildren(Fold parent) {
63         this.parent = parent;
64         indexGapLength = INITIAL_INDEX_GAP_LENGTH;
65     }
66     
67     /**
68      * Get total count of subfolds contained in this fold.
69      *
70      * @return count of subfolds contained in this fold.
71      * Zero means there are no subfolds under this fold.
72      */

73     public int getFoldCount() {
74         return size();
75     }
76
77     /**
78      * Get fold with the given index.
79      *
80      * @param index &gt;=0 &amp;&amp; &lt;{@link #getFoldCount()}
81      * index of the fold.
82      */

83     public Fold getFold(int index) {
84         return (Fold)get(index);
85     }
86     
87     public int getFoldIndex(Fold child) {
88         int index = getTranslatedFoldIndex(ApiPackageAccessor.get().foldGetRawIndex(child));
89         if (index < 0 || index >= getFoldCount() || getFold(index) != child) {
90             index = -1;
91         }
92         return index;
93     }
94     
95     public Fold[] foldsToArray(int index, int length) {
96         Fold[] folds = new Fold[length];
97         copyItems(index, index + length, folds, 0);
98         return folds;
99     }
100     
101     /**
102      * Insert the given fold at the requested index.
103      */

104     public void insert(int index, Fold fold) {
105         moveIndexGap(index);
106         //ensureCapacity(1);
107
insertImpl(index, fold);
108     }
109    
110     /**
111      * Insert the given folds at the requested index.
112      */

113     public void insert(int index, Fold[] folds) {
114         moveIndexGap(index);
115         insertImpl(index, folds);
116     }
117
118     public void remove(int index, int length) {
119         moveIndexGap(index + length);
120         for (int i = index + length - 1; i >= index; i--) {
121             ApiPackageAccessor.get().foldSetParent(getFold(i), null);
122         }
123         super.remove(index, length);
124         indexGapLength += length;
125         indexGapIndex -= length;
126     }
127     
128     /**
129      * Extract given area of folds into new FoldChildren instance
130      * parented by the given fold.
131      *
132      * @param index start of the area of folds to be extracted.
133      * @param length length of the area of folds to be extracted.
134      * @param fold fold that will own the newly created fold children.
135      */

136     public FoldChildren extractToChildren(int index, int length, Fold fold) {
137         FoldChildren foldChildren = new FoldChildren(fold);
138         if (length == 1) {
139             Fold insertFold = getFold(index);
140             remove(index, length); // removal prior insertion to set children parents properly
141
foldChildren.insert(0, insertFold);
142         } else {
143             Fold[] insertFolds = foldsToArray(index, length);
144             remove(index, length); // removal prior insertion to set children parents properly
145
foldChildren.insert(0, insertFolds);
146         }
147
148         // Insert the fold into list of current children
149
insertImpl(index, fold);
150         
151         return foldChildren;
152     }
153
154     public void replaceByChildren(int index, FoldChildren children) {
155         remove(index, 1);
156         
157         if (children != null) {
158             // Index gap already moved by preceding remove()
159
int childCount = children.getFoldCount();
160             //ensureCapacity(childCount);
161
insertImpl(index, children, 0, childCount);
162         }
163     }
164
165     private void insertImpl(int index, FoldChildren children,
166     int childIndex, int childCount) {
167
168         switch (childCount) {
169             case 0: // nothing to do
170
break;
171
172             case 1: // single item insert
173
insertImpl(index, children.getFold(childIndex));
174                 break;
175                 
176             default: // multiple items insert
177
Fold[] folds = children.foldsToArray(childIndex, childCount);
178                 insertImpl(index, folds);
179                 break;
180         }
181     }
182
183     private void insertImpl(int index, Fold fold) {
184         indexGapLength--;
185         indexGapIndex++;
186         ApiPackageAccessor api = ApiPackageAccessor.get();
187         api.foldSetRawIndex(fold, index);
188         api.foldSetParent(fold, parent);
189         add(index, fold);
190     }
191     
192     private void insertImpl(int index, Fold[] folds) {
193         ApiPackageAccessor api = ApiPackageAccessor.get();
194         int foldsLength = folds.length;
195         indexGapLength -= foldsLength;
196         indexGapIndex += foldsLength;
197         for (int i = foldsLength - 1; i >= 0; i--) {
198             Fold fold = folds[i];
199             api.foldSetRawIndex(fold, index + i);
200             api.foldSetParent(fold, parent);
201         }
202         addArray(index, folds);
203     }
204     
205     private int getTranslatedFoldIndex(int rawIndex) {
206         if (rawIndex >= indexGapLength) {
207             rawIndex -= indexGapLength;
208         }
209         return rawIndex;
210     }
211
212     private void moveIndexGap(int index) {
213         if (index != indexGapIndex) {
214             ApiPackageAccessor api = ApiPackageAccessor.get();
215             int gapLen = indexGapLength; // cache to local var
216
if (index < indexGapIndex) { // fix back from indexGapIndex till index
217
for (int i = indexGapIndex - 1; i >= index; i--) {
218                     api.foldUpdateRawIndex(getFold(i), +gapLen);
219                 }
220
221             } else { // index > indexGapIndex => fix up from indexGapIndex till index
222
for (int i = indexGapIndex; i < index; i++) {
223                     api.foldUpdateRawIndex(getFold(i), -gapLen);
224                 }
225             }
226             indexGapIndex = index;
227         }
228     }
229
230 }
231
Popular Tags