1 package org
.spearce
.jgit
.awtui
;
3 import java
.awt
.BasicStroke
;
5 import java
.awt
.Component
;
6 import java
.awt
.Graphics
;
7 import java
.awt
.Graphics2D
;
8 import java
.awt
.Polygon
;
9 import java
.awt
.Stroke
;
10 import java
.text
.DateFormat
;
11 import java
.text
.SimpleDateFormat
;
13 import javax
.swing
.JTable
;
14 import javax
.swing
.ListSelectionModel
;
15 import javax
.swing
.table
.AbstractTableModel
;
16 import javax
.swing
.table
.DefaultTableCellRenderer
;
17 import javax
.swing
.table
.JTableHeader
;
18 import javax
.swing
.table
.TableColumn
;
19 import javax
.swing
.table
.TableColumnModel
;
20 import javax
.swing
.table
.TableModel
;
22 import org
.spearce
.jgit
.awtui
.SwingCommitList
.SwingLane
;
23 import org
.spearce
.jgit
.lib
.PersonIdent
;
24 import org
.spearce
.jgit
.revplot
.AbstractPlotRenderer
;
25 import org
.spearce
.jgit
.revplot
.PlotCommit
;
26 import org
.spearce
.jgit
.revplot
.PlotCommitList
;
29 * Draws a commit graph in a JTable.
31 * This class is currently a very primitive commit visualization tool. It shows
32 * a table of 3 columns:
34 * <li>Commit graph and short message</li>
35 * <li>Author name and email address</li>
36 * <li>Author date and time</li>
39 public class CommitGraphPane
extends JTable
{
40 private static final long serialVersionUID
= 1L;
42 private final SwingCommitList allCommits
;
44 /** Create a new empty panel. */
45 public CommitGraphPane() {
46 allCommits
= new SwingCommitList();
48 setShowHorizontalLines(false);
50 setSelectionMode(ListSelectionModel
.SINGLE_SELECTION
);
54 * Get the commit list this pane renders from.
56 * @return the list the caller must populate.
58 public PlotCommitList
getCommitList() {
63 public void setModel(final TableModel dataModel
) {
64 if (dataModel
!= null && !(dataModel
instanceof CommitTableModel
))
65 throw new ClassCastException("Must be special table model.");
66 super.setModel(dataModel
);
70 protected TableModel
createDefaultDataModel() {
71 return new CommitTableModel();
74 private void configureHeader() {
75 final JTableHeader th
= getTableHeader();
76 final TableColumnModel cols
= th
.getColumnModel();
78 final TableColumn graph
= cols
.getColumn(0);
79 final TableColumn author
= cols
.getColumn(1);
80 final TableColumn date
= cols
.getColumn(2);
82 graph
.setHeaderValue("");
83 author
.setHeaderValue("Author");
84 date
.setHeaderValue("Date");
86 graph
.setCellRenderer(new GraphCellRender());
87 author
.setCellRenderer(new NameCellRender());
88 date
.setCellRenderer(new DateCellRender());
91 class CommitTableModel
extends AbstractTableModel
{
92 private static final long serialVersionUID
= 1L;
94 PlotCommit
<SwingLane
> lastCommit
;
96 PersonIdent lastAuthor
;
98 public int getColumnCount() {
102 public int getRowCount() {
103 return allCommits
!= null ? allCommits
.size() : 0;
106 public Object
getValueAt(final int rowIndex
, final int columnIndex
) {
107 final PlotCommit
<SwingLane
> c
= allCommits
.get(rowIndex
);
108 switch (columnIndex
) {
120 PersonIdent
authorFor(final PlotCommit
<SwingLane
> c
) {
121 if (c
!= lastCommit
) {
123 lastAuthor
= c
.getAuthorIdent();
129 class NameCellRender
extends DefaultTableCellRenderer
{
130 private static final long serialVersionUID
= 1L;
132 public Component
getTableCellRendererComponent(final JTable table
,
133 final Object value
, final boolean isSelected
,
134 final boolean hasFocus
, final int row
, final int column
) {
135 final PersonIdent pi
= (PersonIdent
) value
;
137 final String valueStr
;
139 valueStr
= pi
.getName() + " <" + pi
.getEmailAddress() + ">";
142 return super.getTableCellRendererComponent(table
, valueStr
,
143 isSelected
, hasFocus
, row
, column
);
147 class DateCellRender
extends DefaultTableCellRenderer
{
148 private static final long serialVersionUID
= 1L;
150 private final DateFormat fmt
= new SimpleDateFormat(
151 "yyyy-MM-dd HH:mm:ss");
153 public Component
getTableCellRendererComponent(final JTable table
,
154 final Object value
, final boolean isSelected
,
155 final boolean hasFocus
, final int row
, final int column
) {
156 final PersonIdent pi
= (PersonIdent
) value
;
158 final String valueStr
;
160 valueStr
= fmt
.format(pi
.getWhen());
163 return super.getTableCellRendererComponent(table
, valueStr
,
164 isSelected
, hasFocus
, row
, column
);
168 class GraphCellRender
extends DefaultTableCellRenderer
{
169 private static final long serialVersionUID
= 1L;
171 private final AWTPlotRenderer renderer
= new AWTPlotRenderer(this);
173 PlotCommit
<SwingLane
> commit
;
175 public Component
getTableCellRendererComponent(final JTable table
,
176 final Object value
, final boolean isSelected
,
177 final boolean hasFocus
, final int row
, final int column
) {
178 super.getTableCellRendererComponent(table
, value
, isSelected
,
179 hasFocus
, row
, column
);
180 commit
= (PlotCommit
<SwingLane
>) value
;
185 protected void paintComponent(final Graphics inputGraphics
) {
186 if (inputGraphics
== null)
188 renderer
.paint(inputGraphics
, commit
);
192 static final Stroke
[] strokeCache
;
195 strokeCache
= new Stroke
[4];
196 for (int i
= 1; i
< strokeCache
.length
; i
++)
197 strokeCache
[i
] = new BasicStroke(i
);
200 static Stroke
stroke(final int width
) {
201 if (width
< strokeCache
.length
)
202 return strokeCache
[width
];
203 return new BasicStroke(width
);
206 final class AWTPlotRenderer
extends AbstractPlotRenderer
<SwingLane
, Color
> {
208 final GraphCellRender cell
;
212 AWTPlotRenderer(final GraphCellRender c
) {
216 void paint(final Graphics in
, final PlotCommit
<SwingLane
> commit
) {
217 g
= (Graphics2D
) in
.create();
219 final int h
= cell
.getHeight();
220 g
.setColor(cell
.getBackground());
221 g
.fillRect(0, 0, cell
.getWidth(), h
);
223 paintCommit(commit
, h
);
231 protected void drawLine(final Color color
, final int x1
, final int y1
,
232 final int x2
, final int y2
, int width
) {
234 g
.setStroke(stroke(width
));
235 g
.drawLine(x1
, y1
, x2
, y2
);
239 protected void drawCommitDot(final int x
, final int y
, final int w
,
241 g
.setColor(Color
.blue
);
242 g
.setStroke(strokeCache
[1]);
243 g
.fillOval(x
, y
, w
, h
);
244 g
.setColor(Color
.black
);
245 g
.drawOval(x
, y
, w
, h
);
249 protected void drawBoundaryDot(final int x
, final int y
, final int w
,
251 g
.setColor(cell
.getBackground());
252 g
.setStroke(strokeCache
[1]);
253 g
.fillOval(x
, y
, w
, h
);
254 g
.setColor(Color
.black
);
255 g
.drawOval(x
, y
, w
, h
);
259 protected void drawText(final String msg
, final int x
, final int y
) {
260 final int texty
= g
.getFontMetrics().getHeight()
261 - g
.getFontMetrics().getDescent();
262 g
.setColor(cell
.getForeground());
263 g
.drawString(msg
, x
, texty
- (cell
.getHeight() - y
* 2));
267 protected Color
laneColor(final SwingLane myLane
) {
268 return myLane
!= null ? myLane
.color
: Color
.black
;
271 void paintTriangleDown(final int cx
, final int y
, final int h
) {
273 final int tipY
= y
+ h
;
274 final int baseX1
= cx
- 10 / 2;
275 final int baseX2
= tipX
+ 10 / 2;
277 final Polygon triangle
= new Polygon();
278 triangle
.addPoint(tipX
, tipY
);
279 triangle
.addPoint(baseX1
, baseY
);
280 triangle
.addPoint(baseX2
, baseY
);
281 g
.fillPolygon(triangle
);
282 g
.drawPolygon(triangle
);