6ecf4a7fdccf43addd6ca15bc2dedaa239852784
braney
  Tue May 9 16:09:07 2017 -0700
ongoing work on hgComposite.  Support add all visible button

diff --git src/hg/hgComposite/hgComposite.c src/hg/hgComposite/hgComposite.c
index 4c89acc..5e34817 100644
--- src/hg/hgComposite/hgComposite.c
+++ src/hg/hgComposite/hgComposite.c
@@ -1,850 +1,896 @@
-/* hgVai - Variant Annotation Integrator. */
+/* hgComposite --- build a composite */
 
-/* Copyright (C) 2014 The Regents of the University of California 
+/* Copyright (C) 2017 The Regents of the University of California 
  * See README in this or parent directory for licensing information. */
 #include "common.h"
 #include "linefile.h"
 #include "hash.h"
 #include "options.h"
 #include "jksql.h"
 #include "htmshell.h"
 #include "web.h"
 #include "cheapcgi.h"
 #include "cart.h"
 #include "cartTrackDb.h"
 #include "genbank.h"
 #include "hgConfig.h"
 #include "hgHgvs.h"
 #include "hui.h"
 #include "grp.h"
 #include "hCommon.h"
 #include "hgFind.h"
 #include "hPrint.h"
 #include "jsHelper.h"
 #include "memalloc.h"
 #include "textOut.h"
 #include "trackHub.h"
 #include "hubConnect.h"
 #include "twoBit.h"
 #include "gpFx.h"
 #include "bigGenePred.h"
 #include "udc.h"
 #include "knetUdc.h"
 #include "cartTrackDb.h"
 #include "trashDir.h"
 #include "customComposite.h"
 
 #define hgCompEditPrefix    "hgCompositeEdit_"
 #define hgsAddTrack hgCompEditPrefix "addTrack"
+#define hgsAddVisTrack hgCompEditPrefix "addVisTrack"
 #define hgsChangeGroup hgCompEditPrefix "changeGroup"
 #define hgsCurrentGroup hgCompEditPrefix "currentGroup"
 #define hgsCurrentComposite hgCompEditPrefix "currentComposite"
 #define hgsNewCompositeName hgCompEditPrefix "newCompositeName"
 #define hgsNewCompositeShortLabel hgCompEditPrefix "newCompositeShortLabel"
 #define hgsNewCompositeLongLabel hgCompEditPrefix "newCompositeLongLabel"
 //#define hgCompositePrefix    "hgComposite_"
 #define hgDoNewComposite      hgCompEditPrefix    "doNewComposite"
 
 struct track
 {
 struct track *next;
 char *name;
 char *shortLabel;
 char *longLabel;
 };
 
 struct composite
 {
 struct composite *next;
 char *name;
 char *shortLabel;
 char *longLabel;
 struct track *trackList;
 };
 
 
 /* Global Variables */
 struct cart *cart;		/* CGI and other variables */
 struct hash *oldVars = NULL;	/* The cart before new cgi stuff added. */
 char *genome = NULL;		/* Name of genome - mouse, human, etc. */
 char *database = NULL;		/* Current genome database - hg17, mm5, etc. */
 struct grp *fullGroupList = NULL;	/* List of all groups. */
 
 // Null terminated list of CGI Variables we don't want to save permanently:
-char *excludeVars[] = {"Submit", "submit", "hgva_startQuery", hgsAddTrack,  hgsNewCompositeName, hgsNewCompositeShortLabel, hgsNewCompositeLongLabel, hgsChangeGroup, NULL};
+char *excludeVars[] = {"Submit", "submit", "hgva_startQuery", hgsAddTrack,  hgsNewCompositeName, hgsNewCompositeShortLabel, hgsNewCompositeLongLabel, hgsChangeGroup, hgsAddVisTrack, NULL};
 
 void nbSpaces(int count)
 /* Print some non-breaking spaces. */
 {
 int i;
 for (i=0; i<count; ++i)
     printf("&nbsp;");
 }
 
 void addSomeCss()
 /*#*** This should go in a .css file of course. */
 {
 printf("<style>\n"
 	"div.sectionLite { border-width: 1px; border-color: #"HG_COL_BORDER"; border-style: solid;"
 	"  background-color: #FFFFFF; padding-left: 10px; padding-right: 10px; "
 	"  padding-top: 8px; padding-bottom: 5px; margin-top: 5px; margin-bottom: 5px }\n"
 	".sectionLiteHeader { font-weight: bold; font-size:larger; color:#000000;"
 	"  text-align:left; vertical-align:bottom; white-space:nowrap; }\n"
 	"div.sectionLiteHeader.noReorderRemove { padding-bottom:5px; }\n"
 	"div.sourceFilter { padding-top: 5px; padding-bottom: 5px }\n"
 	"</style>\n");
 }
 
 
 INLINE void startCollapsibleSection(char *sectionSuffix, char *title, boolean onByDefault)
 // Wrap shared args to jsBeginCollapsibleSectionFontSize
 {
 jsBeginCollapsibleSectionFontSize(cart, "hgva", sectionSuffix, title, onByDefault, "1.1em");
 }
 
 INLINE void startSmallCollapsibleSection(char *sectionSuffix, char *title, boolean onByDefault)
 // Wrap shared args to jsBeginCollapsibleSectionFontSize
 {
 jsBeginCollapsibleSectionFontSize(cart, "hgva", sectionSuffix, title, onByDefault, "0.9em");
 }
 
 #define endCollapsibleSection jsEndCollapsibleSection
 
 
 static struct dyString *onChangeStart()
 /* Start up a javascript onChange command */
 {
 struct dyString *dy = jsOnChangeStart();
 return dy;
 }
 
 
 static char *onChangeClade()
 /* Return javascript executed when they change clade. */
 {
 struct dyString *dy = onChangeStart();
 jsDropDownCarryOver(dy, "clade");
 dyStringAppend(dy, " document.hiddenForm.org.value=0;");
 dyStringAppend(dy, " document.hiddenForm.db.value=0;");
 return jsOnChangeEnd(&dy);
 }
 
 static char *onChangeOrg()
 /* Return javascript executed when they change organism. */
 {
 struct dyString *dy = onChangeStart();
 jsDropDownCarryOver(dy, "clade");
 jsDropDownCarryOver(dy, "org");
 dyStringAppend(dy, " document.hiddenForm.db.value=0;");
 return jsOnChangeEnd(&dy);
 }
 
 static char *onChangeDb()
 /* Return javascript executed when they change database. */
 {
 struct dyString *dy = onChangeStart();
 jsDropDownCarryOver(dy, "clade");
 jsDropDownCarryOver(dy, "db");
 return jsOnChangeEnd(&dy);
 }
 
 INLINE void printOption(char *val, char *selectedVal, char *label)
 /* For rolling our own select without having to build conditional arrays/lists. */
 {
 printf("<OPTION VALUE='%s'%s>%s\n", val, (sameString(selectedVal, val) ? " SELECTED" : ""), label);
 }
 
 
 static struct composite *getCompositeList(char *db, char *hubName, struct hash *nameHash)
 {
 struct composite *compositeList = NULL;
 FILE *f;
 
 if ((hubName != NULL) && ((f = fopen(hubName, "r")) != NULL))
     {
     fclose(f);
     // read hub to find names of composites and add them to compositeList
     struct trackDb *tdbList = trackDbFromRa(hubName, NULL);
     struct trackDb *tdb, *tdbNext;
     struct composite *composite = NULL;
     struct track *track = NULL;
 
     for(tdb = tdbList; tdb; tdb = tdbNext)
         {
         hashAdd(nameHash, tdb->track, tdb);
         tdbNext = tdb->next;
         trackDbFieldsFromSettings(tdb);
         if (trackDbSetting(tdb, "compositeTrack"))
             {
             AllocVar(composite);
             slAddHead(&compositeList, composite);
             composite->name = tdb->track;
             composite->shortLabel = tdb->shortLabel;
             composite->longLabel = tdb->shortLabel;
             }
         else
             {
             if (composite == NULL)
                 errAbort("track not in composite");
             AllocVar(track);
             track->name = tdb->track;
             track->shortLabel = tdb->shortLabel;
             track->longLabel = tdb->shortLabel;
             slAddHead(&composite->trackList, track);
             }
         }
     }
 
 return compositeList;
 }
 
 static char *getSqlBigWig(char *db, struct trackDb *tdb)
 {
 struct sqlConnection *conn = hAllocConn(db);
 
 char buffer[4096];
 
 safef(buffer, sizeof buffer, "NOSQLINJ select fileName from %s", tdb->table);
 return sqlQuickString(conn, buffer);
 }
 
 static int snakePalette2[] =
 {
 0x1f77b4, 0xaec7e8, 0xff7f0e, 0xffbb78, 0x2ca02c, 0x98df8a, 0xd62728, 0xff9896, 0x9467bd, 0xc5b0d5, 0x8c564b, 0xc49c94, 0xe377c2, 0xf7b6d2, 0x7f7f7f, 0xc7c7c7, 0xbcbd22, 0xdbdb8d, 0x17becf, 0x9edae5
 };
 
 
 void outTdb(char *db, FILE *f, char *name,  struct trackDb *tdb, char *parent, unsigned int color)
 {
 char *dataUrl = NULL;
 char *bigDataUrl = trackDbSetting(tdb, "bigDataUrl");
 if (bigDataUrl == NULL)
     {
     if (startsWith("bigWig", tdb->type))
         dataUrl = getSqlBigWig(db, tdb);
     }
 struct hashCookie cookie = hashFirst(tdb->settingsHash);
 struct hashEl *hel;
 fprintf(f, "\ttrack %s\n", name);
 while ((hel = hashNext(&cookie)) != NULL)
     {
     if (differentString(hel->name, "parent") && differentString(hel->name, "polished")&& differentString(hel->name, "color")&& differentString(hel->name, "track"))
         fprintf(f, "\t%s %s\n", hel->name, (char *)hel->val);
     }
 if (bigDataUrl == NULL)
     {
     if (dataUrl != NULL)
         fprintf(f, "\tbigDataUrl %s\n", dataUrl);
     }
 fprintf(f, "\tparent %s\n",parent);
 fprintf(f, "\tcolor %d,%d,%d\n", (color >> 16) & 0xff,(color >> 8) & 0xff,color & 0xff);
 fprintf(f, "\n");
 }
 
 static void outComposite(FILE *f, struct composite *composite)
 {
 char *parent = composite->name;
 char *shortLabel = composite->shortLabel;
 char *longLabel = composite->longLabel;
 fprintf(f,"track %s\n\
 shortLabel %s\n\
 compositeTrack on\n\
 aggregate none\n\
 longLabel %s\n\
 %s on\n\
 type wig \n\
 visibility full\n\n", parent, shortLabel, longLabel, CUSTOM_COMPOSITE_SETTING);
 }
 
 static struct trackDb *findTrack(char *name, struct trackDb *fullTrackList)
 {
 struct trackDb *tdb;
 for (tdb = fullTrackList; tdb != NULL; tdb = tdb->next)
     {
     if (sameString(name, tdb->track))
         return tdb;            
     }
 errAbort("cannot find track");
 return NULL;
 }
 
 static void outHubHeader(FILE *f, char *db, char *hubName)
 {
 char *hubFile = strrchr(hubName, '/') + 1;
 
 fprintf(f,"hub hub1\n\
 shortLabel User Composite\n\
 longLabel User Composite\n\
 genomesFile %s\n\
 email braney@soe.ucsc.edu\n\
 descriptionUrl hub.html\n\n", hubFile);
 fprintf(f,"genome %s\n\
 trackDb %s\n\n", db, hubFile);
 }
 
 static char *getHubName(char *db)
 {
 struct tempName hubTn;
 char buffer[4096];
 safef(buffer, sizeof buffer, "%s-%s", customCompositeCartName, db);
 char *hubName = cartOptionalString(cart, buffer);
 
 if (hubName == NULL)
     {
     trashDirDateFile(&hubTn, "hgComposite", "hub", ".txt");
     hubName = cloneString(hubTn.forCgi);
     cartSetString(cart, buffer, hubName);
     FILE *f = mustOpen(hubName, "a");
     outHubHeader(f, db, hubName);
     fclose(f);
     cartSetString(cart, "hubUrl", hubName);
     cartSetString(cart, hgHubConnectRemakeTrackHub, hubName);
     }
 return hubName;
 }
 
 
 //static void outputCompositeHub(char *db, char *hubName, struct trackDb *fullTrackList, struct composite *compositeList, struct hash *nameHash)
 static void outputCompositeHub(char *db, char *hubName,  struct composite *compositeList, struct hash *nameHash)
 {
 // Do we already have a hub?
 chmod(hubName, 0666);
 FILE *f = mustOpen(hubName, "w");
 
 outHubHeader(f, db, hubName);
 int useColor = 0;
 struct composite *composite;
 for(composite = compositeList; composite; composite = composite->next)
     {
     outComposite(f, composite);
     struct trackDb *tdb;
     struct track *track;
     for (track = composite->trackList; track; track = track->next)
         {
         tdb = hashMustFindVal(nameHash, track->name);
         //tdb = findTrack(track->name, fullTrackList);
 
         outTdb(db, f, track->name,tdb, composite->name, snakePalette2[useColor]);
         useColor++;
         if (useColor == (sizeof snakePalette2 / sizeof(int)))
             useColor = 0;
         }
     }
 fclose(f);
 }
 
 
 void topLabelSpansStart(char *label)
 {
 printf("<span style='display: inline-block; padding-right: 5px;'>"
        "<span style='display: block;'>%s</span>\n"
        "<span style='display: block; padding-bottom: 5px;'>\n", label);
 }
 
 void topLabelSpansEnd()
 {
 printf("</span></span>");
 }
 
 
 void printCtAndHubButtons()
 /* Print a div with buttons for hgCustom and hgHubConnect */
 {
 boolean hasCustomTracks = customTracksExist(cart, NULL);
 puts("<div style='padding-top: 5px; padding-bottom: 5px'>");
 hOnClickButton("prtCtHub_CtBut", "document.customTrackForm.submit(); return false;",
 	       hasCustomTracks ? CT_MANAGE_BUTTON_LABEL : CT_ADD_BUTTON_LABEL);
 printf(" ");
 if (hubConnectTableExists())
     hOnClickButton("prtCtHub_TrkHub", "document.trackHubForm.submit(); return false;", "track hubs");
 nbSpaces(3);
 printf("To reset <B>all</B> user cart settings (including custom tracks), \n"
        "<A HREF=\"cartReset?destination=%s\">click here</A>.\n",
        cgiScriptName());
 puts("</div>");
 }
 
 void hgGatewayCladeGenomeDb()
 /* Make a row of labels and row of buttons like hgGateway, but not using tables. */
 {
 boolean gotClade = hGotClade();
 if (gotClade)
     {
     topLabelSpansStart("clade");
     printCladeListHtml(genome, "change", onChangeClade());
     topLabelSpansEnd();
     }
 topLabelSpansStart("genome");
 if (gotClade)
     printGenomeListForCladeHtml(database, "change", onChangeOrg());
 else
     printGenomeListHtml(database, "change", onChangeOrg());
 topLabelSpansEnd();
 topLabelSpansStart("assembly");
 printAssemblyListHtml(database, "change", onChangeDb());
 topLabelSpansEnd();
 puts("<BR>");
 topLabelSpansEnd();
 topLabelSpansStart("");
 printf("</span>\n");
 topLabelSpansEnd();
 puts("<BR>");
 }
 
 void printAssemblySection()
 /* Print assembly-selection stuff.
  * Redrawing the whole page when the assembly changes seems fine to me. */
 {
 //#*** ---------- More copied verbatim, from hgTables/mainPage.c: -----------
 /* Hidden form - for benefit of javascript. */
     {
     static char *saveVars[] = {
       "clade", "org", "db", };
     jsCreateHiddenForm(cart, cgiScriptName(), saveVars, ArraySize(saveVars));
     }
 
 hPrintf("<FORM ACTION='%s' NAME='changeGroupForm'>", cgiScriptName());
 cartSaveSession(cart);
 cgiMakeHiddenVar(hgsCurrentGroup, "");
 hPrintf("</FORM>\n");
 
 hPrintf("<FORM ACTION='%s' NAME='changeCompositeForm'>", cgiScriptName());
 cartSaveSession(cart);
 cgiMakeHiddenVar(hgsCurrentComposite, "");
 hPrintf("</FORM>\n");
 
 hPrintf("<FORM ACTION='%s' NAME='makeNewCompositeForm'>", cgiScriptName());
 cartSaveSession(cart);
 cgiMakeHiddenVar(hgsNewCompositeName, "");
 cgiMakeHiddenVar(hgsNewCompositeShortLabel, "");
 cgiMakeHiddenVar(hgsNewCompositeLongLabel, "");
 hPrintf("</FORM>\n");
 
+hPrintf("<FORM ACTION='%s' NAME='addVisTrackForm'>", cgiScriptName());
+cartSaveSession(cart);
+cgiMakeHiddenVar(hgsAddVisTrack, "");
+hPrintf("</FORM>\n");
+
 hPrintf("<FORM ACTION='%s' NAME='addTrackForm'>", cgiScriptName());
 cartSaveSession(cart);
 cgiMakeHiddenVar(hgsAddTrack, "");
 hPrintf("</FORM>\n");
 
 /* Hidden form for jumping to custom tracks CGI. */
 hPrintf("<FORM ACTION='%s' NAME='customTrackForm'>", hgCustomName());
 cartSaveSession(cart);
 hPrintf("</FORM>\n");
 
 /* Hidden form for jumping to track hub manager CGI. */
 hPrintf("<FORM ACTION='%s' NAME='trackHubForm'>", hgHubConnectName());
 cartSaveSession(cart);
 hPrintf("</FORM>\n");
 
 printf("<FORM ACTION=\"%s\" NAME=\"mainForm\" ID=\"mainForm\" METHOD=%s>\n",
 	cgiScriptName(), cartUsualString(cart, "formMethod", "GET"));
 cartSaveSession(cart);
 
 //#*** ------------------ end verbatim ---------------
 
 printf("<div class='sectionLiteHeader noReorderRemove'>"
        "Select Genome Assembly</div>\n");
 
 /* Print clade, genome and assembly line. */
 hgGatewayCladeGenomeDb();
 
 }
 
 static void printCompositeList(struct composite *compositeList, struct composite *currentComposite)
 {
 if (compositeList == NULL)
     return;
 
 printf("<div class='sectionLiteHeader noReorderRemove'>"
        "My Composites</div>\n");
 
 int count = slCount(compositeList);
 char *labels[count];
 char *names[count];
 count = 0;
 for(; compositeList; compositeList = compositeList->next)
     {
     labels[count] = compositeList->shortLabel;
     names[count] = compositeList->name;
     count++;
     }
 cgiMakeDropListFull("compositeList", labels, names, count,
                     currentComposite->name,
                     "change", 
                     "var e = document.getElementById('compositeList'); \
                     var strUser = e.options[e.selectedIndex].value; \
                     document.changeCompositeForm.elements['"hgsCurrentComposite"'].value = strUser; \
                     document.changeCompositeForm.submit();");
                     //document.addTrackForm.elements['hgComp_track'] = strUser;");
 
 }
 
 
 static void makeAddComposite()
 {
 printf("<BR>");
 printf("<BR>");
 printf("<H3>Make New Composite</H3>");
 printf("name ");
 cgiMakeTextVar(hgsNewCompositeName, "", 29);
 printf("<BR>short label ");
 cgiMakeTextVar(hgsNewCompositeShortLabel, "", 29);
 printf("<BR>long label ");
 cgiMakeTextVar(hgsNewCompositeLongLabel, "", 29);
 printf("<BR>");
 hOnClickButton("selVar_MakeNewComposite", 
                     "var e = document.getElementById('"hgsNewCompositeName"'); \
                     document.makeNewCompositeForm.elements['"hgsNewCompositeName"'].value = e.value; \
                     var e = document.getElementById('"hgsNewCompositeShortLabel"'); \
                     document.makeNewCompositeForm.elements['"hgsNewCompositeShortLabel"'].value = e.value; \
                     var e = document.getElementById('"hgsNewCompositeLongLabel"'); \
                     document.makeNewCompositeForm.elements['"hgsNewCompositeLongLabel"'].value = e.value; \
 document.makeNewCompositeForm.submit(); return false;", "submit");
 printf("<BR>");
 }
 
 static void printTrackList(struct composite *composite)
 {
 printf("<div class='sectionLiteHeader noReorderRemove'>"
        "Tracks in Composite</div>\n");
 printf("<BR>");
 printf("<div style=\"max-width:1024px\">");
 printf("<table id=\"sessionTable\" class=\"sessionTable stripe hover row-border compact\" borderwidth=0>\n");
 printf("<thead><tr>");
 printf("<TH><TD><B>Name</B></TD></TH>");
 printf("</tr></thead><tbody>");
 
 struct track *track;
 if (composite)
     for(track = composite->trackList; track; track = track->next)
         {
         printf("<TR><TD>%s</TD></TR>\n",track->shortLabel);
         }
 //printf("<TR><TD>track1</TD></TR>");
 //printf("<TR><TD>track2</TD></TR>");
 printf("</table>");
 }
 
 
 static boolean trackCanBeAdded(struct trackDb *tdb)
 {
 return  (tdb->subtracks == NULL) && !startsWith("wigMaf",tdb->type) &&  (startsWith("wig",tdb->type) || startsWith("bigWig",tdb->type)) ;
 }
 
 static void availableTracks(char *db, struct grp *groupList, struct trackDb *fullTrackList)
 {
 printf("<H4>Add tracks from %s</H4>", db);
 
 char *curGroupName = cartOptionalString(cart, hgsCurrentGroup);
 printf("<BR>groups: ");
 char **labels, **names;
 int count = slCount(groupList);
 AllocArray(labels, count);
 AllocArray(names, count);
 count = 0;
 struct grp *grp;
 for(grp = groupList; grp; grp = grp->next)
     {
     labels[count] = grp->label;
     names[count] = grp->name;
     count++;
     }
 cgiMakeDropListFull("availGroups", labels, names, count,
                     curGroupName,
                     "change", 
     "var e = document.getElementById('availGroups'); \
     var strUser = e.options[e.selectedIndex].value; \
     document.changeGroupForm.elements['"hgsCurrentGroup"'].value =  strUser;  \
     document.changeGroupForm.submit();");
 
 struct grp *curGroup;
 if (curGroupName == NULL)
     curGroup = groupList;
 else
     {
     for(curGroup = groupList; curGroup; curGroup = curGroup->next)
         {
         if (sameString(curGroupName, curGroup->name))
             break;
         }
     if (curGroup == NULL)
         errAbort("cannot find current group");
     }
 
 struct trackDb *tdb;
 count = 0;
 for(tdb = fullTrackList; tdb; tdb = tdb->next)
     {
     if (sameString(tdb->grp, curGroup->name))
         count++;
     }
 
 //char **labels, **names;
 AllocArray(labels, count);
 AllocArray(names, count);
 count = 0;
 for(tdb = fullTrackList; tdb; tdb = tdb->next)
     {
     if (sameString(tdb->grp, curGroup->name))
         {
         labels[count] = tdb->shortLabel;
         names[count] = tdb->track;
         count++;
         }
     }
 
 printf("track:");
 cgiMakeDropListFull("availTracks", labels, names, count,
                     *names, 
                     "change", 
                     "var e = document.getElementById('availTracks'); \
                     var strUser = e.options[e.selectedIndex].value; \
                     document.addTrackForm.elements['"hgsAddTrack"'].value = strUser;");
                     //document.addTrackForm.elements['hgComp_track'] = strUser;");
 hOnClickButton("addTrack", 
     "var e = document.getElementById('availTracks'); \
     var strUser = e.options[e.selectedIndex].value;  \
     document.addTrackForm.elements['"hgsAddTrack"'].value =  strUser;  \
     document.addTrackForm.submit();"
 , "add track");
 
 printf("<BR>");
 printf("<BR>");
 printf("<BR>");
-hOnClickButton("selVar_AddAllVis", "document.trackHubForm.submit(); return false;", "Add All Visibile Wiggles");
+hOnClickButton("selVar_AddAllVis", "document.addVisTrackForm.submit(); return false;", "Add All Visibile Wiggles");
 }
 
 void doMainPage(char *db, struct grp *groupList,  struct trackDb *fullTrackList, struct composite *currentComposite, struct composite *compositeList)
 /* Print out initial HTML of control page. */
 {
 //struct composite *currentComposite = compositeList;
 jsInit();
 webIncludeResourceFile("jquery-ui.css");
 webIncludeResourceFile("ui.dropdownchecklist.css");
 boolean alreadyAgreed = cartUsualBoolean(cart, "hgva_agreedToDisclaimer", FALSE);
 jsInlineF(
     "$(document).ready(function() { hgva.disclaimer.init(%s, hgva.userClickedAgree); });\n"
     , alreadyAgreed ? "true" : "false");
 addSomeCss();
 printAssemblySection();
 
 puts("<BR>");
 printf("<div class='sectionLiteHeader noReorderRemove'>"
        "Add Hubs and Custom Tracks </div>\n");
 printCtAndHubButtons();
 
 //struct hashEl *hel = cartFindPrefix(cart, hgCompEditPrefix);
 //if (hel != NULL)
     {
  //   printf("printing EditCom\n");
   ///  printEditComposite();
     }
 
 printf("</FORM>");
 puts("<BR>");
 puts("<BR>");
 printCompositeList(compositeList, currentComposite);
 makeAddComposite();
 puts("<BR>");
 printTrackList(currentComposite);
 puts("<BR>");
 availableTracks(db, groupList, fullTrackList);
 puts("<BR>");
 
 // Make wrapper table for collapsible sections:
 //selectVariants();
 //char *geneTrack = selectGenes();
 //if (geneTrack != NULL)
     {
     //selectRegulatory();
     //selectAnnotations(geneTrack);
     //selectFilters();
     //selectOutput();
     //submitAndDisclaimer();
     }
 
 printf("</FORM>");
 jsReloadOnBackButton(cart);
 
 webNewSection("Using the Composite Builder");
-webIncludeHelpFileSubst("hgCompositeHelpText", cart, FALSE);
+webIncludeHelpFileSubst("hgCompositeHelp", cart, FALSE);
 jsIncludeFile("jquery-ui.js", NULL);
 jsIncludeFile("hgVarAnnogrator.js", NULL);
 jsIncludeFile("ui.dropdownchecklist.js", NULL);
 jsIncludeFile("ddcl.js", NULL);
 }
 
 
 
 
 
 
 void doUi(char *db, struct grp *groupList, struct trackDb *fullTrackList,struct composite *currentComposite, struct composite *compositeList) 
 /* Set up globals and make web page */
 {
 cartWebStart(cart, db, "Composite Editor");
 doMainPage(database, groupList, fullTrackList, currentComposite, compositeList);
 cartWebEnd();
 /* Save variables. */
 //cartCheckout(&cart);
 }
 
 static struct hash *addWigs(struct trackDb **wigList, struct trackDb *list)
 {
 struct hash *hash = newHash(4);
 if (list == NULL)
     return hash;
 
 struct trackDb *tdb, *tdbNext;
 for(tdb = list; tdb; tdb = tdbNext)
     {
     tdbNext = tdb->next;
     addWigs(wigList, tdb->subtracks);
 
     if (trackCanBeAdded(tdb))
         {
         slAddHead(wigList, tdb);
         hashStore(hash, tdb->grp);
         }
     }
 
 return hash;
 }
 
 char *makeUnique(struct hash *nameHash, struct trackDb *tdb)
 {
 if (hashLookup(nameHash, tdb->track) == NULL)
     {
     hashAdd(nameHash, tdb->track, tdb);
     return tdb->track;
     }
 
 unsigned count = 0;
 char buffer[4096];
 
 for(;; count++)
     {
     safef(buffer, sizeof buffer, "%s%d", tdb->track, count);
     if (hashLookup(nameHash, buffer) == NULL)
         {
         hashAdd(nameHash, buffer, tdb);
         return cloneString(buffer);
         }
     }
 
 return NULL;
 }
 
