eb78be0ea632442a7ff6c55321f5bb6cafb2c7d2 braney Tue Mar 6 09:36:21 2018 -0800 add tool tips and the ability to put multiwigs into collections from hgTracks diff --git src/hg/hgCollection/hgCollection.c src/hg/hgCollection/hgCollection.c index 99c2e80..792317c 100644 --- src/hg/hgCollection/hgCollection.c +++ src/hg/hgCollection/hgCollection.c @@ -8,30 +8,35 @@ #include "trashDir.h" #include "hubConnect.h" #include "hui.h" #include "grp.h" #include "cheapcgi.h" #include "jsHelper.h" #include "web.h" #include "knetUdc.h" #include "api.h" #include "genbank.h" #include "htmshell.h" #include "jsonParse.h" #include "customComposite.h" #include "stdlib.h" +/* Tool tips */ +#define COLLECTIONTITLE "Double-click to edit name and color" +#define FOLDERTITLE "Click to open node" +#define TRACKTITLE "Press Green Plus to add track to collection" + /* Global Variables */ struct hash *oldVars = NULL; /* The cart before new cgi stuff added. */ // Null terminated list of CGI Variables we don't want to save permanently: char *excludeVars[] = {"Submit", "submit", "cmd", "track", "collection", "jsonp", NULL,}; struct track { struct track *next; struct track *trackList; struct trackDb *tdb; char *name; char *shortLabel; char *longLabel; char *visibility; unsigned long color; @@ -72,41 +77,49 @@ } return NULL; } static boolean trackCanBeAdded(struct trackDb *tdb) // are we allowing this track into a custom composite { return (tdb->subtracks == NULL) && !startsWith("wigMaf",tdb->type) && (startsWith("wig",tdb->type) || startsWith("bigWig",tdb->type) || startsWith("bedGraph",tdb->type)) ; } static void printTrack(char *parent, struct trackDb *tdb, boolean user) // output list elements for a group { char *userString = ""; +char *title; + +if (user) + title = COLLECTIONTITLE; +else if (tdb->subtracks) + title = FOLDERTITLE; +else + title = TRACKTITLE; if (tdb->subtracks) userString = "icon:'../images/folderC.png',children:true,"; else if (user) userString = "icon:'fa fa-minus-square',"; else userString = "icon:'fa fa-plus',"; #define IMAKECOLOR_32(r,g,b) ( ((unsigned int)b<<0) | ((unsigned int)g << 8) | ((unsigned int)r << 16)) -jsInlineF("{%s id:'%s',li_attr:{shortlabel:'%s', longlabel:'%s',color:'#%06x',name:'%s'},text:'%s (%s)',parent:'%s'}",userString, trackHubSkipHubName(tdb->track), tdb->shortLabel, tdb->longLabel, IMAKECOLOR_32(tdb->colorR,tdb->colorG,tdb->colorB),trackHubSkipHubName(tdb->track),tdb->shortLabel,tdb->longLabel,parent); +jsInlineF("{%s id:'%s',li_attr:{title:'%s',shortlabel:'%s', longlabel:'%s',color:'#%06x',name:'%s'},text:'%s (%s)',parent:'%s'}",userString, trackHubSkipHubName(tdb->track),title, tdb->shortLabel, tdb->longLabel, IMAKECOLOR_32(tdb->colorR,tdb->colorG,tdb->colorB),trackHubSkipHubName(tdb->track),tdb->shortLabel,tdb->longLabel,parent); } static void outHubHeader(FILE *f, char *db) // output a track hub header { fprintf(f,"hub hub1\n\ shortLabel Track Collections\n\ longLabel Track Collections\n\ useOneFile on\n\ email genome-www@soe.ucsc.edu\n\n"); fprintf(f,"genome %s\n\n", db); } static char *getHubName(struct cart *cart, char *db) @@ -254,31 +267,31 @@ { struct trackDb *tdb; struct trackDbRef *tdbRefList = NULL, *tdbRef; for(tdb = trackList; tdb; tdb = tdb->next) { 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:'#'"); +dyStringPrintf(rootChildren, "{icon:'../images/folderC.png',id:'visible', text:'Visible Tracks', parent:'#', li_attr:{title:'%s'} ", FOLDERTITLE); 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) jsInlineF(","); } jsInlineF("];"); } void printSubtracks(char *arrayName, struct trackDb *parentTdb, boolean user) @@ -366,52 +379,55 @@ } else jsInlineF("collectionData['#'] = [];"); jsInlineF("var collectionNames = new Set([%s]);", dy->string); jsInlineF("var trackData = []; "); struct dyString *rootChildren = newDyString(512); addVisibleTracks(groupHash, rootChildren, cart, trackList); for(curGroup = groupList; curGroup; curGroup = curGroup->next) { if ((hubName != NULL) && sameString(curGroup->name, hubName)) continue; if (!isEmpty(rootChildren->string)) dyStringPrintf(rootChildren, ","); - dyStringPrintf(rootChildren, "{icon:'../images/folderC.png',id:'%s', text:'%s', parent:'#', children:true}", curGroup->name, curGroup->label); + dyStringPrintf(rootChildren, "{icon:'../images/folderC.png',id:'%s', text:'%s', parent:'#', children:true,li_attr:{title:'%s'}}", curGroup->name, curGroup->label, FOLDERTITLE); struct trackDb *tdb; jsInlineF("trackData['%s'] = [", curGroup->name); boolean first = TRUE; for(tdb = trackList; tdb; tdb = tdb->next) { if ( sameString(tdb->grp, curGroup->name)) { if (!first) jsInlineF(","); printTrack(curGroup->name, tdb, FALSE); first = FALSE; } } jsInlineF("];"); for(tdb = trackList; tdb; tdb = tdb->next) { if ( sameString(tdb->grp, curGroup->name)) printSubtracks("trackData", tdb, FALSE); } } jsInlineF("trackData['#'] = [%s];", rootChildren->string); +jsInlineF("var collectionTitle='%s';\n", COLLECTIONTITLE); +jsInlineF("var folderTitle='%s';\n", FOLDERTITLE); +jsInlineF("var trackTitle='%s';\n", TRACKTITLE); jsInlineF("hgCollection.init();\n"); } static void printHelp() // print out the help page { puts( "
\n" "
\n" "

