ff4af73ba2a52b18ce5423aae3104fae1d1a3473 hiram Fri Nov 20 17:25:43 2020 -0800 converted to single file for json data instead of one file for each track refs #21980 diff --git src/hg/hgTracks/hgTracks.c src/hg/hgTracks/hgTracks.c index 9ecc41d..2fe1854 100644 --- src/hg/hgTracks/hgTracks.c +++ src/hg/hgTracks/hgTracks.c @@ -61,30 +61,31 @@ #include "errCatch.h" #include "iupac.h" #include "botDelay.h" #include "chromInfo.h" #include "extTools.h" #include "basicBed.h" #include "customFactory.h" #include "genbank.h" #include "bigWarn.h" #include "wigCommon.h" #include "knetUdc.h" #include "hex.h" #include <openssl/sha.h> #include "customComposite.h" #include "chromAlias.h" +#include "jsonWrite.h" //#include "bed3Sources.h" /* Other than submit and Submit all these vars should start with hgt. * to avoid weeding things out of other program's namespaces. * Because the browser is a central program, most of its cart * variables are not hgt. qualified. It's a good idea if other * program's unique variables be qualified with a prefix though. */ char *excludeVars[] = { "submit", "Submit", "dirty", "hgt.reset", "hgt.in1", "hgt.in2", "hgt.in3", "hgt.inBase", "hgt.out1", "hgt.out2", "hgt.out3", "hgt.out4", "hgt.left1", "hgt.left2", "hgt.left3", "hgt.right1", "hgt.right2", "hgt.right3", "hgt.dinkLL", "hgt.dinkLR", "hgt.dinkRL", "hgt.dinkRR", "hgt.tui", "hgt.hideAll", "hgt.visAllFromCt", @@ -148,31 +149,39 @@ boolean hideControls = FALSE; /* Hide all controls? */ boolean trackImgOnly = FALSE; /* caller wants just the track image and track table html */ boolean ideogramToo = FALSE; /* caller wants the ideoGram (when requesting just one track) */ /* Structure returned from resolvePosition. * We use this to to expand any tracks to full * that were found to contain the searched-upon * position string */ struct hgPositions *hgp = NULL; /* Other global variables. */ struct group *groupList = NULL; /* List of all tracks. */ char *browserName; /* Test, preview, or public browser */ char *organization; /* UCSC */ +/* mouseOver popUp global data, each track that wants to send json + * data will need to know the json file name from mouseOverJson + * and will write the track data to mouseOverJson. The structure + * of the data in the json output will depend upon what the track needs + * to send. + */ boolean enableMouseOver = FALSE; +struct tempName *mouseOverJsonFile = NULL; +struct jsonWrite *mouseOverJson = NULL; struct hash *trackHash = NULL; /* Hash of the tracks by their name. */ #ifdef DEBUG void uglySnoopTrackList(int depth, struct track *trackList) /* Print out some info on track list. */ { struct track *track; for (track = trackList; track != NULL; track = track->next) { if (stringIn("FaireH1h", track->track)) { repeatCharOut(uglyOut, '+', depth); } uglySnoopTrackList(depth+1, track->subtracks); @@ -5031,30 +5040,41 @@ imagePixelHeight = pixHeight; if (psOutput) { hvg = hvGfxOpenPostScript(pixWidth, pixHeight, psOutput); hvgSide = hvg; // Always only one image } else { boolean transparentImage = FALSE; if (theImgBox!=NULL) transparentImage = TRUE; // transparent because BG (blue ruler lines) is separate image if (measureTiming) measureTime("Time at start of obtaining trash hgt png image file"); trashDirFile(&pngTn, "hgt", "hgt", ".png"); + if (enableMouseOver) + { /* created here at this time to get the same name as .png file */ + /* this file name should actually be a copy of pngTn with the suffix + * changed png -> json since the name does have a time element thrown + * in. This name needs to be identical since the javascript only sees + * the .png name and thus needs to figure out the .json name + */ + /* will open this file upon successful exit to write the data */ + AllocVar(mouseOverJsonFile); + trashDirFile(mouseOverJsonFile, "hgt", "hgt", ".json"); + } hvg = hvGfxOpenPng(pixWidth, pixHeight, pngTn.forCgi, transparentImage); if (theImgBox) { // Adds one single image for all tracks (COULD: build the track by track images) theOneImg = imgBoxImageAdd(theImgBox,pngTn.forHtml,NULL,pixWidth, pixHeight,FALSE); theSideImg = theOneImg; // Unlkess this is overwritten below, there is a single image } hvgSide = hvg; // Unless this is overwritten below, there is a single image if (theImgBox && theImgBox->showPortal && withLeftLabels) { // TODO: It would be great to make the two images smaller, // but keeping both the same full size for now @@ -8680,30 +8700,34 @@ { // TODO should be more than this. But at least this makes the same trackList mods to the other windows. if (nukeIdeoFromList) { struct track *ideoTrack = chromIdeoTrack(window->trackList); if (ideoTrack) { slRemoveEl(&window->trackList, ideoTrack); } } } } setGlobalsFromWindow(windows); // first window // restore globals +/* DBG - a message box to display information from the javascript +hPrintf("<div id='mouseDbg'><span id='dbgMouseOver'><p>. . . dbgMouseOver</p></span></div>\n"); + */ + #ifdef USE_NAVIGATION_LINKS hPrintf("<TABLE BORDER=0 CELLPADDING=0 width='%d'><tr style='font-size:small;'>\n", tl.picWidth);//min(tl.picWidth, 800)); hPrintf("<td width='40' align='left'><a href='?hgt.left3=1' " "title='move 95% to the left'><<<</a>\n"); hPrintf("<td width='30' align='left'><a href='?hgt.left2=1' " "title='move 47.5% to the left'><<</a>\n"); hPrintf("<td width='20' align='left'><a href='?hgt.left1=1' " "title='move 10% to the left'><</a>\n"); hPrintf("<td> </td>\n"); // Without width cell expands table with, forcing others to sides hPrintf("<td width='40' align='left'><a href='?hgt.in1=1' " "title='zoom in 1.5x'>> <</a>\n"); hPrintf("<td width='60' align='left'><a href='?hgt.in2=1' " "title='zoom in 3x'>>> <<</a>\n"); @@ -9810,30 +9834,31 @@ if (virtWinEnd > virtSeqBaseCount) { virtWinEnd = virtSeqBaseCount; } if (virtWinStart > virtSeqBaseCount) { virtWinStart = virtSeqBaseCount - 1000; } virtWinBaseCount = virtWinEnd - virtWinStart; if (virtWinBaseCount <= 0) hUserAbort("Window out of range on %s", virtChromName); + if (!cartUsualBoolean(cart, "hgt.psOutput", FALSE) && !cartUsualBoolean(cart, "hgt.imageV1" , FALSE)) { // TODO GALT Guidelines broken on virtChrom for 3X. // works in demo0 or real chrom. Only the guidelines seem to be messed up. // Other stuff works. 1X works too. // Since we are not using 3X for now, I will leave this for a future fix. // To test 3X, do make clean; make CFLAGS=-DIMAGEv2_DRAG_SCROLL_SZ=3 // Start an imagebox (global for now to avoid huge rewrite of hgTracks) // Set up imgBox dimensions int sideSliceWidth = 0; // Just being explicit if (withLeftLabels) sideSliceWidth = (fullInsideX - gfxBorder*3) + 2; @@ -10540,31 +10565,42 @@ } } extern boolean issueBotWarning; void doMiddle(struct cart *theCart) /* Print the body of an html file. */ { cart = theCart; measureTiming = hPrintStatus() && isNotEmpty(cartOptionalString(cart, "measureTiming")); if (measureTiming) measureTime("Startup (bottleneck %d ms) ", botDelayMillis); char *mouseOverEnabled = cfgOption("mouseOverEnabled"); if (sameWordOk(mouseOverEnabled, "on")) + { enableMouseOver = TRUE; + /* mouseOverJsonFile will be initializes and created at the same + * time as the browser .png image file + */ + mouseOverJson = jsonWriteNew(); + jsonWriteObjectStart(mouseOverJson, NULL); + /* this jsonWrite structure will finish off upon successful exit. + * each track will start a list with the track name: + * jsonWriteListStart(mouseOverJson, tg->track); + */ + } else enableMouseOver = FALSE; if (issueBotWarning) { char *ip = getenv("REMOTE_ADDR"); botDelayMessage(ip, botDelayMillis); } char *debugTmp = NULL; /* Uncomment this to see parameters for debugging. */ /* struct dyString *state = NULL; */ /* Initialize layout and database. */ if (measureTiming) measureTime("Get cart of %d for user:%s session:%s", theCart->hash->elCount, @@ -10660,30 +10696,31 @@ if (!searching) // NOT doing search { webIncludeResourceFile("jquery.contextmenu.css"); jsIncludeFile("jquery.contextmenu.js", NULL); webIncludeResourceFile("ui.dropdownchecklist.css"); jsIncludeFile("ui.dropdownchecklist.js", NULL); jsIncludeFile("ddcl.js", NULL); } hPrintf("<div id='hgTrackUiDialog' style='display: none'></div>\n"); hPrintf("<div id='hgTracksDialog' style='display: none'></div>\n"); cartFlushHubWarnings(); } + if (cartVarExists(cart, "chromInfoPage")) { cartRemove(cart, "chromInfoPage"); chromInfoPage(); } else if (differentString(cartUsualString(cart, TRACK_SEARCH,"0"),"0")) { doSearchTracks(groupList); } else if (sameWord(configPageCall, "configure") || sameWord(configPageCall, "configure tracks and display")) { cartRemove(cart, "hgTracksConfigPage"); configPage(); } @@ -10759,30 +10796,41 @@ checkAddHighlight(); // call again in case tracksDisplay's call to resolvePosition changed vars char *highlightDef = cartOptionalString(cart, "highlight"); if (highlightDef) jsonObjectAdd(jsonForClient, "highlight", newJsonString(highlightDef)); jsonObjectAdd(jsonForClient, "enableHighlightingDialog", newJsonBoolean(cartUsualBoolean(cart, "enableHighlightingDialog", TRUE))); struct dyString *dy = dyStringNew(1024); jsonDyStringPrint(dy, (struct jsonElement *) jsonForClient, "hgTracks", 0); jsInline(dy->string); dyStringFree(&dy); dy = dyStringNew(1024); if (enableMouseOver) { + jsonWriteObjectEnd(mouseOverJson); + /* if any data was written, it is longer than 4 bytes */ + if (strlen(mouseOverJson->dy->string) > 4) + { + FILE *trashJson = mustOpen(mouseOverJsonFile->forCgi, "w"); + fputs(mouseOverJson->dy->string,trashJson); + carefulClose(&trashJson); + } + + hPrintf("<div id='mouseOverVerticalLine' class='mouseOverVerticalLine'></div>\n"); + hPrintf("<div id='mouseOverText' class='mouseOverText'></div>\n"); dyStringPrintf(dy, "window.browserTextSize=%s;\n", tl.textSize); dyStringPrintf(dy, "window.mouseOverEnabled=true;\n"); } else { dyStringPrintf(dy, "window.mouseOverEnabled=false;\n"); } jsInline(dy->string); dyStringFree(&dy); if (measureTiming) measureTime("Time at end of doMiddle, next up cart write"); if (cartOptionalString(cart, "udcTimeout")) {