1 11 package org.eclipse.jface.text.source; 12 13 14 import java.util.Iterator ; 15 16 import org.eclipse.swt.SWT; 17 import org.eclipse.swt.custom.StyledText; 18 import org.eclipse.swt.events.DisposeEvent; 19 import org.eclipse.swt.events.DisposeListener; 20 import org.eclipse.swt.events.MouseEvent; 21 import org.eclipse.swt.events.MouseListener; 22 import org.eclipse.swt.events.PaintEvent; 23 import org.eclipse.swt.events.PaintListener; 24 import org.eclipse.swt.graphics.Font; 25 import org.eclipse.swt.graphics.GC; 26 import org.eclipse.swt.graphics.Image; 27 import org.eclipse.swt.graphics.Point; 28 import org.eclipse.swt.graphics.Rectangle; 29 import org.eclipse.swt.widgets.Canvas; 30 import org.eclipse.swt.widgets.Composite; 31 import org.eclipse.swt.widgets.Control; 32 import org.eclipse.swt.widgets.Display; 33 34 35 import org.eclipse.jface.text.BadLocationException; 36 import org.eclipse.jface.text.IDocument; 37 import org.eclipse.jface.text.IRegion; 38 import org.eclipse.jface.text.ITextListener; 39 import org.eclipse.jface.text.ITextViewer; 40 import org.eclipse.jface.text.ITextViewerExtension5; 41 import org.eclipse.jface.text.IViewportListener; 42 import org.eclipse.jface.text.JFaceTextUtil; 43 import org.eclipse.jface.text.Position; 44 import org.eclipse.jface.text.Region; 45 import org.eclipse.jface.text.TextEvent; 46 47 48 58 public final class VerticalRuler implements IVerticalRuler, IVerticalRulerExtension { 59 60 63 class InternalListener implements IViewportListener, IAnnotationModelListener, ITextListener { 64 65 68 public void viewportChanged(int verticalPosition) { 69 if (verticalPosition != fScrollPos) 70 redraw(); 71 } 72 73 76 public void modelChanged(IAnnotationModel model) { 77 update(); 78 } 79 80 83 public void textChanged(TextEvent e) { 84 if (fTextViewer != null && e.getViewerRedrawState()) 85 redraw(); 86 } 87 } 88 89 90 private ITextViewer fTextViewer; 91 92 private Canvas fCanvas; 93 94 private IAnnotationModel fModel; 95 96 private int fScrollPos; 97 98 private Image fBuffer; 99 100 private int fLastMouseButtonActivityLine= -1; 101 102 private InternalListener fInternalListener= new InternalListener(); 103 104 private int fWidth; 105 109 private IAnnotationAccess fAnnotationAccess; 110 111 116 public VerticalRuler(int width) { 117 this(width, null); 118 } 119 120 128 public VerticalRuler(int width, IAnnotationAccess annotationAcccess) { 129 fWidth= width; 130 fAnnotationAccess= annotationAcccess; 131 } 132 133 136 public Control getControl() { 137 return fCanvas; 138 } 139 140 143 public Control createControl(Composite parent, ITextViewer textViewer) { 144 145 fTextViewer= textViewer; 146 147 fCanvas= new Canvas(parent, SWT.NO_BACKGROUND); 148 149 fCanvas.addPaintListener(new PaintListener() { 150 public void paintControl(PaintEvent event) { 151 if (fTextViewer != null) 152 doubleBufferPaint(event.gc); 153 } 154 }); 155 156 fCanvas.addDisposeListener(new DisposeListener() { 157 public void widgetDisposed(DisposeEvent e) { 158 handleDispose(); 159 fTextViewer= null; 160 } 161 }); 162 163 fCanvas.addMouseListener(new MouseListener() { 164 public void mouseUp(MouseEvent event) { 165 } 166 167 public void mouseDown(MouseEvent event) { 168 fLastMouseButtonActivityLine= toDocumentLineNumber(event.y); 169 } 170 171 public void mouseDoubleClick(MouseEvent event) { 172 fLastMouseButtonActivityLine= toDocumentLineNumber(event.y); 173 } 174 }); 175 176 if (fTextViewer != null) { 177 fTextViewer.addViewportListener(fInternalListener); 178 fTextViewer.addTextListener(fInternalListener); 179 } 180 181 return fCanvas; 182 } 183 184 187 private void handleDispose() { 188 189 if (fTextViewer != null) { 190 fTextViewer.removeViewportListener(fInternalListener); 191 fTextViewer.removeTextListener(fInternalListener); 192 fTextViewer= null; 193 } 194 195 if (fModel != null) 196 fModel.removeAnnotationModelListener(fInternalListener); 197 198 if (fBuffer != null) { 199 fBuffer.dispose(); 200 fBuffer= null; 201 } 202 } 203 204 205 210 private void doubleBufferPaint(GC dest) { 211 212 Point size= fCanvas.getSize(); 213 214 if (size.x <= 0 || size.y <= 0) 215 return; 216 217 if (fBuffer != null) { 218 Rectangle r= fBuffer.getBounds(); 219 if (r.width != size.x || r.height != size.y) { 220 fBuffer.dispose(); 221 fBuffer= null; 222 } 223 } 224 if (fBuffer == null) 225 fBuffer= new Image(fCanvas.getDisplay(), size.x, size.y); 226 227 GC gc= new GC(fBuffer); 228 gc.setFont(fTextViewer.getTextWidget().getFont()); 229 try { 230 gc.setBackground(fCanvas.getBackground()); 231 gc.fillRectangle(0, 0, size.x, size.y); 232 233 if (fTextViewer instanceof ITextViewerExtension5) 234 doPaint1(gc); 235 else 236 doPaint(gc); 237 238 } finally { 239 gc.dispose(); 240 } 241 242 dest.drawImage(fBuffer, 0, 0); 243 } 244 245 252 private int getInclusiveTopIndexStartOffset() { 253 254 StyledText textWidget= fTextViewer.getTextWidget(); 255 if (textWidget != null && !textWidget.isDisposed()) { 256 int top= JFaceTextUtil.getPartialTopIndex(fTextViewer); 257 try { 258 IDocument document= fTextViewer.getDocument(); 259 return document.getLineOffset(top); 260 } catch (BadLocationException x) { 261 } 262 } 263 264 return -1; 265 } 266 267 268 269 274 protected void doPaint(GC gc) { 275 276 if (fModel == null || fTextViewer == null) 277 return; 278 279 IAnnotationAccessExtension annotationAccessExtension= null; 280 if (fAnnotationAccess instanceof IAnnotationAccessExtension) 281 annotationAccessExtension= (IAnnotationAccessExtension) fAnnotationAccess; 282 283 StyledText styledText= fTextViewer.getTextWidget(); 284 IDocument doc= fTextViewer.getDocument(); 285 286 int topLeft= getInclusiveTopIndexStartOffset(); 287 int bottomRight= fTextViewer.getBottomIndexEndOffset(); 288 int viewPort= bottomRight - topLeft; 289 290 Point d= fCanvas.getSize(); 291 fScrollPos= styledText.getTopPixel(); 292 293 int topLine= -1, bottomLine= -1; 294 try { 295 IRegion region= fTextViewer.getVisibleRegion(); 296 topLine= doc.getLineOfOffset(region.getOffset()); 297 bottomLine= doc.getLineOfOffset(region.getOffset() + region.getLength()); 298 } catch (BadLocationException x) { 299 return; 300 } 301 302 Rectangle r= new Rectangle(0, 0, 0, 0); 304 int maxLayer= 1; 306 for (int layer= 0; layer < maxLayer; layer++) { 307 Iterator iter= fModel.getAnnotationIterator(); 308 while (iter.hasNext()) { 309 IAnnotationPresentation annotationPresentation= null; 310 Annotation annotation= (Annotation) iter.next(); 311 312 int lay= IAnnotationAccessExtension.DEFAULT_LAYER; 313 if (annotationAccessExtension != null) 314 lay= annotationAccessExtension.getLayer(annotation); 315 else if (annotation instanceof IAnnotationPresentation) { 316 annotationPresentation= (IAnnotationPresentation)annotation; 317 lay= annotationPresentation.getLayer(); 318 } 319 maxLayer= Math.max(maxLayer, lay+1); if (lay != layer) continue; 322 323 Position position= fModel.getPosition(annotation); 324 if (position == null) 325 continue; 326 327 if (!position.overlapsWith(topLeft, viewPort)) 328 continue; 329 330 try { 331 332 int offset= position.getOffset(); 333 int length= position.getLength(); 334 335 int startLine= doc.getLineOfOffset(offset); 336 if (startLine < topLine) 337 startLine= topLine; 338 339 int endLine= startLine; 340 if (length > 0) 341 endLine= doc.getLineOfOffset(offset + length - 1); 342 if (endLine > bottomLine) 343 endLine= bottomLine; 344 345 startLine -= topLine; 346 endLine -= topLine; 347 348 r.x= 0; 349 r.y= JFaceTextUtil.computeLineHeight(styledText, 0, startLine, startLine) - fScrollPos; 350 351 r.width= d.x; 352 int lines= endLine - startLine; 353 354 r.height= JFaceTextUtil.computeLineHeight(styledText, startLine, endLine + 1, (lines+1)); 355 356 if (r.y < d.y && annotationAccessExtension != null) annotationAccessExtension.paint(annotation, gc, fCanvas, r); 358 else if (annotationPresentation != null) 359 annotationPresentation.paint(gc, fCanvas, r); 360 361 } catch (BadLocationException e) { 362 } 363 } 364 } 365 } 366 367 374 protected void doPaint1(GC gc) { 375 376 if (fModel == null || fTextViewer == null) 377 return; 378 379 IAnnotationAccessExtension annotationAccessExtension= null; 380 if (fAnnotationAccess instanceof IAnnotationAccessExtension) 381 annotationAccessExtension= (IAnnotationAccessExtension) fAnnotationAccess; 382 383 ITextViewerExtension5 extension= (ITextViewerExtension5) fTextViewer; 384 StyledText textWidget= fTextViewer.getTextWidget(); 385 386 fScrollPos= textWidget.getTopPixel(); 387 Point dimension= fCanvas.getSize(); 388 389 Rectangle r= new Rectangle(0, 0, 0, 0); 391 int maxLayer= 1; 393 for (int layer= 0; layer < maxLayer; layer++) { 394 Iterator iter= fModel.getAnnotationIterator(); 395 while (iter.hasNext()) { 396 IAnnotationPresentation annotationPresentation= null; 397 Annotation annotation= (Annotation) iter.next(); 398 399 int lay= IAnnotationAccessExtension.DEFAULT_LAYER; 400 if (annotationAccessExtension != null) 401 lay= annotationAccessExtension.getLayer(annotation); 402 else if (annotation instanceof IAnnotationPresentation) { 403 annotationPresentation= (IAnnotationPresentation)annotation; 404 lay= annotationPresentation.getLayer(); 405 } 406 maxLayer= Math.max(maxLayer, lay+1); if (lay != layer) continue; 409 410 Position position= fModel.getPosition(annotation); 411 if (position == null) 412 continue; 413 414 IRegion widgetRegion= extension.modelRange2WidgetRange(new Region(position.getOffset(), position.getLength())); 415 if (widgetRegion == null) 416 continue; 417 418 int startLine= extension.widgetLineOfWidgetOffset(widgetRegion.getOffset()); 419 if (startLine == -1) 420 continue; 421 422 int endLine= extension.widgetLineOfWidgetOffset(widgetRegion.getOffset() + Math.max(widgetRegion.getLength() -1, 0)); 423 if (endLine == -1) 424 continue; 425 426 r.x= 0; 427 r.y= JFaceTextUtil.computeLineHeight(textWidget, 0, startLine, startLine) - fScrollPos; 428 429 r.width= dimension.x; 430 int lines= endLine - startLine; 431 432 r.height= JFaceTextUtil.computeLineHeight(textWidget, startLine, endLine + 1, lines+1); 433 434 if (r.y < dimension.y && annotationAccessExtension != null) annotationAccessExtension.paint(annotation, gc, fCanvas, r); 436 else if (annotationPresentation != null) 437 annotationPresentation.paint(gc, fCanvas, r); 438 } 439 } 440 } 441 442 446 449 public void update() { 450 if (fCanvas != null && !fCanvas.isDisposed()) { 451 Display d= fCanvas.getDisplay(); 452 if (d != null) { 453 d.asyncExec(new Runnable () { 454 public void run() { 455 redraw(); 456 } 457 }); 458 } 459 } 460 } 461 462 465 private void redraw() { 466 if (fCanvas != null && !fCanvas.isDisposed()) { 467 GC gc= new GC(fCanvas); 468 doubleBufferPaint(gc); 469 gc.dispose(); 470 } 471 } 472 473 476 public void setModel(IAnnotationModel model) { 477 if (model != fModel) { 478 479 if (fModel != null) 480 fModel.removeAnnotationModelListener(fInternalListener); 481 482 fModel= model; 483 484 if (fModel != null) 485 fModel.addAnnotationModelListener(fInternalListener); 486 487 update(); 488 } 489 } 490 491 494 public IAnnotationModel getModel() { 495 return fModel; 496 } 497 498 501 public int getWidth() { 502 return fWidth; 503 } 504 505 508 public int getLineOfLastMouseButtonActivity() { 509 return fLastMouseButtonActivityLine; 510 } 511 512 515 public int toDocumentLineNumber(int y_coordinate) { 516 if (fTextViewer == null || y_coordinate == -1) 517 return -1; 518 519 StyledText text= fTextViewer.getTextWidget(); 520 int line= text.getLineIndex(y_coordinate); 521 522 if (line == text.getLineCount() - 1) { 523 if (y_coordinate > text.getLinePixel(line + 1)) 525 return -1; 526 } 527 528 return widgetLine2ModelLine(fTextViewer, line); 529 } 530 531 539 protected final static int widgetLine2ModelLine(ITextViewer viewer, int widgetLine) { 540 541 if (viewer instanceof ITextViewerExtension5) { 542 ITextViewerExtension5 extension= (ITextViewerExtension5) viewer; 543 return extension.widgetLine2ModelLine(widgetLine); 544 } 545 546 try { 547 IRegion r= viewer.getVisibleRegion(); 548 IDocument d= viewer.getDocument(); 549 return widgetLine += d.getLineOfOffset(r.getOffset()); 550 } catch (BadLocationException x) { 551 } 552 return widgetLine; 553 } 554 555 559 public void setFont(Font font) { 560 } 561 562 566 public void setLocationOfLastMouseButtonActivity(int x, int y) { 567 fLastMouseButtonActivityLine= toDocumentLineNumber(y); 568 } 569 570 577 public void addMouseListener(MouseListener listener) { 578 if (fCanvas != null && !fCanvas.isDisposed()) 579 fCanvas.addMouseListener(listener); 580 } 581 582 589 public void removeMouseListener(MouseListener listener) { 590 if (fCanvas != null && !fCanvas.isDisposed()) 591 fCanvas.removeMouseListener(listener); 592 } 593 } 594 | Popular Tags |