1 11 package org.eclipse.jface.text; 12 13 14 import java.util.ArrayList ; 15 import java.util.Iterator ; 16 import java.util.NoSuchElementException ; 17 18 import org.eclipse.swt.custom.StyleRange; 19 import org.eclipse.swt.custom.StyledText; 20 21 import org.eclipse.core.runtime.Assert; 22 23 24 37 public class TextPresentation { 38 39 46 public static void applyTextPresentation(TextPresentation presentation, StyledText text) { 47 48 StyleRange[] ranges= new StyleRange[presentation.getDenumerableRanges()]; 49 50 int i= 0; 51 Iterator e= presentation.getAllStyleRangeIterator(); 52 while (e.hasNext()) 53 ranges[i++]= (StyleRange) e.next(); 54 55 text.setStyleRanges(ranges); 56 } 57 58 59 60 61 64 class FilterIterator implements Iterator { 65 66 67 protected int fIndex; 68 69 protected int fLength; 70 71 protected boolean fSkipDefaults; 72 73 protected IRegion fWindow; 74 75 81 protected FilterIterator(boolean skipDefaults) { 82 83 fSkipDefaults= skipDefaults; 84 85 fWindow= fResultWindow; 86 fIndex= getFirstIndexInWindow(fWindow); 87 fLength= getFirstIndexAfterWindow(fWindow); 88 89 if (fSkipDefaults) 90 computeIndex(); 91 } 92 93 96 public Object next() { 97 try { 98 StyleRange r= (StyleRange) fRanges.get(fIndex++); 99 return createWindowRelativeRange(fWindow, r); 100 } catch (ArrayIndexOutOfBoundsException x) { 101 throw new NoSuchElementException (); 102 } finally { 103 if (fSkipDefaults) 104 computeIndex(); 105 } 106 } 107 108 111 public boolean hasNext() { 112 return fIndex < fLength; 113 } 114 115 118 public void remove() { 119 throw new UnsupportedOperationException (); 120 } 121 122 128 protected boolean skip(Object o) { 129 StyleRange r= (StyleRange) o; 130 return r.similarTo(fDefaultRange); 131 } 132 133 136 protected void computeIndex() { 137 while (fIndex < fLength && skip(fRanges.get(fIndex))) 138 ++ fIndex; 139 } 140 } 141 142 143 private StyleRange fDefaultRange; 144 145 private ArrayList fRanges; 146 147 private IRegion fResultWindow; 148 152 private IRegion fExtent; 153 154 155 158 public TextPresentation() { 159 fRanges= new ArrayList (50); 160 } 161 162 168 public TextPresentation(int sizeHint) { 169 Assert.isTrue(sizeHint > 0); 170 fRanges= new ArrayList (sizeHint); 171 } 172 173 181 public TextPresentation(IRegion extent, int sizeHint) { 182 this(sizeHint); 183 Assert.isNotNull(extent); 184 fExtent= extent; 185 } 186 187 196 public void setResultWindow(IRegion resultWindow) { 197 fResultWindow= resultWindow; 198 } 199 200 207 public void setDefaultStyleRange(StyleRange range) { 208 fDefaultRange= range; 209 } 210 211 217 public StyleRange getDefaultStyleRange() { 218 StyleRange range= createWindowRelativeRange(fResultWindow, fDefaultRange); 219 if (range == null) 220 return null; 221 return (StyleRange)range.clone(); 222 223 } 224 225 231 public void addStyleRange(StyleRange range) { 232 checkConsistency(range); 233 fRanges.add(range); 234 } 235 236 243 public void replaceStyleRange(StyleRange range) { 244 applyStyleRange(range, false); 245 } 246 247 254 public void mergeStyleRange(StyleRange range) { 255 applyStyleRange(range, true); 256 } 257 258 266 private void applyStyleRange(StyleRange range, boolean merge) { 267 if (range.length == 0) 268 return; 269 270 checkConsistency(range); 271 272 int start= range.start; 273 int length= range.length; 274 int end= start + length; 275 276 if (fRanges.size() == 0) { 277 StyleRange defaultRange= getDefaultStyleRange(); 278 if (defaultRange == null) 279 defaultRange= range; 280 281 defaultRange.start= start; 282 defaultRange.length= length; 283 applyStyle(range, defaultRange, merge); 284 fRanges.add(defaultRange); 285 } else { 286 IRegion rangeRegion= new Region(start, length); 287 int first= getFirstIndexInWindow(rangeRegion); 288 289 if (first == fRanges.size()) { 290 StyleRange defaultRange= getDefaultStyleRange(); 291 if (defaultRange == null) 292 defaultRange= range; 293 defaultRange.start= start; 294 defaultRange.length= length; 295 applyStyle(range, defaultRange, merge); 296 fRanges.add(defaultRange); 297 return; 298 } 299 300 int last= getFirstIndexAfterWindow(rangeRegion); 301 for (int i= first; i < last && length > 0; i++) { 302 303 StyleRange current= (StyleRange)fRanges.get(i); 304 int currentStart= current.start; 305 int currentEnd= currentStart + current.length; 306 307 if (end <= currentStart) { 308 fRanges.add(i, range); 309 return; 310 } 311 312 if (start >= currentEnd) 313 continue; 314 315 StyleRange currentCopy= null; 316 if (end < currentEnd) 317 currentCopy= (StyleRange)current.clone(); 318 319 if (start < currentStart) { 320 StyleRange defaultRange= getDefaultStyleRange(); 322 if (defaultRange == null) 323 defaultRange= new StyleRange(); 324 325 defaultRange.start= start; 326 defaultRange.length= currentStart - start; 327 applyStyle(range, defaultRange, merge); 328 fRanges.add(i, defaultRange); 329 i++; last++; 330 331 332 current.length= Math.min(end, currentEnd) - currentStart; 334 applyStyle(range, current, merge); 335 } 336 337 if (start >= currentStart) { 338 current.length= start - currentStart; 340 341 if (current.length > 0) { 343 current= (StyleRange)current.clone(); 344 i++; last++; 345 fRanges.add(i, current); 346 } 347 applyStyle(range, current, merge); 348 current.start= start; 349 current.length= Math.min(end, currentEnd) - start; 350 } 351 352 if (end < currentEnd) { 353 currentCopy.start= end; 355 currentCopy.length= currentEnd - end; 356 i++; last++; 357 fRanges.add(i, currentCopy); 358 } 359 360 range.start= currentEnd; 362 range.length= Math.max(end - currentEnd, 0); 363 start= range.start; 364 length= range.length; 365 } 366 if (length > 0) { 367 StyleRange defaultRange= getDefaultStyleRange(); 369 if (defaultRange == null) 370 defaultRange= range; 371 defaultRange.start= start; 372 defaultRange.length= end - start; 373 defaultRange.background= range.background; 374 fRanges.add(last, defaultRange); 375 } 376 } 377 } 378 379 387 public void replaceStyleRanges(StyleRange[] ranges) { 388 applyStyleRanges(ranges, false); 389 } 390 391 399 public void mergeStyleRanges(StyleRange[] ranges) { 400 applyStyleRanges(ranges, true); 401 } 402 403 412 private void applyStyleRanges(StyleRange[] ranges, boolean merge) { 413 int j= 0; 414 ArrayList oldRanges= fRanges; 415 ArrayList newRanges= new ArrayList (2*ranges.length + oldRanges.size()); 416 for (int i= 0, n= ranges.length; i < n; i++) { 417 StyleRange range= ranges[i]; 418 fRanges= oldRanges; for (int m= getFirstIndexAfterWindow(new Region(range.start, range.length)); j < m; j++) 420 newRanges.add(oldRanges.get(j)); 421 fRanges= newRanges; applyStyleRange(range, merge); 423 } 424 for (int m= oldRanges.size(); j < m; j++) 425 newRanges.add(oldRanges.get(j)); 426 fRanges= newRanges; 427 } 428 429 437 private void applyStyle(StyleRange template, StyleRange target, boolean merge) { 438 if (merge) { 439 if (template.font != null) 440 target.font= template.font; 441 if (template.metrics != null) 442 target.metrics= template.metrics; 443 if (template.foreground != null) 444 target.foreground= template.foreground; 445 if (template.background != null) 446 target.background= template.background; 447 target.fontStyle |= template.fontStyle; 448 target.strikeout= template.strikeout || target.strikeout; 449 target.underline= template.underline || target.underline; 450 } else { 451 target.foreground= template.foreground; 452 target.background= template.background; 453 target.fontStyle= template.fontStyle; 454 target.strikeout= template.strikeout; 455 target.underline= template.underline; 456 target.font= template.font; 457 target.metrics= template.metrics; 458 } 459 } 460 461 468 private void checkConsistency(StyleRange range) { 469 470 if (range == null) 471 throw new IllegalArgumentException (); 472 473 if (fDefaultRange != null) { 474 475 if (range.start < fDefaultRange.start) 476 range.start= fDefaultRange.start; 477 478 int defaultEnd= fDefaultRange.start + fDefaultRange.length; 479 int end= range.start + range.length; 480 if (end > defaultEnd) 481 range.length -= (end - defaultEnd); 482 } 483 } 484 485 492 private int getFirstIndexInWindow(IRegion window) { 493 if (window != null) { 494 int start= window.getOffset(); 495 int i= -1, j= fRanges.size(); 496 while (j - i > 1) { 497 int k= (i + j) >> 1; 498 StyleRange r= (StyleRange) fRanges.get(k); 499 if (r.start + r.length > start) 500 j= k; 501 else 502 i= k; 503 } 504 return j; 505 } 506 return 0; 507 } 508 509 516 private int getFirstIndexAfterWindow(IRegion window) { 517 if (window != null) { 518 int end= window.getOffset() + window.getLength(); 519 int i= -1, j= fRanges.size(); 520 while (j - i > 1) { 521 int k= (i + j) >> 1; 522 StyleRange r= (StyleRange) fRanges.get(k); 523 if (r.start < end) 524 i= k; 525 else 526 j= k; 527 } 528 return j; 529 } 530 return fRanges.size(); 531 } 532 533 542 private StyleRange createWindowRelativeRange(IRegion window, StyleRange range) { 543 if (window == null || range == null) 544 return range; 545 546 int start= range.start - window.getOffset(); 547 if (start < 0) 548 start= 0; 549 550 int rangeEnd= range.start + range.length; 551 int windowEnd= window.getOffset() + window.getLength(); 552 int end= (rangeEnd > windowEnd ? windowEnd : rangeEnd); 553 end -= window.getOffset(); 554 555 StyleRange newRange= (StyleRange) range.clone(); 556 newRange.start= start; 557 newRange.length= end - start; 558 return newRange; 559 } 560 561 569 private IRegion createWindowRelativeRegion(IRegion coverage) { 570 if (fResultWindow == null || coverage == null) 571 return coverage; 572 573 int start= coverage.getOffset() - fResultWindow.getOffset(); 574 if (start < 0) 575 start= 0; 576 577 int rangeEnd= coverage.getOffset() + coverage.getLength(); 578 int windowEnd= fResultWindow.getOffset() + fResultWindow.getLength(); 579 int end= (rangeEnd > windowEnd ? windowEnd : rangeEnd); 580 end -= fResultWindow.getOffset(); 581 582 return new Region(start, end - start); 583 } 584 585 592 public Iterator getNonDefaultStyleRangeIterator() { 593 return new FilterIterator(fDefaultRange != null); 594 } 595 596 603 public Iterator getAllStyleRangeIterator() { 604 return new FilterIterator(false); 605 } 606 607 613 public boolean isEmpty() { 614 return (fDefaultRange == null && getDenumerableRanges() == 0); 615 } 616 617 623 public int getDenumerableRanges() { 624 int size= getFirstIndexAfterWindow(fResultWindow) - getFirstIndexInWindow(fResultWindow); 625 return (size < 0 ? 0 : size); 626 } 627 628 634 public StyleRange getFirstStyleRange() { 635 try { 636 637 StyleRange range= (StyleRange) fRanges.get(getFirstIndexInWindow(fResultWindow)); 638 return createWindowRelativeRange(fResultWindow, range); 639 640 } catch (NoSuchElementException x) { 641 } catch (IndexOutOfBoundsException x) { 642 } 643 644 return null; 645 } 646 647 652 public StyleRange getLastStyleRange() { 653 try { 654 655 StyleRange range= (StyleRange) fRanges.get(getFirstIndexAfterWindow(fResultWindow) - 1); 656 return createWindowRelativeRange(fResultWindow, range); 657 658 } catch (NoSuchElementException x) { 659 return null; 660 } catch (IndexOutOfBoundsException x) { 661 return null; 662 } 663 } 664 665 671 public IRegion getCoverage() { 672 673 if (fDefaultRange != null) { 674 StyleRange range= getDefaultStyleRange(); 675 return new Region(range.start, range.length); 676 } 677 678 StyleRange first= getFirstStyleRange(); 679 StyleRange last= getLastStyleRange(); 680 681 if (first == null || last == null) 682 return null; 683 684 return new Region(first.start, last.start - first. start + last.length); 685 } 686 687 694 public IRegion getExtent() { 695 if (fExtent != null) 696 return createWindowRelativeRegion(fExtent); 697 return getCoverage(); 698 } 699 700 704 public void clear() { 705 fDefaultRange= null; 706 fResultWindow= null; 707 fRanges.clear(); 708 } 709 710 711 } 712 | Popular Tags |