230b2b23ed69e202ac634bb16c62a833354f2fcd
max
  Tue Dec 9 13:18:48 2014 -0800
new tdb statement "labelOnFeature", refs #14512
diff --git src/hg/hgTracks/simpleTracks.c src/hg/hgTracks/simpleTracks.c
index f290ecf..8de7056 100644
--- src/hg/hgTracks/simpleTracks.c
+++ src/hg/hgTracks/simpleTracks.c
@@ -1190,30 +1190,68 @@
                     blendCount = maxCount;
                     }
                 }
             maxCount = binCount;
             maxColor = col;
             }
         }
     if (blendCount >= maxCount)
         maxColor = blendColor;
     }
 if (w < 1)
     w = 1;
 hvGfxBox(hvg, x1, y, w, height, maxColor);
 }
 
+void drawScaledBoxSampleLabel(struct hvGfx *hvg,
+     int chromStart, int chromEnd, double scale,
+     int xOff, int y, int height, Color color, MgFont *font,  char *label)
+/* Draw a box scaled from chromosome to window coordinates and draw a label onto it. */
+{
+//int i;
+int x1, x2, w;
+x1 = round((double)(chromStart-winStart)*scale) + xOff;
+x2 = round((double)(chromEnd-winStart)*scale) + xOff;
+
+if (x2 >= MAXPIXELS)
+    x2 = MAXPIXELS - 1;
+
+if (x2 < xOff)
+    x2 = xOff;
+if (x2 > xOff+insideWidth)
+    x2 = xOff+insideWidth;
+if (x1 < xOff)
+    x1 = xOff;
+if (x1 > xOff+insideWidth)
+    x1 = xOff+insideWidth;
+w = x2-x1;
+if (w < 1)
+    w = 1;
+hvGfxBox(hvg, x1, y, w, height, color);
+
+char *shortLabel = cloneString(label);
+/* calculate how many characters we can squeeze into box */
+int charsInBox = w / mgFontCharWidth(font, 'm');
+if (charsInBox > 4)
+    {
+    if (charsInBox < strlen(label))
+        strcpy(shortLabel+charsInBox-3, "...");
+    Color labelColor = hvGfxContrastingColor(hvg, color);
+    hvGfxTextCentered(hvg, x1, y, w, height, labelColor, font, shortLabel);
+    }
+}
+
 void drawScaledBoxSample(struct hvGfx *hvg,
                          int chromStart, int chromEnd, double scale,
                          int xOff, int y, int height, Color color, int score)
 /* Draw a box scaled from chromosome to window coordinates. */
 {
 //int i;
 int x1, x2, w;
 x1 = round((double)(chromStart-winStart)*scale) + xOff;
 x2 = round((double)(chromEnd-winStart)*scale) + xOff;
 
 if (x2 >= MAXPIXELS)
     x2 = MAXPIXELS - 1;
 w = x2-x1;
 if (w < 1)
     w = 1;
@@ -2749,30 +2787,40 @@
         &&  (e-s <= 3 || !baseColorNeedsCodons))
             baseColorDrawItem(tg, lf, sf->grayIx, hvg, xOff, y, scale, font, s, e, heightPer,
                               zoomedToCodonLevel, mrnaSeq, sf, psl, drawOpt, MAXPIXELS, winStart,
                               color);
         else
             {
 	    if (lf->highlightColor && (lf->highlightMode == highlightOutline))
 		{
 		drawScaledBoxSample(hvg, s, e, scale, xOff, y, heightPer,
 				    lf->highlightColor, lf->score );
 		drawScaledBoxSample(hvg, s, e, scale, xOff+1, y+1, heightPer-2,
 				    color, lf->score );
 		}
 	    else
 		{
+		if (tg->drawLabelInBox)
+                    {
+		    drawScaledBoxSampleLabel(hvg, s, e, scale, xOff, y, heightPer,
+                                color, font, lf->name );
+                    // exon arrows would overlap the text
+                    exonArrowsAlways = FALSE;
+                    exonArrows = FALSE;
+                    }
+
+		else
 		    drawScaledBoxSample(hvg, s, e, scale, xOff, y, heightPer,
 					color, lf->score);
                 }
 
             /* Display barbs only if no intron is visible on the item.
                This occurs when the exon completely spans the window,
                or when it is the first or last intron in the feature and
                the following/preceding intron isn't visible */
             if (exonArrowsAlways
             || (  exonArrows
                && (sf->start <= winStart || sf->start == lf->start)
                && (sf->end   >= winEnd   || sf->end   == lf->end)))
                 {
                 Color barbColor = hvGfxContrastingColor(hvg, color);
                 x1 = round((double)((int)s-winStart)*scale) + xOff;
@@ -3075,30 +3123,33 @@
 static void genericDrawItem(struct track *tg, struct spaceNode *sn,
                             struct hvGfx *hvg, int xOff, int yOff, int width,
                             MgFont *font, Color color, Color labelColor, enum trackVisibility vis,
                             double scale, boolean withLeftLabels)
 /* draw one non-overflow item */
 {
 struct slList *item = sn->val;
 int s = tg->itemStart(tg, item);
 int e = tg->itemEnd(tg, item);
 int sClp = (s < winStart) ? winStart : s;
 int eClp = (e > winEnd)   ? winEnd   : e;
 int x1 = round((sClp - winStart)*scale) + xOff;
 int x2 = round((eClp - winStart)*scale) + xOff;
 int textX = x1;
 
+if (tg->drawLabelInBox)
+    withLeftLabels = FALSE;
+
 if (tg->itemNameColor != NULL)
     {
     color = tg->itemNameColor(tg, item, hvg);
     labelColor = color;
     if (withLeftLabels && isTooLightForTextOnWhite(hvg, color))
 	labelColor = somewhatDarkerColor(hvg, color);
     }
 int y = yOff + tg->lineHeight * sn->row;
 tg->drawItemAt(tg, item, hvg, xOff, y, scale, font, color, vis);
 
 /* pgSnpDrawAt may change withIndividualLabels between items */
 boolean withLabels = (withLeftLabels && withIndividualLabels && (vis == tvPack) && !tg->drawName);
 if (withLabels)
     {
     char *name = tg->itemName(tg, item);
@@ -3440,30 +3491,34 @@
 /* Draw linked features items. */
 {
 clearColorBin();
 if (vis == tvDense && tg->colorShades)
     slSort(&tg->items, cmpLfsWhiteToBlack);
 genericDrawItems(tg, seqStart, seqEnd, hvg, xOff, yOff, width,
 	font, color, vis);
 }
 
 void linkedFeaturesDraw(struct track *tg, int seqStart, int seqEnd,
                         struct hvGfx *hvg, int xOff, int yOff, int width,
                         MgFont *font, Color color, enum trackVisibility vis)
 /* Draw linked features items. */
 {
 clearColorBin();
+
+// optional setting to draw labels onto the feature boxes, not next to them
+tg->drawLabelInBox = cartOrTdbBoolean(cart, tg->tdb, "labelOnFeature" , FALSE);
+
 if (tg->items == NULL && vis == tvDense && canDrawBigBedDense(tg))
     {
     bigBedDrawDense(tg, seqStart, seqEnd, hvg, xOff, yOff, width, font, color);
     }
 else
     {
     if (vis == tvDense && tg->colorShades)
 	slSort(&tg->items, cmpLfWhiteToBlack);
     genericDrawItems(tg, seqStart, seqEnd, hvg, xOff, yOff, width,
 	    font, color, vis);
     }
 }
 
 void incRange(UBYTE *start, int size)
 /* Add one to range of bytes, taking care to not overflow. */