001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.spi.editor.fold;
043:
044: import javax.swing.text.BadLocationException;
045: import org.netbeans.api.editor.fold.Fold;
046: import org.netbeans.api.editor.fold.FoldHierarchy;
047: import org.netbeans.api.editor.fold.FoldType;
048: import org.netbeans.modules.editor.fold.FoldHierarchyTransactionImpl;
049: import org.netbeans.modules.editor.fold.FoldOperationImpl;
050: import org.netbeans.modules.editor.fold.SpiPackageAccessor;
051:
052: /**
053: * Fold operation represents services
054: * provided to an individual fold manager.
055: * <br>
056: * Each manager has its own dedicated instance
057: * of fold operation.
058: *
059: * <p>
060: * There are three main services - creation of a new fold
061: * and adding or removing it from the hierarchy.
062: * <br>
063: * Adding and removing of the folds requires a valid transaction
064: * that can be obtained by {@link #openTransaction()}.
065: *
066: * @author Miloslav Metelka
067: * @version 1.00
068: */
069:
070: public final class FoldOperation {
071:
072: private static boolean spiPackageAccessorRegistered;
073:
074: static {
075: ensureSpiAccessorRegistered();
076: }
077:
078: private static void ensureSpiAccessorRegistered() {
079: if (!spiPackageAccessorRegistered) {
080: spiPackageAccessorRegistered = true;
081: SpiPackageAccessor.register(new SpiPackageAccessorImpl());
082: }
083: }
084:
085: private final FoldOperationImpl impl;
086:
087: private FoldOperation(FoldOperationImpl impl) {
088: this .impl = impl;
089: }
090:
091: /**
092: * Create new fold instance and add it to the hierarchy.
093: * <br>
094: * The fold will either become part of the hierarchy directly or it will
095: * become blocked by another fold already present in the hierarchy.
096: * <br>
097: * Once the blocking fold gets removed this fold will be phyiscally added
098: * to the hierarchy automatically.
099: *
100: * <p>
101: * The fold is logically bound to the fold manager that uses this fold operation.
102: * <br>
103: * The fold can only be removed by this fold operation.
104: *
105: * @param type type of the fold to be assigned to the fold.
106: * @param description textual description of the fold that will be displayed
107: * once the fold becomes collapsed.
108: * @param collapsed whether the fold should initially be collapsed or expanded.
109: * @param startOffset starting offset of the fold. The fold creates swing position
110: * for the offset.
111: * @param endOffset ending offset of the fold. The fold creates swing position
112: * for the offset.
113: * @param startGuardedLength >=0 initial guarded area of the fold (starting at the start offset).
114: * If the guarded area is modified the fold will be removed automatically.
115: * @param endGuardedLength >=0 ending guarded area of the fold (ending at the end offset).
116: * If the guarded area is modified the fold will be removed automatically.
117: * @param extraInfo arbitrary extra information specific for the fold being created.
118: * It's not touched or used by the folding infrastructure in any way.
119: * <code>null<code> can be passed if there is no extra information.
120: * <br>
121: * The extra info of the existing fold can be obtained by
122: * {@link #getExtraInfo(org.netbeans.api.editor.fold.Fold)}.
123: *
124: * @return new fold instance that was added to the hierarchy.
125: */
126: public Fold addToHierarchy(FoldType type, String description,
127: boolean collapsed, int startOffset, int endOffset,
128: int startGuardedLength, int endGuardedLength,
129: Object extraInfo, FoldHierarchyTransaction transaction)
130: throws BadLocationException {
131: Fold fold = impl.createFold(type, description, collapsed,
132: startOffset, endOffset, startGuardedLength,
133: endGuardedLength, extraInfo);
134: impl.addToHierarchy(fold, transaction.getImpl());
135: return fold;
136: }
137:
138: /**
139: * This static method can be used to check whether the bounds
140: * of the fold that is planned to be added are valid.
141: * <br>
142: * The conditions are:<pre>
143: * startOffset < endOffset
144: * </pre>
145: *
146: * <pre>
147: * startGuardedLength >= 0
148: * </pre>
149: *
150: * <pre>
151: * endGuardedLength >= 0
152: * </pre>
153: *
154: * <pre>
155: * startOffset + startGuardedLength <= endOffset - endGuardedLength
156: * </pre>
157: *
158: * @return true if the bounds are OK or false otherwise.
159: */
160: public static boolean isBoundsValid(int startOffset, int endOffset,
161: int startGuardedLength, int endGuardedLength) {
162: return (startOffset < endOffset)
163: && (startGuardedLength >= 0)
164: && (endGuardedLength >= 0)
165: && ((startOffset + startGuardedLength) <= (endOffset - endGuardedLength));
166: }
167:
168: /**
169: * Remove the fold that is either present in the hierarchy or blocked
170: * by another fold.
171: *
172: * @param fold fold to be removed
173: * @param transaction non-null transaction under which the fold should be removed.
174: */
175: public void removeFromHierarchy(Fold fold,
176: FoldHierarchyTransaction transaction) {
177: impl.removeFromHierarchy(fold, transaction.getImpl());
178: }
179:
180: /**
181: * Return extra info object passed to fold at time of its creation.
182: *
183: * @return extra information object specific for the fold
184: * or null if there was no extra info.
185: */
186: public Object getExtraInfo(Fold fold) {
187: return impl.getExtraInfo(fold);
188: }
189:
190: /**
191: * Check whether the starting guarded area of the fold
192: * is damaged by a document modification.
193: *
194: * @param fold fold to check. The fold must be managed by this fold operation.
195: * @return true if the starting area of the fold was damaged by the modification
196: * or false otherwise.
197: */
198: public boolean isStartDamaged(Fold fold) {
199: return impl.isStartDamaged(fold);
200: }
201:
202: /**
203: * Check whether the ending guarded area of the fold
204: * is damaged by a document modification.
205: *
206: * @param fold fold to check. The fold must be managed by this fold operation.
207: * @return true if the ending area of the fold was damaged by the modification
208: * or false otherwise.
209: */
210: public boolean isEndDamaged(Fold fold) {
211: return impl.isEndDamaged(fold);
212: }
213:
214: /**
215: * Open a new transaction over the fold hierarchy.
216: * <br>
217: * <b>Note:</b> Always use the following pattern:
218: * <pre>
219: * FoldHierarchyTransaction transaction = operation.openTransaction();
220: * try {
221: * ...
222: * } finally {
223: * transaction.commit();
224: * }
225: * </pre>
226: *
227: * @return opened transaction for further use.
228: */
229: public FoldHierarchyTransaction openTransaction() {
230: return impl.openTransaction().getTransaction();
231: }
232:
233: /**
234: * Check whether the fold is currently present in the hierarchy or blocked.
235: *
236: * @return true if the fold is currently present in the hierarchy or blocked
237: * or false otherwise.
238: */
239: public boolean isAddedOrBlocked(Fold fold) {
240: return impl.isAddedOrBlocked(fold);
241: }
242:
243: /**
244: * Is the given fold blocked by another fold?
245: */
246: public boolean isBlocked(Fold fold) {
247: return impl.isBlocked(fold);
248: }
249:
250: /**
251: * Get the hierarchy for which this fold operations works.
252: */
253: public FoldHierarchy getHierarchy() {
254: return impl.getHierarchy();
255: }
256:
257: public boolean isReleased() {
258: return impl.isReleased();
259: }
260:
261: private static final class SpiPackageAccessorImpl extends
262: SpiPackageAccessor {
263:
264: public FoldHierarchyTransaction createFoldHierarchyTransaction(
265: FoldHierarchyTransactionImpl impl) {
266: return new FoldHierarchyTransaction(impl);
267: }
268:
269: public FoldHierarchyTransactionImpl getImpl(
270: FoldHierarchyTransaction transaction) {
271: return transaction.getImpl();
272: }
273:
274: public FoldOperation createFoldOperation(FoldOperationImpl impl) {
275: return new FoldOperation(impl);
276: }
277:
278: }
279: }
|