442fef159db4b61a41789813c9068776ef2f8cfb
kate
  Mon Sep 17 19:39:24 2018 -0700
Pack mode. refs #21917

diff --git src/hg/hgTracks/interactTrack.c src/hg/hgTracks/interactTrack.c
index f0ce9e1..0e55e1a 100644
--- src/hg/hgTracks/interactTrack.c
+++ src/hg/hgTracks/interactTrack.c
@@ -1,23 +1,24 @@
 /* interactTrack -- draw interaction between two genomic regions */
 
 /* Copyright (C) 2018 The Regents of the University of California 
  * See README in this or parent directory for licensing information. */
 
 #include "common.h"
 #include "obscure.h"
 #include "hgTracks.h"
+#include "bedCart.h"
 #include "bigWarn.h"
 #include "interact.h"
 #include "interactUi.h"
 
 static int interactTotalHeight(struct track *tg, enum trackVisibility vis)
 /* calculate height of all the interactions being displayed */
 {
 if ( tg->visibility == tvDense)
     return  tl.fontHeight;
 int min, max, deflt, current; 
 cartTdbFetchMinMaxPixels(cart, tg->tdb, 
                                 INTERACT_MINHEIGHT, INTERACT_MAXHEIGHT, atoi(INTERACT_DEFHEIGHT),
                                 &min, &max, &deflt, &current);
 return tg->height = current;
 }
@@ -47,31 +48,31 @@
 
 boolean interactSourceInWindow(struct interact *inter)
 /* True if midpoint of source is on screen */
 {
 unsigned s = interactRegionCenter(inter->sourceStart, inter->sourceEnd);
 return (s >= winStart) && (s < winEnd);
 }
 
 boolean interactTargetInWindow(struct interact *inter)
 /* True if midpoint of target is on screen */
 {
 unsigned t = interactRegionCenter(inter->targetStart, inter->targetEnd);
 return (t >= winStart) && (t < winEnd);
 }
 
-void interactLoadItems(struct track *tg)
+static void loadAndFilterItems(struct track *tg)
 /* Load all interact items in region */
 {
 loadSimpleBedWithLoader(tg, (bedItemLoader)interactLoadAndValidate);
 
 if (slCount(tg->items) == 0 && tg->limitedVisSet)
     {
     // too many items to display
     // borrowed behaviors in bamTrack and vcfTrack
     // TODO BRANEY: make this behavior generic for bigBeds
     // (bigBedSelectRange)
     tg->drawItems = bigDrawWarning;
     tg->networkErrMsg = "Too many items in display (zoom in)"; 
     tg->totalHeight = bigWarnTotalHeight;
     return;
     }
@@ -99,43 +100,82 @@
             {
             if (!(sOnScreen || tOnScreen))
                 continue;
             }
         }
     slAddHead(&filteredItems, inter);
     }
 
 slReverse(&filteredItems);
 // consider sorting by score/value so highest scored items draw last (on top)
 if (slCount(filteredItems) != count)
     labelTrackAsFiltered(tg);
 tg->items = filteredItems;
 }
 
