git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[EGIT PATCH 4/6] Add tags to the graphical history display.

From
Robin Rosenberg <robin.rosenberg@dewire.com>
Date
Oct 5, 2008, 23:36 UTC
Message-ID
<1223249802-9959-5-git-send-email-robin.rosenberg@dewire.com>
In-Reply-To
<1223249802-9959-4-git-send-email-robin.rosenberg@dewire.com>

Both the SWT (Eclipse) drawing and Swing versions are updated. The coloring and shapes are intentionally not the same as for gitk.

Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
---
 .../egit/core/internal/storage/KidWalk.java        |    3 +-
 .../egit/ui/internal/history/SWTCommit.java        |    5 +-
 .../egit/ui/internal/history/SWTPlotRenderer.java  |   64 +++++++++++++++++++-
 .../spearce/egit/ui/internal/history/SWTWalk.java  |    5 +-
 .../org/spearce/jgit/awtui/AWTPlotRenderer.java    |   46 ++++++++++++++
 .../spearce/jgit/revplot/AbstractPlotRenderer.java |   18 +++++-
 .../src/org/spearce/jgit/revplot/PlotCommit.java   |    8 ++-
 .../src/org/spearce/jgit/revplot/PlotWalk.java     |   56 ++++++++++++++++-
 .../src/org/spearce/jgit/revwalk/RevWalk.java      |   19 +++++-
 9 files changed, 209 insertions(+), 15 deletions(-)
diff --git a/org.spearce.egit.core/src/org/spearce/egit/core/internal/storage/KidWalk.java b/org.spearce.egit.core/src/org/spearce/egit/core/internal/storage/KidWalk.java
index 6b8f468..b337efe 100644
--- a/org.spearce.egit.core/src/org/spearce/egit/core/internal/storage/KidWalk.java
+++ b/org.spearce.egit.core/src/org/spearce/egit/core/internal/storage/KidWalk.java
@@ -11,6 +11,7 @@
 import org.spearce.jgit.lib.AnyObjectId;
 import org.spearce.jgit.lib.Repository;
 import org.spearce.jgit.revwalk.RevCommit;
