5be304c4bdd41bd4452a4b9f1b8fcf37930079e4
braney
  Fri Feb 3 11:09:59 2017 -0800
allow arbitrary fields with a bigBed file to be used for labels.  #18782

diff --git src/hg/lib/hui.c src/hg/lib/hui.c
index 2b37af1..661a1c3 100644
--- src/hg/lib/hui.c
+++ src/hg/lib/hui.c
@@ -4037,48 +4037,50 @@
 {
 case cfgBedScore:
 		    {
 		    char *scoreMax = trackDbSettingClosestToHome(tdb, SCORE_FILTER _MAX);
 		    int maxScore = (scoreMax ? sqlUnsigned(scoreMax):1000);
 		    scoreCfgUi(db, cart,tdb,prefix,title,maxScore,boxed);
 		    }
 		    break;
 case cfgPeak:
 		    encodePeakCfgUi(cart,tdb,prefix,title,boxed);
 		    break;
 case cfgWig:        wigCfgUi(cart,tdb,prefix,title,boxed);
 		    break;
 case cfgWigMaf:     wigMafCfgUi(cart,tdb,prefix,title,boxed, db);
 		    break;
-case cfgGenePred:   genePredCfgUi(cart,tdb,prefix,title,boxed);
+case cfgGenePred:   genePredCfgUi(db, cart,tdb,prefix,title,boxed);
 		    break;
 case cfgChain:      chainCfgUi(db,cart,tdb,prefix,title,boxed, NULL);
 		    break;
 case cfgNetAlign:   netAlignCfgUi(db,cart,tdb,prefix,title,boxed);
 		    break;
 case cfgBedFilt:    bedFiltCfgUi(cart,tdb,prefix,title, boxed);
 		    break;
 case cfgBam:        bamCfgUi(cart, tdb, prefix, title, boxed);
 		    break;
 case cfgVcf:        vcfCfgUi(cart, tdb, prefix, title, boxed);
 		    break;
 case cfgLong:       longRangeCfgUi(cart, tdb, prefix, title, boxed);
 		    break;
 case cfgSnake:      snakeCfgUi(cart, tdb, prefix, title, boxed);
 		    break;
 case cfgPsl:        pslCfgUi(db,cart,tdb,prefix,title,boxed);
 		    break;
+case cfgBigBed:     labelCfgUi(db, cart, tdb);
+		    break;
 default:            warn("Track type is not known to multi-view composites. type is: %d ",
 			 cType);
 		    break;
 }
 }
 
 char *encodeRestrictionDate(char *db,struct trackDb *trackDb,boolean excludePast)
 // Create a string for ENCODE restriction date of this track
 // if return is not null, then free it after use
 {
 if (!trackDb)
 return NULL;
 
 char *date = NULL;
 
@@ -5786,39 +5788,65 @@
 // initial value of chromosome coloring option is "on", unless
 // overridden by the colorChromDefault setting in the track
 char *colorDefault = trackDbSettingOrDefault(tdb, "colorChromDefault", "on");
 
 printf("<p><b>Color track based on chromosome:</b> ");
 safef(colorVar, sizeof(colorVar), "%s.color", tdb->track);
 colorSetting = cartUsualString(cart, colorVar, colorDefault);
 cgiMakeRadioButton(colorVar, "on", sameString(colorSetting, "on"));
 printf(" on ");
 cgiMakeRadioButton(colorVar, "off", sameString(colorSetting, "off"));
 printf(" off ");
 printf("<br><br>");
 filterByChromCfgUi(cart,tdb);
 }
 
+void labelCfgUi(char *db, struct cart *cart, struct trackDb *tdb)
+/* If there is a labelFields for a bigBed, this routine is called to put up the label options. */
+{
+char *labelFields = trackDbSettingClosestToHome(tdb, "labelFields");
+if (labelFields == NULL)
+    return;
+
+struct slName *thisLabel, *labelIds = slNameListFromComma(labelFields);
+struct asObject *as = asForDb(tdb, db);  
+char varName[1024];
+
+printf("<B>Label:</B> ");
+for(thisLabel = labelIds; thisLabel; thisLabel = thisLabel->next)
+    {
+    struct asColumn *col = asColumnFind(as, thisLabel->name);
+
+    safef(varName, sizeof(varName), "%s.label.%s", tdb->track, thisLabel->name);
+    boolean option = cartUsualBoolean(cart, varName, thisLabel==labelIds);
+    cgiMakeCheckBox(varName, option);
+    printf(" %s&nbsp;&nbsp;&nbsp;", col->comment);
+
+    }
+}
+
 void pslCfgUi(char *db, struct cart *cart, struct trackDb *tdb, char *name, char *title,
               boolean boxed)
 /* Put up UI for psl tracks */
 {
 boxed = cfgBeginBoxAndTitle(tdb, boxed, title);
 
 char *typeLine = cloneString(tdb->type);
 char *words[8];
 int wordCount = wordCount = chopLine(typeLine, words);
+if (sameString(tdb->type, "bigPsl"))
+    labelCfgUi(db, cart, tdb);
 if (wordCount == 3 && sameWord(words[1], "xeno"))
     crossSpeciesCfgUi(cart,tdb);
 baseColorDropLists(cart, tdb, name);
 indelShowOptionsWithName(cart, tdb, name);
 cfgEndBox(boxed);
 }
 
 
 void netAlignCfgUi(char *db, struct cart *cart, struct trackDb *tdb, char *prefix, char *title,
                    boolean boxed)
 /* Put up UI for net tracks */
 {
 boxed = cfgBeginBoxAndTitle(tdb, boxed, title);
 
 boolean parentLevel = isNameAtParentLevel(tdb,prefix);
@@ -6158,38 +6186,39 @@
     printf("<TD align='left'%s> (%d to %d)",(filterByRange?"":" colspan=3"),minLimit, maxLimit);
     if (trackDbSettingClosestToHome(tdb, GRAY_LEVEL_SCORE_MIN) != NULL)
         {
         printf("<TR><TD align='right'colspan=5>");
         scoreGrayLevelCfgUi(cart, tdb, name, 1000);
         puts("</TR>");
         }
     }
 if (opened)
     {
     puts("</TABLE>");
     cfgEndBox(boxed);
     }
 }
 
-void genePredCfgUi(struct cart *cart, struct trackDb *tdb, char *name, char *title, boolean boxed)
+void genePredCfgUi(char *db, struct cart *cart, struct trackDb *tdb, char *name, char *title, boolean boxed)
 /* Put up gencode-specific controls */
 {
 char varName[64];
 boolean parentLevel = isNameAtParentLevel(tdb,name);
 char *geneLabel = cartUsualStringClosestToHome(cart, tdb,parentLevel, "label", "gene");
 boxed = cfgBeginBoxAndTitle(tdb, boxed, title);
 
+labelCfgUi(db, cart, tdb);
 if (sameString(name, "acembly"))
     {
     char *acemblyClass = cartUsualStringClosestToHome(cart,tdb,parentLevel,"type",
                                                       acemblyEnumToString(0));
     printf("<p><b>Gene Class: </b>");
     acemblyDropDown("acembly.type", acemblyClass);
     printf("  ");
     }
 else if (startsWith("wgEncodeGencode", name)
      ||  sameString("wgEncodeSangerGencode", name)
      ||  (startsWith("encodeGencode", name) && !sameString("encodeGencodeRaceFrags", name)))
     {
     printf("<B>Label:</B> ");
     safef(varName, sizeof(varName), "%s.label", name);
     cgiMakeRadioButton(varName, "gene", sameString("gene", geneLabel));