2 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
6 * Redistribution and use in source and binary forms, with or
7 * without modification, are permitted provided that the following
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * - Neither the name of the Git Development Community nor the
19 * names of its contributors may be used to endorse or promote
20 * products derived from this software without specific prior
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
24 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
25 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
28 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
35 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 package org
.spearce
.jgit
.revplot
;
40 import org
.spearce
.jgit
.revwalk
.RevFlag
;
43 * Basic commit graph renderer for graphical user interfaces.
45 * Lanes are drawn as columns left-to-right in the graph, and the commit short
46 * message is drawn to the right of the lane lines for this cell. It is assumed
47 * that the commits are being drawn as rows of some sort of table.
49 * Client applications can subclass this implementation to provide the necessary
50 * drawing primitives required to display a commit graph. Most of the graph
51 * layout is handled by this class, allowing applications to implement only a
52 * handful of primitive stubs.
54 * This class is suitable for us within an AWT TableCellRenderer or within a SWT
55 * PaintListener registered on a Table instance. It is meant to rubber stamp the
56 * graphics necessary for one row of a plotted commit list.
58 * Subclasses should call {@link #paintCommit(PlotCommit, int)} after they have
59 * otherwise configured their instance to draw one commit into the current
62 * All drawing methods assume the coordinate space for the current commit's cell
63 * starts at (upper left corner is) 0,0. If this is not true (like say in SWT)
64 * the implementation must perform the cell offset computations within the
65 * various draw methods.
68 * type of lane being used by the application.
70 * type of color object used by the graphics library.
72 public abstract class AbstractPlotRenderer
<TLane
extends PlotLane
, TColor
> {
73 private static final int LANE_WIDTH
= 14;
75 private static final int LINE_WIDTH
= 2;
77 private static final int LEFT_PAD
= 2;
80 * Paint one commit using the underlying graphics library.
83 * the commit to render in this cell. Must not be null.
85 * total height (in pixels) of this cell.
87 protected void paintCommit(final PlotCommit
<TLane
> commit
, final int h
) {
88 final int dotSize
= computeDotSize(h
);
89 final TLane myLane
= commit
.getLane();
90 final int myLaneX
= laneC(myLane
);
91 final TColor myColor
= laneColor(myLane
);
94 for (final TLane passingLane
: (TLane
[]) commit
.passingLanes
) {
95 final int cx
= laneC(passingLane
);
96 final TColor c
= laneColor(passingLane
);
97 drawLine(c
, cx
, 0, cx
, h
, LINE_WIDTH
);
98 maxCenter
= Math
.max(maxCenter
, cx
);
101 final int nParent
= commit
.getParentCount();
102 for (int i
= 0; i
< nParent
; i
++) {
103 final PlotCommit
<TLane
> p
;
108 p
= (PlotCommit
<TLane
>) commit
.getParent(i
);
113 pColor
= laneColor(pLane
);
116 if (Math
.abs(myLaneX
- cx
) > LANE_WIDTH
) {
118 final int ix
= cx
- LANE_WIDTH
/ 2;
119 drawLine(pColor
, myLaneX
, h
/ 2, ix
, h
/ 2, LINE_WIDTH
);
120 drawLine(pColor
, ix
, h
/ 2, cx
, h
, LINE_WIDTH
);
122 final int ix
= cx
+ LANE_WIDTH
/ 2;
123 drawLine(pColor
, myLaneX
, h
/ 2, ix
, h
/ 2, LINE_WIDTH
);
124 drawLine(pColor
, ix
, h
/ 2, cx
, h
, LINE_WIDTH
);
127 drawLine(pColor
, myLaneX
, h
/ 2, cx
, h
, LINE_WIDTH
);
129 maxCenter
= Math
.max(maxCenter
, cx
);
132 final int dotX
= myLaneX
- dotSize
/ 2 - 1;
133 final int dotY
= (h
- dotSize
) / 2;
135 if (commit
.getChildCount() > 0)
136 drawLine(myColor
, myLaneX
, 0, myLaneX
, dotY
, LINE_WIDTH
);
138 if (commit
.has(RevFlag
.UNINTERESTING
))
139 drawBoundaryDot(dotX
, dotY
, dotSize
, dotSize
);
141 drawCommitDot(dotX
, dotY
, dotSize
, dotSize
);
143 final String msg
= commit
.getShortMessage();
144 final int textx
= Math
.max(maxCenter
+ LANE_WIDTH
/ 2, dotX
+ dotSize
) + 8;
145 drawText(msg
, textx
, h
/ 2);
148 private int computeDotSize(final int h
) {
149 int d
= (int) (Math
.min(h
, LANE_WIDTH
) * 0.50f
);
155 * Obtain the color reference used to paint this lane.
157 * Colors returned by this method will be passed to the other drawing
158 * primitives, so the color returned should be application specific.
160 * If a null lane is supplied the return value must still be acceptable to a
161 * drawing method. Usually this means the implementation should return a
165 * the current lane. May be null.
166 * @return graphics specific color reference. Must be a valid color.
168 protected abstract TColor
laneColor(TLane myLane
);
171 * Draw a single line within this cell.
174 * the color to use while drawing the line.
176 * starting X coordinate, 0 based.
178 * starting Y coordinate, 0 based.
180 * ending X coordinate, 0 based.
182 * ending Y coordinate, 0 based.
184 * number of pixels wide for the line. Always at least 1.
186 protected abstract void drawLine(TColor color
, int x1
, int y1
, int x2
,
190 * Draw a single commit dot.
192 * Usually the commit dot is a filled oval in blue, then a drawn oval in
193 * black, using the same coordinates for both operations.
196 * upper left of the oval's bounding box.
198 * upper left of the oval's bounding box.
200 * width of the oval's bounding box.
202 * height of the oval's bounding box.
204 protected abstract void drawCommitDot(int x
, int y
, int w
, int h
);
207 * Draw a single boundary commit (aka uninteresting commit) dot.
209 * Usually a boundary commit dot is a light gray oval with a white center.
212 * upper left of the oval's bounding box.
214 * upper left of the oval's bounding box.
216 * width of the oval's bounding box.
218 * height of the oval's bounding box.
220 protected abstract void drawBoundaryDot(int x
, int y
, int w
, int h
);
223 * Draw a single line of text.
225 * The font and colors used to render the text are left up to the
229 * the text to draw. Does not contain LFs.
231 * first pixel from the left that the text can be drawn at.
232 * Character data must not appear before this position.
234 * pixel coordinate of the centerline of the text.
235 * Implementations must adjust this coordinate to account for the
236 * way their implementation handles font rendering.
238 protected abstract void drawText(String msg
, int x
, int y
);
240 private int laneX(final PlotLane myLane
) {
241 final int p
= myLane
!= null ? myLane
.getPosition() : 0;
242 return LEFT_PAD
+ LANE_WIDTH
* p
;
245 private int laneC(final PlotLane myLane
) {
246 return laneX(myLane
) + LANE_WIDTH
/ 2;