+import org.spearce.jgit.lib.Ref;
 import org.spearce.jgit.revwalk.RevWalk;
 
 class KidWalk extends RevWalk {
@@ -19,7 +20,7 @@ KidWalk(final Repository repo) {
 	}
 
 	@Override
-	protected RevCommit createCommit(final AnyObjectId id) {
+	protected RevCommit createCommit(final AnyObjectId id, final Ref[] tags) {
 		return new KidCommit(id);
 	}
 }
diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/SWTCommit.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/SWTCommit.java
index fa0d25d..2341fbd 100644
--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/SWTCommit.java
+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/SWTCommit.java
@@ -10,12 +10,13 @@
 import org.eclipse.swt.widgets.Widget;
 import org.spearce.jgit.lib.AnyObjectId;
 import org.spearce.jgit.revplot.PlotCommit;
+import org.spearce.jgit.lib.Ref;
 
 class SWTCommit extends PlotCommit<SWTCommitList.SWTLane> {
 	Widget widget;
 
-	SWTCommit(final AnyObjectId id) {
-		super(id);
+	SWTCommit(final AnyObjectId id, final Ref[] tags) {
+		super(id, tags);
 	}
 
 	@Override
diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/SWTPlotRenderer.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/SWTPlotRenderer.java
index 23ec255..56d5842 100644
--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/SWTPlotRenderer.java
+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/SWTPlotRenderer.java
@@ -15,7 +15,10 @@
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Event;
 import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.ui.themes.ColorUtil;
 import org.spearce.egit.ui.internal.history.SWTCommitList.SWTLane;
+import org.spearce.jgit.lib.Constants;
+import org.spearce.jgit.lib.Ref;
 import org.spearce.jgit.revplot.AbstractPlotRenderer;
 import org.spearce.jgit.revplot.PlotCommit;
 
@@ -26,7 +29,13 @@
 
 	private final Color sys_gray;
 
-	private Color sys_darkblue;
+	private final Color sys_darkblue;
+
+	private final Color sys_yellow;
+
+	private final Color sys_green;
+
+	private final Color sys_white;
 
 	GC g;
 
@@ -43,6 +52,9 @@ SWTPlotRenderer(final Display d) {
 		sys_black = d.getSystemColor(SWT.COLOR_BLACK);
 		sys_gray = d.getSystemColor(SWT.COLOR_GRAY);
 		sys_darkblue = d.getSystemColor(SWT.COLOR_DARK_BLUE);
+		sys_yellow = d.getSystemColor(SWT.COLOR_YELLOW);
+		sys_green = d.getSystemColor(SWT.COLOR_GREEN);
+		sys_white = d.getSystemColor(SWT.COLOR_WHITE);
 	}
 
 	void paint(final Event event) {
@@ -92,7 +104,57 @@ protected void drawText(final String msg, final int x, final int y) {
 		g.drawString(msg, cellX + x, cellY + texty);
 	}
 
+	@Override
+	protected int drawLabel(int x, int y, Ref ref) {
+		String txt;
+		String name = ref.getOrigName();
+		if (name.startsWith(Constants.R_HEADS)) {
+			g.setBackground(sys_green);
+			txt = name.substring(Constants.R_HEADS.length());
+		} else if (name.startsWith(Constants.R_REMOTES)){
+			g.setBackground(sys_gray);
+			txt = name.substring(Constants.R_REMOTES.length());
+		} else if (name.startsWith(Constants.R_TAGS)){
+			g.setBackground(sys_yellow);
+			txt = name.substring(Constants.R_TAGS.length());
+		} else {
+			// Whatever this would be
+			g.setBackground(sys_white);
+			if (name.startsWith(Constants.R_REFS))
+				txt = name.substring(Constants.R_REFS.length());
+			else
+				txt = name; // HEAD and such
+		}
+		Color peeledColor = null;
+		if (ref.getPeeledObjectId() != null) {
+			peeledColor = new Color(g.getDevice(), ColorUtil.blend(g.getBackground().getRGB(), sys_white.getRGB()));
+			g.setBackground(peeledColor);
+		}
+		if (txt.length() > 12)
+			txt = txt.substring(0,11) + "\u2026"; // ellipsis "…" (in UTF-8)
+
+		Point testsz = g.stringExtent(txt);
+		final int texty = (y * 2 - testsz.y) / 2;
+		g.setForeground(sys_black);
+		g.drawString(txt, x + 2, cellY + texty);
+		g.setLineWidth(2);
+		Color blend1 = new Color(g.getDevice(), ColorUtil.blend(g.getBackground().getRGB(), sys_gray.getRGB()));
+		g.setForeground(blend1);
+		g.drawRoundRectangle(x, cellY + texty -2, testsz.x + 3, testsz.y + 3, testsz.y/4, testsz.y/4);
+		g.setLineWidth(2);
+		Color blend2 = new Color(g.getDevice(), ColorUtil.blend(g.getBackground().getRGB(), sys_black.getRGB()));
+		g.setForeground(blend2);
+		g.drawRoundRectangle(x + 1, cellY + texty -1, testsz.x + 1, testsz.y + 1, testsz.y/4, testsz.y/4);
+
+		blend1.dispose();
+		blend2.dispose();
+		if (peeledColor != null)
+			peeledColor.dispose();
+		return 8 + testsz.x;
+	}
+
 	protected Color laneColor(final SWTLane myLane) {
 		return myLane != null ? myLane.color : sys_black;
 	}
+
 }
diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/SWTWalk.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/SWTWalk.java
index 527d284..bc347db 100644
--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/SWTWalk.java
+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/SWTWalk.java
@@ -11,6 +11,7 @@
 import org.spearce.jgit.lib.Repository;
 import org.spearce.jgit.revplot.PlotWalk;
 import org.spearce.jgit.revwalk.RevCommit;
+import org.spearce.jgit.lib.Ref;
 
 class SWTWalk extends PlotWalk {
 	SWTWalk(final Repository repo) {
@@ -18,7 +19,7 @@ SWTWalk(final Repository repo) {
 	}
 
 	@Override
-	protected RevCommit createCommit(final AnyObjectId id) {
-		return new SWTCommit(id);
+	protected RevCommit createCommit(final AnyObjectId id, final Ref[] tags) {
+		return new SWTCommit(id, tags);
 	}
 }
diff --git a/org.spearce.jgit/src/org/spearce/jgit/awtui/AWTPlotRenderer.java b/org.spearce.jgit/src/org/spearce/jgit/awtui/AWTPlotRenderer.java
index b6b715c..5dcddf5 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/awtui/AWTPlotRenderer.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/awtui/AWTPlotRenderer.java
@@ -44,6 +44,8 @@
 
 import org.spearce.jgit.awtui.CommitGraphPane.GraphCellRender;
 import org.spearce.jgit.awtui.SwingCommitList.SwingLane;
+import org.spearce.jgit.lib.Constants;
+import org.spearce.jgit.lib.Ref;
 import org.spearce.jgit.revplot.AbstractPlotRenderer;
 import org.spearce.jgit.revplot.PlotCommit;
 
@@ -134,4 +136,48 @@ void paintTriangleDown(final int cx, final int y, final int h) {
 		g.drawPolygon(triangle);
 	}
 
+	@Override
+	protected int drawLabel(int x, int y, Ref ref) {
+		String txt;
+		String name = ref.getOrigName();
+		if (name.startsWith(Constants.R_HEADS)) {
+			g.setBackground(Color.GREEN);
+			txt = name.substring(Constants.R_HEADS.length());
+		} else if (name.startsWith(Constants.R_REMOTES)){
+			g.setBackground(Color.LIGHT_GRAY);
+			txt = name.substring(Constants.R_REMOTES.length());
+		} else if (name.startsWith(Constants.R_TAGS)){
+			g.setBackground(Color.YELLOW);
+			txt = name.substring(Constants.R_TAGS.length());
+		} else {
+			// Whatever this would be
+			g.setBackground(Color.WHITE);
+			if (name.startsWith(Constants.R_REFS))
+				txt = name.substring(Constants.R_REFS.length());
+			else
+				txt = name; // HEAD and such
+		}
+		if (ref.getPeeledObjectId() != null) {
+			float[] colorComponents = g.getBackground().getRGBColorComponents(null);
+			colorComponents[0] *= 0.9;
+			colorComponents[1] *= 0.9;
+			colorComponents[2] *= 0.9;
+			g.setBackground(new Color(colorComponents[0],colorComponents[1],colorComponents[2]));
+		}
+		if (txt.length() > 12)
+			txt = txt.substring(0,11) + "\u2026"; // ellipsis "…" (in UTF-8)
+
+		final int texth = g.getFontMetrics().getHeight();
+		int textw = g.getFontMetrics().stringWidth(txt);
+		g.setColor(g.getBackground());
+		int arcHeight = texth/4;
+		int y0 = y - texth/2 + (cell.getHeight() - texth)/2;
+		g.fillRoundRect(x , y0, textw + arcHeight*2, texth -1, arcHeight, arcHeight);
+		g.setColor(g.getColor().darker());
+		g.drawRoundRect(x, y0, textw + arcHeight*2, texth -1 , arcHeight, arcHeight);
+		g.setColor(Color.BLACK);
+		g.drawString(txt, x + arcHeight, y0 + texth - g.getFontMetrics().getDescent());
+
+		return arcHeight * 3 + textw;
+	}
 }
\ No newline at end of file
diff --git a/org.spearce.jgit/src/org/spearce/jgit/revplot/AbstractPlotRenderer.java b/org.spearce.jgit/src/org/spearce/jgit/revplot/AbstractPlotRenderer.java
index f175c9d..603547b 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/revplot/AbstractPlotRenderer.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/revplot/AbstractPlotRenderer.java
@@ -37,6 +37,7 @@
 
 package org.spearce.jgit.revplot;
 
+import org.spearce.jgit.lib.Ref;
 import org.spearce.jgit.revwalk.RevFlag;
 
 /**
@@ -140,11 +141,24 @@ protected void paintCommit(final PlotCommit<TLane> commit, final int h) {
 		else
 			drawCommitDot(dotX, dotY, dotSize, dotSize);
 
+		int textx = Math.max(maxCenter + LANE_WIDTH / 2, dotX + dotSize) + 8;
+		int n = commit.refs == null ? 0 : commit.refs.length;
+		for (int i = 0; i < n; ++i) {
+			textx += drawLabel(textx + dotSize, h/2, commit.refs[i]);
+		}
+
 		final String msg = commit.getShortMessage();
-		final int textx = Math.max(maxCenter + LANE_WIDTH / 2, dotX + dotSize) + 8;
-		drawText(msg, textx, h / 2);
+		drawText(msg, textx + dotSize + n*2, h / 2);
 	}
 
+	/** FIXME: supply text 
+	 * @param x 
+	 * @param y 
+	 * @param ref TODO
+	 * @return TODO
+	 */
+	protected abstract int drawLabel(int x, int y, Ref ref);
+
 	private int computeDotSize(final int h) {
 		int d = (int) (Math.min(h, LANE_WIDTH) * 0.50f);
 		d += (d & 1);
diff --git a/org.spearce.jgit/src/org/spearce/jgit/revplot/PlotCommit.java b/org.spearce.jgit/src/org/spearce/jgit/revplot/PlotCommit.java
index 5a5ef1e..fac89f5 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/revplot/PlotCommit.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/revplot/PlotCommit.java
@@ -39,6 +39,7 @@
 
 import org.spearce.jgit.lib.AnyObjectId;
 import org.spearce.jgit.revwalk.RevCommit;
+import org.spearce.jgit.lib.Ref;
 
 /**
  * A commit reference to a commit in the DAG.
@@ -58,14 +59,19 @@
 
 	PlotCommit[] children;
 
+	Ref[] refs;
+
 	/**
 	 * Create a new commit.
 	 * 
 	 * @param id
 	 *            the identity of this commit.
+	 * @param tags
+	 *            the tags associated with this commit, null for no tags
 	 */
-	protected PlotCommit(final AnyObjectId id) {
+	protected PlotCommit(final AnyObjectId id, final Ref[] tags) {
 		super(id);
+		this.refs = tags;
 		passingLanes = NO_LANES;
 		children = NO_CHILDREN;
 	}
diff --git a/org.spearce.jgit/src/org/spearce/jgit/revplot/PlotWalk.java b/org.spearce.jgit/src/org/spearce/jgit/revplot/PlotWalk.java
index e5e8aba..6e253f4 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/revplot/PlotWalk.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/revplot/PlotWalk.java
@@ -37,14 +37,26 @@
 
 package org.spearce.jgit.revplot;
 
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+
 import org.spearce.jgit.lib.AnyObjectId;
+import org.spearce.jgit.lib.Commit;
+import org.spearce.jgit.lib.Ref;
 import org.spearce.jgit.lib.Repository;
+import org.spearce.jgit.lib.Tag;
 import org.spearce.jgit.revwalk.RevCommit;
 import org.spearce.jgit.revwalk.RevSort;
 import org.spearce.jgit.revwalk.RevWalk;
 
 /** Specialized RevWalk for visualization of a commit graph. */
 public class PlotWalk extends RevWalk {
+
+	Map<AnyObjectId, List<Ref>> reverseRefMap;
+
 	/**
 	 * Create a new revision walker for a given repository.
 	 * 
@@ -54,6 +66,7 @@
 	public PlotWalk(final Repository repo) {
 		super(repo);
 		super.sort(RevSort.TOPO, true);
+		reverseRefMap = repo.getAllRefsByPeeledObjectId();
 	}
 
 	@Override
@@ -64,7 +77,46 @@ public void sort(final RevSort s, final boolean use) {
 	}
 
 	@Override
-	protected RevCommit createCommit(final AnyObjectId id) {
-		return new PlotCommit(id);
+	protected RevCommit createCommit(final AnyObjectId id, final Ref[] tags) {
+		return new PlotCommit(id, tags);
+	}
+
+	@Override
+	protected Ref[] getTags(final AnyObjectId commitId) {
+		List<Ref> list = reverseRefMap.get(commitId);
+		Ref[] tags;
+		if (list == null)
+			tags = null;
+		else {
+			if (list != null && list.size() > 1) {
+				Collections.sort(list, new Comparator<Ref>() {
+					public int compare(Ref o1, Ref o2) {
+						try {
+							Object obj1 = getRepository().mapObject(o1.getObjectId(), o1.getName());
+							Object obj2 = getRepository().mapObject(o2.getObjectId(), o2.getName());
+							long t1 = timeof(obj1);
+							long t2 = timeof(obj2);
+							if (t1 > t2)
+								return -1;
+							if (t1 < t2)
+								return 1;
+							return 0;
+						} catch (IOException e) {
+							// ignore
+							return 0;
+						}
+					}
+					long timeof(Object o) {
+						if (o instanceof Commit)
+							return ((Commit)o).getCommitter().getWhen().getTime();
+						if (o instanceof Tag)
+							return ((Tag)o).getTagger().getWhen().getTime();
+						return 0;
+					}
+				});
+			}
+			tags = list.toArray(new Ref[list.size()]);
+		}
+		return tags;
 	}
 }
diff --git a/org.spearce.jgit/src/org/spearce/jgit/revwalk/RevWalk.java b/org.spearce.jgit/src/org/spearce/jgit/revwalk/RevWalk.java
index d7e4c58..41d57c6 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/revwalk/RevWalk.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/revwalk/RevWalk.java
@@ -53,6 +53,7 @@
 import org.spearce.jgit.lib.ObjectId;
 import org.spearce.jgit.lib.ObjectIdSubclassMap;
 import org.spearce.jgit.lib.ObjectLoader;
+import org.spearce.jgit.lib.Ref;
 import org.spearce.jgit.lib.Repository;
 import org.spearce.jgit.lib.WindowCursor;
 import org.spearce.jgit.revwalk.filter.RevFilter;
@@ -541,7 +542,7 @@ public RevTree lookupTree(final AnyObjectId id) {
 	public RevCommit lookupCommit(final AnyObjectId id) {
 		RevCommit c = (RevCommit) objects.get(id);
 		if (c == null) {
-			c = createCommit(id);
+			c = createCommit(id, getTags(id));
 			objects.add(c);
 		}
 		return c;
@@ -564,7 +565,7 @@ public RevObject lookupAny(final AnyObjectId id, final int type) {
 		if (r == null) {
 			switch (type) {
 			case Constants.OBJ_COMMIT:
-				r = createCommit(id);
+				r = createCommit(id, getTags(id));
 				break;
 			case Constants.OBJ_TREE:
 				r = new RevTree(id);
@@ -687,7 +688,7 @@ public RevObject parseAny(final AnyObjectId id)
 			final int type = ldr.getType();
 			switch (type) {
 			case Constants.OBJ_COMMIT: {
-				final RevCommit c = createCommit(ldr.getId());
+				final RevCommit c = createCommit(ldr.getId(), getTags(ldr.getId()));
 				c.parseCanonical(this, data);
 				r = c;
 				break;
@@ -718,6 +719,14 @@ public RevObject parseAny(final AnyObjectId id)
 	}
 
 	/**
+	 * @param commitId
+	 * @return the list of refs associated with a commit, possibly filtered
+	 */
+	protected Ref[] getTags(final AnyObjectId commitId) {
+		return null; // Don't get tags in the basic case
+	}
+
+	/**
 	 * Ensure the object's content has been parsed.
 	 * <p>
 	 * This method only returns successfully if the object exists and was parsed
@@ -1008,9 +1017,11 @@ private boolean isNotStarted() {
 	 * 
 	 * @param id
 	 *            the object this walker requires a commit reference for.
+	 * @param tags
+	 *            tags attached to the commit
 	 * @return a new unparsed reference for the object.
 	 */
-	protected RevCommit createCommit(final AnyObjectId id) {
+	protected RevCommit createCommit(final AnyObjectId id, final Ref[] tags) {
 		return new RevCommit(id);
 	}
 
-- 
1.6.0.1.310.gf789d0.dirty
Previous: Robin RosenbergNext: Robin Rosenberg
Message 5 of 14 in “(unknown)”
  1. Robin RosenbergOct 5, 2008
  2. 1/6 Keep original ref name when reading refsRobin Rosenberg, Oct 5, 2008
  3. 2/6 Peel annotated tags when getting all refsRobin Rosenberg, Oct 5, 2008
  4. 3/6 Add a method to get refs by object IdRobin Rosenberg, Oct 5, 2008
  5. 4/6 Add tags to the graphical history display.Robin Rosenberg, Oct 5, 2008
  6. 5/6 Add decorate option to log programRobin Rosenberg, Oct 5, 2008
  7. 6/6 Comment the getId method and hint for copy to actually get an ObjectIdRobin Rosenberg, Oct 5, 2008
  8. Shawn O. PearceOct 6, 2008
  9. Robin RosenbergOct 6, 2008
  10. Shawn O. PearceOct 6, 2008
  11. Shawn O. PearceOct 6, 2008
  12. Robin RosenbergOct 6, 2008
  13. Shawn O. PearceOct 6, 2008
  14. Shawn O. PearceOct 6, 2008

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.