Package org.eclipse.egit.ui.internal.commit

Source Code of org.eclipse.egit.ui.internal.commit.DiffStyleRangeFormatter

/*******************************************************************************
*  Copyright (c) 2011, 2013 GitHub Inc. 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:
*    Kevin Sawicki (GitHub Inc.) - initial API and implementation
*    Tobias Pfeifer (SAP AG) - customizable font and color for the first header line - https://bugs.eclipse.org/397723
*******************************************************************************/
package org.eclipse.egit.ui.internal.commit;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.egit.core.internal.CompareCoreUtils;
import org.eclipse.egit.ui.internal.commit.DiffStyleRangeFormatter.DiffStyleRange.Type;
import org.eclipse.egit.ui.internal.history.FileDiff;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.diff.EditList;
import org.eclipse.jgit.diff.RawText;
import org.eclipse.jgit.diff.DiffEntry.ChangeType;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.graphics.Color;

/**
* Diff style range formatter class that builds up a list of
* {@link DiffStyleRange} instances as each {@link FileDiff} is being written to
* an {@link IDocument}.
*/
public class DiffStyleRangeFormatter extends DiffFormatter {

  /**
   * Diff style range
   */
  public static class DiffStyleRange extends StyleRange {

    /**
     * Diff type
     */
    public enum Type {

      /**
       * Added line
       */
      ADD,

      /**
       * Removed line
       */
      REMOVE,

      /**
       * Hunk line
       */
      HUNK,

      /**
       * Headline
       */
      HEADLINE,

      /**
       * Other line
       */
      OTHER,

    }

    @Override
    public boolean equals(Object object) {
      return super.equals(object);
    }

    @Override
    public int hashCode() {
      return super.hashCode();
    }

    /**
     * Diff type
     */
    public Type diffType = Type.OTHER;

    /**
     * Line background
     */
    public Color lineBackground = null;

    public boolean similarTo(StyleRange style) {
      return super.similarTo(style) && style instanceof DiffStyleRange
          && diffType == ((DiffStyleRange) style).diffType;
    }
  }

  private static class DocumentOutputStream extends OutputStream {

    private String charset;

    private IDocument document;

    private int offset;

    private StringBuilder lineBuffer = new StringBuilder();

    public DocumentOutputStream(IDocument document, int offset) {
      this.document = document;
      this.offset = offset;
    }

    private void write(String content) throws IOException {
      try {
        this.document.replace(this.offset, 0, content);
        this.offset += content.length();
      } catch (BadLocationException e) {
        throw new IOException(e.getMessage());
      }
    }

    public void write(byte[] b, int off, int len) throws IOException {
      if (charset == null)
        lineBuffer.append(new String(b, off, len, "UTF-8")); //$NON-NLS-1$
      else
        lineBuffer.append(new String(b, off, len, charset));
    }

    public void write(byte[] b) throws IOException {
      write(b, 0, b.length);
    }

    public void write(int b) throws IOException {
      write(new byte[] { (byte) b });
    }

    @Override
    public void flush() throws IOException {
      flushLine();
    }

    protected void flushLine() throws IOException {
      if (lineBuffer.length() > 0) {
        write(lineBuffer.toString());
        lineBuffer.setLength(0);
      }
    }
  }

  private DocumentOutputStream stream;

  private List<DiffStyleRange> ranges = new ArrayList<DiffStyleRange>();

  /**
   * @param document
   * @param offset
   */
  public DiffStyleRangeFormatter(IDocument document, int offset) {
    super(new DocumentOutputStream(document, offset));
    this.stream = (DocumentOutputStream) getOutputStream();
  }

  /**
   * @param document
   */
  public DiffStyleRangeFormatter(IDocument document) {
    this(document, document.getLength());
  }

  /**
   * Write diff
   *
   * @param repository
   * @param diff
   * @return this formatter
   * @throws IOException
   */
  public DiffStyleRangeFormatter write(Repository repository, FileDiff diff)
      throws IOException {
    this.stream.charset = CompareCoreUtils.getResourceEncoding(repository,
        diff.getPath());
    diff.outputDiff(null, repository, this, true);
    flush();
    return this;
  }

  /**
   * Get diff style ranges
   *
   * @return non-null but possibly empty array
   */
  public DiffStyleRange[] getRanges() {
    return this.ranges.toArray(new DiffStyleRange[this.ranges.size()]);
  }

  /**
   * Create and add diff style range
   *
   * @param type
   *            the {@link Type}
   * @param start
   *            start offset
   * @param end
   *            end offset
   * @return added range
   */
  protected DiffStyleRange addRange(Type type, int start, int end) {
    DiffStyleRange range = new DiffStyleRange();
    range.start = start;
    range.diffType = type;
    range.length = end - start;
    ranges.add(range);
    return range;
  }

  /**
   * @see org.eclipse.jgit.diff.DiffFormatter#writeHunkHeader(int, int, int,
   *      int)
   */
  protected void writeHunkHeader(int aStartLine, int aEndLine,
      int bStartLine, int bEndLine) throws IOException {
    int start = stream.offset;
    super.writeHunkHeader(aStartLine, aEndLine, bStartLine, bEndLine);
    stream.flushLine();
    addRange(Type.HUNK, start, stream.offset);
  }

  /**
   * @see org.eclipse.jgit.diff.DiffFormatter#writeLine(char,
   *      org.eclipse.jgit.diff.RawText, int)
   */
  protected void writeLine(char prefix, RawText text, int cur)
      throws IOException {
    if (prefix == ' ') {
      super.writeLine(prefix, text, cur);
      stream.flushLine();
    } else {
      Type type = prefix == '+' ? Type.ADD : Type.REMOVE;
      int start = stream.offset;
      super.writeLine(prefix, text, cur);
      stream.flushLine();
      addRange(type, start, stream.offset);
    }
  }

  /**
   * @see org.eclipse.jgit.diff.DiffFormatter#formatGitDiffFirstHeaderLine(ByteArrayOutputStream
   *      o, ChangeType type, String oldPath, String newPath)
   */
  @Override
  protected void formatGitDiffFirstHeaderLine(ByteArrayOutputStream o,
      final ChangeType type, final String oldPath, final String newPath)
      throws IOException {
    stream.flushLine();
    int offset = stream.offset;
    int start = o.size();
    super.formatGitDiffFirstHeaderLine(o, type, oldPath, newPath);
    int end = o.size();
    addRange(Type.HEADLINE, offset + start, offset + end);
  }

  @Override
  public void format(final EditList edits, final RawText a, final RawText b)
      throws IOException {
    // Flush header before formatting of edits begin
    stream.flushLine();
    super.format(edits, a, b);
  }
}
TOP

Related Classes of org.eclipse.egit.ui.internal.commit.DiffStyleRangeFormatter

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.