KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > text > source > ChangeRulerColumn


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jface.text.source;
12
13 import org.eclipse.swt.SWT;
14 import org.eclipse.swt.custom.StyledText;
15 import org.eclipse.swt.events.DisposeEvent;
16 import org.eclipse.swt.events.DisposeListener;
17 import org.eclipse.swt.events.MouseEvent;
18 import org.eclipse.swt.events.MouseListener;
19 import org.eclipse.swt.events.MouseMoveListener;
20 import org.eclipse.swt.events.PaintEvent;
21 import org.eclipse.swt.events.PaintListener;
22 import org.eclipse.swt.graphics.Color;
23 import org.eclipse.swt.graphics.Font;
24 import org.eclipse.swt.graphics.GC;
25 import org.eclipse.swt.graphics.Image;
26 import org.eclipse.swt.graphics.Point;
27 import org.eclipse.swt.graphics.Rectangle;
28 import org.eclipse.swt.widgets.Canvas;
29 import org.eclipse.swt.widgets.Composite;
30 import org.eclipse.swt.widgets.Control;
31 import org.eclipse.swt.widgets.Display;
32
33 import org.eclipse.core.runtime.Assert;
34
35 import org.eclipse.jface.internal.text.revisions.RevisionPainter;
36 import org.eclipse.jface.internal.text.source.DiffPainter;
37 import org.eclipse.jface.viewers.ISelectionProvider;
38
39 import org.eclipse.jface.text.BadLocationException;
40 import org.eclipse.jface.text.IDocument;
41 import org.eclipse.jface.text.IRegion;
42 import org.eclipse.jface.text.ITextListener;
43 import org.eclipse.jface.text.ITextViewer;
44 import org.eclipse.jface.text.ITextViewerExtension5;
45 import org.eclipse.jface.text.IViewportListener;
46 import org.eclipse.jface.text.JFaceTextUtil;
47 import org.eclipse.jface.text.TextEvent;
48 import org.eclipse.jface.text.revisions.IRevisionRulerColumn;
49 import org.eclipse.jface.text.revisions.RevisionInformation;
50
51 /**
52  * A vertical ruler column displaying line numbers and serving as a UI for quick diff.
53  * Clients instantiate and configure object of this class.
54  *
55  * @since 3.0
56  */

