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 */ {