Mercurial > projects > dwt-addons
diff dwtx/jface/text/source/ChangeRulerColumn.d @ 129:eb30df5ca28b
Added JFace Text sources
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sat, 23 Aug 2008 19:10:48 +0200 |
parents | |
children | c4fb132a086c |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/text/source/ChangeRulerColumn.d Sat Aug 23 19:10:48 2008 +0200 @@ -0,0 +1,562 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Port to the D programming language: + * Frank Benoit <benoit@tionex.de> + *******************************************************************************/ +module dwtx.jface.text.source.ChangeRulerColumn; + +import dwt.dwthelper.utils; + + + + + +import dwt.DWT; +import dwt.custom.StyledText; +import dwt.events.DisposeEvent; +import dwt.events.DisposeListener; +import dwt.events.MouseEvent; +import dwt.events.MouseListener; +import dwt.events.MouseMoveListener; +import dwt.events.PaintEvent; +import dwt.events.PaintListener; +import dwt.graphics.Color; +import dwt.graphics.Font; +import dwt.graphics.GC; +import dwt.graphics.Image; +import dwt.graphics.Point; +import dwt.graphics.Rectangle; +import dwt.widgets.Canvas; +import dwt.widgets.Composite; +import dwt.widgets.Control; +import dwt.widgets.Display; +import dwtx.core.runtime.Assert; +import dwtx.jface.internal.text.revisions.RevisionPainter; +import dwtx.jface.internal.text.source.DiffPainter; +import dwtx.jface.text.BadLocationException; +import dwtx.jface.text.IDocument; +import dwtx.jface.text.IRegion; +import dwtx.jface.text.ITextListener; +import dwtx.jface.text.ITextViewer; +import dwtx.jface.text.ITextViewerExtension5; +import dwtx.jface.text.IViewportListener; +import dwtx.jface.text.JFaceTextUtil; +import dwtx.jface.text.TextEvent; +import dwtx.jface.text.revisions.IRevisionRulerColumn; +import dwtx.jface.text.revisions.RevisionInformation; +import dwtx.jface.viewers.ISelectionProvider; + +/** + * A vertical ruler column displaying line numbers and serving as a UI for quick diff. + * Clients instantiate and configure object of this class. + * + * @since 3.0 + */ +public final class ChangeRulerColumn : IVerticalRulerColumn, IVerticalRulerInfo, IVerticalRulerInfoExtension, IChangeRulerColumn, IRevisionRulerColumn { + /** + * Handles all the mouse interaction in this line number ruler column. + */ + private class MouseHandler : MouseListener, MouseMoveListener { + + /* + * @see dwt.events.MouseListener#mouseUp(dwt.events.MouseEvent) + */ + public void mouseUp(MouseEvent event) { + } + + /* + * @see dwt.events.MouseListener#mouseDown(dwt.events.MouseEvent) + */ + public void mouseDown(MouseEvent event) { + fParentRuler.setLocationOfLastMouseButtonActivity(event.x, event.y); + } + + /* + * @see dwt.events.MouseListener#mouseDoubleClick(dwt.events.MouseEvent) + */ + public void mouseDoubleClick(MouseEvent event) { + fParentRuler.setLocationOfLastMouseButtonActivity(event.x, event.y); + } + + /* + * @see dwt.events.MouseMoveListener#mouseMove(dwt.events.MouseEvent) + */ + public void mouseMove(MouseEvent event) { + fParentRuler.setLocationOfLastMouseButtonActivity(event.x, event.y); + } + } + + /** + * Internal listener class. + */ + private class InternalListener : IViewportListener, ITextListener { + + /* + * @see IViewportListener#viewportChanged(int) + */ + public void viewportChanged(int verticalPosition) { + if (verticalPosition !is fScrollPos) + redraw(); + } + + /* + * @see ITextListener#textChanged(TextEvent) + */ + public void textChanged(TextEvent event) { + + if (!event.getViewerRedrawState()) + return; + + if (fSensitiveToTextChanges || event.getDocumentEvent() is null) + postRedraw(); + + } + } + + /** + * The view(port) listener. + */ + private final InternalListener fInternalListener= new InternalListener(); + /** + * The mouse handler. + * @since 3.2 + */ + private final MouseHandler fMouseHandler= new MouseHandler(); + /** + * The revision painter. + * @since 3.2 + */ + private final RevisionPainter fRevisionPainter; + /** + * The diff info painter. + * @since 3.2 + */ + private final DiffPainter fDiffPainter; + + /** This column's parent ruler */ + private CompositeRuler fParentRuler; + /** Cached text viewer */ + private ITextViewer fCachedTextViewer; + /** Cached text widget */ + private StyledText fCachedTextWidget; + /** The columns canvas */ + private Canvas fCanvas; + /** The background color */ + private Color fBackground; + /** The ruler's annotation model. */ + private IAnnotationModel fAnnotationModel; + /** The width of the change ruler column. */ + private final int fWidth= 5; + + /** Cache for the actual scroll position in pixels */ + private int fScrollPos; + /** The buffer for double buffering */ + private Image fBuffer; + /** Indicates whether this column reacts on text change events */ + private bool fSensitiveToTextChanges= false; + + /** + * Creates a new ruler column. + * + * @deprecated since 3.2 use {@link #ChangeRulerColumn(ISharedTextColors)} instead + */ + public ChangeRulerColumn() { + fRevisionPainter= null; + fDiffPainter= new DiffPainter(this, null); + } + + /** + * Creates a new revision ruler column. + * + * @param sharedColors the colors to look up RGBs + * @since 3.2 + */ + public ChangeRulerColumn(ISharedTextColors sharedColors) { + Assert.isNotNull(sharedColors); + fRevisionPainter= new RevisionPainter(this, sharedColors); + fDiffPainter= new DiffPainter(this, null); // no shading + } + + /** + * Returns the System background color for list widgets. + * + * @return the System background color for list widgets + */ + private Color getBackground() { + if (fBackground is null) + return fCachedTextWidget.getDisplay().getSystemColor(DWT.COLOR_LIST_BACKGROUND); + return fBackground; + } + + /* + * @see IVerticalRulerColumn#createControl(CompositeRuler, Composite) + */ + public Control createControl(CompositeRuler parentRuler, Composite parentControl) { + + fParentRuler= parentRuler; + fCachedTextViewer= parentRuler.getTextViewer(); + fCachedTextWidget= fCachedTextViewer.getTextWidget(); + + fCanvas= new Canvas(parentControl, DWT.NONE); + fCanvas.setBackground(getBackground()); + + fCanvas.addPaintListener(new PaintListener() { + public void paintControl(PaintEvent event) { + if (fCachedTextViewer !is null) + doubleBufferPaint(event.gc); + } + }); + + fCanvas.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + handleDispose(); + fCachedTextViewer= null; + fCachedTextWidget= null; + } + }); + + fCanvas.addMouseListener(fMouseHandler); + fCanvas.addMouseMoveListener(fMouseHandler); + + if (fCachedTextViewer !is null) { + + fCachedTextViewer.addViewportListener(fInternalListener); + fCachedTextViewer.addTextListener(fInternalListener); + } + + fRevisionPainter.setParentRuler(parentRuler); + fDiffPainter.setParentRuler(parentRuler); + + return fCanvas; + } + + /** + * Disposes the column's resources. + */ + protected void handleDispose() { + + if (fCachedTextViewer !is null) { + fCachedTextViewer.removeViewportListener(fInternalListener); + fCachedTextViewer.removeTextListener(fInternalListener); + } + + if (fBuffer !is null) { + fBuffer.dispose(); + fBuffer= null; + } + } + + /** + * Double buffer drawing. + * + * @param dest the GC to draw into + */ + private void doubleBufferPaint(GC dest) { + + Point size= fCanvas.getSize(); + + if (size.x <= 0 || size.y <= 0) + return; + + if (fBuffer !is null) { + Rectangle r= fBuffer.getBounds(); + if (r.width !is size.x || r.height !is size.y) { + fBuffer.dispose(); + fBuffer= null; + } + } + if (fBuffer is null) + fBuffer= new Image(fCanvas.getDisplay(), size.x, size.y); + + GC gc= new GC(fBuffer); + gc.setFont(fCanvas.getFont()); + + try { + gc.setBackground(getBackground()); + gc.fillRectangle(0, 0, size.x, size.y); + + doPaint(gc); + } finally { + gc.dispose(); + } + + dest.drawImage(fBuffer, 0, 0); + } + + /** + * Returns the view port height in lines. + * + * @return the view port height in lines + * @deprecated as of 3.2 the number of lines in the viewport cannot be computed because + * StyledText supports variable line heights + */ + protected int getVisibleLinesInViewport() { + // Hack to reduce amount of copied code. + return LineNumberRulerColumn.getVisibleLinesInViewport(fCachedTextWidget); + } + + /** + * Returns <code>true</code> if the viewport displays the entire viewer contents, i.e. the + * viewer is not vertically scrollable. + * + * @return <code>true</code> if the viewport displays the entire contents, <code>false</code> otherwise + * @since 3.2 + */ + protected final bool isViewerCompletelyShown() { + return JFaceTextUtil.isShowingEntireContents(fCachedTextWidget); + } + + /** + * Draws the ruler column. + * + * @param gc the GC to draw into + */ + private void doPaint(GC gc) { + ILineRange visibleModelLines= computeVisibleModelLines(); + if (visibleModelLines is null) + return; + + fSensitiveToTextChanges= isViewerCompletelyShown(); + + fScrollPos= fCachedTextWidget.getTopPixel(); + + fRevisionPainter.paint(gc, visibleModelLines); + if (!fRevisionPainter.hasInformation()) // don't paint quick diff colors if revisions are painted + fDiffPainter.paint(gc, visibleModelLines); + } + + /* + * @see IVerticalRulerColumn#redraw() + */ + public void redraw() { + + if (fCachedTextViewer !is null && fCanvas !is null && !fCanvas.isDisposed()) { + GC gc= new GC(fCanvas); + doubleBufferPaint(gc); + gc.dispose(); + } + } + + /* + * @see IVerticalRulerColumn#setFont(Font) + */ + public void setFont(Font font) { + } + + /** + * Returns the parent (composite) ruler of this ruler column. + * + * @return the parent ruler + * @since 3.0 + */ + private CompositeRuler getParentRuler() { + return fParentRuler; + } + + /* + * @see dwtx.jface.text.source.IVerticalRulerInfo#getLineOfLastMouseButtonActivity() + */ + public int getLineOfLastMouseButtonActivity() { + return getParentRuler().getLineOfLastMouseButtonActivity(); + } + + /* + * @see dwtx.jface.text.source.IVerticalRulerInfo#toDocumentLineNumber(int) + */ + public int toDocumentLineNumber(int y_coordinate) { + return getParentRuler().toDocumentLineNumber(y_coordinate); + } + + /* + * @see dwtx.jface.text.source.IVerticalRulerInfoExtension#getHover() + */ + public IAnnotationHover getHover() { + int activeLine= getParentRuler().getLineOfLastMouseButtonActivity(); + if (fRevisionPainter.hasHover(activeLine)) + return fRevisionPainter.getHover(); + if (fDiffPainter.hasHover(activeLine)) + return fDiffPainter.getHover(); + return null; + } + + /* + * @see dwtx.jface.text.source.IChangeRulerColumn#setHover(dwtx.jface.text.source.IAnnotationHover) + */ + public void setHover(IAnnotationHover hover) { + fRevisionPainter.setHover(hover); + fDiffPainter.setHover(hover); + } + + /* + * @see IVerticalRulerColumn#setModel(IAnnotationModel) + */ + public void setModel(IAnnotationModel model) { + setAnnotationModel(model); + fRevisionPainter.setModel(model); + fDiffPainter.setModel(model); + } + + private void setAnnotationModel(IAnnotationModel model) { + if (fAnnotationModel !is model) + fAnnotationModel= model; + } + + /* + * @see dwtx.jface.text.source.IChangeRulerColumn#setBackground(dwt.graphics.Color) + */ + public void setBackground(Color background) { + fBackground= background; + if (fCanvas !is null && !fCanvas.isDisposed()) + fCanvas.setBackground(getBackground()); + fRevisionPainter.setBackground(background); + fDiffPainter.setBackground(background); + } + + /* + * @see dwtx.jface.text.source.IChangeRulerColumn#setAddedColor(dwt.graphics.Color) + */ + public void setAddedColor(Color addedColor) { + fDiffPainter.setAddedColor(addedColor); + } + + /* + * @see dwtx.jface.text.source.IChangeRulerColumn#setChangedColor(dwt.graphics.Color) + */ + public void setChangedColor(Color changedColor) { + fDiffPainter.setChangedColor(changedColor); + } + + /* + * @see dwtx.jface.text.source.IChangeRulerColumn#setDeletedColor(dwt.graphics.Color) + */ + public void setDeletedColor(Color deletedColor) { + fDiffPainter.setDeletedColor(deletedColor); + } + + /* + * @see dwtx.jface.text.source.IVerticalRulerInfoExtension#getModel() + */ + public IAnnotationModel getModel() { + return fAnnotationModel; + } + + /* + * @see IVerticalRulerColumn#getControl() + */ + public Control getControl() { + return fCanvas; + } + + /* + * @see dwtx.jface.text.source.IVerticalRulerInfo#getWidth() + */ + public int getWidth() { + return fWidth; + } + + /** + * Triggers a redraw in the display thread. + */ + protected final void postRedraw() { + if (fCanvas !is null && !fCanvas.isDisposed()) { + Display d= fCanvas.getDisplay(); + if (d !is null) { + d.asyncExec(new Runnable() { + public void run() { + redraw(); + } + }); + } + } + } + + /* + * @see dwtx.jface.text.source.IVerticalRulerInfoExtension#addVerticalRulerListener(dwtx.jface.text.source.IVerticalRulerListener) + */ + public void addVerticalRulerListener(IVerticalRulerListener listener) { + throw new UnsupportedOperationException(); + } + + /* + * @see dwtx.jface.text.source.IVerticalRulerInfoExtension#removeVerticalRulerListener(dwtx.jface.text.source.IVerticalRulerListener) + */ + public void removeVerticalRulerListener(IVerticalRulerListener listener) { + throw new UnsupportedOperationException(); + } + + /** + * Computes the document based line range visible in the text widget. + * + * @return the document based line range visible in the text widget + * @since 3.2 + */ + private final ILineRange computeVisibleModelLines() { + IDocument doc= fCachedTextViewer.getDocument(); + if (doc is null) + return null; + + int topLine; + IRegion coverage; + + if (fCachedTextViewer instanceof ITextViewerExtension5) { + ITextViewerExtension5 extension= (ITextViewerExtension5) fCachedTextViewer; + + // ITextViewer.getTopIndex returns the fully visible line, but we want the partially + // visible one + int widgetTopLine= JFaceTextUtil.getPartialTopIndex(fCachedTextWidget); + topLine= extension.widgetLine2ModelLine(widgetTopLine); + + coverage= extension.getModelCoverage(); + + } else { + topLine= JFaceTextUtil.getPartialTopIndex(fCachedTextViewer); + coverage= fCachedTextViewer.getVisibleRegion(); + } + + int bottomLine= fCachedTextViewer.getBottomIndex(); + if (bottomLine !is -1) + ++ bottomLine; + + // clip by coverage window + try { + int firstLine= doc.getLineOfOffset(coverage.getOffset()); + if (firstLine > topLine) + topLine= firstLine; + + int lastLine= doc.getLineOfOffset(coverage.getOffset() + coverage.getLength()); + if (lastLine < bottomLine || bottomLine is -1) + bottomLine= lastLine; + } catch (BadLocationException x) { + x.printStackTrace(); + return null; + } + + ILineRange visibleModelLines= new LineRange(topLine, bottomLine - topLine + 1); + return visibleModelLines; + } + + /* + * @see dwtx.jface.text.revisions.IRevisionRulerColumn#setRevisionInformation(dwtx.jface.text.revisions.RevisionInformation) + */ + public void setRevisionInformation(RevisionInformation info) { + fRevisionPainter.setRevisionInformation(info); + fRevisionPainter.setBackground(getBackground()); + } + + /** + * Returns the revision selection provider. + * + * @return the revision selection provider + * @since 3.2 + */ + public ISelectionProvider getRevisionSelectionProvider() { + return fRevisionPainter.getRevisionSelectionProvider(); + } +}