7976e2588e92dca0567231cf3998759bf6f1827f
max
  Thu May 7 03:27:42 2015 -0700
implementing the external tools "send to" menu, refs #15113

diff --git src/hg/hgTracks/menu.c src/hg/hgTracks/menu.c
index deaa91b..56af8bd 100644
--- src/hg/hgTracks/menu.c
+++ src/hg/hgTracks/menu.c
@@ -5,53 +5,65 @@
 
 #include "common.h"
 #include "dystring.h"
 #include "ensFace.h"
 #include "agpFrag.h"
 #include "ctgPos.h"
 #include "hCommon.h"
 #include "htmshell.h"
 #include "hash.h"
 #include "liftOver.h"
 #include "wikiLink.h"
 #include "web.h"
 #include "geoMirror.h"
 #include "hgTracks.h"
 #include "trackHub.h"
+#include "extTools.h"
 
 /* list of links to display in a menu */
 struct hotLink
     {
     struct hotLink *next;
     char *name;
     char *url;
     char *id;
+    char *mouseOver;
+    boolean inactive; /* greyed out */
     boolean external;
     };
 
 static void appendLink(struct hotLink **links, char *url, char *name, char *id, boolean external)
 {
 // append to list of links for later printing and/or communication with javascript client
 struct hotLink *link;
 AllocVar(link);
 link->name = cloneString(name);
 link->url = cloneString(url);
 link->id = cloneString(id);
 link->external = external;
+link->inactive = FALSE;
 slAddTail(links, link);
 }
 
