123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- /*
- * Copyright (C) 2008, 2014 Shawn O. Pearce <spearce@spearce.org>
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- * names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
- package org.eclipse.jgit.revplot;
-
- import org.eclipse.jgit.lib.Ref;
- import org.eclipse.jgit.revwalk.RevFlag;
-
- /**
- * Basic commit graph renderer for graphical user interfaces.
- * <p>
- * Lanes are drawn as columns left-to-right in the graph, and the commit short
- * message is drawn to the right of the lane lines for this cell. It is assumed
- * that the commits are being drawn as rows of some sort of table.
- * <p>
- * Client applications can subclass this implementation to provide the necessary
- * drawing primitives required to display a commit graph. Most of the graph
- * layout is handled by this class, allowing applications to implement only a
- * handful of primitive stubs.
- * <p>
- * This class is suitable for us within an AWT TableCellRenderer or within a SWT
- * PaintListener registered on a Table instance. It is meant to rubber stamp the
- * graphics necessary for one row of a plotted commit list.
- * <p>
- * Subclasses should call {@link #paintCommit(PlotCommit, int)} after they have
- * otherwise configured their instance to draw one commit into the current
- * location.
- * <p>
- * All drawing methods assume the coordinate space for the current commit's cell
- * starts at (upper left corner is) 0,0. If this is not true (like say in SWT)
- * the implementation must perform the cell offset computations within the
- * various draw methods.
- *
- * @param <TLane>
- * type of lane being used by the application.
- * @param <TColor>
- * type of color object used by the graphics library.
- */
- public abstract class AbstractPlotRenderer<TLane extends PlotLane, TColor> {
- private static final int LANE_WIDTH = 14;
-
- private static final int LINE_WIDTH = 2;
-
- private static final int LEFT_PAD = 2;
-
- /**
- * Paint one commit using the underlying graphics library.
- *
- * @param commit
- * the commit to render in this cell. Must not be null.
- * @param h
- * total height (in pixels) of this cell.
- */
- @SuppressWarnings("unchecked")
- protected void paintCommit(final PlotCommit<TLane> commit, final int h) {
- final int dotSize = computeDotSize(h);
- final TLane myLane = commit.getLane();
- final int myLaneX = laneC(myLane);
- final TColor myColor = laneColor(myLane);
-
- int maxCenter = myLaneX;
- for (final TLane passingLane : (TLane[]) commit.passingLanes) {
- final int cx = laneC(passingLane);
- final TColor c = laneColor(passingLane);
- drawLine(c, cx, 0, cx, h, LINE_WIDTH);
- maxCenter = Math.max(maxCenter, cx);
- }
-
- final int dotX = myLaneX - dotSize / 2 - 1;
- final int dotY = (h - dotSize) / 2;
-
- final int nParent = commit.getParentCount();
- if (nParent > 0) {
- drawLine(myColor, myLaneX, h, myLaneX, (h + dotSize) / 2,
- LINE_WIDTH);
-
- for (int i = 0; i < commit.mergingLanes.length; i++) {
- final TLane pLane = (TLane) commit.mergingLanes[i];
- final TColor pColor = laneColor(pLane);
- final int cx = laneC(pLane);
-
- if (Math.abs(myLaneX - cx) > LANE_WIDTH) {
- final int ix;
- if (myLaneX < cx)
- ix = cx - LANE_WIDTH / 2;
- else
- ix = cx + LANE_WIDTH / 2;
-
- drawLine(pColor, myLaneX, h / 2, ix, h / 2, LINE_WIDTH);
- drawLine(pColor, ix, h / 2, cx, h, LINE_WIDTH);
- } else
- drawLine(pColor, myLaneX, h / 2, cx, h, LINE_WIDTH);
-
- maxCenter = Math.max(maxCenter, cx);
- }
- }
-
-
- if (commit.getChildCount() > 0) {
- for (int i = 0; i < commit.forkingOffLanes.length; i++) {
- final TLane childLane = (TLane) commit.forkingOffLanes[i];
- final TColor cColor = laneColor(childLane);
- final int cx = laneC(childLane);
- if (Math.abs(myLaneX - cx) > LANE_WIDTH) {
- final int ix;
- if (myLaneX < cx)
- ix = cx - LANE_WIDTH / 2;
- else
- ix = cx + LANE_WIDTH / 2;
-
- drawLine(cColor, myLaneX, h / 2, ix, h / 2, LINE_WIDTH);
- drawLine(cColor, ix, h / 2, cx, 0, LINE_WIDTH);
- } else {
- drawLine(cColor, myLaneX, h / 2, cx, 0, LINE_WIDTH);
- }
- maxCenter = Math.max(maxCenter, cx);
- }
-
- int nonForkingChildren = commit.getChildCount()
- - commit.forkingOffLanes.length;
- if (nonForkingChildren > 0)
- drawLine(myColor, myLaneX, 0, myLaneX, dotY, LINE_WIDTH);
- }
-
- if (commit.has(RevFlag.UNINTERESTING))
- drawBoundaryDot(dotX, dotY, dotSize, dotSize);
- else
- drawCommitDot(dotX, dotY, dotSize, dotSize);
-
- int textx = Math.max(maxCenter + LANE_WIDTH / 2, dotX + dotSize) + 8;
- int n = commit.refs.length;
- for (int i = 0; i < n; ++i) {
- textx += drawLabel(textx + dotSize, h/2, commit.refs[i]);
- }
-
- final String msg = commit.getShortMessage();
- drawText(msg, textx + dotSize, h);
- }
-
- /**
- * Draw a decoration for the Ref ref at x,y
- *
- * @param x
- * left
- * @param y
- * top
- * @param ref
- * A peeled ref
- * @return width of label in pixels
- */
- protected abstract int drawLabel(int x, int y, Ref ref);
-
- private static int computeDotSize(final int h) {
- int d = (int) (Math.min(h, LANE_WIDTH) * 0.50f);
- d += (d & 1);
- return d;
- }
-
- /**
- * Obtain the color reference used to paint this lane.
- * <p>
- * Colors returned by this method will be passed to the other drawing
- * primitives, so the color returned should be application specific.
- * <p>
- * If a null lane is supplied the return value must still be acceptable to a
- * drawing method. Usually this means the implementation should return a
- * default color.
- *
- * @param myLane
- * the current lane. May be null.
- * @return graphics specific color reference. Must be a valid color.
- */
- protected abstract TColor laneColor(TLane myLane);
-
- /**
- * Draw a single line within this cell.
- *
- * @param color
- * the color to use while drawing the line.
- * @param x1
- * starting X coordinate, 0 based.
- * @param y1
- * starting Y coordinate, 0 based.
- * @param x2
- * ending X coordinate, 0 based.
- * @param y2
- * ending Y coordinate, 0 based.
- * @param width
- * number of pixels wide for the line. Always at least 1.
- */
- protected abstract void drawLine(TColor color, int x1, int y1, int x2,
- int y2, int width);
-
- /**
- * Draw a single commit dot.
- * <p>
- * Usually the commit dot is a filled oval in blue, then a drawn oval in
- * black, using the same coordinates for both operations.
- *
- * @param x
- * upper left of the oval's bounding box.
- * @param y
- * upper left of the oval's bounding box.
- * @param w
- * width of the oval's bounding box.
- * @param h
- * height of the oval's bounding box.
- */
- protected abstract void drawCommitDot(int x, int y, int w, int h);
-
- /**
- * Draw a single boundary commit (aka uninteresting commit) dot.
- * <p>
- * Usually a boundary commit dot is a light gray oval with a white center.
- *
- * @param x
- * upper left of the oval's bounding box.
- * @param y
- * upper left of the oval's bounding box.
- * @param w
- * width of the oval's bounding box.
- * @param h
- * height of the oval's bounding box.
- */
- protected abstract void drawBoundaryDot(int x, int y, int w, int h);
-
- /**
- * Draw a single line of text.
- * <p>
- * The font and colors used to render the text are left up to the
- * implementation.
- *
- * @param msg
- * the text to draw. Does not contain LFs.
- * @param x
- * first pixel from the left that the text can be drawn at.
- * Character data must not appear before this position.
- * @param y
- * pixel coordinate of the baseline of the text. Implementations
- * must adjust this coordinate to account for the way their
- * implementation handles font rendering.
- */
- protected abstract void drawText(String msg, int x, int y);
-
- private static int laneX(final PlotLane myLane) {
- final int p = myLane != null ? myLane.getPosition() : 0;
- return LEFT_PAD + LANE_WIDTH * p;
- }
-
- private static int laneC(final PlotLane myLane) {
- return laneX(myLane) + LANE_WIDTH / 2;
- }
- }
|