1f5a7c5b430943462e3fed00385b4112a65e5f9d
jcasper
  Thu May 12 15:31:45 2022 -0700
First pass - fixing a barChart draw issue and enabling the trackDb minimum
width/padding variables, refs #28062

diff --git src/hg/hgTracks/barChartTrack.c src/hg/hgTracks/barChartTrack.c
index 162287f..3c967e2 100644
--- src/hg/hgTracks/barChartTrack.c
+++ src/hg/hgTracks/barChartTrack.c
@@ -763,67 +763,63 @@
     drawGraphBox(tg, itemInfo, hvg, x0, yZero+1);
 
 struct rgbColor lineColor = {.r=0};
 int lineColorIx = hvGfxFindColorIx(hvg, lineColor.r, lineColor.g, lineColor.b);
 int barWidth = extras->barWidth;
 char *colorScheme = cartUsualStringClosestToHome(cart, tg->tdb, FALSE, BAR_CHART_COLORS, 
                         BAR_CHART_COLORS_DEFAULT);
 Color clipColor = MG_MAGENTA;
 
 // draw bar graph
 int i;
 int expCount = bed->expCount;
 struct barChartCategory *categ;
 int barCount = filteredCategoryCount(extras), barsDrawn = 0;
 double invCount = 1.0/barCount;
-char *userSettingMinBarWidth = trackDbSetting(tg->tdb, BAR_CHART_USER_BAR_MIN_WIDTH);
-int userMinBarWidth = 0;
-if (userSettingMinBarWidth)
-    userMinBarWidth = sqlUnsigned(userSettingMinBarWidth);
+
 for (i=0, categ=extras->categories; i<expCount && categ != NULL; i++, categ=categ->next)
     {
     if (!filterCategory(extras, categ->name))
         continue;
+
+    int cStart = barsDrawn * graphWidth * invCount;
+    int cEnd = (barsDrawn+1) * graphWidth * invCount;
+    // note - removed userMinBarWidth here, as it's already been imposed in the initial barWidth calculation.
+    // Stretch mode only ever extends bars, not shrinks them, so the minimum doesn't need to be re-imposed here.
+    barWidth = cEnd - cStart - extras->padding;
+    // stop before going off the right edge
+    if (x1 + barWidth > x0 + graphWidth)
+        break;
+
     struct rgbColor fillColor = extras->colors[i];
     int fillColorIx = hvGfxFindColorIx(hvg, fillColor.r, fillColor.g, fillColor.b);
     double expScore = bed->expScores[i];
     int height = valToClippedHeight(expScore, extras->maxMedian, extras->maxViewLimit, 
                                         extras->maxHeight, extras->doLogTransform);
     boolean isClipped = (!extras->doLogTransform && expScore > extras->maxViewLimit);
     int barTop = yZero - height + 1;
+
     if (extras->padding == 0 || sameString(colorScheme, BAR_CHART_COLORS_USER))
-        {
-        int cStart = barsDrawn * graphWidth * invCount;
-        int cEnd = (barsDrawn+1) * graphWidth * invCount;
-        if (i >= 1)
-            x1 += barWidth + extras->padding;
-        barWidth = max(userMinBarWidth, cEnd - cStart - extras->padding);
-        if (x1 + barWidth > x0 + graphWidth)
-            break;
         hvGfxBox(hvg, x1, barTop, barWidth, height, fillColorIx);
-        if (isClipped)
-            hvGfxBox(hvg, x1, barTop, barWidth, 2, clipColor);
-        barsDrawn += 1;
-        }
     else
-        {
         hvGfxOutlinedBox(hvg, x1, barTop, barWidth, height, fillColorIx, lineColorIx);
+
     // mark clipped bar with magenta tip
     if (isClipped)
         hvGfxBox(hvg, x1, barTop, barWidth, 2, clipColor);
-        x1 = x1 + barWidth + extras->padding;
-        }
+    x1 += barWidth + extras->padding;
+    barsDrawn += 1;
     }
 }
 
 static char *chartMapText(struct track *tg, struct barChartCategory *categ, double expScore)
 /* Construct mouseover text for a chart bar */
 {
 static char buf[256];
 struct barChartTrack *extras = (struct barChartTrack *)tg->extraUiData;
 safef(buf, sizeof(buf), "%s (%.1f %s)", categ->label, expScore, extras->unit);
 subChar(buf, '_', ' ');
 return buf;
 }
 
 static int barChartItemStart(struct track *tg, void *item)
 /* Return end chromosome coordinate of item, including graph */
