Package org.eclipse.jface.text.source

Source Code of org.eclipse.jface.text.source.ChangeRulerColumn$InternalListener

/*******************************************************************************
* Copyright (c) 2000, 2010 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
*******************************************************************************/
package org.eclipse.jface.text.source;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;

import org.eclipse.core.runtime.Assert;

import org.eclipse.jface.internal.text.revisions.RevisionPainter;
import org.eclipse.jface.internal.text.source.DiffPainter;
import org.eclipse.jface.util.Util;
import org.eclipse.jface.viewers.ISelectionProvider;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextListener;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.ITextViewerExtension5;
import org.eclipse.jface.text.IViewportListener;
import org.eclipse.jface.text.JFaceTextUtil;
import org.eclipse.jface.text.TextEvent;
import org.eclipse.jface.text.revisions.IRevisionRulerColumn;
import org.eclipse.jface.text.revisions.RevisionInformation;

/**
* 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 implements IChangeRulerColumn, IRevisionRulerColumn {
  /**
   * Handles all the mouse interaction in this line number ruler column.
   */
  private class MouseHandler implements MouseListener, MouseMoveListener {

    /*
     * @see org.eclipse.swt.events.MouseListener#mouseUp(org.eclipse.swt.events.MouseEvent)
     */
    public void mouseUp(MouseEvent event) {
    }

    /*
     * @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
     */
    public void mouseDown(MouseEvent event) {
      fParentRuler.setLocationOfLastMouseButtonActivity(event.x, event.y);
    }

    /*
     * @see org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
     */
    public void mouseDoubleClick(MouseEvent event) {
      fParentRuler.setLocationOfLastMouseButtonActivity(event.x, event.y);
    }

    /*
     * @see org.eclipse.swt.events.MouseMoveListener#mouseMove(org.eclipse.swt.events.MouseEvent)
     */
    public void mouseMove(MouseEvent event) {
      fParentRuler.setLocationOfLastMouseButtonActivity(event.x, event.y);
    }
  }

  /**
   * Internal listener class.
   */
  private class InternalListener implements IViewportListener, ITextListener {

    /*
     * @see IViewportListener#viewportChanged(int)
     */
    public void viewportChanged(int verticalPosition) {
      if (verticalPosition != fScrollPos)
        redraw();
    }

    /*
     * @see ITextListener#textChanged(TextEvent)
     */
    public void textChanged(TextEvent event) {

      if (!event.getViewerRedrawState())
        return;

      if (fSensitiveToTextChanges || event.getDocumentEvent() == null)
        postRedraw();

    }
  }

  /**
   * <code>true</code> if we're on a Mac, where "new GC(canvas)" is expensive.
   * @see <a href="https://bugs.eclipse.org/298936">bug 298936</a>
   * @since 3.6
   */
  private static final boolean IS_MAC= Util.isMac();

  /**
   * 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 boolean 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 == null)
      return fCachedTextWidget.getDisplay().getSystemColor(SWT.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, SWT.NONE);
    fCanvas.setBackground(getBackground());

    fCanvas.addPaintListener(new PaintListener() {
      public void paintControl(PaintEvent event) {
        if (fCachedTextViewer != 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 != 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 != null) {
      fCachedTextViewer.removeViewportListener(fInternalListener);
      fCachedTextViewer.removeTextListener(fInternalListener);
    }

    if (fBuffer != 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 != null) {
      Rectangle r= fBuffer.getBounds();
      if (r.width != size.x || r.height != size.y) {
        fBuffer.dispose();
        fBuffer= null;
      }
    }
    if (fBuffer == 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 boolean 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 == 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 != null && fCanvas != null && !fCanvas.isDisposed()) {
      if (IS_MAC) {
        fCanvas.redraw();
        fCanvas.update();
      } else {
        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 org.eclipse.jface.text.source.IVerticalRulerInfo#getLineOfLastMouseButtonActivity()
   */
  public int getLineOfLastMouseButtonActivity() {
    return getParentRuler().getLineOfLastMouseButtonActivity();
  }

  /*
   * @see org.eclipse.jface.text.source.IVerticalRulerInfo#toDocumentLineNumber(int)
   */
  public int toDocumentLineNumber(int y_coordinate) {
    return getParentRuler().toDocumentLineNumber(y_coordinate);
  }

  /*
   * @see org.eclipse.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 org.eclipse.jface.text.source.IChangeRulerColumn#setHover(org.eclipse.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 != model)
      fAnnotationModel= model;
  }

  /*
   * @see org.eclipse.jface.text.source.IChangeRulerColumn#setBackground(org.eclipse.swt.graphics.Color)
   */
  public void setBackground(Color background) {
    fBackground= background;
    if (fCanvas != null && !fCanvas.isDisposed())
      fCanvas.setBackground(getBackground());
    fRevisionPainter.setBackground(background);
    fDiffPainter.setBackground(background);
  }

  /*
   * @see org.eclipse.jface.text.source.IChangeRulerColumn#setAddedColor(org.eclipse.swt.graphics.Color)
   */
  public void setAddedColor(Color addedColor) {
    fDiffPainter.setAddedColor(addedColor);
  }

  /*
   * @see org.eclipse.jface.text.source.IChangeRulerColumn#setChangedColor(org.eclipse.swt.graphics.Color)
   */
  public void setChangedColor(Color changedColor) {
    fDiffPainter.setChangedColor(changedColor);
  }

  /*
   * @see org.eclipse.jface.text.source.IChangeRulerColumn#setDeletedColor(org.eclipse.swt.graphics.Color)
   */
  public void setDeletedColor(Color deletedColor) {
    fDiffPainter.setDeletedColor(deletedColor);
  }

  /*
   * @see org.eclipse.jface.text.source.IVerticalRulerInfoExtension#getModel()
   */
  public IAnnotationModel getModel() {
    return fAnnotationModel;
  }

  /*
   * @see IVerticalRulerColumn#getControl()
   */
  public Control getControl() {
    return fCanvas;
  }

  /*
   * @see org.eclipse.jface.text.source.IVerticalRulerInfo#getWidth()
   */
  public int getWidth() {
    return fWidth;
  }

  /**
   * Triggers a redraw in the display thread.
   */
  protected final void postRedraw() {
    if (fCanvas != null && !fCanvas.isDisposed()) {
      Display d= fCanvas.getDisplay();
      if (d != null) {
        d.asyncExec(new Runnable() {
          public void run() {
            redraw();
          }
        });
      }
    }
  }

  /*
   * @see org.eclipse.jface.text.source.IVerticalRulerInfoExtension#addVerticalRulerListener(org.eclipse.jface.text.source.IVerticalRulerListener)
   */
  public void addVerticalRulerListener(IVerticalRulerListener listener) {
    throw new UnsupportedOperationException();
  }

  /*
   * @see org.eclipse.jface.text.source.IVerticalRulerInfoExtension#removeVerticalRulerListener(org.eclipse.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 == 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 != -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 == -1)
        bottomLine= lastLine;
    } catch (BadLocationException x) {
      x.printStackTrace();
      return null;
    }

    ILineRange visibleModelLines= new LineRange(topLine, bottomLine - topLine + 1);
    return visibleModelLines;
  }

  /*
   * @see org.eclipse.jface.text.revisions.IRevisionRulerColumn#setRevisionInformation(org.eclipse.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();
    }
}
TOP

Related Classes of org.eclipse.jface.text.source.ChangeRulerColumn$InternalListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.