c35f61249daf6b5f463754b180c3fe74ef42d39d
max
  Tue Oct 15 06:13:50 2024 -0700
when hiding tracks on right-click, hide parents if possible, rather than their children, refs #27890

diff --git src/hg/hgTracks/imageV2.c src/hg/hgTracks/imageV2.c
index 7745a9c..a174751 100644
--- src/hg/hgTracks/imageV2.c
+++ src/hg/hgTracks/imageV2.c
@@ -194,30 +194,43 @@
 return kindOfParent;
 }
 
 enum kindOfChild tdbKindOfChild(struct trackDb *tdb)
 {
 enum kindOfChild kindOfChild = kocOrphan;
 if (tdbIsFolderContent(tdb))
     kindOfChild = kocFolderContent;
 else if (tdbIsCompositeChild(tdb))
     kindOfChild = kocCompositeChild;
 else if (tdbIsMultiTrackChild(tdb))
     kindOfChild = kocMultiTrackChild;
 return kindOfChild;
 }
 
+char* tdbTopParent(struct trackDb *tdb)
+/* return the name of the top-most parent, so the parent of a composite or the name of the superTrack for 
+ * a composite in a superTrack. Or return NULL if this is already a top-level track. */
+{
+    if (!tdb->parent)
+        return NULL;
+
+    while (tdb->parent) {
+        tdb = tdb->parent;
+    }
+    return tdb->track;
+}
+
 /////////////////////////
 // JSON support.  Eventually the whole imgTbl could be written out as JSON
 
 
 static void jsonTdbSettingsInit(struct jsonElement *settings)
 // Inititializes trackDbJson
 {
 struct jsonElement *ele = newJsonObject(newHash(8));
 jsonObjectAdd(ele, "shortLabel", newJsonString("ruler"));
 jsonObjectAdd(ele, "type", newJsonString("ruler"));
 jsonObjectAdd(ele, "longLabel", newJsonString("Base Position Controls"));
 jsonObjectAdd(ele, "canPack", newJsonNumber(0));
 jsonObjectAdd(ele, "visibility", newJsonNumber(rulerMode));
 jsonObjectAdd(ele, "configureBy", newJsonString("popup"));
 jsonObjectAdd(ele, "kindOfParent", newJsonNumber(0));
@@ -226,30 +239,34 @@
 
 void jsonTdbSettingsBuild(struct jsonElement *settings, struct track *track, boolean configurable)
 // Adds trackDb settings to the jsonTdbSettings
 {
 struct jsonElement *ele = newJsonObject(newHash(8));
 jsonObjectAdd(settings, track->track, (struct jsonElement *) ele);
 // track name and type
 jsonObjectAdd(ele, "type", newJsonString(track->tdb->type));
 
 // Tell which kind of parent and which kind of child
 enum kindOfParent kindOfParent = tdbKindOfParent(track->tdb);
 enum kindOfChild  kindOfChild  = tdbKindOfChild(track->tdb);
 jsonObjectAdd(ele, "kindOfParent", newJsonNumber(kindOfParent));
 jsonObjectAdd(ele, "kindOfChild", newJsonNumber(kindOfChild));
 
+char* topParent = tdbTopParent(track->tdb);
+if (topParent)
+    jsonObjectAdd(ele, "topParent", newJsonString(topParent));
+
 // Tell something about the parent and/or children
 if (kindOfChild != kocOrphan)
     {
     struct trackDb *parentTdb = (kindOfChild == kocFolderContent ? track->tdb->parent
                                                                  : tdbGetContainer(track->tdb));
     jsonObjectAdd(ele, "parentTrack", newJsonString(parentTdb->track));
     jsonObjectAdd(ele, "parentLabel", newJsonString(parentTdb->shortLabel));
     if (kindOfChild != kocFolderContent && !track->canPack)
         {
         jsonObjectAdd(ele, "shouldPack", newJsonNumber(0)); // default vis is full,
         track->canPack = rTdbTreeCanPack(parentTdb);        // but pack is an option
         }
     }
 
 boolean isCustomComposite = trackDbSettingOn(track->tdb, CUSTOM_COMPOSITE_SETTING);