Track Collection Builder Help

\n" "
\n" ); puts( "
\n" "
\n" @@ -564,30 +580,40 @@ longLabel %s\n\ %s on\n\ color %ld,%ld,%ld \n\ type mathWig\n\ priority %d\n\ visibility full\n\n", parent, shortLabel, longLabel, CUSTOM_COMPOSITE_SETTING, 0xff& (collection->color >> 16),0xff& (collection->color >> 8),0xff& (collection->color), priority); } static void modifyName(struct trackDb *tdb, char *hubName, struct hash *collectionNameHash) /* If this is a new track in the collection we want to make sure * it gets a different name than the track in trackDb. * If it's a native track, we want to squirrel away the original track name. */ { +if (tdb->subtracks) + { + struct trackDb *subTdb; + for (subTdb = tdb->subtracks; subTdb; subTdb = subTdb->next) + { + modifyName(subTdb, hubName, collectionNameHash); + } + return; + } + if ((tdb->grp == NULL) || (hubName == NULL) || differentString(tdb->grp, hubName)) { if (collectionNameHash) hashStore(collectionNameHash, tdb->track); char *bigDataUrl = trackDbSetting(tdb, "bigDataUrl"); if (bigDataUrl == NULL) { char *table = trackDbSetting(tdb, "table"); if (table == NULL) hashAdd(tdb->settingsHash, "table", tdb->track); } } } @@ -826,121 +852,146 @@ hashStore(superHash, tdb->parent->track); slAddHead(&newList, tdb->parent); } slAddTail(&tdb->parent->subtracks, tdb); } else slAddHead(&newList, tdb); } slReverse(&newList); return newList; } -static void outOneTdb(char *db, struct sqlConnection *conn, FILE *f, struct trackDb *tdb, int numTabs) +static void outOneTdb(char *db, struct sqlConnection *conn, FILE *f, struct trackDb *tdb, int numTabs, int priority) /* Put out a single trackDb entry to our collections hub. */ { char *tabs = ""; if (numTabs == 1) tabs = "\t"; else if (numTabs == 2) tabs = "\t\t"; else if (numTabs == 3) tabs = "\t\t\t"; struct hashEl *hel = hashLookup(tdb->settingsHash, "track"); fprintf(f, "%s%s %s\n", tabs,hel->name, trackHubSkipHubName((char *)hel->val)); +fprintf(f, "%s%s %d\n", tabs, "priority", priority); char *dataUrl = NULL; char *bigDataUrl = trackDbSetting(tdb, "bigDataUrl"); if (bigDataUrl == NULL) { if (startsWith("bigWig", tdb->type)) { if (conn == NULL) errAbort("track hub has bigWig without bigDataUrl"); dataUrl = getSqlBigWig(conn, db, tdb); } } struct hashCookie cookie = hashFirst(tdb->settingsHash); while ((hel = hashNext(&cookie)) != NULL) { if (sameString("parent", hel->name)) fprintf(f, "%s%s %s\n", tabs,hel->name, trackHubSkipHubName((char *)hel->val)); - else if (!(sameString("track", hel->name) || sameString("polished", hel->name) || sameString("group", hel->name))) + else if (!(sameString("track", hel->name) || sameString("polished", hel->name)|| sameString("group", hel->name) || sameString("priority", hel->name))) fprintf(f, "%s%s %s\n", tabs,hel->name, (char *)hel->val); } if (bigDataUrl == NULL) { if (dataUrl != NULL) fprintf(f, "%sbigDataUrl %s\n", tabs,dataUrl); } fprintf(f, "\n"); } -static void outTrackDbList(char *db, struct sqlConnection *conn, FILE *f, char *hubName, struct trackDb *list, char *collectionName, struct trackDb *newTdb, int numTabs) +static void outTrackDbList(char *db, struct sqlConnection *conn, FILE *f, char *hubName, struct trackDb *list, char *collectionName, struct trackDb *newTdb, int numTabs, int priority) /* Put a list of trackDb entries into a collection, adding a new track to the collection. */ { if (list == NULL) return; struct trackDb *tdb; for(tdb = list; tdb; tdb = tdb->next) { if (tdb->grp != NULL) if ((hubName == NULL) || differentString(hubName, tdb->grp)) continue; - outOneTdb(db, conn, f, tdb, numTabs); + outOneTdb(db, conn, f, tdb, numTabs, priority++); struct hashEl *hel = hashLookup(tdb->settingsHash, "track"); if ((hel != NULL) && (hel->val != NULL) && sameString((char *)hel->val, collectionName)) - outOneTdb(db, conn, f, newTdb, numTabs + 1); + { + if (newTdb->subtracks) + { + struct trackDb *subTdb; + slReverse(&newTdb->subtracks); + for(subTdb = newTdb->subtracks; subTdb; subTdb = subTdb->next) + { + outOneTdb(db, conn, f, subTdb, numTabs + 1, priority++); + } + } + else + outOneTdb(db, conn, f, newTdb, numTabs + 1, priority++); + } - outTrackDbList(db, conn, f, hubName, tdb->subtracks, collectionName, newTdb, numTabs + 1); + outTrackDbList(db, conn, f, hubName, tdb->subtracks, collectionName, newTdb, numTabs + 1, priority); } } static void doAddTrack(struct cart *cart, char *db, struct trackDb *trackList, char *trackName, char *collectionName, struct hash *nameHash) /* Add a track to a collection in a hub. */ { char *fileName = getHubName(cart, db); char *hubName = hubNameFromUrl(fileName); FILE *f = fopen(fileName, "w"); struct trackDb *newTdb = hashMustFindVal(nameHash, trackHubSkipHubName(trackName)); +if (newTdb->subtracks) + { + struct trackDb *subTdb; + for(subTdb = newTdb->subtracks; subTdb; subTdb = subTdb->next) + { + hashReplace(subTdb->settingsHash, "track", makeUnique(nameHash, subTdb->track)); + hashReplace(subTdb->settingsHash, "parent", trackHubSkipHubName(collectionName)); + } + } +else + { hashReplace(newTdb->settingsHash, "track", makeUnique(nameHash, trackName)); hashReplace(newTdb->settingsHash, "parent", trackHubSkipHubName(collectionName)); + } char *tdbType = trackDbSetting(newTdb, "tdbType"); if (tdbType != NULL) { hashReplace(newTdb->settingsHash, "type", tdbType); hashReplace(newTdb->settingsHash, "shortLabel", trackDbSetting(newTdb, "name")); hashReplace(newTdb->settingsHash, "longLabel", trackDbSetting(newTdb, "description")); } outHubHeader(f, db); struct sqlConnection *conn = NULL; if (!trackHubDatabase(db)) conn = hAllocConn(db); modifyName(newTdb, hubName, NULL); -outTrackDbList(db, conn, f, hubName, trackList, collectionName, newTdb, 0); +outTrackDbList(db, conn, f, hubName, trackList, collectionName, newTdb, 0, 0); hFreeConn(&conn); fclose(f); } static void doMiddle(struct cart *cart) /* Set up globals and make web page */ { char *db; char *genome; getDbAndGenome(cart, &db, &genome, oldVars); initGenbankTableNames(db); int timeout = cartUsualInt(cart, "udcTimeout", 300); if (udcCacheTimeout() < timeout) udcSetCacheTimeout(timeout);