90575b28d8d97732503671e4c5c80f7fbf2d3ac2
tdreszer
  Tue Oct 11 13:57:16 2011 -0700
With subCfg, when only one subtrack, highlevel shouuld show subtrack controls, so that rightClick and subCfg work together.
diff --git src/hg/lib/hui.c src/hg/lib/hui.c
index 2d7277f..d62ee79 100644
--- src/hg/lib/hui.c
+++ src/hg/lib/hui.c
@@ -3704,45 +3704,67 @@
     safef(htmlIdentifier, sizeof(htmlIdentifier), "%s.priority", tdb->track);
     char *cartHas = cartOptionalString(cart,htmlIdentifier);
     if(cartHas != NULL)
 	{
 	tdb->priority = atof(cartHas);
 	cartPriorities = TRUE;
 	}
     }
 slSort(tdbRefList, trackDbRefCmp);
 return cartPriorities;
 }
 
 void cfgByCfgType(eCfgType cType,char *db, struct cart *cart, struct trackDb *tdb,char *prefix, char *title, boolean boxed)
 // Methods for putting up type specific cfgs used by composites/subtracks in hui.c and exported for common use
 {
+#ifdef SUBTRACK_CFG
+// When only one subtrack, then show it's cfg settings instead of composite/view level settings
+// This simplifies the UI where hgTrackUi won't have 2 levels of cfg,
+// while hgTracks still supports rightClick cfg of the subtrack.
+if (configurableByAjax(tdb,cType) > 0) // Only if subtrack's configurable by ajax do we consider this option
+    {
+    if (tdbIsComposite(tdb)                       // called for the composite
+    && !tdbIsCompositeView(tdb->subtracks)        // and there is no view level
+    && slCount(tdb->subtracks) == 1)              // and there is only one subtrack
+        {
+        //warn("What do you mean by having a composite (%s) with only one subtrack (%s) ???",tdb->track,tdb->subtracks->track);
+        tdb = tdb->subtracks; // show subtrack cfg instead
+        prefix = tdb->track;
+        }
+    else if (tdb->parent != NULL
+        && tdbIsCompositeView(tdb->parent)       // subtrack has view
+        && differentString(prefix,tdb->track)    // and this has been called for the view
+        && slCount(tdb->parent->subtracks) == 1) // and there is only one subtrack
+        prefix = tdb->track; // removes reference to view level
+    }
+#endif///def SUBTRACK_CFG
 switch(cType)
     {
     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);
+    case cfgWigMaf:     // NOTE: wigMaf is using non-standard view level naming methods so isn't configurable by ajax
+                        wigMafCfgUi(cart,tdb,prefix,title,boxed, db);
                         break;
     case cfgGenePred:   genePredCfgUi(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:    bedUi(tdb,cart,title, boxed);
                  	break;
 #ifdef USE_BAM
     case cfgBam:        bamCfgUi(cart, tdb, prefix, title, boxed);
 			break;
 #endif
     case cfgVcf:	vcfCfgUi(cart, tdb, prefix, title, boxed);
 			break;
@@ -4004,32 +4026,32 @@
     int ix;
 
     // Determine whether subtrack is checked, visible, configurable, has group membership, etc.
     int fourState = subtrackFourStateChecked(subtrack,cart);
     boolean checkedCB = fourStateChecked(fourState);
     boolean enabledCB = fourStateEnabled(fourState);
     boolean visibleCB = fourStateVisible(fourState);
     membership_t *membership = subgroupMembershipGet(subtrack);
     eCfgType cType = cfgNone;
     if (!tdbIsMultiTrack(parentTdb))  // MultiTracks never have configurable subtracks!
         cType = cfgTypeFromTdb(subtrack,FALSE);
     if (cType != cfgNone)
         {
     #ifdef SUBTRACK_CFG
         // Turn off configuring for certain track type or if explicitly turned off
-        int cfgSubterack = configurableByPopup(subtrack,cType);
-        if (cfgSubterack <= 0)
+        int cfgSubterack = configurableByAjax(subtrack,cType);
+        if (cfgSubterack <= cfgNone)
             cType = cfgNone;
         else if (membersForAll->members[dimV]) // subtrack only configurable if more than one subtrack in view
             {                                  // find "view" in subgroup membership: e.g. "signal"
             if (-1 != (ix = stringArrayIx(membersForAll->members[dimV]->groupTag, membership->subgroups, membership->count)))
                 {
                 int ix2;                       // find "signal" in set of all views
                 if (-1 != (ix2 = stringArrayIx(membership->membership[ix], membersForAll->members[dimV]->tags, membersForAll->members[dimV]->count)))
                     {
                     if (membersForAll->members[dimV]->subtrackCount[ix2] < 2)
                         cType = cfgNone;
                     }
                 }
             }
         else if (slCount(subtrackRefList) < 2 && cfgTypeFromTdb(parentTdb,FALSE) != cfgNone)
             cType = cfgNone;  // don't bother if there is a single subtrack but the composite is configurable.
@@ -4175,32 +4197,31 @@
         // How to make this thing float to the left?  Container is overflow:visible
         // and contained (made in js) is position:relative; left: -{some pixels}
         #define CFG_SUBTRACK_DIV "<DIV id='div_cfg_%s' class='subCfg %s' style='display:none; overflow:visible;'></DIV>"
         #define MAKE_CFG_SUBTRACK_DIV(table,view) printf(CFG_SUBTRACK_DIV,(table),(view)?(view):"noView")
         char * view = NULL;
         if (membersForAll->members[dimV] && -1 != (ix = stringArrayIx(membersForAll->members[dimV]->groupTag, membership->subgroups, membership->count)))
             view = membership->membership[ix];
         MAKE_CFG_SUBTRACK_DIV(subtrack->track,view);
     #else///ifndef SUBTRACK_CFG
         dependentCfgsNeedBinding = TRUE; // configurable subtrack needs to be bound to composite settings
         #define CFG_SUBTRACK_DIV "<DIV id='div_%s_cfg'%s><INPUT TYPE=HIDDEN NAME='%s' value='%s'>\n"
         #define MAKE_CFG_SUBTRACK_DIV(table,cfgVar,open) printf(CFG_SUBTRACK_DIV,(table),((open)?"":" style='display:none'"),(cfgVar),((open)?"on":"off"))
         safef(buffer,sizeof(buffer),"%s.childShowCfg",subtrack->track);
         boolean open = cartUsualBoolean(cart, buffer,FALSE);
         MAKE_CFG_SUBTRACK_DIV(subtrack->track,buffer,open);
-        safef(buffer,sizeof(buffer),"%s",subtrack->track);
-        cfgByCfgType(cType,db,cart,subtrack,buffer,"Subtrack",TRUE);
+        cfgByCfgType(cType,db,cart,subtrack,subtrack->track,"Subtrack",TRUE);
         printf("</DIV>");
     #endif///ndef SUBTRACK_CFG
         }
 
     // A schema link for each track
     printf("</td>\n<TD>&nbsp;");
     makeSchemaLink(db,subtrack,"schema");
     printf("&nbsp;");
 
     // Do we have a restricted until date?
     if (restrictions)
         {
         char *dateDisplay = encodeRestrictionDate(db,subtrack,FALSE); // includes dates in the past
         if (dateDisplay)
             {
@@ -5473,53 +5494,67 @@
 
 filterBy_t *filterBySet = filterBySetGet(tdb,cart,name);
 if(filterBySet != NULL)
     {
     printf("<BR>");
     filterBySetCfgUi(cart,tdb,filterBySet,FALSE);
     filterBySetFree(&filterBySet);
     }
 
 cfgEndBox(boxed);
 }
 
 static boolean isSpeciesOn(struct cart *cart, struct trackDb *tdb, char *species, char *option, int optionSize, boolean defaultState)
 /* check the cart to see if species is turned off or on (default is defaultState) */
 {
+#ifdef SUBTRACK_CFG
+        // FIXME: works now in configByAjax but affects not seen in track image!!!
+boolean compositeLevel = isNameAtCompositeLevel(tdb,option);
+if (*option == '\0')
+    safef(option, optionSize, "%s.%s", tdb->track, species);
+else
+    {
+    char *suffix = option + strlen(option);
+    int suffixSize = optionSize - strlen(option);
+    safef(suffix,suffixSize,".%s",species);
+    }
+return cartUsualBooleanClosestToHome(cart,tdb, compositeLevel, species,defaultState);
+#else///ifndef SUBTRACK_CFG
 boolean ret = defaultState;
 safef(option, optionSize, "%s.%s", tdb->track, species);
 
 /* see if this is a simple multiz (not composite track) */
 char *s = cartOptionalString(cart, option);
 if (s != NULL)
     ret =  (sameString(s, "on") || atoi(s) > 0);
 else
     {
     /* check parent to see if it has these variables */
     if (tdb->parent != NULL)
 	{
 	char *viewString;
 	if (subgroupFind(tdb, "view", &viewString))
 	    {
 	    safef(option, optionSize, "%s.%s.%s",
 		tdb->parent->track, viewString,  species);
 	    ret = cartUsualBoolean(cart, option, ret);
 	    }
 	}
     }
 
 return ret;
+#endif///ndef SUBTRACK_CFG
 }
 
 char **wigMafGetSpecies(struct cart *cart, struct trackDb *tdb, char *db, struct wigMafSpecies **list, int *groupCt)
 {
 int speciesCt = 0;
 char *speciesGroup = trackDbSettingClosestToHome(tdb, SPECIES_GROUP_VAR);
 char *speciesUseFile = trackDbSettingClosestToHome(tdb, SPECIES_USE_FILE);
 char *speciesOrder = trackDbSettingClosestToHome(tdb, SPECIES_ORDER_VAR);
 char sGroup[24];
 //Ochar *groups[20];
 struct wigMafSpecies *wmSpecies, *wmSpeciesList = NULL;
 int group;
 int i;
 #define MAX_SP_SIZE 2000
 #define MAX_GROUPS 20
@@ -5547,30 +5582,33 @@
     }
 
 for (group = 0; group < *groupCt; group++)
     {
     if (*groupCt != 1 || !speciesOrder)
         {
         safef(sGroup, sizeof sGroup, "%s%s",
                                 SPECIES_GROUP_PREFIX, groups[group]);
         speciesOrder = trackDbRequiredSetting(tdb, sGroup);
         }
     speciesCt = chopLine(speciesOrder, species);
     for (i = 0; i < speciesCt; i++)
         {
         AllocVar(wmSpecies);
         wmSpecies->name = cloneString(species[i]);
+#ifdef SUBTRACK_CFG
+        *option = '\0'; // signal to look for the lowest level
+#endif///def SUBTRACK_CFG
 	wmSpecies->on = isSpeciesOn(cart, tdb, wmSpecies->name, option, sizeof option, TRUE);
         wmSpecies->group = group;
         slAddHead(&wmSpeciesList, wmSpecies);
         }
     }
 slReverse(&wmSpeciesList);
 *list = wmSpeciesList;
 
 return groups;
 }
 
 
 struct wigMafSpecies * wigMafSpeciesTable(struct cart *cart,
     struct trackDb *tdb, char *name, char *db)
 {
@@ -5750,57 +5788,63 @@
                 puts("</TD>");
                 fflush(stdout);
                 lineBreakJustPrinted = FALSE;
                 j++;
                 }
             sqlFreeResult(&sr);
             hFreeConn(&conn);
             }
         }
     else
     	{
     	puts("<TD>");
 	boolean defaultState = TRUE;
 	if (offHash != NULL)
 	    defaultState = (hashLookup(offHash, wmSpecies->name) == NULL);
+#ifdef SUBTRACK_CFG
+        safecpy(option, sizeof(option), name);
+#endif///def SUBTRACK_CFG
         wmSpecies->on = isSpeciesOn(cart, tdb, wmSpecies->name, option, sizeof option, defaultState );
         cgiMakeCheckBoxWithId(option, wmSpecies->on,id);
     	label = hOrganism(wmSpecies->name);
     	if (label == NULL)
 		label = wmSpecies->name;
         if (lowerFirstChar)
             *label = tolower(*label);
     	printf ("%s<BR>", label);
     	puts("</TD>");
         lineBreakJustPrinted = FALSE;
         j++;
         }
     }
 puts("</TR></TABLE><BR>\n");
 return wmSpeciesList;
 }
 
 void wigMafCfgUi(struct cart *cart, struct trackDb *tdb,char *name, char *title, boolean boxed, char *db)
 /* UI for maf/wiggle track
  * NOTE: calls wigCfgUi */
 {
 bool lowerFirstChar = TRUE;
 int i;
 char option[MAX_SP_SIZE];
 char *viewString = NULL;
 
+// FIXME: wigMaf is using non-standard view level naming methods so isn't configurable by ajax
+#ifndef SUBTRACK_CFG
 subgroupFind(tdb, "view", &viewString);
+#endif///ndef SUBTRACK_CFG
 
 boxed = cfgBeginBoxAndTitle(tdb, boxed, title);
 
 char *defaultCodonSpecies = trackDbSetting(tdb, SPECIES_CODON_DEFAULT);
 char *framesTable = trackDbSetting(tdb, "frames");
 char *firstCase = trackDbSetting(tdb, ITEM_FIRST_CHAR_CASE);
 if (firstCase != NULL)
     {
     if (sameWord(firstCase, "noChange")) lowerFirstChar = FALSE;
     }
 char *treeImage = NULL;
 struct consWiggle *consWig, *consWiggles = wigMafWiggles(db, tdb);
 
 
 boolean isWigMafProt = FALSE;