-void interactLoadBedItems(struct track *tg)
-/* Load interact items as linked features */
+void interactDrawLeftLabels(struct track *tg, int seqStart, int seqEnd,
+    struct hvGfx *hvg, int xOff, int yOff, int width, int height,
+    boolean withCenterLabels, MgFont *font,
+    Color color, enum trackVisibility vis)
+/* Override default */
+{
+}
+
+void interactFreeItems(struct track *tg)
+/* Free up interact items track */
+{
+interactFreeList((struct interact **)(&tg->items));
+}
+
+static boolean isBedMode(struct track *tg)
+/* Pack and squish modes display using BED linked features code */
 {
-interactLoadItems(tg);
+return tg->visibility == tvPack || tg->visibility == tvDense;
+}
+
+void interactLoadItems(struct track *tg)
+/* Load interact items in interact format */
+{
+loadAndFilterItems(tg);
+if (isBedMode(tg))
+    {
+    /* convert to BEDs for linked feature display */
     struct interact *inters = tg->items, *inter;
-struct bed *beds = NULL, *bed;
+    struct linkedFeatures *lfs = NULL, *lf;
     for (inter = inters; inter; inter = inter->next)
         {
-    bed = interactToBed(inter);
-    slAddHead(&beds, bed);
+        struct bed *bed = interactToBed(inter);
+        lf = lfFromBed(bed);
+        if (!tg->colorShades)
+            {
+            lf->extra = (void *)USE_ITEM_RGB;   /* signal for coloring */
+            lf->filterColor = bed->itemRgb;
+            }
+        bedFree(&bed);
+        // TODO: use lfFromBedExtra with scoreMin, scoreMax
+        slAddHead(&lfs, lf);
+        }
+    slReverse(&lfs);
+    tg->items = lfs;
+    }
+else
+    {
+    tg->mapsSelf = TRUE;
+    tg->totalHeight = interactTotalHeight;
+    tg->drawLeftLabels = interactDrawLeftLabels;
+    tg->freeItems = interactFreeItems;
     }
-slReverse(&beds);
-tg->items = beds;
 }
 
 char *interactMouseover(struct interact *inter, char *otherChrom)
 /* Make mouseover text for an interaction */
 {
 struct dyString *ds = dyStringNew(0);
 if (isEmptyTextField(inter->name))
     {
     if (!isEmptyTextField(inter->exp))
         dyStringPrintf(ds, "%s ", inter->exp);
     if (otherChrom)
         dyStringPrintf(ds, "%s", otherChrom);
     else
         {
         char buf[4096];
@@ -324,31 +364,31 @@
                    tg->track, item, itemBuf, NULL, TRUE, clickArg);
 }
 
 void drawPeakMapbox(struct track *tg, struct hvGfx *hvg, int seqStart, int seqEnd, char *item, char *status,
                         int x, int y, Color peakColor, Color highlightColor, boolean drawUp)
 /* Draw grab box and add map box */
 {
 if (drawUp)
     y = flipY(tg, y);
 hvGfxBox(hvg, x-1, y-1, 3, 3, peakColor);
 hvGfxBox(hvg, x, y, 1, 1, highlightColor);
 mapBoxHgcOrHgGene(hvg, seqStart, seqEnd, x-1, y-1, 3, 3,
                    tg->track, item, status, NULL, TRUE, NULL);
 }
 
-void interactDrawItems(struct track *tg, int seqStart, int seqEnd,
+static void drawInteractItems(struct track *tg, int seqStart, int seqEnd,
         struct hvGfx *hvg, int xOff, int yOff, int width, 
         MgFont *font, Color color, enum trackVisibility vis)
 /* Draw a list of interact structures. */
 {
 #define DRAW_LINE       0
 #define DRAW_CURVE      1
 #define DRAW_ELLIPSE    2
 
 // Determine drawing mode
 int draw = DRAW_LINE;
 boolean doDashes = FALSE;
 if (vis != tvDense)
     {
     char *drawMode = cartUsualStringClosestToHome(cart, tg->tdb, FALSE,
                                 INTERACT_DRAW, INTERACT_DRAW_DEFAULT);
@@ -586,49 +626,44 @@
             ellipseOrient = ELLIPSE_TOP;
             yLeft = yOff + tg->height - peakHeight;
             yTop = yOff + tg->height + peakHeight;
             }
         hvGfxEllipseDraw(hvg, lowerX, yLeft, upperX, yTop, color, ellipseOrient,
                                 isReversed && doDashes);
         // draw grab box and map box on peak
         int maxY = peakHeight + yOff;
         int peakX = ((upperX - lowerX + 1) / 2) + lowerX;
         drawPeakMapbox(tg, hvg, inter->chromStart, inter->chromEnd, inter->name, statusBuf,
                             peakX, maxY, peakColor, highlightColor, drawUp);
         }
     }
 }
 
-void interactDrawLeftLabels(struct track *tg, int seqStart, int seqEnd,
-    struct hvGfx *hvg, int xOff, int yOff, int width, int height,
-    boolean withCenterLabels, MgFont *font,
-    Color color, enum trackVisibility vis)
-/* Override default */
+void interactDrawItems(struct track *tg, int seqStart, int seqEnd,
+        struct hvGfx *hvg, int xOff, int yOff, int width, 
+        MgFont *font, Color color, enum trackVisibility vis)
+/* Draw a list of interact structures. */
 {
+if (isBedMode(tg))
+    {
+    tg->drawItemAt = linkedFeaturesDrawAt;
+    linkedFeaturesDraw(tg, seqStart, seqEnd, hvg, xOff, yOff, width, font, color, vis);
+    }
+else
+    drawInteractItems(tg, seqStart, seqEnd, hvg, xOff, yOff, width, font, color, vis);
 }
 
 void interactMethods(struct track *tg)
 /* Interact track type methods */
 {
-tg->canPack = TRUE;
-if (tg->visibility == tvPack)
-//if (1)
-    {
-    bedMethods(tg);
-    tg->loadItems = interactLoadBedItems;
-    }
-else
-    {
+tg->bedSize = 12;
+linkedFeaturesMethods(tg);         // for pack and squish modes 
 tg->loadItems = interactLoadItems;
 tg->drawItems = interactDrawItems;
-    tg->drawLeftLabels = interactDrawLeftLabels;
-    tg->totalHeight = interactTotalHeight;
-    tg->mapsSelf = TRUE;
-    }
 }
 
 void interactCtMethods(struct track *tg)
 /* Interact track methods for custom track */
 {
 interactMethods(tg);
 }