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.modules.editor.fold;
043:
044: import javax.swing.event.DocumentEvent;
045: import javax.swing.text.BadLocationException;
046: import javax.swing.text.Document;
047: import org.netbeans.spi.editor.fold.FoldManager;
048: import org.netbeans.api.editor.fold.Fold;
049: import org.netbeans.api.editor.fold.FoldHierarchy;
050: import org.netbeans.spi.editor.fold.FoldOperation;
051: import org.netbeans.api.editor.fold.FoldType;
052:
053: /**
054: * This is SPI (Service Provider Interface) object corresponding
055: * to the <code>FoldHierarchy</code> in one-to-one relationship.
056: * <br>
057: * The <code>FoldHierarchy</code> delegates all its operations
058: * to this object.
059: *
060: * <p>
061: * All the changes performed in to the folds are always done
062: * in terms of a transaction represented by {@link FoldHierarchyTransaction}.
063: * The transaction can be opened by {@link #openTransaction()}.
064: *
065: * <p>
066: * This class changes its state upon displayability change
067: * of the associated copmonent by listening on "ancestor" component property.
068: * <br>
069: * If the component is not displayable then the list of root folds becomes empty
070: * while if the component gets displayable the root folds are created
071: * according to registered managers.
072: *
073: * @author Miloslav Metelka
074: * @version 1.00
075: */
076:
077: public final class FoldOperationImpl {
078:
079: private static final boolean debug = Boolean
080: .getBoolean("netbeans.debug.editor.fold");
081:
082: /** Dump the stacktraces for certain opertaions
083: * such as creating of the folds.
084: * Has only effect with the "debug" turned on.
085: */
086: private static final boolean debugStack = Boolean
087: .getBoolean("netbeans.debug.editor.fold.stack");
088:
089: private FoldOperation operation;
090:
091: private FoldHierarchyExecution execution;
092:
093: private FoldManager manager;
094:
095: private int priority;
096:
097: private boolean released;
098:
099: public FoldOperationImpl(FoldHierarchyExecution execution,
100: FoldManager manager, int priority) {
101: this .execution = execution;
102: this .manager = manager;
103: this .priority = priority;
104:
105: this .operation = SpiPackageAccessor.get().createFoldOperation(
106: this );
107: if (manager != null) { // manager for root-fold is null
108: manager.init(getOperation());
109: }
110: }
111:
112: public FoldOperation getOperation() {
113: return operation;
114: }
115:
116: public void initFolds(FoldHierarchyTransactionImpl transaction) {
117: manager.initFolds(transaction.getTransaction());
118: }
119:
120: public FoldHierarchy getHierarchy() {
121: return execution.getHierarchy();
122: }
123:
124: public FoldManager getManager() {
125: return manager;
126: }
127:
128: public int getPriority() {
129: return priority;
130: }
131:
132: public Document getDocument() {
133: return execution.getComponent().getDocument();
134: }
135:
136: public Fold createFold(FoldType type, String description,
137: boolean collapsed, int startOffset, int endOffset,
138: int startGuardedLength, int endGuardedLength,
139: Object extraInfo) throws BadLocationException {
140: if (debug) {
141: /*DEBUG*/System.err.println("Creating fold: type="
142: + type // NOI18N
143: + ", description='" + description
144: + "', collapsed="
145: + collapsed // NOI18N
146: + ", startOffset=" + startOffset + ", endOffset="
147: + endOffset // NOI18N
148: + ", startGuardedLength=" + startGuardedLength // NOI18N
149: + ", endGuardedLength=" + endGuardedLength // NOI18N
150: + ", extraInfo=" + extraInfo // NOI18N
151: );
152:
153: if (debugStack) {
154: /*DEBUG*/Thread.dumpStack();
155: }
156: }
157:
158: return getAccessor().createFold(this , type, description,
159: collapsed, getDocument(), startOffset, endOffset,
160: startGuardedLength, endGuardedLength, extraInfo);
161: }
162:
163: public Object getExtraInfo(Fold fold) {
164: checkFoldOperation(fold);
165: return getAccessor().foldGetExtraInfo(fold);
166: }
167:
168: public boolean isStartDamaged(Fold fold) {
169: checkFoldOperation(fold);
170: return getAccessor().foldIsStartDamaged(fold);
171: }
172:
173: public boolean isEndDamaged(Fold fold) {
174: checkFoldOperation(fold);
175: return getAccessor().foldIsEndDamaged(fold);
176: }
177:
178: public FoldHierarchyTransactionImpl openTransaction() {
179: return execution.openTransaction();
180: }
181:
182: public boolean addToHierarchy(Fold fold,
183: FoldHierarchyTransactionImpl transaction) {
184: checkFoldOperation(fold);
185: return execution.add(fold, transaction);
186: }
187:
188: public void removeFromHierarchy(Fold fold,
189: FoldHierarchyTransactionImpl transaction) {
190: checkFoldOperation(fold);
191: execution.remove(fold, transaction);
192: }
193:
194: public boolean isAddedOrBlocked(Fold fold) {
195: checkFoldOperation(fold);
196: return execution.isAddedOrBlocked(fold);
197: }
198:
199: public boolean isBlocked(Fold fold) {
200: checkFoldOperation(fold);
201: return execution.isBlocked(fold);
202: }
203:
204: public void setEndOffset(Fold fold, int endOffset,
205: FoldHierarchyTransactionImpl transaction)
206: throws BadLocationException {
207: checkFoldOperation(fold);
208: int origEndOffset = fold.getEndOffset();
209: ApiPackageAccessor api = getAccessor();
210: api.foldSetEndOffset(fold, getDocument(), endOffset);
211: api.foldStateChangeEndOffsetChanged(transaction
212: .getFoldStateChange(fold), origEndOffset);
213: }
214:
215: public void insertUpdate(DocumentEvent evt,
216: FoldHierarchyTransactionImpl transaction) {
217: manager.insertUpdate(evt, transaction.getTransaction());
218: }
219:
220: public void removeUpdate(DocumentEvent evt,
221: FoldHierarchyTransactionImpl transaction) {
222: manager.removeUpdate(evt, transaction.getTransaction());
223: }
224:
225: public void changedUpdate(DocumentEvent evt,
226: FoldHierarchyTransactionImpl transaction) {
227: manager.changedUpdate(evt, transaction.getTransaction());
228: }
229:
230: public void release() {
231: released = true;
232: manager.release();
233: }
234:
235: public boolean isReleased() {
236: return released;
237: }
238:
239: private void checkFoldOperation(Fold fold) {
240: FoldOperationImpl foldOperation = getAccessor()
241: .foldGetOperation(fold);
242: if (foldOperation != this ) {
243: throw new IllegalStateException("Attempt to use the fold "
244: + fold // NOI18N
245: + " with invalid fold operation " // NOI18N
246: + foldOperation + " instead of " + this // NOI18N
247: );
248: }
249: }
250:
251: private static ApiPackageAccessor getAccessor() {
252: return ApiPackageAccessor.get();
253: }
254:
255: }
|