bd5ebb2dc0b10ad589ed54c3319da1fac28d2b26 max Wed May 7 06:38:51 2025 -0700 adding html to genePred exon mouseover, refs #33749 diff --git src/hg/hgTracks/simpleTracks.c src/hg/hgTracks/simpleTracks.c index 7019c9e5acb..55dfafa301c 100644 --- src/hg/hgTracks/simpleTracks.c +++ src/hg/hgTracks/simpleTracks.c @@ -2659,53 +2659,55 @@ if (*pNewWinEnd > virtSeqBaseCount) *pNewWinEnd = virtSeqBaseCount; *pNewWinStart = *pNewWinEnd - newWinSize; } #define EXONTEXTLEN 256 static void makeExonFrameText(int exonIntronNumber, int numExons, int startPhase, int endPhase, char *buf) /* Write mouseover text that describes the exon's phase into buf[EXONTEXTLEN]. Note that start/end-phases are in the direction of transcription: if transcript is on + strand, the start phase is the exonFrame value, and the end phase is the next exonFrame (3' on DNA) value if transcript is on - strand, the start phase is the previous (=3' on DNA) exonFrame and the end phase is the exonFrame */ { +static const char *phaseHelp = "<a style='float:right' target=_blank href='../goldenPath/help/codonPhase.html'>Phase?</a><br>"; + if (startPhase==-1) // UTRs don't have a frame at all { - safef(buf, EXONTEXTLEN, ", untranslated region"); + safef(buf, EXONTEXTLEN, "<b>No Codon:</b> Untranslated region<br>"); } else { char *exonNote = ""; boolean isNotLastExon = (exonIntronNumber<numExons); if (isNotLastExon) { if (startPhase==endPhase) exonNote = ": in-frame exon"; else exonNote = ": out-of-frame exon"; - safef(buf, EXONTEXTLEN, ", codon phase: start %d, end %d%s", startPhase, endPhase, exonNote); + safef(buf, EXONTEXTLEN, "<b>Codon phase:</b> start %d, end %d%s<br>%s", startPhase, endPhase, exonNote, phaseHelp); } else { if (startPhase==0) exonNote = ": in-frame exon"; else exonNote = ": out-of-frame exon"; - safef(buf, EXONTEXTLEN, ", start codon phase %d%s", startPhase, exonNote); + safef(buf, EXONTEXTLEN, "<b>Codon phase:</b> start %d%s<br>%s", startPhase, exonNote, phaseHelp); } } } boolean linkedFeaturesNextPrevItem(struct track *tg, struct hvGfx *hvg, void *item, int x, int y, int w, int h, boolean next) /* Draw a mapBox over the arrow-button on an *item already in the window*. */ /* Clicking this will do one of several things: */ { boolean result = FALSE; struct linkedFeatures *lf = item; struct simpleFeature *exons = lf->components; struct simpleFeature *exon = exons; char *nextExonText; char *prevExonText; long newWinSize = virtWinEnd - virtWinStart; @@ -2998,39 +3000,38 @@ } else { exonIntronNumber = numExonIntrons-exonIx+1; strandChar = '-'; } // we still need to show the existing mouseover text char* existingText = lf->mouseOver; if (isEmpty(existingText)) existingText = lf->name; // construct a string that tells the user about the codon frame situation of this exon // char *frameText = ""; // for coding exons, determine the start and end phase of the exon and an English text describing both: // if transcript is on + strand, the start phase is the exonFrame value, and the end phase is the next exonFrame (3' on DNA) value - // if transcript is on - strand, the start phase is the previous (=3' on DNA) exonFrame and the end phase is the exonFrame */ + // if transcript is on - strand, the start phase is the previous (=3' on DNA) exonFrame and the end phase is the exonFrame int startPhase = -1; int endPhase = -1; char phaseText[EXONTEXTLEN]; phaseText[0] = 0; if ((gp != NULL) && gp->exonFrames && isExon) { startPhase = gp->exonFrames[exonIx-1]; - //printf("start phase is set<br>"); if (!revStrand) endPhase = gp->exonFrames[exonIx]; else if (exonIx>1) endPhase = gp->exonFrames[exonIx-2]; // construct a string that tells the user about the codon frame situation of this exon makeExonFrameText(exonIntronNumber, numExons, startPhase, endPhase, phaseText); } if (w > 0) // draw exon or intron if width is greater than 0 { // draw mapBoxes for the codons if we are zoomed in far enough if (isExon && lf->codons && zoomedToCdsColorLevel) { struct simpleFeature *codon; @@ -3054,52 +3055,52 @@ if (codonsx <= picEnd && codonex >= picStart) { // clip it to avail pic codonsx = (codonsx < picStart) ? picStart : codonsx; codonex = (codonex > picEnd) ? picEnd : codonex; int w = codonex - codonsx; if (w > 0) { // temporarily remove the mouseOver from the lf, since linkedFeatureMapItem will always // prefer a lf->mouseOver over the itemName char *oldMouseOver = lf->mouseOver; lf->mouseOver = NULL; dyStringClear(codonDy); if (!isEmpty(existingText)) - dyStringPrintf(codonDy, "%s, ", existingText); + dyStringPrintf(codonDy, "<b>Transcript: </b> %s<br>", existingText); int codonHgvsIx = (codon->codonIndex - 1) * 3; if (codonHgvsIx >= 0) - dyStringPrintf(codonDy, "c.%d-%d, ", codonHgvsIx + 1, codonHgvsIx + 3); - dyStringPrintf(codonDy, "strand %c, %s %d of %d%s", + dyStringPrintf(codonDy, "<b>cDNA: </b> c.%d-%d<br>", codonHgvsIx + 1, codonHgvsIx + 3); + dyStringPrintf(codonDy, "<b>Strand: </b> %c<br><b>Exon: </b>%s %d of %d<br>%s", strandChar, exonIntronText, exonIntronNumber, numExonIntrons, phaseText); tg->mapItem(tg, hvg, item, codonDy->string, tg->mapItemName(tg, item), sItem, eItem, codonsx, y, w, heightPer); // and restore the mouseOver lf->mouseOver = oldMouseOver; } } } } } else // either an intron, or else an exon zoomed out too far for codons (or no codons) { char *sep = ""; if (!isEmpty(existingText)) - sep = ", "; + sep = "<br>"; - safef(mouseOverText, sizeof(mouseOverText), "%s%sstrand %c, %s %d of %d%s", + safef(mouseOverText, sizeof(mouseOverText), "<b>Transcript:</b> %s%s<b>Strand:</b> %c<br><b>Exon:</b> %s %d of %d<br>%s", existingText, sep, strandChar, exonIntronText, exonIntronNumber, numExonIntrons, phaseText); // temporarily remove the mouseOver from the lf, since linkedFeatureMapItem will always // prefer a lf->mouseOver over the itemName char *oldMouseOver = lf->mouseOver; lf->mouseOver = NULL; tg->mapItem(tg, hvg, item, mouseOverText, tg->mapItemName(tg, item), sItem, eItem, sx, y, w, heightPer); // and restore the old mouseOver lf->mouseOver = oldMouseOver; picStart = ex; // prevent pileups. is this right? add 1? does it work? // JC: Why do we care about pileups? First mapbox drawn wins. } }