57 public final class ChangeRulerColumn implements IVerticalRulerColumn, IVerticalRulerInfo, IVerticalRulerInfoExtension, IChangeRulerColumn, IRevisionRulerColumn {
58     /**
59      * Handles all the mouse interaction in this line number ruler column.
60      */

61     private class MouseHandler implements MouseListener, MouseMoveListener {
62
63         /*
64          * @see org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent)
65          */

66         public void mouseUp(MouseEvent event) {
67         }
68
69         /*
70          * @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
71          */

72         public void mouseDown(MouseEvent event) {
73             fParentRuler.setLocationOfLastMouseButtonActivity(event.x, event.y);
74         }
75
76         /*
77          * @see org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
78          */

79         public void mouseDoubleClick(MouseEvent event) {
80             fParentRuler.setLocationOfLastMouseButtonActivity(event.x, event.y);
81         }
82
83         /*
84          * @see org.eclipse.swt.events.MouseMoveListener#mouseMove(org.eclipse.swt.events.MouseEvent)
85          */

86         public void mouseMove(MouseEvent event) {
87             fParentRuler.setLocationOfLastMouseButtonActivity(event.x, event.y);
88         }
89     }
90
91     /**
92      * Internal listener class.
93      */

94     private class InternalListener implements IViewportListener, ITextListener {
95
96         /*
97          * @see IViewportListener#viewportChanged(int)
98          */

99         public void viewportChanged(int verticalPosition) {
100             if (verticalPosition != fScrollPos)
101                 redraw();
102         }
103
104         /*
105          * @see ITextListener#textChanged(TextEvent)
106          */

107         public void textChanged(TextEvent event) {
108
109             if (!event.getViewerRedrawState())
110                 return;
111
112             if (fSensitiveToTextChanges || event.getDocumentEvent() == null)
113                 postRedraw();
114
115         }
116     }
117     
118     /**
119      * The view(port) listener.
120      */

121     private final InternalListener fInternalListener= new InternalListener();
122     /**
123      * The mouse handler.
124      * @since 3.2
125      */

126     private final MouseHandler fMouseHandler= new MouseHandler();
127     /**
128      * The revision painter.
129      * @since 3.2
130      */

131     private final RevisionPainter fRevisionPainter;
132     /**
133      * The diff info painter.
134      * @since 3.2
135      */

136     private final DiffPainter fDiffPainter;
137
138     /** This column's parent ruler */
139     private CompositeRuler fParentRuler;
140     /** Cached text viewer */
141     private ITextViewer fCachedTextViewer;
142     /** Cached text widget */
143     private StyledText fCachedTextWidget;
144     /** The columns canvas */
145     private Canvas fCanvas;
146     /** The background color */
147     private Color fBackground;
148     /** The ruler's annotation model. */
149     private IAnnotationModel fAnnotationModel;
150     /** The width of the change ruler column. */
151     private final int fWidth= 5;
152     
153     /** Cache for the actual scroll position in pixels */
154     private int fScrollPos;
155     /** The buffer for double buffering */
156     private Image fBuffer;
157     /** Indicates whether this column reacts on text change events */
158     private boolean fSensitiveToTextChanges= false;
159
160     /**
161      * Creates a new ruler column.
162      *
163      * @deprecated since 3.2 use {@link #ChangeRulerColumn(ISharedTextColors)} instead
164      */

165     public ChangeRulerColumn() {
166         fRevisionPainter= null;
167         fDiffPainter= new DiffPainter(this, null);
168     }
169     
170     /**
171      * Creates a new revision ruler column.
172      *
173      * @param sharedColors the colors to look up RGBs
174      * @since 3.2
175      */

176     public ChangeRulerColumn(ISharedTextColors sharedColors) {
177         Assert.isNotNull(sharedColors);
178         fRevisionPainter= new RevisionPainter(this, sharedColors);
179         fDiffPainter= new DiffPainter(this, null); // no shading
180
}
181     
182     /**
183      * Returns the System background color for list widgets.
184      *
185      * @return the System background color for list widgets
186      */

187     private Color getBackground() {
188         if (fBackground == null)
189             return fCachedTextWidget.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
190         return fBackground;
191     }
192
193     /*
194      * @see IVerticalRulerColumn#createControl(CompositeRuler, Composite)
195      */

196     public Control createControl(CompositeRuler parentRuler, Composite parentControl) {
197
198         fParentRuler= parentRuler;
199         fCachedTextViewer= parentRuler.getTextViewer();
200         fCachedTextWidget= fCachedTextViewer.getTextWidget();
201
202         fCanvas= new Canvas(parentControl, SWT.NONE);
203         fCanvas.setBackground(getBackground());
204
205         fCanvas.addPaintListener(new PaintListener() {
206             public void paintControl(PaintEvent event) {
207                 if (fCachedTextViewer != null)
208                     doubleBufferPaint(event.gc);
209             }
210         });
211
212         fCanvas.addDisposeListener(new DisposeListener() {
213             public void widgetDisposed(DisposeEvent e) {
214                 handleDispose();
215                 fCachedTextViewer= null;
216                 fCachedTextWidget= null;
217             }
218         });
219
220         fCanvas.addMouseListener(fMouseHandler);
221         fCanvas.addMouseMoveListener(fMouseHandler);
222
223         if (fCachedTextViewer != null) {
224
225             fCachedTextViewer.addViewportListener(fInternalListener);
226             fCachedTextViewer.addTextListener(fInternalListener);
227         }
228         
229         fRevisionPainter.setParentRuler(parentRuler);
230         fDiffPainter.setParentRuler(parentRuler);
231
232         return fCanvas;
233     }
234
235     /**
236      * Disposes the column's resources.
237      */

238     protected void handleDispose() {
239
240         if (fCachedTextViewer != null) {
241             fCachedTextViewer.removeViewportListener(fInternalListener);
242             fCachedTextViewer.removeTextListener(fInternalListener);
243         }
244
245         if (fBuffer != null) {
246             fBuffer.dispose();
247             fBuffer= null;
248         }
249     }
250
251     /**
252      * Double buffer drawing.
253      *
254      * @param dest the GC to draw into
255      */

256     private void doubleBufferPaint(GC dest) {
257
258         Point size= fCanvas.getSize();
259
260         if (size.x <= 0 || size.y <= 0)
261             return;
262
263         if (fBuffer != null) {
264             Rectangle r= fBuffer.getBounds();
265             if (r.width != size.x || r.height != size.y) {
266                 fBuffer.dispose();
267                 fBuffer= null;
268             }
269         }
270         if (fBuffer == null)
271             fBuffer= new Image(fCanvas.getDisplay(), size.x, size.y);
272
273         GC gc= new GC(fBuffer);
274         gc.setFont(fCanvas.getFont());
275
276         try {
277             gc.setBackground(getBackground());
278             gc.fillRectangle(0, 0, size.x, size.y);
279
280             doPaint(gc);
281         } finally {
282             gc.dispose();
283         }
284
285         dest.drawImage(fBuffer, 0, 0);
286     }
287
288     /**
289      * Returns the view port height in lines.
290      *
291      * @return the view port height in lines
292      * @deprecated as of 3.2 the number of lines in the viewport cannot be computed because
293      * StyledText supports variable line heights
294      */

295     protected int getVisibleLinesInViewport() {
296         // Hack to reduce amount of copied code.
297
return LineNumberRulerColumn.getVisibleLinesInViewport(fCachedTextWidget);
298     }
299
300     /**
301      * Returns <code>true</code> if the viewport displays the entire viewer contents, i.e. the
302      * viewer is not vertically scrollable.
303      *
304      * @return <code>true</code> if the viewport displays the entire contents, <code>false</code> otherwise
305      * @since 3.2
306      */

307     protected final boolean isViewerCompletelyShown() {
308         return JFaceTextUtil.isShowingEntireContents(fCachedTextWidget);
309     }
310
311     /**
312      * Draws the ruler column.
313      *
314      * @param gc the GC to draw into
315      */

316     private void doPaint(GC gc) {
317         ILineRange visibleModelLines= computeVisibleModelLines();
318         if (visibleModelLines == null)
319             return;
320
321         fSensitiveToTextChanges= isViewerCompletelyShown();
322
323         fScrollPos= fCachedTextWidget.getTopPixel();
324
325         fRevisionPainter.paint(gc, visibleModelLines);
326         if (!fRevisionPainter.hasInformation()) // don't paint quick diff colors if revisions are painted
327
fDiffPainter.paint(gc, visibleModelLines);
328     }
329
330     /*
331      * @see IVerticalRulerColumn#redraw()
332      */

333     public void redraw() {
334
335         if (fCachedTextViewer != null && fCanvas != null && !fCanvas.isDisposed()) {
336             GC gc= new GC(fCanvas);
337             doubleBufferPaint(gc);
338             gc.dispose();
339         }
340     }
341
342     /*
343      * @see IVerticalRulerColumn#setFont(Font)
344      */

345     public void setFont(Font font) {
346     }
347
348     /**
349      * Returns the parent (composite) ruler of this ruler column.
350      *
351      * @return the parent ruler
352      * @since 3.0
353      */

354     private CompositeRuler getParentRuler() {
355         return fParentRuler;
356     }
357
358     /*
359      * @see org.eclipse.jface.text.source.IVerticalRulerInfo#getLineOfLastMouseButtonActivity()
360      */

361     public int getLineOfLastMouseButtonActivity() {
362         return getParentRuler().getLineOfLastMouseButtonActivity();
363     }
364
365     /*
366      * @see org.eclipse.jface.text.source.IVerticalRulerInfo#toDocumentLineNumber(int)
367      */

368     public int toDocumentLineNumber(int y_coordinate) {
369         return getParentRuler().toDocumentLineNumber(y_coordinate);
370     }
371
372     /*
373      * @see org.eclipse.jface.text.source.IVerticalRulerInfoExtension#getHover()
374      */

375     public IAnnotationHover getHover() {
376         int activeLine= getParentRuler().getLineOfLastMouseButtonActivity();
377         if (fRevisionPainter.hasHover(activeLine))
378             return fRevisionPainter.getHover();
379         if (fDiffPainter.hasHover(activeLine))
380             return fDiffPainter.getHover();
381         return null;
382     }
383
384     /*
385      * @see org.eclipse.jface.text.source.IChangeRulerColumn#setHover(org.eclipse.jface.text.source.IAnnotationHover)
386      */

387     public void setHover(IAnnotationHover hover) {
388         fRevisionPainter.setHover(hover);
389         fDiffPainter.setHover(hover);
390     }
391
392     /*
393      * @see IVerticalRulerColumn#setModel(IAnnotationModel)
394      */

395     public void setModel(IAnnotationModel model) {
396         setAnnotationModel(model);
397         fRevisionPainter.setModel(model);
398         fDiffPainter.setModel(model);
399     }
400
401     private void setAnnotationModel(IAnnotationModel model) {
402         if (fAnnotationModel != model)
403             fAnnotationModel= model;
404     }
405
406     /*
407      * @see org.eclipse.jface.text.source.IChangeRulerColumn#setBackground(org.eclipse.swt.graphics.Color)
408      */

409     public void setBackground(Color background) {
410         fBackground= background;
411         if (fCanvas != null && !fCanvas.isDisposed())
412             fCanvas.setBackground(getBackground());
413         fRevisionPainter.setBackground(background);
414         fDiffPainter.setBackground(background);
415     }
416
417     /*
418      * @see org.eclipse.jface.text.source.IChangeRulerColumn#setAddedColor(org.eclipse.swt.graphics.Color)
419      */

420     public void setAddedColor(Color addedColor) {
421         fDiffPainter.setAddedColor(addedColor);
422     }
423
424     /*
425      * @see org.eclipse.jface.text.source.IChangeRulerColumn#setChangedColor(org.eclipse.swt.graphics.Color)
426      */

427     public void setChangedColor(Color changedColor) {
428         fDiffPainter.setChangedColor(changedColor);
429     }
430
431     /*
432      * @see org.eclipse.jface.text.source.IChangeRulerColumn#setDeletedColor(org.eclipse.swt.graphics.Color)
433      */

434     public void setDeletedColor(Color deletedColor) {
435         fDiffPainter.setDeletedColor(deletedColor);
436     }
437
438     /*
439      * @see org.eclipse.jface.text.source.IVerticalRulerInfoExtension#getModel()
440      */

441     public IAnnotationModel getModel() {
442         return fAnnotationModel;
443     }
444
445     /*
446      * @see IVerticalRulerColumn#getControl()
447      */

448     public Control getControl() {
449         return fCanvas;
450     }
451
452     /*
453      * @see org.eclipse.jface.text.source.IVerticalRulerInfo#getWidth()
454      */

455     public int getWidth() {
456         return fWidth;
457     }
458
459     /**
460      * Triggers a redraw in the display thread.
461      */

462     protected final void postRedraw() {
463         if (fCanvas != null && !fCanvas.isDisposed()) {
464             Display d= fCanvas.getDisplay();
465             if (d != null) {
466                 d.asyncExec(new Runnable JavaDoc() {
467                     public void run() {
468                         redraw();
469                     }
470                 });
471             }
472         }
473     }
474
475     /*
476      * @see org.eclipse.jface.text.source.IVerticalRulerInfoExtension#addVerticalRulerListener(org.eclipse.jface.text.source.IVerticalRulerListener)
477      */

478     public void addVerticalRulerListener(IVerticalRulerListener listener) {
479         throw new UnsupportedOperationException JavaDoc();
480     }
481
482     /*
483      * @see org.eclipse.jface.text.source.IVerticalRulerInfoExtension#removeVerticalRulerListener(org.eclipse.jface.text.source.IVerticalRulerListener)
484      */

485     public void removeVerticalRulerListener(IVerticalRulerListener listener) {
486         throw new UnsupportedOperationException JavaDoc();
487     }
488     
489     /**
490      * Computes the document based line range visible in the text widget.
491      *
492      * @return the document based line range visible in the text widget
493      * @since 3.2
494      */

495     private final ILineRange computeVisibleModelLines() {
496         IDocument doc= fCachedTextViewer.getDocument();
497         if (doc == null)
498             return null;
499         
500         int topLine;
501         IRegion coverage;
502         
503         if (fCachedTextViewer instanceof ITextViewerExtension5) {
504             ITextViewerExtension5 extension= (ITextViewerExtension5) fCachedTextViewer;
505             
506             // ITextViewer.getTopIndex returns the fully visible line, but we want the partially
507
// visible one
508
int widgetTopLine= JFaceTextUtil.getPartialTopIndex(fCachedTextWidget);
509             topLine= extension.widgetLine2ModelLine(widgetTopLine);
510             
511             coverage= extension.getModelCoverage();
512             
513         } else {
514             topLine= JFaceTextUtil.getPartialTopIndex(fCachedTextViewer);
515             coverage= fCachedTextViewer.getVisibleRegion();
516         }
517         
518         int bottomLine= fCachedTextViewer.getBottomIndex();
519         if (bottomLine != -1)
520             ++ bottomLine;
521         
522         // clip by coverage window
523
try {
524             int firstLine= doc.getLineOfOffset(coverage.getOffset());
525             if (firstLine > topLine)
526                 topLine= firstLine;
527             
528             int lastLine= doc.getLineOfOffset(coverage.getOffset() + coverage.getLength());
529             if (lastLine < bottomLine || bottomLine == -1)
530                 bottomLine= lastLine;
531         } catch (BadLocationException x) {
532             x.printStackTrace();
533             return null;
534         }
535         
536         ILineRange visibleModelLines= new LineRange(topLine, bottomLine - topLine + 1);
537         return visibleModelLines;
538     }
539     
540     /*
541      * @see org.eclipse.jface.text.revisions.IRevisionRulerColumn#setRevisionInformation(org.eclipse.jface.text.revisions.RevisionInformation)
542      */

543     public void setRevisionInformation(RevisionInformation info) {
544         fRevisionPainter.setRevisionInformation(info);
545         fRevisionPainter.setBackground(getBackground());
546     }
547
548     /**
549      * Returns the revision selection provider.
550      *
551      * @return the revision selection provider
552      * @since 3.2
553      */

554     public ISelectionProvider getRevisionSelectionProvider() {
555         return fRevisionPainter.getRevisionSelectionProvider();
556     }
557 }
558
Popular Tags