c2e376e7b6d980f41ff903e6374378d668f11770
kate
  Thu Oct 22 14:41:52 2020 -0700
Multi-region features for sparse tracks.  With virt->multi, needs debug. refs #26385

diff --git src/hg/hgTracks/hgTracks.c src/hg/hgTracks/hgTracks.c
index d541c7d..d214c99 100644
--- src/hg/hgTracks/hgTracks.c
+++ src/hg/hgTracks/hgTracks.c
@@ -2238,31 +2238,33 @@
 struct highlightVar *hlList = parseHighlightInfo();
 
 if(hlList && theImgBox == NULL) // Only highlight region when imgBox is not used. (pdf and show-image)
     {
     struct highlightVar *h;
     for (h=hlList; h; h=h->next)
         {
         if (virtualSingleChrom()) // DISGUISE VMODE
             {
             if ((h->db && sameString(h->db, database))
             &&  (h->chrom && sameString(h->chrom,chromName)))
                 {
                 char position[1024];
                 safef(position, sizeof position, "%s:%ld-%ld", h->chrom, h->chromStart, h->chromEnd);
                 char *newPosition = undisguisePosition(position); // UN-DISGUISE VMODE
-                if (startsWith("virt:", newPosition))
+                if (startsWith(MULTI_REGION_CHROM, newPosition))
+                   newPosition = replaceChars(position, OLD_MULTI_REGION_CHROM, MULTI_REGION_CHROM);
+                if (startsWith(MULTI_REGION_CHROM, newPosition))
                     {
                     parseVPosition(newPosition, &h->chrom, &h->chromStart, &h->chromEnd);
                     }
                 }
             }
 
         if ((h->db && sameString(h->db, database))
         &&  (h->chrom && sameString(h->chrom,virtChromName))
         &&  (h->chromEnd != 0)
         &&  (h->chromStart <= virtWinEnd && h->chromEnd >= virtWinStart))
             {
 
             h->chromStart = max(h->chromStart, virtWinStart);
             h->chromEnd = min(h->chromEnd, virtWinEnd);
             double pixelsPerBase = (double)fullInsideWidth/(virtWinEnd - virtWinStart);
@@ -2765,31 +2767,31 @@
 	{
 	int s = max(start, w->winStart);
 	int e = min(end, w->winEnd);
 	long cs = s - w->winStart + w->virtStart;
 	long ce = e - w->winStart + w->virtStart;
 	if (newStart == -1)
 	    newStart = cs;
 	newEnd = ce;
 	}
     lastW = w;
    }
 if (newStart == -1) // none of the windows intersected with the position
     return position; // return original
 //  return new virt undisguised position as a string
 char newPos[1024];
-safef (newPos, sizeof newPos, "virt:%ld-%ld", (newStart+1), newEnd);
+safef (newPos, sizeof newPos, "%s:%ld-%ld", MULTI_REGION_CHROM, (newStart+1), newEnd);
 return cloneString(newPos);
 }
 
 
 char *windowsSpanPosition()
 /* Return a position string that spans all the windows.
  * Windows should be on same chrom and ascending and non-overlapping.*/
 {
 char buf[256];
 char *chromName = windows->chromName;
 int start = windows->winStart;
 struct window *w = windows, *last = NULL;
 while(w->next) // find last window
     {
     last = w;
@@ -5364,35 +5366,37 @@
         }
 
     if (!exists)
         {
 
         hvGfxSetClip(bgImg, fullInsideX, 0, fullInsideWidth, pixHeight);
         y = gfxBorder;
 
 	if (virtMode)
 	    {
 	    // vertical windows separators
 
 	    if (emAltHighlight)
 		{
 		// light blue alternating backgrounds
-		Color lightBlue = hvGfxFindRgb(bgImg, &guidelineColor);
+		Color lightBlue = hvGfxFindRgb(bgImg, &lightGuidelineColor);
+                //int highlightY = (baseTitle ? titleHeight+1000 : 0);
+                int highlightY = 0;
 		for (window=windows; window; window=window->next) // background under every other window
 		    {
 		    if (window->regionOdd)
-			hvGfxBox(bgImg, window->insideX, 0, window->insideWidth, pixHeight, lightBlue);
+                        hvGfxBox(bgImg, window->insideX, highlightY, window->insideWidth, pixHeight, lightBlue);
 		    }
 		}
 	    else
 		{
 		// red vertical lines
 		Color lightRed = hvGfxFindRgb(bgImg, &vertWindowSeparatorColor);
 		for (window=windows->next; window; window=window->next) // skip first window, not needed
 		    hvGfxBox(bgImg, window->insideX, 0, 1, pixHeight, lightRed);
 		}
 	    }
 	else
 	    {
 	    int x;
 	    Color lightBlue = hvGfxFindRgb(bgImg, &guidelineColor);
 	    for (x = fullInsideX+guidelineSpacing-1; x<pixWidth; x += guidelineSpacing)
@@ -8597,30 +8601,41 @@
 	hPrintf("<CENTER>");
 	}
 
 
     /* Make line that says position. */
 	{
 	char buf[256];
 	char *survey = cfgOptionEnv("HGDB_SURVEY", "survey");
 	char *surveyLabel = cfgOptionEnv("HGDB_SURVEY_LABEL", "surveyLabel");
 	    char *javascript = "document.location = '/cgi-bin/hgTracks?db=' + document.TrackForm.db.options[document.TrackForm.db.selectedIndex].value;";
 	    if (containsStringNoCase(database, "zoo"))
 		{
 		hPuts("Organism ");
 		printAssemblyListHtmlExtra(database, "change", javascript);
 		}
+        if (sameString(virtModeType, "default"))
+            {
+            hButtonMaybePressed("hgTracksConfigMultiRegionPage", "multi-region", 
+                    "Configure view in multi-region display mode",
+                    "popUpHgt.hgTracks('multi-region config'); return false;", FALSE);
+            }
+        else
+            {
+            hButtonWithMsg("hgt.exitMultiRegion", "exit multi-region", "Exit multi-region display mode");
+            }
+        hPrintf(" ");
 
 	if (virtualSingleChrom()) // DISGUISE VMODE
 	    safef(buf, sizeof buf, "%s", windowsSpanPosition());
 	else
 	    safef(buf, sizeof buf, "%s:%ld-%ld", virtChromName, virtWinStart+1, virtWinEnd);
 	
 	position = cloneString(buf);
         char *pressedClass = "", *showVirtRegions = "";
         if (differentString(virtModeType, "default"))
             {
             pressedClass = "pressed";
             showVirtRegions = "show multi-region position ranges and ";
             }
 	hPrintf("<span class='positionDisplay %s' id='positionDisplay' "
                 "title='click to %s copy position to input box'>%s</span>", 
@@ -9442,49 +9457,57 @@
 {
 char titleVar[256];
 char *oldPosition = cartUsualString(cart, "oldPosition", "");
 boolean findNearest = cartUsualBoolean(cart, "findNearest", FALSE);
 cartRemove(cart, "findNearest");
 
 boolean positionIsVirt = FALSE;
 position = getPositionFromCustomTracks();
 if (NULL == position)
     {
     position = cartGetPosition(cart, database, &lastDbPosCart);
     if (sameOk(cgiOptionalString("position"), "lastDbPos"))
 	{
         restoreSavedVirtPosition();
 	}
-    if (startsWith("virt:", position))
+    if (startsWith(OLD_MULTI_REGION_CHROM, position))
+        position = replaceChars(position, OLD_MULTI_REGION_CHROM, MULTI_REGION_CHROM);
+    if (startsWith(MULTI_REGION_CHROM, position))
 	{
 	position = stripCommas(position); // sometimes the position string arrives with commas in it.
 	positionIsVirt = TRUE;
 	}
     }
 
-
 if (sameString(position, ""))
     {
     hUserAbort("Please go back and enter a coordinate range or a search term in the \"search term\" field.<br>For example: chr22:20100000-20200000.\n");
     }
 
 if (!positionIsVirt)
     {
     if (! resolvePosition(&position))
         return;
     }
 
+if  (cgiVarExists("hgt.exitMultiRegion"))
+    {
+    cartRemove(cart, "hgt.exitMultiRegion");
+    cartSetString(cart, "virtModeType", "default");
+    cartSetBoolean(cart, "virtMode", FALSE);
+    }
+
 virtMode = cartUsualBoolean(cart, "virtMode", FALSE);
 
 /* Figure out basic dimensions of display.  This
  * needs to be done early for the sake of the
  * zooming and dinking routines. */
 setLayoutGlobals();
 
 virtModeType = cartUsualString(cart, "virtModeType", virtModeType);
 
 if (positionIsVirt && virtualSingleChrom())
     {
     // we need chromName to be set before initRegionList() gets called.
     position = cartUsualString(cart, "nonVirtPosition", "");
     if (!sameString(position,""))
 	parseNonVirtPosition(position);
@@ -9560,31 +9583,33 @@
 	jsonForConvert = newJsonObject(newHash(8));
 	jsonObjectAdd(jsonForConvert, "virtWinStart", newJsonNumber(virtWinStart));
 	jsonObjectAdd(jsonForConvert, "virtWinEnd", newJsonNumber(virtWinEnd));
 
 	struct dyString *dy = dyStringNew(1024);
 	jsonDyStringPrint(dy, (struct jsonElement *) jsonForConvert, "convertChromToVirtChrom", 0);
 	jsInline(dy->string);
 	dyStringFree(&dy);
 	}
     return;
     }
 
 lastVirtModeExtraState = cartUsualString(cart, "lastVirtModeExtraState", lastVirtModeExtraState);
 
 // DISGUISED POSITION
-if (!startsWith("virt:", position) && (virtualSingleChrom()))
+if (startsWith(OLD_MULTI_REGION_CHROM, position))
+    position = replaceChars(position, OLD_MULTI_REGION_CHROM, MULTI_REGION_CHROM);
+if (!startsWith(MULTI_REGION_CHROM, position) && (virtualSingleChrom()))
     {
     // "virtualSingleChrom trying to find best vchrom location corresponding to chromName, winStart, winEnd
     findNearest = TRUE;
 
      // try to find the nearest match
     if (!(chromName && findNearestVirtMatch(chromName, winStart, winEnd, findNearest, &virtWinStart, &virtWinEnd)))
 	{ // create 10k window near middle of vchrom
 	warn("Your new regions are not near previous location. Using middle of new coordinates.");
 	virtWinStart = virtSeqBaseCount / 2;
 	virtWinEnd = virtWinStart + 10000;
 	if (virtWinEnd > virtSeqBaseCount)
 	    virtWinEnd = virtSeqBaseCount;
 	}
     virtMode = TRUE;
     }
@@ -9695,31 +9720,31 @@
 	    { // try to set view to entire vchrom
 	    virtWinStart = 0;
 	    virtWinEnd = virtSeqBaseCount;
 	    virtMode = TRUE;
 	    // TODO what if the full-vchrom view has "too many windows"
 	    // check if virtRegionCount > 4000?
 	    }
 
 	remapHighlightPos();
 
 	}
 
     }
 
 if (virtMode)
-    virtChromName = "virt";
+    virtChromName = MULTI_REGION_CHROM;
 else
     virtChromName = chromName;
 
 virtWinBaseCount = virtWinEnd - virtWinStart;
 
 
 baseShowPos = cartUsualBoolean(cart, BASE_SHOWPOS, FALSE);
 baseShowAsm = cartUsualBoolean(cart, BASE_SHOWASM, FALSE);
 baseShowScaleBar = cartUsualBoolean(cart, BASE_SCALE_BAR, TRUE);
 baseShowRuler = cartUsualBoolean(cart, BASE_SHOWRULER, TRUE);
 safef(titleVar,sizeof(titleVar),"%s_%s", BASE_TITLE, database);
 baseTitle = cartUsualString(cart, titleVar, "");
 if (sameString(baseTitle, ""))
     baseTitle = NULL;