Use thicker lines when drawing revplot diagrams
[egit/zawir.git] / org.spearce.jgit / src / org / spearce / jgit / revplot / AbstractPlotRenderer.java
bloba682856cad3baa2ca34fe609f34add7e8fd784ad
1 /*
2 * Copyright (C) 2008 Shawn Pearce <spearce@spearce.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License, version 2, as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
17 package org.spearce.jgit.revplot;
19 import org.spearce.jgit.revwalk.RevFlag;
21 /**
22 * Basic commit graph renderer for graphical user interfaces.
23 * <p>
24 * Lanes are drawn as columns left-to-right in the graph, and the commit short
25 * message is drawn to the right of the lane lines for this cell. It is assumed
26 * that the commits are being drawn as rows of some sort of table.
27 * <p>
28 * Client applications can subclass this implementation to provide the necessary
29 * drawing primitives required to display a commit graph. Most of the graph
30 * layout is handled by this class, allowing applications to implement only a
31 * handful of primitive stubs.
32 * <p>
33 * This class is suitable for us within an AWT TableCellRenderer or within a SWT
34 * PaintListener registered on a Table instance. It is meant to rubber stamp the
35 * graphics necessary for one row of a plotted commit list.
36 * <p>
37 * Subclasses should call {@link #paintCommit(PlotCommit, int)} after they have
38 * otherwise configured their instance to draw one commit into the current
39 * location.
40 * <p>
41 * All drawing methods assume the coordinate space for the current commit's cell
42 * starts at (upper left corner is) 0,0. If this is not true (like say in SWT)
43 * the implementation must perform the cell offset computations within the
44 * various draw methods.
46 * @param <TLane>
47 * type of lane being used by the application.
48 * @param <TColor>
49 * type of color object used by the graphics library.
51 public abstract class AbstractPlotRenderer<TLane extends PlotLane, TColor> {
52 private static final int LANE_WIDTH = 14;
54 private static final int LINE_WIDTH = 2;
56 private static final int LEFT_PAD = 2;
58 /**
59 * Paint one commit using the underlying graphics library.
61 * @param commit
62 * the commit to render in this cell. Must not be null.
63 * @param h
64 * total height (in pixels) of this cell.
66 protected void paintCommit(final PlotCommit<TLane> commit, final int h) {
67 final int dotSize = Math.max(0, Math.min(LANE_WIDTH - 2, h - 8)) + 1;
68 final TLane myLane = commit.getLane();
69 final int myLaneX = laneC(myLane);
70 final TColor myColor = laneColor(myLane);
72 int maxCenter = 0;
73 for (final TLane passingLane : (TLane[]) commit.passingLanes) {
74 final int cx = laneC(passingLane);
75 final TColor c = laneColor(passingLane);
76 drawLine(c, cx, 0, cx, h, LINE_WIDTH);
77 maxCenter = Math.max(maxCenter, cx);
80 final int nParent = commit.getParentCount();
81 for (int i = 0; i < nParent; i++) {
82 final PlotCommit<TLane> p;
83 final TLane pLane;
84 final TColor pColor;
85 final int cx;
87 p = (PlotCommit<TLane>) commit.getParent(i);
88 pLane = p.getLane();
89 if (pLane == null)
90 continue;
92 pColor = laneColor(pLane);
93 cx = laneC(pLane);
95 if (Math.abs(myLaneX - cx) > LANE_WIDTH) {
96 if (myLaneX < cx) {
97 final int ix = cx - LANE_WIDTH / 2;
98 drawLine(pColor, myLaneX, h / 2, ix, h / 2, LINE_WIDTH);
99 drawLine(pColor, ix, h / 2, cx, h, LINE_WIDTH);
100 } else {
101 final int ix = cx + LANE_WIDTH / 2;
102 drawLine(pColor, myLaneX, h / 2, ix, h / 2, LINE_WIDTH);
103 drawLine(pColor, ix, h / 2, cx, h, LINE_WIDTH);
105 } else {
106 drawLine(pColor, myLaneX, h / 2, cx, h, LINE_WIDTH);
108 maxCenter = Math.max(maxCenter, cx);
111 final int dotX = myLaneX - dotSize / 2 - 1;
112 final int dotY = (h - dotSize) / 2;
114 if (commit.getChildCount() > 0)
115 drawLine(myColor, myLaneX, 0, myLaneX, dotY, LINE_WIDTH);
117 if (commit.has(RevFlag.UNINTERESTING))
118 drawBoundaryDot(dotX, dotY, dotSize, dotSize);
119 else
120 drawCommitDot(dotX, dotY, dotSize, dotSize);
122 final String msg = commit.getShortMessage();
123 final int textx = Math.max(maxCenter + LANE_WIDTH / 2, dotX + dotSize) + 8;
124 drawText(msg, textx, h / 2);
128 * Obtain the color reference used to paint this lane.
129 * <p>
130 * Colors returned by this method will be passed to the other drawing
131 * primitives, so the color returned should be application specific.
132 * <p>
133 * If a null lane is supplied the return value must still be acceptable to a
134 * drawing method. Usually this means the implementation should return a
135 * default color.
137 * @param myLane
138 * the current lane. May be null.
139 * @return graphics specific color reference. Must be a valid color.
141 protected abstract TColor laneColor(TLane myLane);
144 * Draw a single line within this cell.
146 * @param color
147 * the color to use while drawing the line.
148 * @param x1
149 * starting X coordinate, 0 based.
150 * @param y1
151 * starting Y coordinate, 0 based.
152 * @param x2
153 * ending X coordinate, 0 based.
154 * @param y2
155 * ending Y coordinate, 0 based.
156 * @param width
157 * number of pixels wide for the line. Always at least 1.
159 protected abstract void drawLine(TColor color, int x1, int y1, int x2,
160 int y2, int width);
163 * Draw a single commit dot.
164 * <p>
165 * Usually the commit dot is a filled oval in blue, then a drawn oval in
166 * black, using the same coordinates for both operations.
168 * @param x
169 * upper left of the oval's bounding box.
170 * @param y
171 * upper left of the oval's bounding box.
172 * @param w
173 * width of the oval's bounding box.
174 * @param h
175 * height of the oval's bounding box.
177 protected abstract void drawCommitDot(int x, int y, int w, int h);
180 * Draw a single boundary commit (aka uninteresting commit) dot.
181 * <p>
182 * Usually a boundary commit dot is a light gray oval with a white center.
184 * @param x
185 * upper left of the oval's bounding box.
186 * @param y
187 * upper left of the oval's bounding box.
188 * @param w
189 * width of the oval's bounding box.
190 * @param h
191 * height of the oval's bounding box.
193 protected abstract void drawBoundaryDot(int x, int y, int w, int h);
196 * Draw a single line of text.
197 * <p>
198 * The font and colors used to render the text are left up to the
199 * implementation.
201 * @param msg
202 * the text to draw. Does not contain LFs.
203 * @param x
204 * first pixel from the left that the text can be drawn at.
205 * Character data must not appear before this position.
206 * @param y
207 * pixel coordinate of the centerline of the text.
208 * Implementations must adjust this coordinate to account for the
209 * way their implementation handles font rendering.
211 protected abstract void drawText(String msg, int x, int y);
213 private int laneX(final PlotLane myLane) {
214 final int p = myLane != null ? myLane.getPosition() : 0;
215 return LEFT_PAD + LANE_WIDTH * p;
218 private int laneC(final PlotLane myLane) {
219 return laneX(myLane) + LANE_WIDTH / 2;