4bb9e8caea515342ba98d3871da76cd4ec69916f chmalee Fri May 1 14:10:00 2026 -0700 Initial myVariants implementation: a form on hgTracks where users can enter item details in one of three ways: hgvs/item search, simple bed form, advanced bed form where additional non-bed fields can dynamically created. Allows changing the color of items, writing descriptions, and editing the items after creation. Show overlaps with hardcoded tracks when hgc page is open (not in the hgc dialog). Next commit has implementation of sharing these tracks with other users diff --git src/hg/hgTracks/makeItemsTrack.c src/hg/hgTracks/makeItemsTrack.c deleted file mode 100644 index f4275bb5417..00000000000 --- src/hg/hgTracks/makeItemsTrack.c +++ /dev/null @@ -1,221 +0,0 @@ -/* makeItemsTrack.c - supports tracks of type makeItems. Users can drag to create an item - * and click to edit one. */ - -/* Copyright (C) 2013 The Regents of the University of California - * See kent/LICENSE or http://genome.ucsc.edu/license/ for licensing information. */ - -#include "common.h" -#include "hash.h" -#include "linefile.h" -#include "jksql.h" -#include "hdb.h" -#include "hgTracks.h" -#include "bed.h" -#include "binRange.h" -#include "makeItemsItem.h" - - -void makeItemsJsCommand(char *command, struct track *trackList, struct hash *trackHash) -/* Execute some command sent to us from the javaScript. All we know for sure is that - * the first word of the command is "makeItems." We expect it to be of format: - * makeItems <trackName> <chrom> <chromStart> <chromEnd> - * If it is indeed of this form then we'll create a new makeItemsItem that references this - * location and stick it in the named track. */ -{ -/* Parse out command into local variables. */ -char *words[6]; -char *dupeCommand = cloneString(command); /* For parsing. */ -int wordCount = chopLine(dupeCommand, words); -if (wordCount != 5) - errAbort("Expecting %d words in jsCommand '%s'", wordCount, command); -char *trackName = words[1]; -char *chrom = words[2]; -int chromStart = sqlUnsigned(words[3]); -int chromEnd = sqlUnsigned(words[4]); - -/* Create a new item based on command. */ -struct makeItemsItem *item; -AllocVar(item); -item->bin = binFromRange(chromStart, chromEnd); -item->chrom = cloneString(chrom); -item->chromStart = item->thickStart = chromStart; -item->chromEnd = item->thickEnd = chromEnd; -item->name = cloneString(""); -item->score = 1000; -item->strand[0] = '.'; -item->description = cloneString(""); - -/* Add item to database. */ -struct track *track = hashMustFindVal(trackHash, trackName); -struct customTrack *ct = track->customPt; -char *tableName = ct->dbTableName; -struct sqlConnection *conn = hAllocConn(CUSTOM_TRASH); -makeItemsItemSaveToDb(conn, item, tableName, 0); -hFreeConn(&conn); - -freez(&dupeCommand); -} - -static int makeItemsExtraHeight(struct track *track) -/* Return extra height of track. */ -{ -return tl.fontHeight+2; -} - -static void updateTextField(char *trackName, struct sqlConnection *conn, - char *tableName, char *fieldName, int id) -/* Update text valued field with new val. */ -{ -char varName[128]; -char sql[256]; -safef(varName, sizeof(varName), "%s_%s", trackName, fieldName); -char *newVal = cartOptionalString(cart, varName); -if (newVal != NULL) - { - sqlSafef(sql, sizeof(sql), "update %s set %s='%s' where id=%d", - tableName, fieldName, newVal, id); - sqlUpdate(conn, sql); - cartRemove(cart, varName); /* We don't need it any more. */ - } -} - -static void makeItemsEditOrDelete(char *trackName, struct sqlConnection *conn, char *tableName) -/* Troll through cart variables looking for things that indicate user edited item - * or deleted it in hgc, and carry out edits. See hgc/makeItemsClick.c. */ -{ -char varName[128]; -char sql[256]; -safef(varName, sizeof(varName), "%s_%s", trackName, "id"); -char *idString = cartOptionalString(cart, varName); -if (idString != NULL) - { - int id = sqlUnsigned(idString); - idString = NULL; // Will be no good after cartRemove - cartRemove(cart, varName); // Remove so only do edits once. - - /* Handle cancel. */ - safef(varName, sizeof(varName), "%s_%s", trackName, "cancel"); - if (cartVarExists(cart, varName)) - { - cartRemove(cart, varName); // Only want to do cancels once - return; - } - - /* Handle delete. */ - safef(varName, sizeof(varName), "%s_%s", trackName, "delete"); - if (cartVarExists(cart, varName)) - { - cartRemove(cart, varName); // Especially only want to do deletes once! - sqlSafef(sql, sizeof(sql), "delete from %s where id=%d", tableName, id); - sqlUpdate(conn, sql); - return; - } - - /* Handle edits. */ - updateTextField(trackName, conn, tableName, "name", id); - updateTextField(trackName, conn, tableName, "description", id); - } -} - -void makeItemsLoadItems(struct track *track) -/* Load up items in track already. Also make up a pseudo-item that is - * where you drag to create an item. */ -{ -struct bed *bedList = NULL; -struct customTrack *ct = track->customPt; -char *tableName = ct->dbTableName; -struct sqlConnection *conn = hAllocConn(CUSTOM_TRASH); -makeItemsEditOrDelete(track->track, conn, tableName); -int rowOffset; -struct sqlResult *sr = hRangeQuery(conn, tableName, chromName, winStart, winEnd, NULL, &rowOffset); -char **row; -while ((row = sqlNextRow(sr)) != NULL) - { - struct bed *bed = bedLoadN(row+rowOffset, 9); - /* Add id to front of name */ - char *id = row[rowOffset + 10]; - char buf[64]; - safef(buf, sizeof(buf), "%s %s", id, bed->name); - freeMem(bed->name); - bed->name = cloneString(buf); - slAddHead(&bedList, bed); - } -sqlFreeResult(&sr); -hFreeConn(&conn); -slReverse(&bedList); -track->items = bedList; -} - -char *makeItemsItemName(struct track *track, void *item) -/* Return name of one of an item to display on left side. */ -{ -struct bed *bed = item; -char *name = bed->name; -name = skipToSpaces(name); -name = skipLeadingSpaces(name); -return name; -} - -void makeItemsDrawItems(struct track *track, int seqStart, int seqEnd, - struct hvGfx *hvg, int xOff, int yOff, int width, - MgFont *font, Color color, enum trackVisibility vis) -/* Draw simple Bed items. */ -{ -int dragBarHeight = makeItemsExtraHeight(track); -hvGfxTextCentered(hvg, xOff, yOff, width, dragBarHeight, color, font, - "--- Drag here or in between items to create a new item. ---"); -bedDrawSimple(track, seqStart, seqEnd, hvg, xOff, yOff + dragBarHeight, width, - font, color, vis); -} - - -void makeItemsDrawLeftLabels(struct track *track, int seqStart, int seqEnd, - struct hvGfx *hvg, int xOff, int yOff, int width, int height, - boolean withCenterLabels, MgFont *font, - Color color, enum trackVisibility vis) -/* Draw left label - just in dense or full mode. Needed to cope with empty space at top of track. */ -{ -int y = yOff + makeItemsExtraHeight(track); -int fontHeight = mgFontLineHeight(font); -if (withCenterLabels) - y += mgFontLineHeight(font); -if (vis == tvDense) - hvGfxTextRight(hvg, xOff, y, width-1, fontHeight, color, font, track->shortLabel); -else if (vis == tvFull) - { - struct bed *bed, *bedList = track->items; - for (bed = bedList; bed != NULL; bed = bed->next) - { - if (track->itemLabelColor != NULL) - color = track->itemLabelColor(track, bed, hvg); - int itemHeight = track->itemHeight(track, bed); - hvGfxTextRight(hvg, xOff, y, width - 1, - itemHeight, color, font, track->itemName(track, bed)); - y += itemHeight; - } - } -/* In pack mode the draw routine takes care of the labels. */ -} - - -int makeItemsTotalHeight(struct track *track, enum trackVisibility vis) -/* Most fixed height track groups will use this to figure out the height - * they use. */ -{ -track->height = tgFixedTotalHeightOptionalOverflow(track, vis, tl.fontHeight+1, tl.fontHeight, FALSE) + - makeItemsExtraHeight(track); -return track->height; -} - - -void makeItemsMethods(struct track *track) -/* Set up special methods for makeItems type tracks. */ -{ -bedMethods(track); -track->totalHeight = makeItemsTotalHeight; -track->drawItems = makeItemsDrawItems; -track->drawLeftLabels = makeItemsDrawLeftLabels; -track->loadItems = makeItemsLoadItems; -track->itemName = makeItemsItemName; -} -