1 19 20 package org.netbeans.api.editor.fold; 21 22 import javax.swing.event.DocumentEvent ; 23 import javax.swing.text.BadLocationException ; 24 import javax.swing.text.Document ; 25 import javax.swing.text.Position ; 26 import org.netbeans.modules.editor.fold.FoldOperationImpl; 27 import org.netbeans.modules.editor.fold.FoldChildren; 28 import org.netbeans.modules.editor.fold.FoldUtilitiesImpl; 29 import org.openide.ErrorManager; 30 31 54 55 public final class Fold { 56 57 private static final Fold[] EMPTY_FOLD_ARRAY = new Fold[0]; 58 59 private static final String DEFAULT_DESCRIPTION = "..."; 61 private final FoldOperationImpl operation; 62 63 private final FoldType type; 64 65 private boolean collapsed; 66 67 private String description; 68 69 private Fold parent; 70 71 private FoldChildren children; 72 73 private int rawIndex; 74 75 private int startGuardedLength; 76 private int endGuardedLength; 77 78 private Position startPos; 79 private Position endPos; 80 81 private Position guardedEndPos; 82 private Position guardedStartPos; 83 84 private Object extraInfo; 85 86 87 Fold(FoldOperationImpl operation, 88 FoldType type, String description, boolean collapsed, 89 Document doc, int startOffset, int endOffset, 90 int startGuardedLength, int endGuardedLength, 91 Object extraInfo) 92 throws BadLocationException { 93 94 if (startGuardedLength < 0) { 95 throw new IllegalArgumentException ("startGuardedLength=" + startGuardedLength + " < 0"); } 98 if (endGuardedLength < 0) { 99 throw new IllegalArgumentException ("endGuardedLength=" + endGuardedLength + " < 0"); } 102 if (startOffset == endOffset) { 103 throw new IllegalArgumentException ("startOffset == endOffset == " + startOffset); 105 } 106 if ((endOffset - startOffset) < (startGuardedLength + endGuardedLength)) { 107 throw new IllegalArgumentException ("(endOffset=" + endOffset + " - startOffset=" + startOffset + ") < " + "(startGuardedLength=" + startGuardedLength + " + endGuardedLength=" + endGuardedLength + ")" ); } 113 114 this.operation = operation; 115 this.type = type; 116 117 this.collapsed = collapsed; 118 this.description = description; 119 120 this.startPos = doc.createPosition(startOffset); 121 this.endPos = doc.createPosition(endOffset); 122 123 this.startGuardedLength = startGuardedLength; 124 this.endGuardedLength = endGuardedLength; 125 126 this.extraInfo = extraInfo; 127 128 updateGuardedStartPos(doc, startOffset); 133 updateGuardedEndPos(doc, endOffset); 134 135 } 136 137 142 public FoldType getType() { 143 return type; 144 } 145 146 155 public Fold getParent() { 156 return parent; 157 } 158 159 void setParent(Fold parent) { 160 if (isRootFold()) { 161 throw new IllegalArgumentException ("Cannot set parent on root"); } else { 163 this.parent = parent; 164 } 165 } 166 171 public FoldHierarchy getHierarchy() { 172 return operation.getHierarchy(); 173 } 174 175 FoldOperationImpl getOperation() { 176 return operation; 177 } 178 179 188 192 193 boolean isRootFold() { 194 return (operation.getManager() == null); 195 } 196 197 206 public int getStartOffset() { 207 return (isRootFold()) ? 0 : startPos.getOffset(); 208 } 209 210 void setStartOffset(Document doc, int startOffset) 211 throws BadLocationException { 212 if (isRootFold()) { 213 throw new IllegalStateException ("Cannot set endOffset of root fold"); } else { 215 this.startPos = doc.createPosition(startOffset); 216 updateGuardedStartPos(doc, startOffset); 217 } 218 } 219 220 231 public int getEndOffset() { 232 return isRootFold() 233 ? operation.getHierarchy().getComponent().getDocument().getLength() 234 : endPos.getOffset(); 235 } 236 237 void setEndOffset(Document doc, int endOffset) 238 throws BadLocationException { 239 if (isRootFold()) { 240 throw new IllegalStateException ("Cannot set endOffset of root fold"); } else { 242 this.endPos = doc.createPosition(endOffset); 243 updateGuardedEndPos(doc, endOffset); 244 } 245 } 246 247 255 public boolean isCollapsed() { 256 return collapsed; 257 } 258 259 void setCollapsed(boolean collapsed) { 260 if (isRootFold()) { 261 throw new IllegalStateException ("Cannot set collapsed flag on root fold."); } 263 this.collapsed = collapsed; 264 } 265 266 274 public String getDescription() { 275 return (description != null) ? description : DEFAULT_DESCRIPTION; 276 } 277 278 void setDescription(String description) { 279 this.description = description; 280 } 281 282 288 public int getFoldCount() { 289 return (children != null) ? children.getFoldCount() : 0; 290 } 291 292 298 public Fold getFold(int index) { 299 if (children != null) { 300 return children.getFold(index); 301 } else { throw new IndexOutOfBoundsException ("index=" + index + " but no children exist."); } 305 } 306 307 Fold[] foldsToArray(int index, int count) { 308 if (children != null) { 309 return children.foldsToArray(index, count); 310 } else { if (count == 0) { 312 return EMPTY_FOLD_ARRAY; 313 } else { throw new IndexOutOfBoundsException ("No children but count=" + count); 316 } 317 } 318 } 319 320 329 void extractToChildren(int index, int length, Fold fold) { 330 if (fold.getFoldCount() != 0 || fold.getParent() != null) { 331 throw new IllegalStateException (); 332 } 333 if (length != 0) { fold.setChildren(children.extractToChildren(index, length, fold)); 335 } else { if (children == null) { 337 children = new FoldChildren(this); 338 } 339 children.insert(index, fold); } 341 } 342 343 350 Fold replaceByChildren(int index) { 351 Fold fold = getFold(index); 352 FoldChildren foldChildren = fold.getChildren(); 353 fold.setChildren(null); 354 children.replaceByChildren(index, foldChildren); 355 return fold; 356 } 357 358 private FoldChildren getChildren() { 359 return children; 360 } 361 362 private void setChildren(FoldChildren children) { 363 this.children = children; 364 } 365 366 Object getExtraInfo() { 367 return extraInfo; 368 } 369 370 380 public int getFoldIndex(Fold child) { 381 return (children != null) ? children.getFoldIndex(child) : -1; 382 } 383 384 private void updateGuardedStartPos(Document doc, int startOffset) throws BadLocationException { 385 if (!isRootFold()) { 386 int guardedStartOffset = isZeroStartGuardedLength() 387 ? startOffset + 1 388 : startOffset + startGuardedLength; 389 this.guardedStartPos = doc.createPosition(guardedStartOffset); 390 } 391 } 392 393 private void updateGuardedEndPos(Document doc, int endOffset) throws BadLocationException { 394 if (!isRootFold()) { 395 int guardedEndOffset = isZeroEndGuardedLength() 396 ? endOffset - 1 397 : endOffset - endGuardedLength; 398 this.guardedEndPos = doc.createPosition(guardedEndOffset); 399 } 400 } 401 402 private boolean isZeroStartGuardedLength() { 403 return (startGuardedLength == 0); 404 } 405 406 private boolean isZeroEndGuardedLength() { 407 return (endGuardedLength == 0); 408 } 409 410 private int getGuardedStartOffset() { 411 return isRootFold() ? getStartOffset() : guardedStartPos.getOffset(); 412 } 413 414 private int getGuardedEndOffset() { 415 return isRootFold() ? getEndOffset() : guardedEndPos.getOffset(); 416 } 417 418 void insertUpdate(DocumentEvent evt) { 419 if (evt.getOffset() + evt.getLength() == getGuardedStartOffset()) { 420 try { 422 updateGuardedStartPos(evt.getDocument(), getStartOffset()); 423 } catch (BadLocationException e) { 424 ErrorManager.getDefault().notify(e); 425 } 426 } 427 } 428 429 void removeUpdate(DocumentEvent evt) { 430 try { 431 if (getStartOffset() == getGuardedStartOffset()) { 432 updateGuardedStartPos(evt.getDocument(), getStartOffset()); 433 } 434 if (getEndOffset() == getGuardedEndOffset()) { 435 updateGuardedEndPos(evt.getDocument(), getEndOffset()); 436 } 437 } catch (BadLocationException e) { 438 ErrorManager.getDefault().notify(e); 439 } 440 } 441 442 445 boolean isStartDamaged() { 446 return (!isZeroStartGuardedLength() && (getInnerStartOffset() - getStartOffset() != startGuardedLength)); 448 } 449 450 453 boolean isEndDamaged() { 454 return (!isZeroEndGuardedLength() && (getEndOffset() - getInnerEndOffset() != endGuardedLength)); 456 } 457 458 boolean isExpandNecessary() { 459 return (isZeroStartGuardedLength() && (getStartOffset() == getGuardedStartOffset())) 463 || (isZeroEndGuardedLength() && (getEndOffset() == getGuardedEndOffset())); 464 } 465 466 470 private int getInnerStartOffset() { 471 return isZeroStartGuardedLength() ? getStartOffset() : getGuardedStartOffset(); 472 } 473 474 478 private int getInnerEndOffset() { 479 return isZeroEndGuardedLength() ? getEndOffset() : getGuardedEndOffset(); 480 } 481 482 487 int getRawIndex() { 488 return rawIndex; 489 } 490 491 496 void setRawIndex(int rawIndex) { 497 this.rawIndex = rawIndex; 498 } 499 500 505 void updateRawIndex(int rawIndexDelta) { 506 this.rawIndex += rawIndexDelta; 507 } 508 509 510 public String toString() { 511 return FoldUtilitiesImpl.foldToString(this) + ", [" + getInnerStartOffset() + ", " + getInnerEndOffset() + "] {" + getGuardedStartOffset() + ", " + getGuardedEndOffset() + '}'; } 516 517 } 518 | Popular Tags |