You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CommitGraphPane.java 6.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*
  2. * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> and others
  3. *
  4. * This program and the accompanying materials are made available under the
  5. * terms of the Eclipse Distribution License v. 1.0 which is available at
  6. * https://www.eclipse.org/org/documents/edl-v10.php.
  7. *
  8. * SPDX-License-Identifier: BSD-3-Clause
  9. */
  10. package org.eclipse.jgit.awtui;
  11. import java.awt.BasicStroke;
  12. import java.awt.Component;
  13. import java.awt.Graphics;
  14. import java.awt.Stroke;
  15. import java.text.DateFormat;
  16. import java.text.SimpleDateFormat;
  17. import javax.swing.JTable;
  18. import javax.swing.ListSelectionModel;
  19. import javax.swing.table.AbstractTableModel;
  20. import javax.swing.table.DefaultTableCellRenderer;
  21. import javax.swing.table.JTableHeader;
  22. import javax.swing.table.TableCellRenderer;
  23. import javax.swing.table.TableColumn;
  24. import javax.swing.table.TableColumnModel;
  25. import javax.swing.table.TableModel;
  26. import org.eclipse.jgit.awtui.SwingCommitList.SwingLane;
  27. import org.eclipse.jgit.lib.PersonIdent;
  28. import org.eclipse.jgit.revplot.PlotCommit;
  29. import org.eclipse.jgit.revplot.PlotCommitList;
  30. import org.eclipse.jgit.util.References;
  31. /**
  32. * Draws a commit graph in a JTable.
  33. * <p>
  34. * This class is currently a very primitive commit visualization tool. It shows
  35. * a table of 3 columns:
  36. * <ol>
  37. * <li>Commit graph and short message</li>
  38. * <li>Author name and email address</li>
  39. * <li>Author date and time</li>
  40. * </ol>
  41. */
  42. public class CommitGraphPane extends JTable {
  43. private static final long serialVersionUID = 1L;
  44. private final SwingCommitList allCommits;
  45. /**
  46. * Create a new empty panel.
  47. */
  48. public CommitGraphPane() {
  49. allCommits = new SwingCommitList();
  50. configureHeader();
  51. setShowHorizontalLines(false);
  52. setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
  53. configureRowHeight();
  54. }
  55. private void configureRowHeight() {
  56. int h = 0;
  57. for (int i = 0; i<getColumnCount(); ++i) {
  58. TableCellRenderer renderer = getDefaultRenderer(getColumnClass(i));
  59. Component c = renderer.getTableCellRendererComponent(this,
  60. "ÅOj", false, false, 0, i); //$NON-NLS-1$
  61. h = Math.max(h, c.getPreferredSize().height);
  62. }
  63. setRowHeight(h + getRowMargin());
  64. }
  65. /**
  66. * Get the commit list this pane renders from.
  67. *
  68. * @return the list the caller must populate.
  69. */
  70. public PlotCommitList getCommitList() {
  71. return allCommits;
  72. }
  73. /** {@inheritDoc} */
  74. @Override
  75. public void setModel(TableModel dataModel) {
  76. if (dataModel != null && !(dataModel instanceof CommitTableModel))
  77. throw new ClassCastException(UIText.get().mustBeSpecialTableModel);
  78. super.setModel(dataModel);
  79. }
  80. /** {@inheritDoc} */
  81. @Override
  82. protected TableModel createDefaultDataModel() {
  83. return new CommitTableModel();
  84. }
  85. private void configureHeader() {
  86. final JTableHeader th = getTableHeader();
  87. final TableColumnModel cols = th.getColumnModel();
  88. final TableColumn graph = cols.getColumn(0);
  89. final TableColumn author = cols.getColumn(1);
  90. final TableColumn date = cols.getColumn(2);
  91. graph.setHeaderValue(""); //$NON-NLS-1$
  92. author.setHeaderValue(UIText.get().author);
  93. date.setHeaderValue(UIText.get().date);
  94. graph.setCellRenderer(new GraphCellRender());
  95. author.setCellRenderer(new NameCellRender());
  96. date.setCellRenderer(new DateCellRender());
  97. }
  98. class CommitTableModel extends AbstractTableModel {
  99. private static final long serialVersionUID = 1L;
  100. PlotCommit<SwingLane> lastCommit;
  101. PersonIdent lastAuthor;
  102. @Override
  103. public int getColumnCount() {
  104. return 3;
  105. }
  106. @Override
  107. public int getRowCount() {
  108. return allCommits != null ? allCommits.size() : 0;
  109. }
  110. @Override
  111. public Object getValueAt(int rowIndex, int columnIndex) {
  112. final PlotCommit<SwingLane> c = allCommits.get(rowIndex);
  113. switch (columnIndex) {
  114. case 0:
  115. return c;
  116. case 1:
  117. return authorFor(c);
  118. case 2:
  119. return authorFor(c);
  120. default:
  121. return null;
  122. }
  123. }
  124. PersonIdent authorFor(PlotCommit<SwingLane> c) {
  125. if (!References.isSameObject(c, lastCommit)) {
  126. lastCommit = c;
  127. lastAuthor = c.getAuthorIdent();
  128. }
  129. return lastAuthor;
  130. }
  131. }
  132. static class NameCellRender extends DefaultTableCellRenderer {
  133. private static final long serialVersionUID = 1L;
  134. @Override
  135. public Component getTableCellRendererComponent(final JTable table,
  136. final Object value, final boolean isSelected,
  137. final boolean hasFocus, final int row, final int column) {
  138. final PersonIdent pi = (PersonIdent) value;
  139. final String valueStr;
  140. if (pi != null)
  141. valueStr = pi.getName() + " <" + pi.getEmailAddress() + ">"; //$NON-NLS-1$ //$NON-NLS-2$
  142. else
  143. valueStr = ""; //$NON-NLS-1$
  144. return super.getTableCellRendererComponent(table, valueStr,
  145. isSelected, hasFocus, row, column);
  146. }
  147. }
  148. static class DateCellRender extends DefaultTableCellRenderer {
  149. private static final long serialVersionUID = 1L;
  150. private final DateFormat fmt = new SimpleDateFormat(
  151. "yyyy-MM-dd HH:mm:ss"); //$NON-NLS-1$
  152. @Override
  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;
  157. final String valueStr;
  158. if (pi != null)
  159. valueStr = fmt.format(pi.getWhen());
  160. else
  161. valueStr = ""; //$NON-NLS-1$
  162. return super.getTableCellRendererComponent(table, valueStr,
  163. isSelected, hasFocus, row, column);
  164. }
  165. }
  166. static class GraphCellRender extends DefaultTableCellRenderer {
  167. private static final long serialVersionUID = 1L;
  168. private final AWTPlotRenderer renderer = new AWTPlotRenderer(this);
  169. PlotCommit<SwingLane> commit;
  170. @Override
  171. @SuppressWarnings("unchecked")
  172. public Component getTableCellRendererComponent(final JTable table,
  173. final Object value, final boolean isSelected,
  174. final boolean hasFocus, final int row, final int column) {
  175. super.getTableCellRendererComponent(table, value, isSelected,
  176. hasFocus, row, column);
  177. commit = (PlotCommit<SwingLane>) value;
  178. return this;
  179. }
  180. @Override
  181. protected void paintComponent(Graphics inputGraphics) {
  182. if (inputGraphics == null)
  183. return;
  184. renderer.paint(inputGraphics, commit);
  185. }
  186. }
  187. static final Stroke[] strokeCache;
  188. static {
  189. strokeCache = new Stroke[4];
  190. for (int i = 1; i < strokeCache.length; i++)
  191. strokeCache[i] = new BasicStroke(i);
  192. }
  193. static Stroke stroke(int width) {
  194. if (width < strokeCache.length)
  195. return strokeCache[width];
  196. return new BasicStroke(width);
  197. }
  198. }