cf979a71d0b61c948b39cb5f85b500f15cfb5c6c
braney
  Wed Feb 28 14:00:15 2018 -0800
fiddle with sorting of tracks in Visible Tracks yet again

diff --git src/hg/hgCollection/hgCollection.c src/hg/hgCollection/hgCollection.c
index ee0a12a..bd46888 100644
--- src/hg/hgCollection/hgCollection.c
+++ src/hg/hgCollection/hgCollection.c
@@ -32,30 +32,31 @@
 struct trackDb *tdb;
 char *name;
 char *shortLabel;
 char *longLabel;
 char *visibility;
 unsigned long color;
 char *viewFunc;        // The method by which calculated tracks should be calculated
 char *missingMethod;   // How should missing data be treated in calculated tracks
 };
 
 struct trackDbRef 
 {
 struct trackDbRef *next;
 struct trackDb *tdb;
 struct grp *grp;
+double priority;
 int order;
 };
 
 static char *makeUnique(struct hash *nameHash, char *name)
 // Make the name of this track unique.
 {
 char *skipHub = trackHubSkipHubName(name);
 if (hashLookup(nameHash, skipHub) == NULL)
     {
     hashStore(nameHash, name);
     return skipHub;
     }
 
 unsigned count = 0;
 char buffer[4096];
@@ -174,89 +175,104 @@
     return FALSE;
 
 char *cartVis = cartOptionalString(cart, tdb->parent->track);
 boolean vis;
 if (cartVis != NULL) 
     vis =  differentString(cartVis, "hide");
 else if (tdbIsSuperTrack(tdb->parent))
     vis = tdb->parent->isShow;
 else
     vis = tdb->parent->visibility != tvHide;
 
 return vis;
 }
 
 
-static void checkForVisible(struct cart *cart, struct hash *groupHash, struct trackDbRef **list, struct trackDb *tdb)
+static void checkForVisible(struct cart *cart, struct hash *groupHash, struct trackDbRef **list, struct trackDb *tdb, double priority, double multiplier)
 /* Walk the trackDb hierarchy looking for visible leaf tracks. */
 {
 struct trackDb *subTdb;
 char buffer[4096];
 
 if (tdb->subtracks)
     {
     for(subTdb = tdb->subtracks; subTdb; subTdb = subTdb->next)
-        checkForVisible(cart, groupHash, list, subTdb);
+        checkForVisible(cart, groupHash, list, subTdb, priority + tdb->priority * multiplier, multiplier / 100.0);
     }
 else
     {
     boolean isVisible = FALSE;
     if (tdb->parent == NULL) 
         {
         char *cartVis = cartOptionalString(cart, tdb->track);
         if (cartVis == NULL)
             isVisible =  tdb->visibility != tvHide;
         else
             isVisible =  differentString(cartVis, "hide");
         }
     else if (isParentVisible(cart, tdb) &&  isSubtrackVisible(cart, tdb))
         isVisible = TRUE;
 
     if (isVisible)
         {
         struct trackDbRef *tdbRef;
         AllocVar(tdbRef);
         tdbRef->tdb = tdb;
         tdbRef->grp = hashMustFindVal(groupHash, tdb->grp);;
         slAddHead(list, tdbRef);
         safef(buffer, sizeof buffer, "%s_imgOrd", tdb->track);
 
-        tdbRef->order = cartUsualInt(cart, buffer, tdb->priority);
+        tdbRef->order = cartUsualInt(cart, buffer,  0);
+        tdbRef->priority = priority + multiplier * tdb->priority;
         }
     }
 }
 
 static int tdbRefCompare (const void *va, const void *vb)
 // Compare to sort on imgTrack->order.
 {
 const struct trackDbRef *a = *((struct trackDbRef **)va);
 const struct trackDbRef *b = *((struct trackDbRef **)vb);
 
-int dif = a->grp->priority - b->grp->priority;
+int dif = a->order - b->order;
+
 if (dif == 0)
-    dif = a->order - b->order;
+    {
+    double ddif = a->priority - b->priority ;
+    if (ddif < 0)
+        dif = -1;
+    else if (ddif > 0)
+        dif = 1;
+    }
+if (dif == 0)
+    dif = strcasecmp(a->tdb->shortLabel, b->tdb->shortLabel);
+
 return dif;
 }       
 
 static void addVisibleTracks(struct hash *groupHash, struct dyString *rootChildren, struct cart *cart, struct trackDb *trackList)
 // add the visible tracks table rows.
 {
 struct trackDb *tdb;
 struct trackDbRef *tdbRefList = NULL, *tdbRef;
+
 for(tdb = trackList; tdb; tdb = tdb->next)
     {
-    checkForVisible(cart, groupHash, &tdbRefList, tdb);
+    struct grp *grp = hashMustFindVal(groupHash, tdb->grp);
+    double priority =  grp->priority + tdb->priority/100.0;
+
+    checkForVisible(cart, groupHash, &tdbRefList, tdb,  priority, 1.0/100.0);
     }
 
 slSort(&tdbRefList, tdbRefCompare);
 if (!isEmpty(rootChildren->string))
     dyStringPrintf(rootChildren, ",");
 dyStringPrintf(rootChildren, "{icon:'../images/folderC.png',id:'visible', text:'Visible Tracks', parent:'#'");
 if (tdbRefList != NULL)
     dyStringPrintf(rootChildren, ",children:true");
 dyStringPrintf(rootChildren, "}");
 
 jsInlineF("trackData['visible'] = [");
 for(tdbRef = tdbRefList; tdbRef; tdbRef = tdbRef->next)
     {
     printTrack("visible", tdbRef->tdb,  FALSE);
     if (tdbRef->next != NULL)
@@ -291,33 +307,38 @@
 
 struct trackDb *tdb;
 for(tdb = parentTdb->subtracks; tdb;  tdb = tdb->next)
     {
     dyStringPrintf(dy, ",'%s'", trackHubSkipHubName(tdb->track));
     addSubtrackNames(dy, tdb);
     }
 }
 
 static void doTable(struct cart *cart, char *db, struct grp *groupList, struct trackDb *trackList)
 // output the tree table
 {
 char *hubName = hubNameFromUrl(getHubName(cart, db));
 struct grp *curGroup;
 struct hash *groupHash = newHash(10);
+int count = 0;
 
 for(curGroup = groupList; curGroup;  curGroup = curGroup->next)
+    {
+    if (curGroup->priority == 0)
+        curGroup->priority = count--;
     hashAdd(groupHash, curGroup->name, curGroup);
+    }
 
 curGroup = NULL;
 if (hubName != NULL)
     curGroup = hashFindVal(groupHash, hubName);
 
 jsInlineF("var collectionData = []; ");
 struct dyString *dy = newDyString(100);
 if (curGroup != NULL)
     {
     // print out all the tracks in all the collections
     struct trackDb *tdb;
     jsInlineF("collectionData['#'] = [");
     boolean first = TRUE;
     for(tdb = trackList; tdb;  tdb = tdb->next)
         {