520d704e34f2eea59592fa24a4b830e1df0adcf4
galt
  Wed Mar 30 15:26:33 2016 -0700
Fixes #17096. Enhanced nextExon hover labels explains what it does now.

diff --git src/hg/hgTracks/simpleTracks.c src/hg/hgTracks/simpleTracks.c
index 9afd22a..08ce117 100644
--- src/hg/hgTracks/simpleTracks.c
+++ src/hg/hgTracks/simpleTracks.c
@@ -2297,40 +2297,43 @@
 /* Draw a mapBox over the arrow-button on an *item already in the window*. */
 /* Clicking this will do one of several things: */
 {
 boolean result = FALSE;
 struct linkedFeatures *lf = item;
 struct simpleFeature *exons = lf->components;
 struct simpleFeature *exon = exons;
 char *nextExonText;
 char *prevExonText;
 long newWinSize = virtWinEnd - virtWinStart;
 long bufferToEdge = 0.05 * newWinSize;
 long newWinStart, newWinEnd;
 int numExons = 0;
 int exonIx = 0;
 struct slRef *exonList = NULL, *ref;
+boolean isExon = FALSE;
 if (startsWith("chain", tg->tdb->type) || startsWith("lrg", tg->tdb->track))
     {
     nextExonText = trackDbSettingClosestToHomeOrDefault(tg->tdb, "nextExonText", "Next Block");
     prevExonText = trackDbSettingClosestToHomeOrDefault(tg->tdb, "prevExonText", "Prev Block");
     }
 else
     {
-    nextExonText = trackDbSettingClosestToHomeOrDefault(tg->tdb, "nextExonText", "Next Exon Edge");
-    prevExonText = trackDbSettingClosestToHomeOrDefault(tg->tdb, "prevExonText", "Prev Exon Edge");
+    nextExonText = trackDbSettingClosestToHomeOrDefault(tg->tdb, "nextExonText", "Next Exon");
+    prevExonText = trackDbSettingClosestToHomeOrDefault(tg->tdb, "prevExonText", "Prev Exon");
     }
+if (sameString(nextExonText,"Next Exon"))
+    isExon = TRUE;
 while (exon != NULL)
 /* Make a stupid list of exons separate from what's given. */
 /* It seems like lf->components isn't necessarily sorted. */
     {
     refAdd(&exonList, exon);
     exon = exon->next;
     }
 /* Now sort it. */
 if (next)
     slSort(&exonList, exonSlRefCmp);
 else
     slSort(&exonList, exonSlRefReverseCmp);
 numExons = slCount(exonList);
 
 // translate tall and exons
@@ -2386,60 +2389,102 @@
     boolean revStrand = (lf->orientation == -1);
     exon = ref->val;
 
     // translate exon
     long xExonStart = cr->vStart, xExonEnd = cr->vEnd;
 
     if ((xExonEnd != -1) && ((xExonEnd - xExonStart) > (newWinSize - (2 * bufferToEdge))))
 	bigExon = TRUE;
     if (next && (xExonEnd != -1) && (xExonEnd > virtWinEnd))
 	/* right overhang (but left side of screen in reverse-strand-display) */
 	{
 	if (xExonStart < virtWinEnd)
 	    {
 	    /* not an intron hanging over edge. */
 	    if ((xTallStart != -1) && (xTallStart > virtWinEnd) && (xTallStart < xExonEnd) && (xTallStart > xExonStart))
+		{
 		linkedFeaturesMoveWinEnd(xTallStart, bufferToEdge, newWinSize, &newWinStart, &newWinEnd);
+		if (isExon)
+		    {
+		    nextExonText = "Coding Start of Exon";
+		    prevExonText = "Coding End of Exon";
+		    }
+		}
 	    else if ((xTallEnd != -1) && (xTallEnd > virtWinEnd) && (xTallEnd < xExonEnd) && (xTallEnd > xExonStart))
+		{
 		linkedFeaturesMoveWinEnd(xTallEnd, bufferToEdge, newWinSize, &newWinStart, &newWinEnd);
+		if (isExon)
+		    {
+		    nextExonText = "Coding End of Exon";
+		    prevExonText = "Coding Start of Exon";
+		    }
+		}
 	    else
+		{
 		linkedFeaturesMoveWinEnd(xExonEnd, bufferToEdge, newWinSize, &newWinStart, &newWinEnd);
+		if (isExon)
+		    {
+		    nextExonText = "End of Exon";
+		    prevExonText = "Start of Exon";
+		    }
+		}
 	    }
 	else if (bigExon)
 	    linkedFeaturesMoveWinStart(xExonStart, bufferToEdge, newWinSize, &newWinStart, &newWinEnd);
 	else
 	    linkedFeaturesMoveWinEnd(xExonEnd, bufferToEdge, newWinSize, &newWinStart, &newWinEnd);
 	if (!revStrand)
 	    safef(mouseOverText, sizeof(mouseOverText), "%s (%d/%d)", nextExonText, exonIx+1, numExons);
 	else
 	    safef(mouseOverText, sizeof(mouseOverText), "%s (%d/%d)", prevExonText, numExons-exonIx, numExons);
 	mapBoxJumpTo(hvg, x, y, w, h, tg, virtChromName, newWinStart, newWinEnd, mouseOverText);
 	result = TRUE;
 	break;
 	}
     else if (!next && (xExonStart != -1) && (xExonStart < virtWinStart))
 	/* left overhang */
 	{
 	if (xExonEnd > virtWinStart)
 	    {
 	    /* not an intron hanging over the edge. */
 	    if ((xTallEnd != -1) && (xTallEnd < virtWinStart) && (xTallEnd > xExonStart) && (xTallEnd < xExonEnd))
+		{
 		linkedFeaturesMoveWinStart(xTallEnd, bufferToEdge, newWinSize, &newWinStart, &newWinEnd);
+		if (isExon)
+		    {
+		    nextExonText = "Coding Start of Exon";
+		    prevExonText = "Coding End of Exon";
+		    }
+		}
 	    else if ((xTallStart != -1) && (xTallStart < virtWinStart) && (xTallStart > xExonStart) && (xTallStart < xExonEnd))
+		{
 		linkedFeaturesMoveWinStart(xTallStart, bufferToEdge, newWinSize, &newWinStart, &newWinEnd);
+		if (isExon)
+		    {
+		    nextExonText = "Coding End of Exon";
+		    prevExonText = "Coding Start of Exon";
+		    }
+		}
 	    else
+		{
 		linkedFeaturesMoveWinStart(xExonStart, bufferToEdge, newWinSize, &newWinStart, &newWinEnd);
+		if (isExon)
+		    {
+		    nextExonText = "End of Exon";
+		    prevExonText = "Start of Exon";
+		    }
+		}
 	    }
 	else if (bigExon)
 	    linkedFeaturesMoveWinEnd(xExonEnd, bufferToEdge, newWinSize, &newWinStart, &newWinEnd);
 	else
 	    linkedFeaturesMoveWinStart(xExonStart, bufferToEdge, newWinSize, &newWinStart, &newWinEnd);
 	if (!revStrand)
 	    safef(mouseOverText, sizeof(mouseOverText), "%s (%d/%d)", prevExonText, numExons-exonIx, numExons);
 	else
 	    safef(mouseOverText, sizeof(mouseOverText), "%s (%d/%d)", nextExonText, exonIx+1, numExons);
 	mapBoxJumpTo(hvg, x, y, w, h, tg, virtChromName, newWinStart, newWinEnd, mouseOverText);
 	result = TRUE;
 	break;
 	}
     }
 slFreeList(&exonList);