+bool trackVisible(struct trackDb *tdb)
+{
+if ((tdb->parent != NULL) && !trackVisible(tdb->parent))
+    return FALSE;
+
+boolean vis = tdb->visibility != tvHide;
+char *cartVis = cartOptionalString(cart, tdb->track);
+
+if (cartVis != NULL) 
+    {
+    if (differentString(cartVis, "hide"))
+        vis = TRUE;
+    else
+        vis = FALSE;
+    }
+
+return vis;
+}
+
+
 int main(int argc, char *argv[])
 /* Process command line. */
 {
 long enteredMainTime = clock1000();
 if (hIsPrivateHost())
     pushCarefulMemHandler(LIMIT_2or6GB);
 
 cgiSpoof(&argc, argv);
 htmlPushEarlyHandlers(); /* Make errors legible during initialization. */
 oldVars = hashNew(10);
 cart = cartAndCookie(hUserCookie(), excludeVars, oldVars);
 
 /* Set up global variables. */
 getDbAndGenome(cart, &database, &genome, oldVars);
 initGenbankTableNames(database);
 
 int timeout = cartUsualInt(cart, "udcTimeout", 300);
 if (udcCacheTimeout() < timeout)
     udcSetCacheTimeout(timeout);
 knetUdcInstall();
 
 struct trackDb *fullTrackList = NULL;	/* List of all tracks in database. */
 struct trackDb *wigTracks = NULL;	/* List of all wig tracks */
 cartTrackDbInit(cart, &fullTrackList, &fullGroupList, TRUE);
 struct hash *groupHash = addWigs(&wigTracks, fullTrackList);
 struct grp *grp, *grpNext,  *groupList = NULL;
 
 for(grp = fullGroupList; grp; grp = grpNext)
     {
     grpNext = grp->next;
     if (hashLookup(groupHash, grp->name) != NULL)
         slAddHead(&groupList, grp);
     }
 
 slReverse(&groupList);
 
 /*
 struct grp *grpList;
 struct trackDb *tdbList = hubCollectTracks(database, &grpList);
 addWigs(&wigTracks, tdbList);
 */
 
 char *hubName = getHubName(database);
 struct hash *nameHash = newHash(5);
 struct composite *compositeList = getCompositeList(database, hubName, nameHash);
 
 struct composite *currentComposite = NULL;
 char *currentCompositeName = cartOptionalString(cart, hgsCurrentComposite);
 
 if (currentCompositeName != NULL)
     {
     for (currentComposite = compositeList; currentComposite; currentComposite = currentComposite->next)
         if (sameString(currentComposite->name, currentCompositeName))
             break;
     }
 
 if (currentComposite == NULL)
     currentComposite = compositeList;
 
 char *newCompositeName = cartOptionalString(cart, hgsNewCompositeName);
 if (newCompositeName != NULL)
     {
     if (isEmpty(newCompositeName))
         warn("Composite name must not be empty string");
     else
         {
         struct composite *composite;
         AllocVar(composite);
         slAddHead(&compositeList, composite);
         currentComposite = composite;
 
         composite->name = cloneString(newCompositeName);
         char *newCompositeShortLabel = cartOptionalString(cart, hgsNewCompositeShortLabel);
         if (isEmpty(newCompositeShortLabel))
             composite->shortLabel = composite->name;
         else
             composite->shortLabel = cloneString(newCompositeShortLabel);
         char *newCompositeLongLabel = cartOptionalString(cart, hgsNewCompositeLongLabel);
         if (isEmpty(newCompositeLongLabel))
             composite->longLabel = composite->name;
         else
             composite->longLabel = cloneString(newCompositeLongLabel);
 
         }
     }
 
 if (currentCompositeName == NULL)
     currentComposite = compositeList;
 
+char *addAllVisible = cartOptionalString(cart, hgsAddVisTrack);
+if (addAllVisible != NULL)
+    {
+    struct trackDb *tdb;
+
+    for(tdb = fullTrackList; tdb; tdb = tdb->next)
+        {
+        if (trackCanBeAdded(tdb) && trackVisible(tdb))
+            {
+            struct track *track;
+            AllocVar(track);
+            track->name = makeUnique(nameHash,  tdb);
+            track->shortLabel = tdb->shortLabel;
+            track->longLabel = tdb->longLabel;
+            slAddHead(&currentComposite->trackList, track);
+            }
+        }
+    }
+
 char *newTrackName = cartOptionalString(cart, hgsAddTrack);
 if (newTrackName != NULL)
     {
     if (currentComposite == NULL)
         warn("cannot add track without specifying a composite");
     else
         {
         struct trackDb *tdb = findTrack(newTrackName, wigTracks);
 
         struct track *track;
         AllocVar(track);
         track->name = makeUnique(nameHash,  tdb);
         track->shortLabel = tdb->shortLabel;
+        track->longLabel = tdb->longLabel;
         slAddHead(&currentComposite->trackList, track);
         }
     }
 
 //struct trackDb *fullTrackList = getFullTrackList(cart);
 doUi(database, groupList, wigTracks, currentComposite, compositeList);
 
 outputCompositeHub(database, hubName,  compositeList, nameHash);
 cartCheckout(&cart);
 cgiExitTime("hgComposite", enteredMainTime);
 return 0;
 }