b409b5a3c5aef834f7604d6da332a1fe864b4e86
kate
Tue Nov 17 17:02:17 2020 -0800
Clean up code supporting barChartCategoryUrl. As bonus feature, dd support for r,g,b color spec. refs #22075
diff --git src/hg/lib/barChartUi.c src/hg/lib/barChartUi.c
index 3855f22..0244574 100644
--- src/hg/lib/barChartUi.c
+++ src/hg/lib/barChartUi.c
@@ -1,23 +1,24 @@
/* Bar chart track controls */
/* Copyright (C) 2015 The Regents of the University of California
* See README in this or parent directory for licensing information. */
#include "cheapcgi.h"
#include "cart.h"
#include "net.h"
+#include "errCatch.h"
#include "hui.h"
#include "trackDb.h"
#include "jsHelper.h"
#include "hCommon.h"
#include "rainbow.h"
#include "htmlColor.h"
#include "barChartCategory.h"
#include "barChartUi.h"
/* Restrict features on right-click (popup) version */
static boolean isPopup = FALSE;
/* Convenience functions for category filter controls */
@@ -148,169 +149,188 @@
safef(cartVar, sizeof(cartVar), "%s.%s", track, BAR_CHART_LOG_TRANSFORM);
boolean isLogTransform = cartCgiUsualBoolean(cart, cartVar, BAR_CHART_LOG_TRANSFORM_DEFAULT);
safef(buf, sizeof buf, "%sViewLimitsMaxLabel %s", track, isLogTransform ? "disabled" : "");
printf("View limits maximum:\n", buf);
safef(cartVar, sizeof(cartVar), "%s.%s", track, BAR_CHART_MAX_VIEW_LIMIT);
int viewMax = cartCgiUsualInt(cart, cartVar, BAR_CHART_MAX_VIEW_LIMIT_DEFAULT);
cgiMakeIntVarWithExtra(cartVar, viewMax, 4, isLogTransform ? "disabled" : "");
char *unit = trackDbSettingClosestToHomeOrDefault(tdb, BAR_CHART_UNIT, "");
printf(" %s (range 0-%d)\n", buf, unit,
round(barChartUiMaxMedianScore(tdb)));
}
// TODO: libify
static boolean isUrl(char *url)
{
-return ((startsWith("http://", url)
+return startsWith("http://", url)
|| startsWith("https://", url)
- || startsWith("ftp://", url)));
+ || startsWith("ftp://", url);
}
-struct barChartCategory *barChartUiGetCategories(char *database, struct trackDb *tdb)
-/* Get category colors and descriptions.
- Use labels in tab-sep file specified by barChartCategoryUrl setting, o/w in barChartBars setting.
- If colors are not specified via barChartColors setting or second column in category file,
- assign rainbow colors.
- */
+static void getCategsFromSettings(char *track, char *labelSetting, char *colorSetting,
+ struct slName **labels, struct slName **colors)
+/* Get category labels and optionally colors, from track settings */
{
-int count = 0;
-struct slName *labels = NULL, *colors = NULL;
-char *fileOrUrl = trackDbSetting(tdb, BAR_CHART_CATEGORY_URL);
-if (isEmpty(fileOrUrl))
- {
- // use trackDb settings for labels and perhaps colors
- char *labelSetting = trackDbSetting(tdb, BAR_CHART_CATEGORY_LABELS);
+if (!labels || !colors)
+ return;
if (isEmpty(labelSetting))
{
errAbort("barChart track %s missing required setting: %s or %s\n",
- tdb->track, BAR_CHART_CATEGORY_LABELS, BAR_CHART_CATEGORY_URL);
+ track, BAR_CHART_CATEGORY_LABELS, BAR_CHART_CATEGORY_URL);
}
char *words[BAR_CHART_MAX_CATEGORIES];
- count = chopLine(cloneString(labelSetting), words);
- labels = slNameListFromStringArray(words, count);
- char *colorSetting = trackDbSetting(tdb, BAR_CHART_CATEGORY_COLORS);
+int labelCount = chopLine(cloneString(labelSetting), words);
+*labels = slNameListFromStringArray(words, labelCount);
if (isNotEmpty(colorSetting))
{
- int ct = chopLine(cloneString(colorSetting), words);
- if (ct != count)
+ int colorCount = chopLine(cloneString(colorSetting), words);
+ if (colorCount != labelCount)
errAbort("barChart track %s settings mismatch: %s (%d) and %s (%d)\n",
- tdb->track, BAR_CHART_CATEGORY_LABELS, count, BAR_CHART_CATEGORY_COLORS, ct);
- colors = slNameListFromStringArray(words, count);
+ track, BAR_CHART_CATEGORY_LABELS, labelCount, BAR_CHART_CATEGORY_COLORS, colorCount);
+ *colors = slNameListFromStringArray(words, labelCount);
}
}
-else
+
+static void getCategsFromFile(char *track, char *categUrl,
+ struct slName **labels, struct slName **colors)
+/* Get category labels and optionally colors, from category file.
+ * This is tab-sep file, column 1 is category label, optional column 2 is a color spec */
{
- // use file for labels and perhaps colors
+if (!labels || !colors) return;
struct lineFile *lf = NULL;
-#ifdef TODO
-// TODO: protect against network error
+// protect against network error
struct errCatch *errCatch = errCatchNew();
if (errCatchStart(errCatch))
{
- if (isUrl(fileOrUrl))
- {
- lf = netLineFileOpen(fileOrUrl);
+ if (isUrl(categUrl))
+ lf = netLineFileOpen(categUrl);
else
- lf = lineFileMayOpen(fileOrUrl, TRUE);
- }
+ lf = lineFileMayOpen(categUrl, TRUE);
}
errCatchEnd(errCatch);
if (errCatch->gotError)
{
if (isNotEmpty(errCatch->message->string))
- warn("unable to open %s: %s", fileOrUrl, errCatch->message->string);
+ warn("unable to open %s track file %s: %s",
+ track, categUrl, errCatch->message->string);
}
errCatchFree(&errCatch);
-#endif
-
- if (isUrl(fileOrUrl))
- lf = netLineFileOpen(fileOrUrl);
- else
- lf = lineFileMayOpen(fileOrUrl, TRUE);
char *line = NULL;
int cols = 0;
while (lineFileNextReal(lf, &line))
{
char *words[2];
int wordCount = chopTabs(line, words);
if (cols)
{
if (wordCount != cols)
errAbort("barChart track %s category file %s expecting %d words, got %d",
- tdb->track, fileOrUrl, cols, wordCount);
+ track, categUrl, cols, wordCount);
}
else
{
cols = wordCount;
}
slAddHead(&labels, slNameNew(words[0]));
if (wordCount == 2)
slAddHead(&colors, slNameNew(words[1]));
- count++;
}
slReverse(&labels);
slReverse(&colors);
}
-// populate categories
+static struct barChartCategory *createCategs(char *track,
+ struct slName *labels, struct slName *colors)
+/* Populate category structs from label and color lists. Assign rainbow if no color list */
+{
struct barChartCategory *categs = NULL, *categ = NULL;
+int count = slCount(labels);
struct rgbColor *rainbow = NULL;
if (!colors)
{
rainbow = getRainbow(&saturatedRainbowAtPos, count);
}
int i;
char buf[6];
for (i=0 ; iid = i;
safef(buf, sizeof buf, "%d", i);
categ->name = cloneString(buf);
categ->label = labels->name;
- if (colors)
+ if (!colors)
+ {
+ // rainbow
+ categ->color = ((rainbow[i].r & 0xff)<<16) +
+ ((rainbow[i].g & 0xff)<<8) +
+ ((rainbow[i].b & 0xff));
+ }
+ else
{
- unsigned rgb;
+ // colors from user
+ unsigned rgb = 0;
char *color = colors->name;
- if (htmlColorForCode(color, &rgb))
+ if (!htmlColorForCode(color, &rgb))
{
- categ->color = rgb;
- }
- else if (htmlColorForName(color, &rgb))
+ if (!htmlColorForName(color, &rgb))
{
- categ->color = rgb;
- }
- else
- warn("barChart track %s unknown color %s. Must be one of %s\n",
- tdb->track, color, slNameListToString(htmlColorNames(),','));
+ /* try r,g,b */
+ if (index(color, ','))
+ {
+ unsigned char r, g, b;
+ parseColor(color, &r, &g, &b);
+ htmlColorFromRGB(&rgb, r, g, b);
}
else
{
- categ->color = ((rainbow[i].r & 0xff)<<16) +
- ((rainbow[i].g & 0xff)<<8) +
- ((rainbow[i].b & 0xff));
+ warn("barChart track %s unknown color %s. Must r,g,b or #ffffff or one of %s\n",
+ track, color, slNameListToString(htmlColorNames(),','));
+ }
+ }
+ }
+ categ->color = rgb;
}
slAddHead(&categs, categ);
labels = labels->next;
if (colors)
colors = colors->next;
}
slReverse(&categs);
return categs;
}
+struct barChartCategory *barChartUiGetCategories(char *database, struct trackDb *tdb)
+/* Get category colors and descriptive labels.
+ Use labels in tab-sep file specified by barChartCategoryUrl setting, o/w in barChartBars setting.
+ If colors are not specified via barChartColors setting or second column in category file,
+ assign rainbow colors. Colors are specified as #fffff or r,g,b or html color name) */
+{
+struct slName *labels = NULL, *colors = NULL;
+char *categUrl = trackDbSetting(tdb, BAR_CHART_CATEGORY_URL);
+if (isNotEmpty(categUrl))
+ getCategsFromFile(tdb->track, categUrl, &labels, &colors);
+else
+ {
+ char *labelSetting = trackDbSetting(tdb, BAR_CHART_CATEGORY_LABELS);
+ char *colorSetting = trackDbSetting(tdb, BAR_CHART_CATEGORY_COLORS);
+ getCategsFromSettings(tdb->track, labelSetting, colorSetting, &labels, &colors);
+ }
+return createCategs(tdb->track, labels, colors);
+}
+
struct barChartCategory *barChartUiGetCategoryById(int id, char *database,
struct trackDb *tdb)
/* Get category info by id */
{
struct barChartCategory *categ;
struct barChartCategory *categs = barChartUiGetCategories(database, tdb);
for (categ = categs; categ != NULL; categ = categ->next)
if (categ->id == id)
return categ;
return NULL;
}
char *barChartUiGetCategoryLabelById(int id, char *database, struct trackDb *tdb)
/* Get label for a category id */
{