1 22 23 package org.gjt.sp.jedit.textarea; 24 25 import java.awt.Toolkit ; 27 import java.util.*; 28 import org.gjt.sp.jedit.buffer.*; 29 import org.gjt.sp.jedit.Debug; 30 import org.gjt.sp.util.Log; 31 33 40 public class DisplayManager 41 { 42 44 static DisplayManager getDisplayManager(JEditBuffer buffer, 46 TextArea textArea) 47 { 48 List l = (List)bufferMap.get(buffer); 49 DisplayManager dmgr; 50 if(l == null) 51 { 52 l = new LinkedList(); 53 bufferMap.put(buffer,l); 54 } 55 56 58 DisplayManager copy = null; 59 Iterator liter = l.iterator(); 60 while(liter.hasNext()) 61 { 62 dmgr = (DisplayManager)liter.next(); 63 copy = dmgr; 64 if(!dmgr.inUse && dmgr.textArea == textArea) 65 { 66 dmgr.inUse = true; 67 return dmgr; 68 } 69 } 70 71 dmgr = new DisplayManager(buffer,textArea,copy); 73 dmgr.inUse = true; 74 l.add(dmgr); 75 76 return dmgr; 77 } 79 static void releaseDisplayManager(DisplayManager dmgr) 81 { 82 dmgr.inUse = false; 83 } 85 public static void bufferClosed(JEditBuffer buffer) 87 { 88 bufferMap.remove(buffer); 89 } 91 static void textAreaDisposed(TextArea textArea) 93 { 94 Iterator biter = bufferMap.values().iterator(); 95 while(biter.hasNext()) 96 { 97 List l = (List)biter.next(); 98 Iterator liter = l.iterator(); 99 while(liter.hasNext()) 100 { 101 DisplayManager dmgr = (DisplayManager) 102 liter.next(); 103 if(dmgr.textArea == textArea) 104 { 105 dmgr.dispose(); 106 liter.remove(); 107 } 108 } 109 } 110 } 112 private static Map bufferMap = new HashMap(); 113 115 119 public JEditBuffer getBuffer() 120 { 121 return buffer; 122 } 124 130 public final boolean isLineVisible(int line) 131 { 132 return folds.search(line) % 2 == 0; 133 } 135 140 public int getFirstVisibleLine() 141 { 142 return folds.first(); 143 } 145 150 public int getLastVisibleLine() 151 { 152 return folds.last(); 153 } 155 161 public int getNextVisibleLine(int line) 162 { 163 if(line < 0 || line >= buffer.getLineCount()) 164 throw new ArrayIndexOutOfBoundsException (line); 165 166 return folds.next(line); 167 } 169 175 public int getPrevVisibleLine(int line) 176 { 177 if(line < 0 || line >= buffer.getLineCount()) 178 throw new ArrayIndexOutOfBoundsException (line); 179 180 return folds.prev(line); 181 } 183 public final int getScreenLineCount(int line) 185 { 186 if(!screenLineMgr.isScreenLineCountValid(line)) 187 throw new RuntimeException ("Invalid screen line count: " + line); 188 189 return screenLineMgr.getScreenLineCount(line); 190 } 192 public final int getScrollLineCount() 194 { 195 return scrollLineCount.scrollLine; 196 } 198 204 public void collapseFold(int line) 205 { 206 int lineCount = buffer.getLineCount(); 207 int start = 0; 208 int end = lineCount - 1; 209 210 if(line != 0 213 && line != buffer.getLineCount() - 1 214 && buffer.isFoldStart(line) 215 && !isLineVisible(line + 1)) 216 { 217 line--; 218 } 219 220 int initialFoldLevel = buffer.getFoldLevel(line); 221 222 if(line != lineCount - 1 224 && buffer.getFoldLevel(line + 1) > initialFoldLevel) 225 { 226 start = line + 1; 228 229 for(int i = line + 1; i < lineCount; i++) 230 { 231 if(buffer.getFoldLevel(i) <= initialFoldLevel) 232 { 233 end = i - 1; 234 break; 235 } 236 } 237 } 238 else 239 { 240 boolean ok = false; 241 242 for(int i = line - 1; i >= 0; i--) 244 { 245 if(buffer.getFoldLevel(i) < initialFoldLevel) 246 { 247 start = i + 1; 248 ok = true; 249 break; 250 } 251 } 252 253 if(!ok) 254 { 255 return; 257 } 258 259 for(int i = line + 1; i < lineCount; i++) 260 { 261 if(buffer.getFoldLevel(i) < initialFoldLevel) 262 { 263 end = i - 1; 264 break; 265 } 266 } 267 } 269 hideLineRange(start,end); 271 272 notifyScreenLineChanges(); 273 textArea.foldStructureChanged(); 274 } 276 283 public int expandFold(int line, boolean fully) 284 { 285 int returnValue = -1; 287 288 int lineCount = buffer.getLineCount(); 289 int start = 0; 290 int end = lineCount - 1; 291 292 int initialFoldLevel = buffer.getFoldLevel(line); 293 294 if(line != lineCount - 1 296 && isLineVisible(line) 297 && !isLineVisible(line + 1) 298 && buffer.getFoldLevel(line + 1) > initialFoldLevel) 299 { 300 302 int index = folds.search(line + 1); 303 if(index == -1) 304 { 305 expandAllFolds(); 306 return -1; 307 } 308 309 start = folds.lookup(index); 310 if(index != folds.count() - 1) 311 end = folds.lookup(index + 1) - 1; 312 else 313 { 314 start = line + 1; 315 316 for(int i = line + 1; i < lineCount; i++) 317 { 318 if( 319 buffer.getFoldLevel(i) <= initialFoldLevel) 320 { 321 end = i - 1; 322 break; 323 } 324 } 325 } 326 } 327 else 328 { 329 int index = folds.search(line); 330 if(index == -1) 331 { 332 expandAllFolds(); 333 return -1; 334 } 335 336 start = folds.lookup(index); 337 if(index != folds.count() - 1) 338 end = folds.lookup(index + 1) - 1; 339 else 340 { 341 for(int i = line + 1; i < lineCount; i++) 342 { 343 if((isLineVisible(i) && 345 buffer.getFoldLevel(i) < initialFoldLevel) 346 || i == getLastVisibleLine()) 347 { 348 end = i - 1; 349 break; 350 } 351 } 352 } 353 } 355 if(fully) 357 { 358 showLineRange(start,end); 359 } 360 else 361 { 362 initialFoldLevel = buffer.getFoldLevel(start); 364 365 int firstVisible = start; 366 367 for(int i = start; i <= end; i++) 368 { 369 if(buffer.getFoldLevel(i) > initialFoldLevel) 370 { 371 if(returnValue == -1 372 && i != 0 373 && buffer.isFoldStart(i - 1)) 374 { 375 returnValue = i - 1; 376 } 377 378 if(firstVisible != i) 379 { 380 showLineRange(firstVisible,i - 1); 381 } 382 firstVisible = i + 1; 383 } 384 } 385 386 if(firstVisible == end + 1) 387 returnValue = -1; 388 else 389 showLineRange(firstVisible,end); 390 391 if(!isLineVisible(line)) 392 { 393 expandFold(line,false); 395 return returnValue; 396 } 397 } 399 notifyScreenLineChanges(); 400 textArea.foldStructureChanged(); 401 402 return returnValue; 403 } 405 410 public void expandAllFolds() 411 { 412 showLineRange(0,buffer.getLineCount() - 1); 413 notifyScreenLineChanges(); 414 textArea.foldStructureChanged(); 415 } 417 422 public void expandFolds(char digit) 423 { 424 if(digit < '1' || digit > '9') 425 { 426 Toolkit.getDefaultToolkit().beep(); 427 return; 428 } 429 else 430 expandFolds((digit - '1') + 1); 431 } 433 439 public void expandFolds(int foldLevel) 440 { 441 if(buffer.getFoldHandler() instanceof IndentFoldHandler) 442 foldLevel = (foldLevel - 1) * buffer.getIndentSize() + 1; 443 444 showLineRange(0,buffer.getLineCount() - 1); 445 446 447 boolean seenVisibleLine = false; 448 449 int firstInvisible = 0; 450 451 for(int i = 0; i < buffer.getLineCount(); i++) 452 { 453 if(!seenVisibleLine || buffer.getFoldLevel(i) < foldLevel) 454 { 455 if(firstInvisible != i) 456 { 457 hideLineRange(firstInvisible, 458 i - 1); 459 } 460 firstInvisible = i + 1; 461 seenVisibleLine = true; 462 } 463 } 464 465 if(firstInvisible != buffer.getLineCount()) 466 hideLineRange(firstInvisible,buffer.getLineCount() - 1); 467 468 notifyScreenLineChanges(); 469 textArea.foldStructureChanged(); 470 } 472 480 public void narrow(int start, int end) 481 { 482 if(start > end || start < 0 || end >= buffer.getLineCount()) 483 throw new ArrayIndexOutOfBoundsException (start + ", " + end); 484 485 if(start < getFirstVisibleLine() || end > getLastVisibleLine()) 486 expandAllFolds(); 487 488 if(start != 0) 489 hideLineRange(0,start - 1); 490 if(end != buffer.getLineCount() - 1) 491 hideLineRange(end + 1,buffer.getLineCount() - 1); 492 493 if(start != buffer.getLineCount() - 1 495 && !isLineVisible(start + 1)) 496 expandFold(start,false); 497 498 textArea.fireNarrowActive(); 499 500 notifyScreenLineChanges(); 501 textArea.foldStructureChanged(); 502 } 504 FirstLine firstLine; 506 ScrollLineCount scrollLineCount; 507 ScreenLineManager screenLineMgr; 508 RangeMap folds; 509 510 void init() 512 { 513 if(initialized) 514 { 515 if(!buffer.isLoading()) 516 resetAnchors(); 517 } 518 else 519 { 520 initialized = true; 521 folds = new RangeMap(); 522 if(buffer.isLoading()) 523 folds.reset(buffer.getLineCount()); 524 else 525 bufferHandler.foldHandlerChanged(buffer); 526 notifyScreenLineChanges(); 527 } 528 } 530 void notifyScreenLineChanges() 532 { 533 if(Debug.SCROLL_DEBUG) 534 Log.log(Log.DEBUG,this,"notifyScreenLineChanges()"); 535 536 if(textArea.getDisplayManager() != this) 539 return; 540 541 try 542 { 543 if(firstLine.callReset) 544 firstLine.reset(); 545 else if(firstLine.callChanged) 546 firstLine.changed(); 547 548 if(scrollLineCount.callReset) 549 { 550 scrollLineCount.reset(); 551 firstLine.ensurePhysicalLineIsVisible(); 552 } 553 else if(scrollLineCount.callChanged) 554 scrollLineCount.changed(); 555 556 if(firstLine.callChanged || scrollLineCount.callReset 557 || scrollLineCount.callChanged) 558 { 559 textArea.updateScrollBar(); 560 textArea.recalculateLastPhysicalLine(); 561 } 562 } 563 finally 564 { 565 firstLine.callReset = firstLine.callChanged = false; 566 scrollLineCount.callReset = scrollLineCount.callChanged = false; 567 } 568 } 570 void setFirstLine(int oldFirstLine, int firstLine) 572 { 573 int visibleLines = textArea.getVisibleLines(); 574 575 if(firstLine >= oldFirstLine + visibleLines) 576 { 577 this.firstLine.scrollDown(firstLine - oldFirstLine); 578 textArea.chunkCache.invalidateAll(); 579 } 580 else if(firstLine <= oldFirstLine - visibleLines) 581 { 582 this.firstLine.scrollUp(oldFirstLine - firstLine); 583 textArea.chunkCache.invalidateAll(); 584 } 585 else if(firstLine > oldFirstLine) 586 { 587 this.firstLine.scrollDown(firstLine - oldFirstLine); 588 textArea.chunkCache.scrollDown(firstLine - oldFirstLine); 589 } 590 else if(firstLine < oldFirstLine) 591 { 592 this.firstLine.scrollUp(oldFirstLine - firstLine); 593 textArea.chunkCache.scrollUp(oldFirstLine - firstLine); 594 } 595 596 notifyScreenLineChanges(); 597 } 599 void setFirstPhysicalLine(int amount, int skew) 601 { 602 int oldFirstLine = textArea.getFirstLine(); 603 604 if(amount == 0) 605 { 606 skew -= this.firstLine.skew; 607 608 if(skew < 0) 611 this.firstLine.scrollUp(-skew); 612 else if(skew > 0) 613 this.firstLine.scrollDown(skew); 614 else 615 { 616 return; 618 } 619 } 620 else if(amount > 0) 621 this.firstLine.physDown(amount,skew); 622 else if(amount < 0) 623 this.firstLine.physUp(-amount,skew); 624 625 int firstLine = textArea.getFirstLine(); 626 int visibleLines = textArea.getVisibleLines(); 627 628 if(firstLine == oldFirstLine) 629 ; 630 else if(firstLine >= oldFirstLine + visibleLines 631 || firstLine <= oldFirstLine - visibleLines) 632 { 633 textArea.chunkCache.invalidateAll(); 634 } 635 else if(firstLine > oldFirstLine) 636 { 637 textArea.chunkCache.scrollDown(firstLine - oldFirstLine); 638 } 639 else if(firstLine < oldFirstLine) 640 { 641 textArea.chunkCache.scrollUp(oldFirstLine - firstLine); 642 } 643 644 notifyScreenLineChanges(); 646 } 648 void invalidateScreenLineCounts() 650 { 651 screenLineMgr.invalidateScreenLineCounts(); 652 firstLine.callReset = true; 653 scrollLineCount.callReset = true; 654 } 656 void updateScreenLineCount(int line) 658 { 659 if(!screenLineMgr.isScreenLineCountValid(line)) 660 { 661 int newCount = textArea.chunkCache 662 .getLineSubregionCount(line); 663 664 setScreenLineCount(line,newCount); 665 } 666 } 668 void bufferLoaded() 670 { 671 folds.reset(buffer.getLineCount()); 672 screenLineMgr.reset(); 673 674 if(textArea.getDisplayManager() == this) 675 { 676 textArea.propertiesChanged(); 677 init(); 678 } 679 680 int collapseFolds = buffer.getIntegerProperty( 681 "collapseFolds",0); 682 if(collapseFolds != 0) 683 expandFolds(collapseFolds); 684 } 686 void foldHandlerChanged() 688 { 689 if(buffer.isLoading()) 690 return; 691 692 folds.reset(buffer.getLineCount()); 693 resetAnchors(); 694 695 int collapseFolds = buffer.getIntegerProperty( 696 "collapseFolds",0); 697 if(collapseFolds != 0) 698 expandFolds(collapseFolds); 699 } 701 703 private boolean initialized; 705 private boolean inUse; 706 private JEditBuffer buffer; 707 private TextArea textArea; 708 private BufferHandler bufferHandler; 709 710 private DisplayManager(JEditBuffer buffer, TextArea textArea, 712 DisplayManager copy) 713 { 714 this.buffer = buffer; 715 this.screenLineMgr = new ScreenLineManager(this,buffer); 716 this.textArea = textArea; 717 718 scrollLineCount = new ScrollLineCount(this,textArea); 719 firstLine = new FirstLine(this,textArea); 720 721 bufferHandler = new BufferHandler(this,textArea,buffer); 722 buffer.addBufferListener(bufferHandler, JEditBuffer.HIGH_PRIORITY); 724 725 if(copy != null) 726 { 727 folds = new RangeMap(copy.folds); 728 initialized = true; 729 } 730 } 732 private void resetAnchors() 734 { 735 firstLine.callReset = true; 736 scrollLineCount.callReset = true; 737 notifyScreenLineChanges(); 738 } 740 private void dispose() 742 { 743 buffer.removeBufferListener(bufferHandler); 744 } 746 private void showLineRange(int start, int end) 748 { 749 if(Debug.FOLD_VIS_DEBUG) 750 { 751 Log.log(Log.DEBUG,this,"showLineRange(" + start 752 + "," + end + ")"); 753 } 754 755 for(int i = start; i <= end; i++) 756 { 757 if(!isLineVisible(i)) 759 { 760 updateScreenLineCount(i); 762 int screenLines = getScreenLineCount(i); 763 if(firstLine.physicalLine >= i) 764 { 765 firstLine.scrollLine += screenLines; 766 firstLine.callChanged = true; 767 } 768 scrollLineCount.scrollLine += screenLines; 769 scrollLineCount.callChanged = true; 770 } 771 } 772 773 774 folds.show(start,end); 775 } 777 private void hideLineRange(int start, int end) 779 { 780 if(Debug.FOLD_VIS_DEBUG) 781 { 782 Log.log(Log.DEBUG,this,"hideLineRange(" + start 783 + "," + end + ")"); 784 } 785 786 int i = start; 787 if(!isLineVisible(i)) 788 i = getNextVisibleLine(i); 789 while(i != -1 && i <= end) 790 { 791 int screenLines = screenLineMgr.getScreenLineCount(i); 792 if(i < firstLine.physicalLine) 793 { 794 firstLine.scrollLine -= screenLines; 795 firstLine.skew = 0; 796 firstLine.callChanged = true; 797 } 798 799 scrollLineCount.scrollLine -= screenLines; 800 scrollLineCount.callChanged = true; 801 802 i = getNextVisibleLine(i); 803 } 804 805 806 folds.hide(start,end); 807 808 if(!isLineVisible(firstLine.physicalLine)) 809 { 810 int firstVisible = getFirstVisibleLine(); 811 if(firstLine.physicalLine < firstVisible) 812 { 813 firstLine.physicalLine = firstVisible; 814 firstLine.scrollLine = 0; 815 } 816 else 817 { 818 firstLine.physicalLine = getPrevVisibleLine( 819 firstLine.physicalLine); 820 firstLine.scrollLine -= 821 screenLineMgr.getScreenLineCount( 822 firstLine.physicalLine); 823 } 824 firstLine.callChanged = true; 825 } 826 } 828 834 private void setScreenLineCount(int line, int count) 835 { 836 int oldCount = screenLineMgr.getScreenLineCount(line); 837 838 841 screenLineMgr.setScreenLineCount(line,count); 842 843 if(count == oldCount) 844 return; 845 846 if(!isLineVisible(line)) 847 return; 848 849 if(firstLine.physicalLine >= line) 850 { 851 if(firstLine.physicalLine == line) 852 firstLine.callChanged = true; 853 else 854 { 855 firstLine.scrollLine += (count - oldCount); 856 firstLine.callChanged = true; 857 } 858 } 859 860 scrollLineCount.scrollLine += (count - oldCount); 861 scrollLineCount.callChanged = true; 862 } 864 } 866 | Popular Tags |