+static void appendLinkMaybeInactive(struct hotLink **links, char *url, char *name, char *id, 
+    boolean external, boolean inactive)
+{
+appendLink(links, url, name, id, external);
+struct hotLink *le = slLastEl(links);
+le->inactive=inactive;
+}
+
 static void printEnsemblAnchor(char *database, char* archive,
                                char *chrName, int start, int end, struct hotLink **links)
 /* Print anchor to Ensembl display on same window. */
 {
 char *scientificName = hScientificName(database);
 char *dir = ensOrgNameFromScientificName(scientificName);
 struct dyString *ensUrl;
 char *name;
 int localStart, localEnd;
 
 name = chrName;
 
 if (sameWord(scientificName, "Takifugu rubripes"))
     {
     /* for Fugu, must give scaffold, not chr coordinates */
@@ -124,35 +136,108 @@
 hFreeConn(&conn);
 if (1 == itemCount)
     {   // verify *entirely* within single contig
     if ((winEnd <= agpItem->chromEnd) &&
 	(winStart >= agpItem->chromStart))
 	{
 	int agpStart = winStart - agpItem->chromStart;
 	int agpEnd = agpStart + winEnd - winStart;
 	printEnsemblAnchor(database, archive, agpItem->frag,
                            agpStart, agpEnd, links);
 	}
     }
 agpFragFree(&agpItem);  // the one we maybe used
 }
 
+void freeLinksAndConvert(struct hotLink *links, struct dyString *menuHtml)
+/* convert the links to html strings and append to the dyString "menu", destroying the links */
+{
+int len = slCount(links);
+int i = 0;
+struct hotLink *link = NULL;
+for(i = 0, link = links; link != NULL; i++, link = link->next)
+    {
+    char class[100];
+    if(i == 0)
+        safef(class, sizeof(class), "first");
+    else if (i + 1 == len)
+        safef(class, sizeof(class), "last");
+    else
+        class[0] = 0;
+    dyStringAppend(menuHtml, "<li");
+    char *encodedName = htmlEncode(link->name);
+    if(*class)
+        dyStringPrintf(menuHtml, " class='%s'", class);
+    dyStringPrintf(menuHtml, "><a href='%s' id='%s'%s>%s</a></li>\n", link->url, link->id,
+        link->external ? " TARGET='_blank'" : "", encodedName);
+    freez(&encodedName);
+
+    freez(&link->name);
+    freez(&link->url);
+    freez(&link->id);
+    }
+slFreeList(links);
+}
+
+static void addSendToMenuItems(struct dyString *viewMenu, char* uiVars)
+/* add the "send to" menu to the "viewMenu" dyString */
+{
+struct hotLink *viewLinks = NULL;
+
+char url[4096];
+char label[4096];
+
+struct extTool *extTools = readExtToolRa("extTools.ra");
+struct extTool *et;
+for(et = extTools; et != NULL; et = et->next)
+    {
+    if (et->dbs!=NULL)
+        {
+        if (!slNameInList(et->dbs, database))
+            continue;
+        }
+    if (et->params==NULL)
+        {
+        char *replUrl = replaceInUrl(et->url, "", cart, database, chromName, winStart, winEnd, NULL, TRUE);
+        safef(url, sizeof(url), "%s", replUrl);
+        //safef(url, sizeof(url), "%s %s", chromName, database);
+        }
+    else
+        safef(url, sizeof(url), "hgTracks?%s&hgt.redirectTool=%s", uiVars, et->tool);
+    boolean inactive = FALSE;
+    if (et->maxSize!=0)
+        {
+        inactive = TRUE;
+        if (et->maxSize>1000)
+            safef(label, sizeof(label), "%s (< %d kbp)", et->shortLabel, et->maxSize/1000);
+        else
+            safef(label, sizeof(label), "%s (< %d bp)", et->shortLabel, et->maxSize);
+        }
+    else
+        safef(label, sizeof(label), "%s", et->shortLabel);
+        
+    appendLinkMaybeInactive(&viewLinks, url, label, "extTool", TRUE, inactive);
+    }
+
+freeLinksAndConvert(viewLinks, viewMenu);
+
+}
+
 void printMenuBar()
 /* Put up the menu bar. */
 {
-struct hotLink *link, *links = NULL;
-int i, len;
+struct hotLink *links = NULL;
 struct sqlConnection *conn = NULL;
 if (!trackHubDatabase(database))
     conn = hAllocConn(database);
 char *menuStr, buf[4096], uiVars[1024];
 safef(uiVars, sizeof(uiVars), "%s=%s", cartSessionVarName(), cartSessionId(cart));
 
 menuStr = menuBar(cart, database);
 
 // Create top items in view menu
 safef(buf, sizeof(buf), "../cgi-bin/hgTracks?%s&hgt.psOutput=on", uiVars);
 appendLink(&links, buf, "PDF/PS", "pdfLink", FALSE);
 safef(buf, sizeof(buf), "%s&o=%d&g=getDna&i=mixed&c=%s&l=%d&r=%d&db=%s&%s",
       hgcNameAndSettings(), winStart, chromName, winStart, winEnd, database, uiVars);
 appendLink(&links, buf, "DNA", "dnaLink", FALSE);
 safef(buf, sizeof(buf), "../cgi-bin/hgConvert?hgsid=%s&db=%s", cartSessionId(cart), database);
@@ -334,39 +419,30 @@
     safef(buf, sizeof(buf), "http://ws120.wormbase.org/db/seq/gbrowse/wormbase?name=%s:%d-%d",
           skipChr(chromName), winStart+1, winEnd);
     appendLink(&links, buf, "WormBase", "wormbaseLink", TRUE);
     }
 
 // finish View menu
 safef(buf, sizeof(buf), "../cgi-bin/hgTracks?%s&hgTracksConfigPage=configure", uiVars);
 appendLink(&links, buf, "Configure Browser", "configureMenuLink", FALSE);
 safef(buf, sizeof(buf), "../cgi-bin/hgTracks?%s&hgt.reset=on", uiVars);
 appendLink(&links, buf, "Default Tracks", "defaultTracksMenuLink", FALSE);
 safef(buf, sizeof(buf), "../cgi-bin/hgTracks?%s&hgt.defaultImgOrder=on", uiVars);
 appendLink(&links, buf, "Default Track Order", "defaultTrackOrderMenuLink", FALSE);
 appendLink(&links, "../cgi-bin/cartReset", "Reset all user settings", "cartResetMenuLink", FALSE);
 
 struct dyString *viewMenu = dyStringCreate("<li class='menuparent' id='view'><span>View</span>\n<ul style='display: none; visibility: hidden;'>\n");
-len = slCount(links);
-for(i = 0, link = links; link != NULL; i++, link = link->next)
+freeLinksAndConvert(links, viewMenu);
+dyStringAppend(viewMenu, "</ul>\n</li>\n");
+
+// add the sendTo menu
+if (fileExists("extTools.ra"))
     {
-    char class[100];
-    if(i == 0)
-        safef(class, sizeof(class), "first");
-    else if (i + 1 == len)
-        safef(class, sizeof(class), "last");
-    else
-        class[0] = 0;
-    char *encodedName = htmlEncode(link->name);
-    dyStringAppend(viewMenu, "<li");
-    if(*class)
-        dyStringPrintf(viewMenu, " class='%s'", class);
-    dyStringPrintf(viewMenu, "><a href='%s' id='%s'%s>%s</a></li>\n", link->url, link->id,
-                   link->external ? " TARGET='_blank'" : "", encodedName);
-    freez(&encodedName);
-    }
+    dyStringAppend(viewMenu, "<li class=\"menuparent\" id=\"sendTo\"><span>Send To</span><ul>");
+    addSendToMenuItems(viewMenu, uiVars);
     dyStringAppend(viewMenu, "</ul>\n</li>\n");
+    }
 
 menuStr = replaceChars(menuStr, "<!-- OPTIONAL_VIEW_MENU -->", dyStringCannibalize(&viewMenu));
 hPuts(menuStr);
 freez(&menuStr);
 }