@@ -895,65 +891,64 @@
 int labelWidth = mgFontStringWidth(tl.font, itemName);
 getItemX(start, end, &x1, &x2);
 if (x1-labelWidth <= insideX)
     labelWidth = 0;
 // map over label
 int itemHeight = itemInfo->height;
 mapBoxHc(hvg, itemStart, itemEnd, x1-labelWidth, y, labelWidth, itemHeight-3, 
                     tg->track, mapItemName, itemName);
 
 
 int graphX = barChartX(bed);
 int graphWidth = chartWidth(tg, itemInfo);
 int barCount = filteredCategoryCount(extras);
 
 char label[256];
-char *userSettingMinBarWidth= trackDbSetting(tg->tdb, BAR_CHART_USER_BAR_MIN_WIDTH);
-int userMinBarWidth = 0;
-if (userSettingMinBarWidth)
-    userMinBarWidth = sqlUnsigned(userSettingMinBarWidth);
 if (barCount <= graphWidth) // Don't create map boxes if less than one pixel per bar
     {
     // add maps to category bars
     struct barChartCategory *categs = getCategories(tg);
     struct barChartCategory *categ = NULL;
     int x0 = insideX + graphX;
     int x1 = x0;
     double invCount = 1.0/barCount;
     int i = 0, barsDrawn = 0, width = 0;
     int extraAtTop = 4;
     for (categ = categs; categ != NULL; categ = categ->next, i++)
         {
         if (!filterCategory(extras, categ->name))
             continue;
         x1 += width;
         int cStart = barsDrawn * graphWidth * invCount;
         barsDrawn += 1;
         int cEnd = barsDrawn * graphWidth * invCount;
-        width = max(userMinBarWidth, max(1, cEnd - cStart));
+        width = max(1, cEnd - cStart);
+        int boxWidth = min(1, width - extras->padding); // forcing min 1 shouldn't ever actually happen, I think
         double expScore = bed->expScores[i];
         int height = valToClippedHeight(expScore, extras->maxMedian, extras->maxViewLimit,
                                             extras->maxHeight, extras->doLogTransform);
         height = min(height+extraAtTop, extras->maxHeight);
-        mapBoxHc(hvg, itemStart, itemEnd, x1, yZero-height, width, height,
+        mapBoxHc(hvg, itemStart, itemEnd, x1, yZero-height, boxWidth, height,
                             tg->track, mapItemName, chartMapText(tg, categ, expScore));
         }
     safef(label, sizeof(label), 
 	"%s - click for faceted view or hover over a bar for sample values", 
 	itemName);
     }
 else
+    // We should never get here; chartWidth always returns a value where at least one pixel
+    // of width is allocated to every category being drawn
     safef(label, sizeof(label), 
 	    "%s - zoom in to resolve individual bars or click for details", 
 	    itemName);
 // map over background of chart
 getItemX(start, end, &x1, &x2);
 mapBoxHc(hvg, itemStart, itemEnd, x1, y, graphWidth, itemHeight-3,
                     tg->track, mapItemName, label);
 }
 
 /* This is lifted nearly wholesale from gtexGene track.  Could be shared */
 
 static int getBarChartHeight(void *item)
 {
 struct barChartItem *itemInfo = (struct barChartItem *)item;
 assert(itemInfo->height != 0);