b73fd861b426ef34c2a56da6a26a311850c276dc tdreszer Mon Jul 16 17:30:32 2012 -0700 Maybe last batch of many checkins as dictated by Jim. Formatting if and limiting lines to 100 chars. Changes (mostly) limited to lines last touched by tdreszer (git blame) so as not to ruin history. Some things not mine were 'fixed' so that my changes were in context. None of these changes should affect executables in any way. diff --git src/hg/hgTracks/imageV2.c src/hg/hgTracks/imageV2.c index 795478f..37dd252 100644 --- src/hg/hgTracks/imageV2.c +++ src/hg/hgTracks/imageV2.c @@ -1,1925 +1,1985 @@ -/* imageV2 - API for creating the image V2 features. */ +// imageV2 - API for creating the image V2 features. #include "common.h" #include "hPrint.h" #include "chromInfo.h" #include "hdb.h" #include "hui.h" #include "jsHelper.h" #include "cheapcgi.h" #include "htmshell.h" #include "imageV2.h" #include "hgTracks.h" #include "hgConfig.h" #include "regexHelper.h" struct imgBox *theImgBox = NULL; // Make this global for now to avoid huge rewrite //struct image *theOneImg = NULL; // Make this global for now to avoid huge rewrite struct imgTrack *curImgTrack = NULL; // Make this global for now to avoid huge rewrite //struct imgSlice *curSlice = NULL; // Make this global for now to avoid huge rewrite //struct mapSet *curMap = NULL; // Make this global for now to avoid huge rewrite //struct mapItem *curMapItem = NULL; // Make this global for now to avoid huge rewrite ///////////////////////// // FLAT TRACKS // A simplistic way of flattening the track list before building the image // NOTE: Strategy is NOT to use imgBox->imgTracks, since this should be independednt of imageV2 ///////////////////////// void flatTracksAdd(struct flatTracks **flatTracks,struct track *track,struct cart *cart) // Adds one track into the flatTracks list { struct flatTracks *flatTrack; AllocVar(flatTrack); flatTrack->track = track; char var[256]; // The whole reason to do this is to reorder tracks/subtracks in the image! safef(var,sizeof(var),"%s_%s",track->tdb->track,IMG_ORDER_VAR); flatTrack->order = cartUsualInt(cart, var,IMG_ANYORDER); if(flatTrack->order >= IMG_ORDERTOP) { cartRemove(cart,var); flatTrack->order = IMG_ANYORDER; } static int topOrder = IMG_ORDERTOP; // keep track of the order added to top of image static int lastOrder = IMG_ORDEREND; // keep track of the order added and beyond end if( flatTrack->order == IMG_ANYORDER) { if (track->customTrack) flatTrack->order = ++topOrder; // Custom tracks go to top else flatTrack->order = ++lastOrder; } slAddHead(flatTracks,flatTrack); } int flatTracksCmp(const void *va, const void *vb) // Compare to sort on flatTrack->order { const struct flatTracks *a = *((struct flatTracks **)va); const struct flatTracks *b = *((struct flatTracks **)vb); if (a->order == b->order) return tgCmpPriority(&(a->track),&(b->track)); return (a->order - b->order); } void flatTracksSort(struct flatTracks **flatTracks) // This routine sorts the imgTracks then forces tight ordering, so new tracks wil go to the end { // flatTracks list has 2 sets of "order": those already dragReordered (below IMG_ORDERTOP) // and those not yet reordered (above). Within those not yet dragReordered are 2 sets: // Those that begin numbering at IMG_ORDERTOP and those that begin at IMG_ORDEREND. // This routine must determine if there are any already dragOrdered, and if so, position the // newcomers in place. Newly appearing customTracks will appear at top, while newly appearing // standard tracks appear at the end of the image. int haveBeenOrderd = 0, imgOrdHighest=0; // Keep track of reordered count and position int notYetOrdered = 0, toBeTopHighest=0; // Keep track of those to be reordered, and top ordered // First determine what if anything needs to be rearranged. struct flatTracks *oneTrack = *flatTracks; for(;oneTrack!=NULL;oneTrack = oneTrack->next) { if (oneTrack->order <= IMG_ORDERTOP) { haveBeenOrderd++; if (imgOrdHighest < oneTrack->order ) imgOrdHighest = oneTrack->order; } else { notYetOrdered++; if (oneTrack->order <= IMG_ORDEREND) // && oneTrack->order >= IMG_ORDERTOP { if (toBeTopHighest < oneTrack->order ) toBeTopHighest = oneTrack->order; } } } // If some have previously been dragOrdered AND some new ones need to be given an explicit order if (haveBeenOrderd > 0 && notYetOrdered > 0) { char var[256]; int gapOnTopNeeded = 0; if (toBeTopHighest > 0) { gapOnTopNeeded = toBeTopHighest - IMG_ORDERTOP; imgOrdHighest += gapOnTopNeeded; // Will be after this loop - // Warning: Will need to throw away ALL previous orderings (even those not currently in image)! + // Warning: Will need to throw away ALL previous orderings + // (even those not currently in image)! safef(var,sizeof(var),"*_%s",IMG_ORDER_VAR); cartRemoveLike(cart, var); } - int gapFromOrderedToEnd = (IMG_ORDEREND - imgOrdHighest); // This difference should be removed from any with IMG_ORDEREND + // This difference should be removed from any with IMG_ORDEREND + int gapFromOrderedToEnd = (IMG_ORDEREND - imgOrdHighest); for(oneTrack = *flatTracks;oneTrack!=NULL;oneTrack = oneTrack->next) { if (oneTrack->order <= IMG_FIXEDPOS) ; // Untouchables else if (oneTrack->order <= IMG_ORDERTOP && gapOnTopNeeded > 0) { // Already order tracks will need to be pushed down. oneTrack->order += gapOnTopNeeded; safef(var,sizeof(var),"%s_%s",oneTrack->track->track,IMG_ORDER_VAR); cartSetInt(cart, var, oneTrack->order); } else if (oneTrack->order >= IMG_ORDERTOP && oneTrack->order < IMG_ORDEREND && gapOnTopNeeded > 0) { // Unordered custom tracks will need to be added to top! oneTrack->order -= IMG_ORDERTOP; // Force to top safef(var,sizeof(var),"%s_%s",oneTrack->track->track,IMG_ORDER_VAR); cartSetInt(cart, var, oneTrack->order); } else if (oneTrack->order >= IMG_ORDEREND && gapFromOrderedToEnd) { // Normal unordered tracks can fill in the trailing numbers oneTrack->order -= gapFromOrderedToEnd; safef(var,sizeof(var),"%s_%s",oneTrack->track->track,IMG_ORDER_VAR); cartSetInt(cart, var, oneTrack->order); } } } if (flatTracks && *flatTracks) slSort(flatTracks, flatTracksCmp); } void flatTracksFree(struct flatTracks **flatTracks) // Frees all memory used to support flatTracks (underlying tracks are untouched) { if(flatTracks && *flatTracks) { struct flatTracks *flatTrack; while((flatTrack = slPopHead(flatTracks)) != NULL) freeMem(flatTrack); } } // TODO: Move to trackDb.h and trackDbCustom.c -enum kindOfParent { +enum kindOfParent + { kopChildless = 0, kopFolder = 1, kopComposite = 2, kopMultiTrack = 3, kopCompositeView = 4 }; -enum kindOfChild { +enum kindOfChild + { kocOrphan = 0, kocFolderContent = 1, kocCompositeChild = 2, kocMultiTrackChild = 3 }; enum kindOfParent tdbKindOfParent(struct trackDb *tdb) { enum kindOfParent kindOfParent = kopChildless; if (tdbIsFolder(tdb)) kindOfParent = kopFolder; else if (tdbIsComposite(tdb)) kindOfParent = kopComposite; else if (tdbIsMultiTrack(tdb)) kindOfParent = kopMultiTrack; else if (tdbIsCompositeView(tdb)) // NOTE: This should not be needed in js kindOfParent = kopCompositeView; 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; } ///////////////////////// // 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)); jsonObjectAdd(settings, "ruler", (struct jsonElement *) ele); } 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)); // Tell something about the parent and/or children if (kindOfChild != kocOrphan) { - struct trackDb *parentTdb = (kindOfChild == kocFolderContent ? track->tdb->parent :tdbGetContainer(track->tdb)); - + 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, but pack is an option - track->canPack = rTdbTreeCanPack(parentTdb); + jsonObjectAdd(ele, "shouldPack", newJsonNumber(0)); // default vis is full, + track->canPack = rTdbTreeCanPack(parentTdb); // but pack is an option } } // XXXX really s/d be numChildren jsonObjectAdd(ele, "hasChildren", newJsonNumber(slCount(track->tdb->subtracks))); // Configuring? int cfgByPopup = configurableByAjax(track->tdb,0); if (!configurable || track->hasUi == FALSE || cfgByPopup == cfgNone) jsonObjectAdd(ele, "configureBy", newJsonString("none")); else if (cfgByPopup < 0) // denied via ajax, but allowed via full normal hgTrackUi page jsonObjectAdd(ele, "configureBy", newJsonString("clickThrough")); else jsonObjectAdd(ele, "configureBy", newJsonString("popup")); // Remote access by URL? if (sameWord(track->tdb->type, "remote") && trackDbSetting(track->tdb, "url") != NULL) jsonObjectAdd(ele, "url", newJsonString(trackDbSetting(track->tdb, "url"))); // Close with some standard vars jsonObjectAdd(ele, "shortLabel", newJsonString(track->shortLabel)); jsonObjectAdd(ele, "longLabel", newJsonString(track->longLabel)); jsonObjectAdd(ele, "canPack", newJsonNumber(track->canPack)); if(track->limitedVis != track->visibility) jsonObjectAdd(ele, "limitedVis", newJsonNumber(track->limitedVis)); jsonObjectAdd(ele, "visibility", newJsonNumber(track->visibility)); } void jsonTdbSettingsUse(struct jsonElement *settings) { // add the settings to the hgTracks output object jsonObjectAdd(jsonForClient, "trackDb", (struct jsonElement *) settings); } ///////////////////////// // IMAGEv2 // The new way to do images: PLEASE REFER TO imageV2.h FOR A DETAILED DESCRIPTION ///////////////////////// /////////////////////// Maps struct mapSet *mapSetStart(char *name,struct image *img,char *linkRoot) -/* Starts a map (aka mapSet) which is the seet of links and image locations used in HTML. - Complete a map by adding items with mapItemAdd() */ +// Starts a map (aka mapSet) which is the seet of links and image locations used in HTML. +// Complete a map by adding items with mapItemAdd() { struct mapSet *map; AllocVar(map); return mapSetUpdate(map,name,img,linkRoot); } struct mapSet *mapSetUpdate(struct mapSet *map,char *name,struct image *img,char *linkRoot) -/* Updates an existing map (aka mapSet) */ +// Updates an existing map (aka mapSet) { if(name != NULL && differentStringNullOk(name,map->name)) { if(map->name != NULL) freeMem(map->name); map->name = cloneString(name); } if(img != NULL && img != map->parentImg) map->parentImg = img; if(linkRoot != NULL && differentStringNullOk(linkRoot,map->linkRoot)) { if(map->linkRoot != NULL) freeMem(map->linkRoot); map->linkRoot = cloneString(linkRoot); } return map; } -struct mapItem *mapSetItemFind(struct mapSet *map,int topLeftX,int topLeftY,int bottomRightX,int bottomRightY) -/* Find a single mapItem based upon coordinates (within a pixel) */ +struct mapItem *mapSetItemFind(struct mapSet *map,int topLeftX,int topLeftY, + int bottomRightX,int bottomRightY) +// Find a single mapItem based upon coordinates (within a pixel) { struct mapItem *item; for(item=map->items;item!=NULL;item=item->next) { if((abs(item->topLeftX - topLeftX) < 2) && (abs(item->topLeftY - topLeftY) < 2) && (abs(item->bottomRightX - bottomRightX) < 2) && (abs(item->bottomRightY - bottomRightY) < 2)) // coordinates within a pixel is okay return item; } return NULL; } -struct mapItem *mapSetItemUpdate(struct mapSet *map,struct mapItem *item,char *link,char *title,int topLeftX,int topLeftY,int bottomRightX,int bottomRightY,char *id) -/* Update a single mapItem */ +struct mapItem *mapSetItemUpdate(struct mapSet *map,struct mapItem *item,char *link,char *title, + int topLeftX,int topLeftY,int bottomRightX,int bottomRightY, + char *id) +// Update a single mapItem { if(title != NULL) item->title = cloneString(title); if(link != NULL) { if(map->linkRoot != NULL && startsWith(map->linkRoot,link)) item->linkVar = cloneString(link + strlen(map->linkRoot)); else item->linkVar = cloneString(link); } item->topLeftX = topLeftX; item->topLeftY = topLeftY; item->bottomRightX = bottomRightX; item->bottomRightY = bottomRightY; freeMem(item->id); item->id = cloneString(id); return item; } -struct mapItem *mapSetItemAdd(struct mapSet *map,char *link,char *title,int topLeftX,int topLeftY,int bottomRightX,int bottomRightY, char *id) -/* Add a single mapItem to a growing mapSet */ +struct mapItem *mapSetItemAdd(struct mapSet *map,char *link,char *title,int topLeftX,int topLeftY, + int bottomRightX,int bottomRightY, char *id) +// Add a single mapItem to a growing mapSet { struct mapItem *item; AllocVar(item); if(title != NULL) item->title = cloneString(title); if(link != NULL) { if(map->linkRoot != NULL && startsWith(map->linkRoot,link)) item->linkVar = cloneString(link + strlen(map->linkRoot)); else item->linkVar = cloneString(link); } item->topLeftX = topLeftX; item->topLeftY = topLeftY; item->bottomRightX = bottomRightX; item->bottomRightY = bottomRightY; item->id = cloneString(id); slAddHead(&(map->items),item); //warn("Added map(%s) item '%s' count:%d",map->name,title,slCount(map->items)); return map->items; } -struct mapItem *mapSetItemUpdateOrAdd(struct mapSet *map,char *link,char *title,int topLeftX,int topLeftY,int bottomRightX,int bottomRightY, char *id) -/* Update or add a single mapItem */ +struct mapItem *mapSetItemUpdateOrAdd(struct mapSet *map,char *link,char *title, + int topLeftX,int topLeftY,int bottomRightX,int bottomRightY, + char *id) +// Update or add a single mapItem { struct mapItem *item = mapSetItemFind(map,topLeftX,topLeftY,bottomRightX,bottomRightY); if(item != NULL) return mapSetItemUpdate(map,item,link,title,topLeftX,topLeftY,bottomRightX,bottomRightY, id); else return mapSetItemAdd(map,link,title,topLeftX,topLeftY,bottomRightX,bottomRightY, id); } -struct mapItem *mapSetItemFindOrAdd(struct mapSet *map,char *link,char *title,int topLeftX,int topLeftY,int bottomRightX,int bottomRightY, char *id) -/* Finds or adds the map item */ +struct mapItem *mapSetItemFindOrAdd(struct mapSet *map,char *link,char *title, + int topLeftX,int topLeftY,int bottomRightX,int bottomRightY, + char *id) +// Finds or adds the map item { struct mapItem *item = mapSetItemFind(map,topLeftX,topLeftY,bottomRightX,bottomRightY); if(item != NULL) return item; else return mapSetItemAdd(map,link,title,topLeftX,topLeftY,bottomRightX,bottomRightY,id); } void mapItemFree(struct mapItem **pItem) -/* frees all memory assocated with a single mapItem */ +// frees all memory assocated with a single mapItem { if(pItem != NULL && *pItem != NULL) { struct mapItem *item = *pItem; if(item->title != NULL) freeMem(item->title); if(item->linkVar != NULL) freeMem(item->linkVar); if(item->id != NULL) freeMem(item->id); freeMem(item); *pItem = NULL; } } boolean mapItemConsistentWithImage(struct mapItem *item,struct image *img,boolean verbose) -/* Test whether a map item is consistent with the image it is supposed to be for */ +// Test whether a map item is consistent with the image it is supposed to be for { if ((item->topLeftX < 0 || item->topLeftX >= img->width) -|| (item->bottomRightX < 0 || item->bottomRightX > img->width || item->bottomRightX < item->topLeftX) +|| (item->bottomRightX < 0 || item->bottomRightX > img->width + || item->bottomRightX < item->topLeftX) || (item->topLeftY < 0 || item->topLeftY >= img->height) -|| (item->bottomRightY < 0 || item->bottomRightY > img->height || item->bottomRightY < item->topLeftY)) +|| (item->bottomRightY < 0 || item->bottomRightY > img->height + || item->bottomRightY < item->topLeftY)) { if (verbose) - warn("mapItem has coordinates (topX:%d topY:%d botX:%d botY:%d) outside of image (width:%d height:%d)", - item->topLeftX,item->topLeftY,item->bottomRightX,item->bottomRightY,img->width,img->height); + warn("mapItem has coordinates (topX:%d topY:%d botX:%d botY:%d) outside of image " + "(width:%d height:%d)",item->topLeftX,item->topLeftY,item->bottomRightX, + item->bottomRightY,img->width,img->height); return FALSE; } return TRUE; } static struct dyString *addIndent(struct dyString **dy,int indent) -/* beginning indent for show functions */ +// beginning indent for show functions { struct dyString *myDy = (dy?*dy:NULL); if(dy == NULL || *dy == NULL) myDy = newDyString(256); else dyStringAppend(myDy,"
"); dyStringAppend(myDy,""); int times = indent; for(;times>0;times--) dyStringAppend(myDy," "); return myDy; } static void mapItemShow(struct dyString **dy,struct mapItem *item,int indent) -/* show the map item */ +// show the map item { if(item) { struct dyString *myDy = addIndent(dy,indent); dyStringPrintf(myDy,"mapItem: title:%s topX:%d topY:%d botX:%d botY:%d", (item->title?item->title:""), item->topLeftX,item->topLeftY,item->bottomRightX,item->bottomRightY); addIndent(&myDy,indent); dyStringPrintf(myDy,"  linkVar:%s", (item->linkVar?item->linkVar:"")); if(dy == NULL) warn("%s",dyStringCannibalize(&myDy)); else *dy = myDy; } } static void mapShow(struct dyString **dy,struct mapSet *map,int indent) -/* show the map */ +// show the map { if(map && map->items) // No map items then why bother? { struct dyString *myDy = addIndent(dy,indent); dyStringPrintf(myDy,"map: name:%s",(map->name?map->name:"")); if(map->linkRoot) dyStringPrintf(myDy," linkRoot:%s",map->linkRoot); if(dy == NULL) warn("%s",dyStringCannibalize(&myDy)); indent++; struct mapItem *item = map->items; for (;item != NULL; item = item->next) mapItemShow(dy,item,indent); if(dy != NULL) *dy = myDy; } } boolean mapSetIsComplete(struct mapSet *map,boolean verbose) -/* Tests the completeness and consistency of this map (mapSet) */ +// Tests the completeness and consistency of this map (mapSet) { if (map == NULL) { if (verbose) warn("map is NULL"); return FALSE; } if (map->parentImg == NULL) { if (verbose) warn("map is missing a parant image."); return FALSE; } if (map->parentImg->file == NULL) { if (verbose) warn("map has image which has no file."); return FALSE; } if (map->items == NULL) // This is okay { //if (verbose) // warn("map(%s) has no items.",(map->name?map->name:map->parentImg->file)); //return FALSE; return TRUE; // Accept this as legitimate } struct mapItem *item = map->items; for (;item != NULL; item = item->next) { if(!mapItemConsistentWithImage(item,map->parentImg,verbose)) return FALSE; if(item->linkVar == NULL && map->linkRoot == NULL) { if (verbose) warn("item for map(%s) has no link.",(map->name?map->name:map->parentImg->file)); return FALSE; } } return TRUE; } void mapSetFree(struct mapSet **pMap) -/* frees all memory (including items) assocated with a single mapSet */ +// frees all memory (including items) assocated with a single mapSet { if(pMap != NULL && *pMap != NULL) { struct mapSet *map = *pMap; struct mapItem *item = NULL; while((item = slPopHead(&(map->items))) != NULL ) mapItemFree(&item); freeMem(map->name); // Don't free parentImg, as it should be freed independently freeMem(map->linkRoot); freeMem(map); *pMap = NULL; } } /////////////////////// Images struct image *imgCreate(char *gif,char *title,int width,int height) -/* Creates a single image container. - A map map be added with imgMapStart(),mapSetItemAdd() */ +// Creates a single image container. +// A map map be added with imgMapStart(),mapSetItemAdd() { struct image *img; AllocVar(img); if(gif != NULL) img->file = cloneString(gif); if(title != NULL) img->title = cloneString(title); img->height = height; img->width = width; img->map = NULL; return img; } struct mapSet *imgMapStart(struct image *img,char *name,char *linkRoot) -/* Starts a map associated with an image. Map items can then be added to the returned pointer with mapSetItemAdd() */ +// Starts a map associated with an image +// Map items can then be added to the returned pointer with mapSetItemAdd() { if(img->map != NULL) { warn("imgAddMap() but map already exists. Being replaced."); mapSetFree(&(img->map)); } img->map = mapSetStart(name,img,linkRoot); return img->map; } struct mapSet *imgGetMap(struct image *img) -/* Gets the map associated with this image. Map items can then be added to the map with mapSetItemAdd() */ +// Gets the map associated with this image. +// Map items can then be added to the map with mapSetItemAdd() { return img->map; } static void imgShow(struct dyString **dy,struct image *img,char *prefix,int indent) -/* show the img */ +// show the img { if(img) { struct dyString *myDy = addIndent(dy,indent); dyStringPrintf(myDy,"%simg: title:%s file:%s width:%d height:%d",(prefix?prefix:""), - (img->title?img->title:""),(img->file?img->file:""),img->width,img->height); + (img->title ? img->title : ""), + (img->file ? img->file : ""),img->width,img->height); indent++; mapShow(&myDy,img->map,indent); if(dy == NULL) warn("%s",dyStringCannibalize(&myDy)); else *dy = myDy; } } void imgFree(struct image **pImg) -/* frees all memory assocated with an image (including a map) */ +// frees all memory assocated with an image (including a map) { if(pImg != NULL && *pImg != NULL) { struct image *img = *pImg; mapSetFree(&(img->map)); freeMem(img->file); freeMem(img->title); freeMem(img); *pImg = NULL; } } /////////////////////// Slices -struct imgSlice *sliceCreate(enum sliceType type,struct image *img,char *title,int width,int height,int offsetX,int offsetY) -/* Creates of a slice which is a portion of an image. - A slice specific map map be added with sliceMapStart(),mapSetItemAdd() */ +struct imgSlice *sliceCreate(enum sliceType type,struct image *img,char *title, + int width,int height,int offsetX,int offsetY) +// Creates of a slice which is a portion of an image. +// A slice specific map map be added with sliceMapStart(),mapSetItemAdd() { if (height <= 0 || width <= 0) return NULL; struct imgSlice *slice; AllocVar(slice); slice->map = NULL; // This is the same as defaulting to slice->parentImg->map return sliceUpdate(slice,type,img,title,width,height,offsetX,offsetY); } -struct imgSlice *sliceUpdate(struct imgSlice *slice,enum sliceType type,struct image *img,char *title,int width,int height,int offsetX,int offsetY) -/* updates an already created slice */ +struct imgSlice *sliceUpdate(struct imgSlice *slice,enum sliceType type,struct image *img, + char *title,int width,int height,int offsetX,int offsetY) +// updates an already created slice { //if(width==0 || height==0) // return NULL; slice->type = type; if(img != NULL && slice->parentImg != img) slice->parentImg = img; if(title != NULL && differentStringNullOk(title,slice->title)) { if(slice->title != NULL) freeMem(slice->title); slice->title = cloneString(title); } slice->width = width; slice->height = height; slice->offsetX = offsetX; slice->offsetY = offsetY; return slice; } char *sliceTypeToString(enum sliceType type) -/* Translate enum slice type to string */ +// Translate enum slice type to string { switch(type) { case stData: return "data"; case stSide: return "side"; case stCenter: return "center"; case stButton: return "button"; default: return "unknown"; } } static char *sliceTypeToClass(enum sliceType type) -/* Translate enum slice type to the class */ +// Translate enum slice type to the class { switch (type) { case stSide: return "sideLab"; case stCenter: return "cntrLab"; case stButton: return "button"; case stData: return "dataImg"; default: return "unknown"; } } struct imgSlice *sliceAddLink(struct imgSlice *slice,char *link,char *title) -/* Adds a slice wide link. The link and map are mutually exclusive */ +// Adds a slice wide link. The link and map are mutually exclusive { if(slice->map != NULL) { warn("sliceAddLink() but slice already has its own map. Being replaced."); mapSetFree(&(slice->map)); } if(slice->link != NULL) { warn("sliceAddLink() but slice already has a link. Being replaced."); freeMem(slice->link); } slice->link = cloneString(link); if(slice->title != NULL) // OK to replace title freeMem(slice->title); slice->title = cloneString(title); return slice; } struct mapSet *sliceMapStart(struct imgSlice *slice,char *name,char *linkRoot) -/* Adds a slice specific map to a slice of an image. Map items can then be added to the returned pointer with mapSetItemAdd()*/ +// Adds a slice specific map to a slice of an image. +// Map items can then be added to the returned pointer with mapSetItemAdd() { if(slice->parentImg == NULL) { warn("sliceAddMap() but slice has no image."); return NULL; } if(slice->link != NULL) { warn("sliceAddMap() but slice already has a link. Being replaced."); freeMem(slice->link); slice->link = NULL; } if(slice->map != NULL && slice->map != slice->parentImg->map) { warn("sliceAddMap() but slice already has its own map. Being replaced."); mapSetFree(&(slice->map)); } char qualifiedName[256]; safef(qualifiedName,sizeof(qualifiedName),"%s_%s",sliceTypeToString(slice->type),name); slice->map = mapSetStart(qualifiedName,slice->parentImg,linkRoot); return slice->map; } struct mapSet *sliceGetMap(struct imgSlice *slice,boolean sliceSpecific) -/* Gets the map associate with a slice which may be sliceSpecific or it map belong to the slices' image. - Map items can then be added to the map returned with mapSetItemAdd() */ +// Gets the map associate with a slice which may be sliceSpecific or it map belong to +// the slices' image. Map items can then be added to the map returned with mapSetItemAdd() { if(!sliceSpecific && slice->map == NULL && slice->parentImg != NULL) return slice->parentImg->map; return slice->map; } struct mapSet *sliceMapFindOrStart(struct imgSlice *slice,char *name,char *linkRoot) -/* Finds the slice specific map or starts it */ +// Finds the slice specific map or starts it { if(slice==NULL) return NULL; struct mapSet *map = sliceGetMap(slice,TRUE); // Must be specific to this slice if (map == NULL) map = sliceMapStart(slice,name,linkRoot); return map; } struct mapSet *sliceMapUpdateOrStart(struct imgSlice *slice,char *name,char *linkRoot) -/* Updates the slice specific map or starts it */ +// Updates the slice specific map or starts it { struct mapSet *map = sliceGetMap(slice,TRUE); // Must be specific to this slice if (map == NULL) return sliceMapStart(slice,name,linkRoot); char qualifiedName[256]; safef(qualifiedName,sizeof(qualifiedName),"%s_%s",sliceTypeToString(slice->type),name); return mapSetUpdate(map,qualifiedName,slice->parentImg,linkRoot); } static void sliceShow(struct dyString **dy,struct imgSlice *slice,int indent) -/* show the slice */ +// show the slice { if(slice) { struct dyString *myDy = addIndent(dy,indent); dyStringPrintf(myDy,"slice(%s): title:%s width:%d height:%d offsetX:%d offsetY:%d", sliceTypeToString(slice->type),(slice->title?slice->title:""), slice->width,slice->height,slice->offsetX,slice->offsetY); if(slice->link) { addIndent(&myDy,indent); dyStringPrintf(myDy,"  link:%s",slice->link); } indent++; imgShow(&myDy,slice->parentImg,"parent ", indent); // Currently we just have the one image mapShow(&myDy,slice->map,indent); if(dy == NULL) warn("%s",dyStringCannibalize(&myDy)); else *dy = myDy; } } boolean sliceIsConsistent(struct imgSlice *slice,boolean verbose) -/* Test whether the slice and it's associated image and map are consistent with each other */ +// Test whether the slice and it's associated image and map are consistent with each other { if (slice == NULL) { if (verbose) warn("slice is NULL"); return FALSE; } if (slice->parentImg == NULL && slice->type != stButton) { if (verbose) warn("slice(%s) has no image",sliceTypeToString(slice->type)); return FALSE; } if ( slice->width == 0 || (slice->parentImg && slice->width > slice->parentImg->width)) { if (verbose) warn("slice(%s) has an invalid width %d (image width %d)", sliceTypeToString(slice->type),slice->width,slice->parentImg->width); return FALSE; } if (slice->height == 0) // FIXME: This may be a temporary solution to empty data slices { if (verbose) warn("slice(%s) has an invalid height %d (image height %d)", sliceTypeToString(slice->type),slice->height,slice->parentImg->height); return FALSE; //return TRUE; // This may be valid (but is sloppy) when there is no data for the slice. } if (slice->parentImg && slice->height > slice->parentImg->height) { if (verbose) warn("slice(%s) has an invalid height %d (image height %d)", sliceTypeToString(slice->type),slice->height,slice->parentImg->height); return FALSE; } if ( slice->parentImg && (slice->offsetX >= slice->parentImg->width || slice->offsetY >= slice->parentImg->height)) { if (verbose) warn("slice(%s) has an invalid X:%d or Y:%d offset (image width:%d height:%d)", sliceTypeToString(slice->type),slice->offsetX,slice->offsetY, slice->parentImg->width,slice->parentImg->height); return FALSE; } if (slice->link != NULL && slice->map != NULL) { warn("slice(%s) has both link and map of links",sliceTypeToString(slice->type)); return FALSE; } if (slice->map != NULL) { //if(slice->map->items == NULL) // mapSetFree(&slice->map); // An empty map is ok but should be removed. //else if(!mapSetIsComplete(slice->map,verbose)) { warn("slice(%s) has bad map",sliceTypeToString(slice->type)); return FALSE; } struct mapItem *item = slice->map->items; for (;item != NULL; item = item->next) { if(!mapItemConsistentWithImage(item,slice->parentImg,verbose)) { warn("slice(%s) map is inconsistent with slice image",sliceTypeToString(slice->type)); return FALSE; } } } return TRUE; } void sliceFree(struct imgSlice **pSlice) -/* frees all memory assocated with a slice (not including the image or a map belonging to the image) */ +// frees all memory assocated with a slice +// (not including the image or a map belonging to the image) { if(pSlice != NULL && *pSlice != NULL) { struct imgSlice *slice = *pSlice; // Don't free parentImg: remember that a slice is a portion of an image struct mapSet *map = sliceGetMap(slice,TRUE);// Only one that belongs to slice, not image if(map != NULL) mapSetFree(&map); freeMem(slice->title); freeMem(slice->link); freeMem(slice); *pSlice = NULL; } } /////////////////////// imgTracks -struct imgTrack *imgTrackStart(struct trackDb *tdb,char *name,char *db,char *chrom,int chromStart,int chromEnd,boolean plusStrand,boolean hasCenterLabel,enum trackVisibility vis,int order) -/* Starts an image track which will contain all image slices needed to render one track - Must completed by adding slices with imgTrackAddSlice() */ +struct imgTrack *imgTrackStart(struct trackDb *tdb,char *name,char *db, + char *chrom,int chromStart,int chromEnd,boolean plusStrand, + boolean hasCenterLabel,enum trackVisibility vis,int order) +// Starts an image track which will contain all image slices needed to render one track +// Must completed by adding slices with imgTrackAddSlice() { struct imgTrack *imgTrack; // gifTn.forHtml, pixWidth, mapName AllocVar(imgTrack); imgTrack->centerLabelSeen = clAlways; -return imgTrackUpdate(imgTrack,tdb,name,db,chrom,chromStart,chromEnd,plusStrand,hasCenterLabel,vis,order); +return imgTrackUpdate(imgTrack,tdb,name,db,chrom,chromStart,chromEnd,plusStrand, + hasCenterLabel,vis,order); } -struct imgTrack *imgTrackUpdate(struct imgTrack *imgTrack,struct trackDb *tdb,char *name,char *db,char *chrom,int chromStart,int chromEnd,boolean plusStrand,boolean hasCenterLabel,enum trackVisibility vis,int order) -/* Updates an already existing image track */ +struct imgTrack *imgTrackUpdate(struct imgTrack *imgTrack,struct trackDb *tdb,char *name, + char *db,char *chrom,int chromStart,int chromEnd,boolean plusStrand, + boolean hasCenterLabel,enum trackVisibility vis,int order) +// Updates an already existing image track { if(tdb != NULL && tdb != imgTrack->tdb) imgTrack->tdb = tdb; if(name != NULL && differentStringNullOk(imgTrack->name,name)) { if(imgTrack->name != NULL) freeMem(imgTrack->name); imgTrack->name = cloneString(name); } if(db != NULL && db != imgTrack->db) imgTrack->db = db; // NOTE: Not allocated if(chrom != NULL && chrom != imgTrack->chrom) imgTrack->chrom = chrom; // NOTE: Not allocated imgTrack->chromStart = chromStart; imgTrack->chromEnd = chromEnd; imgTrack->plusStrand = plusStrand; imgTrack->hasCenterLabel = hasCenterLabel; imgTrack->vis = vis; static int lastOrder = IMG_ORDEREND; // keep track of the order these images get added if(order == IMG_FIXEDPOS) { imgTrack->reorderable = FALSE; if(name != NULL && sameString(RULER_TRACK_NAME,name)) imgTrack->order = 0; else imgTrack->order = 9999; } else { imgTrack->reorderable = TRUE; if(order == IMG_ANYORDER) { if(imgTrack->order <= 0) imgTrack->order = ++lastOrder; } else if(imgTrack->order != order) imgTrack->order = order; } return imgTrack; } void imgTrackMarkForAjaxRetrieval(struct imgTrack *imgTrack,boolean ajaxRetrieval) -/* Updates the imgTrack to trigger an ajax callback from the html client to get this track */ +// Updates the imgTrack to trigger an ajax callback from the html client to get this track { imgTrack->ajaxRetrieval = ajaxRetrieval; } int imgTrackOrderCmp(const void *va, const void *vb) -/* Compare to sort on imgTrack->order */ +// Compare to sort on imgTrack->order { const struct imgTrack *a = *((struct imgTrack **)va); const struct imgTrack *b = *((struct imgTrack **)vb); return (a->order - b->order); } -struct imgSlice *imgTrackSliceAdd(struct imgTrack *imgTrack,enum sliceType type, struct image *img,char *title,int width,int height,int offsetX,int offsetY) -/* Adds slices to an image track. Expected are types: stData, stButton, stSide and stCenter */ +struct imgSlice *imgTrackSliceAdd(struct imgTrack *imgTrack,enum sliceType type, struct image *img, + char *title,int width,int height,int offsetX,int offsetY) +// Adds slices to an image track. Expected are types: stData, stButton, stSide and stCenter { struct imgSlice *slice = sliceCreate(type,img,title,width,height,offsetX,offsetY); if(slice) slAddHead(&(imgTrack->slices),slice); return imgTrack->slices; //slAddTail(&(imgTrack->slices),slice); //return slice; } struct imgSlice *imgTrackSliceGetByType(struct imgTrack *imgTrack,enum sliceType type) -/* Gets a specific slice already added to an image track. Expected are types: stData, stButton, stSide and stCenter */ +// Gets a specific slice already added to an image track. +// Expected are types: stData, stButton, stSide and stCenter { struct imgSlice *slice; for(slice = imgTrack->slices;slice != NULL;slice=slice->next) { if(slice->type == type) return slice; } return NULL; } -struct imgSlice *imgTrackSliceFindOrAdd(struct imgTrack *imgTrack,enum sliceType type, struct image *img,char *title,int width,int height,int offsetX,int offsetY) -/* Find the slice or adds it */ +struct imgSlice *imgTrackSliceFindOrAdd(struct imgTrack *imgTrack,enum sliceType type, + struct image *img,char *title,int width,int height, + int offsetX,int offsetY) +// Find the slice or adds it { struct imgSlice *slice = imgTrackSliceGetByType(imgTrack,type); if (slice == NULL) slice = imgTrackSliceAdd(imgTrack,type,img,title,width,height,offsetX,offsetY); return slice; } -struct imgSlice *imgTrackSliceUpdateOrAdd(struct imgTrack *imgTrack,enum sliceType type, struct image *img,char *title,int width,int height,int offsetX,int offsetY) -/* Updates the slice or adds it */ +struct imgSlice *imgTrackSliceUpdateOrAdd(struct imgTrack *imgTrack,enum sliceType type, + struct image *img,char *title,int width,int height, + int offsetX,int offsetY) +// Updates the slice or adds it { struct imgSlice *slice = imgTrackSliceGetByType(imgTrack,type); if (slice == NULL) return imgTrackSliceAdd(imgTrack,type,img,title,width,height,offsetX,offsetY); return sliceUpdate(slice,type,img,title,width,height,offsetX,offsetY); } struct mapSet *imgTrackGetMapByType(struct imgTrack *imgTrack,enum sliceType type) -/* Gets the map assocated with a specific slice belonging to the imgTrack */ +// Gets the map assocated with a specific slice belonging to the imgTrack { struct imgSlice *slice = imgTrackSliceGetByType(imgTrack,type); if(slice == NULL) return NULL; return sliceGetMap(slice,FALSE); // Map could belong to image or could be slice specific } -int imgTrackAddMapItem(struct imgTrack *imgTrack,char *link,char *title,int topLeftX,int topLeftY,int bottomRightX,int bottomRightY, char *id) -/* Will add a map item to an imgTrack's appropriate slice's map. Since a map item may span - * slices, the imgTrack is in the best position to determine where to put the map item - * returns count of map items added, which could be 0, 1 or more than one if item spans slices - * NOTE: Precedence is given to first map item when adding items with same coordinates! */ +int imgTrackAddMapItem(struct imgTrack *imgTrack,char *link,char *title, + int topLeftX,int topLeftY,int bottomRightX,int bottomRightY, char *id) +// Will add a map item to an imgTrack's appropriate slice's map. Since a map item may span +// slices, the imgTrack is in the best position to determine where to put the map item +// returns count of map items added, which could be 0, 1 or more than one if item spans slices +// NOTE: Precedence is given to first map item when adding items with same coordinates! { struct imgSlice *slice; char *imgFile = NULL; // name of file that hold the image char *neededId = NULL; // id is only added it it is NOT the trackId. if (imgTrack->tdb == NULL || differentStringNullOk(id, imgTrack->tdb->track)) neededId = id; int count = 0; for(slice = imgTrack->slices;slice != NULL;slice=slice->next) { if(slice->type == stButton) // Buttons don't have maps. Overlap will be ignored! continue; if(slice->parentImg != NULL) { if(imgFile == NULL) imgFile = slice->parentImg->file; - //else if(differentString(imgFile,slice->parentImg->file)) - // { - // char * name = (imgTrack->name != NULL ? imgTrack->name : imgTrack->tdb != NULL ? imgTrack->tdb->track : imgFile); - // warn("imgTrackAddMapItem(%s) called, but not all slice images are the same for this track.",name); - // } - // Not a valid warning! Side image and data image may be different!!! } if(topLeftX < (slice->offsetX + slice->width-1) && bottomRightX > (slice->offsetX + 1) && topLeftY < (slice->offsetY + slice->height-1) && bottomRightY > (slice->offsetY + 1)) // Overlap of a pixel or 2 is tolerated { struct mapSet *map = sliceGetMap(slice,FALSE); if(map!=NULL) - { // NOTE: using find or add gives precedence to first of same coordinate map items added - mapSetItemFindOrAdd(map,link,title,max(topLeftX,slice->offsetX),max(topLeftY,slice->offsetY),min(bottomRightX,slice->offsetX + slice->width),min(bottomRightY,slice->offsetY + slice->height), neededId); + { // NOTE: using find or add gives precedence to first of same coordinate map items + mapSetItemFindOrAdd(map,link,title,max(topLeftX,slice->offsetX), + max(topLeftY,slice->offsetY), + min(bottomRightX,slice->offsetX + slice->width), + min(bottomRightY,slice->offsetY + slice->height), neededId); count++; } else - { // FIXME: This is assuming that if there is no map then the entire slice should get the link! - char * name = (imgTrack->name != NULL ? imgTrack->name : imgTrack->tdb != NULL ? imgTrack->tdb->track : imgFile); - warn("imgTrackAddMapItem(%s,%s) mapItem(lx:%d,rx:%d) is overlapping slice:%s(lx:%d,rx:%d)",name,title,topLeftX,bottomRightX, + { // NOTE: This assumes that if there is no map then the entire slice should get the link! + char * name = (imgTrack->name != NULL ? imgTrack->name + : imgTrack->tdb != NULL ? imgTrack->tdb->track + : imgFile); + warn("imgTrackAddMapItem(%s,%s) mapItem(lx:%d,rx:%d) is overlapping " + "slice:%s(lx:%d,rx:%d)",name,title,topLeftX,bottomRightX, sliceTypeToString(slice->type),slice->offsetX,(slice->offsetX + slice->width - 1)); sliceAddLink(slice,link,title); count++; } } } -//if(count>=2) -// { -// char * name = (imgTrack->name != NULL ? imgTrack->name : imgTrack->tdb != NULL ? imgTrack->tdb->track : imgFile); -// warn("imgTrackAddMapItem(%s) called for map items stretching across %d slice(s).",name,count); -// } return count; } static char *centerLabelSeenToString(enum centerLabelSeen seen) -/* Translate enum slice type to string */ +// Translate enum slice type to string { switch(seen) { case clAlways: return "always"; case clNowSeen:return "now"; case clNotSeen:return "notNow"; default: return "unknown"; } } static void imgTrackShow(struct dyString **dy,struct imgTrack *imgTrack,int indent) -/* show the imgTrack */ +// show the imgTrack { if(imgTrack) { struct dyString *myDy = addIndent(dy,indent); dyStringPrintf(myDy,"imgTrack: name:%s tdb:%s", - (imgTrack->name?imgTrack->name:""),(imgTrack->tdb && imgTrack->tdb->track?imgTrack->tdb->track:"")); + (imgTrack->name ? imgTrack->name : ""), + (imgTrack->tdb && imgTrack->tdb->track ? imgTrack->tdb->track : "")); if(imgTrack->hasCenterLabel) dyStringPrintf(myDy," centerLabel:%s",centerLabelSeenToString(imgTrack->centerLabelSeen)); if(imgTrack->reorderable) dyStringPrintf(myDy," reorderable"); if(imgTrack->ajaxRetrieval) dyStringPrintf(myDy," ajaxRetrieval"); dyStringPrintf(myDy," order:%d vis:%s",imgTrack->order,hStringFromTv(imgTrack->vis)); if(dy == NULL) warn("%s",dyStringCannibalize(&myDy)); indent++; struct imgSlice *slice = imgTrack->slices; for(; slice != NULL; slice = slice->next ) sliceShow(dy,slice,indent); if(dy != NULL) *dy = myDy; } } boolean imgTrackIsComplete(struct imgTrack *imgTrack,boolean verbose) -/* Tests the completeness and consistency of this imgTrack (including slices) */ +// Tests the completeness and consistency of this imgTrack (including slices) { if (imgTrack == NULL) { if (verbose) warn("imgTrack is NULL"); return FALSE; } if (imgTrack->tdb == NULL && imgTrack->name == NULL) { if (verbose) { warn("imgTrack has no tdb or name"); imgTrackShow(NULL,imgTrack,0); } return FALSE; } char * name = (imgTrack->name != NULL ? imgTrack->name : imgTrack->tdb->track); if (imgTrack->db == NULL) { if (verbose) { warn("imgTrack(%s) has no db.",name); imgTrackShow(NULL,imgTrack,0); } return FALSE; } if (imgTrack->db == NULL) { if (verbose) { warn("imgTrack(%s) has no chrom.",name); imgTrackShow(NULL,imgTrack,0); } return FALSE; } if (imgTrack->chromStart >= imgTrack->chromEnd) { if (verbose) { warn("imgTrack(%s) for %s.%s:%d-%d has bad genome range.",name, imgTrack->db,imgTrack->chrom,imgTrack->chromStart,imgTrack->chromEnd); imgTrackShow(NULL,imgTrack,0); } return FALSE; } if(imgTrack->slices == NULL) { if (verbose) { warn("imgTrack(%s) has no slices.",name); imgTrackShow(NULL,imgTrack,0); } return FALSE; } // Can have no more than one of each type of slice if(imgTrack->slices && imgTrack->slices->type == stData) slReverse(&imgTrack->slices); boolean found[stMaxSliceTypes] = { FALSE,FALSE,FALSE,FALSE}; struct imgSlice *slice = imgTrack->slices; for(; slice != NULL; slice = slice->next ) { if(found[slice->type]) { if (verbose) { warn("imgTrack(%s) found more than one slice of type %s.", name,sliceTypeToString(slice->type)); imgTrackShow(NULL,imgTrack,0); } return FALSE; } found[slice->type] = TRUE; if(!sliceIsConsistent(slice,verbose)) { if (verbose) { warn("imgTrack(%s) has bad slice",name); imgTrackShow(NULL,imgTrack,0); } return FALSE; } } -// This is not a requirement as the data portion could be empty (height==0) FIXME This still needs to be properly resolved //if(!found[stData]) -// { -// if (verbose) -// { -// warn("imgTrack(%s) has no DATA slice.",name); -// imgTrackShow(NULL,imgTrack,0); -// } -// return FALSE; -// } +// This is not a requirement as the data portion could be empty (height==0) return TRUE; } void imgTrackFree(struct imgTrack **pImgTrack) -/* frees all memory assocated with an imgTrack (including slices) */ +// frees all memory assocated with an imgTrack (including slices) { if(pImgTrack != NULL && *pImgTrack != NULL) { struct imgTrack *imgTrack = *pImgTrack; struct imgSlice *slice; while((slice = slPopHead(&(imgTrack->slices))) != NULL ) sliceFree(&slice); freeMem(imgTrack->name); freeMem(imgTrack); *pImgTrack = NULL; } } /////////////////////// Image Box -struct imgBox *imgBoxStart(char *db,char *chrom,int chromStart,int chromEnd,boolean plusStrand,int sideLabelWidth,int width) -/* Starts an imgBox which should contain all info needed to draw the hgTracks image with multiple tracks - The image box must be completed using imgBoxImageAdd() and imgBoxTrackAdd() */ +struct imgBox *imgBoxStart(char *db,char *chrom,int chromStart,int chromEnd,boolean plusStrand, + int sideLabelWidth,int width) +// Starts an imgBox which should contain all info needed to draw the hgTracks image with +// multiple tracks. The image box must be completed using imgBoxImageAdd() and imgBoxTrackAdd() { struct imgBox * imgBox; // gifTn.forHtml, pixWidth, mapName AllocVar(imgBox); if(db != NULL) imgBox->db = cloneString(db); // NOTE: Is allocated if(chrom != NULL) imgBox->chrom = cloneString(chrom); // NOTE: Is allocated imgBox->chromStart = chromStart; imgBox->chromEnd = chromEnd; imgBox->plusStrand = plusStrand; imgBox->showSideLabel = (sideLabelWidth != 0); imgBox->sideLabelWidth = sideLabelWidth; imgBox->images = NULL; imgBox->bgImg = NULL; imgBox->width = width; imgBox->showPortal = FALSE; //int oneThird = (chromEnd - chromStart)/3; // TODO: Currently defaulting to 1/3 of image width imgBox->portalStart = chromStart;// + oneThird; imgBox->portalEnd = chromEnd;// - oneThird; imgBox->portalWidth = chromEnd - chromStart; -imgBox->basesPerPixel = ((double)imgBox->chromEnd - imgBox->chromStart)/(imgBox->width - imgBox->sideLabelWidth); +imgBox->basesPerPixel = + ((double)imgBox->chromEnd - imgBox->chromStart)/(imgBox->width - imgBox->sideLabelWidth); return imgBox; } -boolean imgBoxPortalDefine(struct imgBox *imgBox,int *chromStart,int *chromEnd,int *imgWidth,double imageMultiple) -/* Defines the portal of the imgBox. The portal is the initial viewable region when dragScroll is being used. - the new chromStart,chromEnd and imgWidth are returned as OUTs, while the portal becomes the initial defined size - returns TRUE if successfully defined as having a portal */ +boolean imgBoxPortalDefine(struct imgBox *imgBox,int *chromStart,int *chromEnd, + int *imgWidth,double imageMultiple) +// Defines the portal of the imgBox. The portal is the initial viewable region when dragScroll +// is being used. The new chromStart,chromEnd and imgWidth are returned as OUTs, while the portal +// becomes the initial defined size. +// returns TRUE if successfully defined as having a portal { if( (int)imageMultiple == 0) imageMultiple = IMAGEv2_DRAG_SCROLL_SZ; imgBox->portalStart = imgBox->chromStart; imgBox->portalEnd = imgBox->chromEnd; imgBox->portalWidth = imgBox->width - imgBox->sideLabelWidth; imgBox->showPortal = FALSE; // Guilty until proven innocent int positionWidth = (int)((imgBox->portalEnd - imgBox->portalStart) * imageMultiple); -*chromStart = imgBox->portalStart - (int)(((imageMultiple - 1)/2) * (imgBox->portalEnd - imgBox->portalStart)); +*chromStart = imgBox->portalStart - (int)( ((imageMultiple - 1)/2) + * (imgBox->portalEnd - imgBox->portalStart)); if( *chromStart < 0) *chromStart = 0; *chromEnd = *chromStart + positionWidth; struct chromInfo *chrInfo = hGetChromInfo(imgBox->db,imgBox->chrom); if(chrInfo == NULL) { *chromStart = imgBox->chromStart; *chromEnd = imgBox->chromEnd; return FALSE; } if (*chromEnd > (int)(chrInfo->size)) // Bound by chrom length { *chromEnd = (int)(chrInfo->size); *chromStart = *chromEnd - positionWidth; if (*chromStart < 0) *chromStart = 0; } // TODO: Normalize to power of 10 boundary // Normalize portal ends int diff = *chromStart - imgBox->portalStart; if(diff < 10 && diff > -10) *chromStart = imgBox->portalStart; diff = *chromEnd - imgBox->portalEnd; if(diff < 10 && diff > -10) *chromEnd = imgBox->portalEnd; double growthOfImage = (*chromEnd - *chromStart)/(imgBox->portalEnd - imgBox->portalStart); *imgWidth = (imgBox->portalWidth * growthOfImage) + imgBox->sideLabelWidth; //if(imgBox->portalStart < *chromStart || imgBox->portalEnd > *chromEnd //|| imgBox->portalWidth > *imgWidth) // { // *imgWidth = imgBox->width; // Undo damage // *chromStart = imgBox->chromStart; // *chromEnd = imgBox->chromEnd; // return FALSE; // } imgBox->width = *imgWidth; imgBox->chromStart = *chromStart; imgBox->chromEnd = *chromEnd; -imgBox->basesPerPixel = ((double)imgBox->chromEnd - imgBox->chromStart)/(imgBox->width - imgBox->sideLabelWidth); +imgBox->basesPerPixel = + ((double)imgBox->chromEnd - imgBox->chromStart)/(imgBox->width - imgBox->sideLabelWidth); imgBox->showPortal = TRUE; -//warn("portal(%d,%d,%d)\nimage(%d,%d,%d) growth:%G",imgBox->portalStart,imgBox->portalEnd,imgBox->portalWidth, -// imgBox->chromStart,imgBox->chromEnd,(imgBox->width - imgBox->sideLabelWidth),growthOfImage); return imgBox->showPortal; } boolean imgBoxPortalRemove(struct imgBox *imgBox,int *chromStart,int *chromEnd,int *imgWidth) -/* Will redefine the imgBox as the portal dimensions and return the dimensions as OUTs. - Returns TRUE if a portal was defined in the first place */ +// Will redefine the imgBox as the portal dimensions and return the dimensions as OUTs. +// Returns TRUE if a portal was defined in the first place { if(imgBox->showPortal == FALSE) { *chromStart=imgBox->chromStart; // return to original coordinates *chromEnd =imgBox->chromEnd; *imgWidth =imgBox->width; return FALSE; } *chromStart=imgBox->chromStart=imgBox->portalStart; // return to original coordinates *chromEnd =imgBox->chromEnd =imgBox->portalEnd; *imgWidth =imgBox->width = (imgBox->portalWidth + imgBox->sideLabelWidth); imgBox->showPortal = FALSE; return TRUE; } -boolean imgBoxPortalDimensions(struct imgBox *imgBox,int *chromStart,int *chromEnd,int *imgWidth,int *sideLabelWidth,int *portalStart,int *portalEnd,int *portalWidth,double *basesPerPixel) -/* returns the imgBox portal dimensions in the OUTs returns TRUE if portal defined */ +boolean imgBoxPortalDimensions(struct imgBox *imgBox,int *chromStart,int *chromEnd, + int *imgWidth,int *sideLabelWidth, + int *portalStart,int *portalEnd,int *portalWidth, + double *basesPerPixel) +// returns the imgBox portal dimensions in the OUTs returns TRUE if portal defined { if ( chromStart ) *chromStart = imgBox->chromStart; if ( chromEnd ) *chromEnd = imgBox->chromEnd; if ( imgWidth ) *imgWidth = imgBox->width; if ( sideLabelWidth ) *sideLabelWidth = imgBox->sideLabelWidth; if(imgBox->showPortal) { if ( portalStart ) *portalStart = imgBox->portalStart; if ( portalEnd ) *portalEnd = imgBox->portalEnd; if ( portalWidth ) *portalWidth = imgBox->portalWidth + imgBox->sideLabelWidth; } else { if ( portalStart ) *portalStart = imgBox->chromStart; if ( portalEnd ) *portalEnd = imgBox->chromEnd; if ( portalWidth ) *portalWidth = imgBox->width; } if ( basesPerPixel ) *basesPerPixel = imgBox->basesPerPixel; return imgBox->showPortal; } -struct image *imgBoxImageAdd(struct imgBox *imgBox,char *gif,char *title,int width,int height,boolean backGround) -/* Adds an image to an imgBox. The image may be extended with imgMapStart(),mapSetItemAdd() */ +struct image *imgBoxImageAdd(struct imgBox *imgBox,char *gif,char *title, + int width,int height,boolean backGround) +// Adds an image to an imgBox. The image may be extended with imgMapStart(),mapSetItemAdd() { struct image *img = imgCreate(gif,title,width,height); if(backGround) { if(imgBox->bgImg != NULL) { warn("imgBoxImageAdd() for background but already exists. Being replaced."); imgFree(&(imgBox->bgImg)); } imgBox->bgImg = img; return imgBox->bgImg; } slAddHead(&(imgBox->images),img); return imgBox->images; } struct image *imgBoxImageFind(struct imgBox *imgBox,char *gif) -/* Finds a specific image already added to this imgBox */ +// Finds a specific image already added to this imgBox { struct image *img = NULL; for (img = imgBox->images; img != NULL; img = img->next ) { if (sameOk(img->file,gif)) return img; } return NULL; } // TODO: Will we need this? //boolean imgBoxImageRemove(struct imgBox *imgBox,struct image *img) //{ //return slRemoveEl(&(imgBox->images),img); //} -struct imgTrack *imgBoxTrackAdd(struct imgBox *imgBox,struct trackDb *tdb,char *name,enum trackVisibility vis,boolean hasCenterLabel,int order) -/* Adds an imgTrack to an imgBox. The imgTrack needs to be extended with imgTrackAddSlice() */ +struct imgTrack *imgBoxTrackAdd(struct imgBox *imgBox,struct trackDb *tdb,char *name, + enum trackVisibility vis,boolean hasCenterLabel,int order) +// Adds an imgTrack to an imgBox. The imgTrack needs to be extended with imgTrackAddSlice() { -struct imgTrack *imgTrack = imgTrackStart(tdb,name,imgBox->db,imgBox->chrom,imgBox->chromStart,imgBox->chromEnd,imgBox->plusStrand,hasCenterLabel,vis,order); +struct imgTrack *imgTrack = imgTrackStart(tdb,name,imgBox->db, + imgBox->chrom,imgBox->chromStart,imgBox->chromEnd, + imgBox->plusStrand,hasCenterLabel,vis,order); slAddHead(&(imgBox->imgTracks),imgTrack); return imgBox->imgTracks; } struct imgTrack *imgBoxTrackFind(struct imgBox *imgBox,struct trackDb *tdb,char *name) -/* Finds a specific imgTrack already added to this imgBox */ +// Finds a specific imgTrack already added to this imgBox { struct imgTrack *imgTrack = NULL; for (imgTrack = imgBox->imgTracks; imgTrack != NULL; imgTrack = imgTrack->next ) { if (name != NULL && sameOk(name,imgTrack->name)) return imgTrack; else if (imgTrack->tdb == tdb) return imgTrack; } return NULL; } -struct imgTrack *imgBoxTrackFindOrAdd(struct imgBox *imgBox,struct trackDb *tdb,char *name,enum trackVisibility vis,boolean hasCenterLabel,int order) -/* Find the imgTrack, or adds it if not found */ +struct imgTrack *imgBoxTrackFindOrAdd(struct imgBox *imgBox,struct trackDb *tdb,char *name, + enum trackVisibility vis,boolean hasCenterLabel,int order) +// Find the imgTrack, or adds it if not found { struct imgTrack *imgTrack = imgBoxTrackFind(imgBox,tdb,name); if( imgTrack == NULL) imgTrack = imgBoxTrackAdd(imgBox,tdb,name,vis,hasCenterLabel,order); return imgTrack; } -struct imgTrack *imgBoxTrackUpdateOrAdd(struct imgBox *imgBox,struct trackDb *tdb,char *name,enum trackVisibility vis,boolean hasCenterLabel,int order) -/* Updates the imgTrack, or adds it if not found */ +struct imgTrack *imgBoxTrackUpdateOrAdd(struct imgBox *imgBox,struct trackDb *tdb,char *name, + enum trackVisibility vis,boolean hasCenterLabel,int order) +// Updates the imgTrack, or adds it if not found { struct imgTrack *imgTrack = imgBoxTrackFind(imgBox,tdb,name); if( imgTrack == NULL) return imgBoxTrackAdd(imgBox,tdb,name,vis,hasCenterLabel,order); -return imgTrackUpdate(imgTrack,tdb,name,imgBox->db,imgBox->chrom,imgBox->chromStart,imgBox->chromEnd,imgBox->plusStrand,hasCenterLabel,vis,order); +return imgTrackUpdate(imgTrack,tdb,name,imgBox->db, + imgBox->chrom,imgBox->chromStart,imgBox->chromEnd, + imgBox->plusStrand,hasCenterLabel,vis,order); } // TODO: Will we need this? //boolean imgBoxTrackRemove(struct imgBox *imgBox,struct imgTrack *imgTrack) //{ //return slRemoveEl(&(imgBox->imgTracks),imgTrack); //} void imgBoxTracksNormalizeOrder(struct imgBox *imgBox) -/* This routine sorts the imgTracks */ +// This routine sorts the imgTracks { slSort(&(imgBox->imgTracks), imgTrackOrderCmp); } void imgBoxShow(struct dyString **dy,struct imgBox *imgBox,int indent) -/* show the imgBox */ +// show the imgBox { if(imgBox) { struct dyString *myDy = addIndent(dy,indent); - dyStringPrintf(myDy,"imgBox: %s.%s:%d-%d %c width:%d basePer:%g sideLabe:%s w:%d portal:%s %d-%d w:%d", - (imgBox->db?imgBox->db:""),(imgBox->chrom?imgBox->chrom:""), - imgBox->chromStart,imgBox->chromEnd,(imgBox->plusStrand?'+':'-'), - imgBox->width,imgBox->basesPerPixel,(imgBox->showSideLabel?"Yes":"No"),imgBox->sideLabelWidth, - (imgBox->showPortal?"Yes":"No"),imgBox->portalStart,imgBox->portalEnd,imgBox->portalWidth); + dyStringPrintf(myDy,"imgBox: %s.%s:%d-%d %c width:%d basePer:%g sideLabe:%s w:%d " + "portal:%s %d-%d w:%d",(imgBox->db ? imgBox->db : ""), + (imgBox->chrom ? imgBox->chrom : ""),imgBox->chromStart,imgBox->chromEnd, + (imgBox->plusStrand ? '+' : '-'),imgBox->width,imgBox->basesPerPixel, + (imgBox->showSideLabel ? "Yes" : "No"),imgBox->sideLabelWidth, + (imgBox->showPortal ? "Yes" : "No"), + imgBox->portalStart,imgBox->portalEnd,imgBox->portalWidth); indent++; struct image *img; for(img=imgBox->images;img!=NULL;img=img->next) imgShow(&myDy,img,"data ",indent); if(imgBox->bgImg) imgShow(&myDy,imgBox->bgImg,"bgnd ",indent); if(dy == NULL) warn("%s",dyStringCannibalize(&myDy)); struct imgTrack *imgTrack = NULL; for (imgTrack = imgBox->imgTracks; imgTrack != NULL; imgTrack = imgTrack->next ) imgTrackShow(dy,imgTrack,indent); if(dy != NULL) *dy = myDy; } } int imgBoxDropEmpties(struct imgBox *imgBox) -/* Empty imageTracks (without slices) is not an error but they should be dropped. - returns remaining current track count */ +// Empty imageTracks (without slices) is not an error but they should be dropped. +// returns remaining current track count { if (imgBox == NULL) return 0; struct imgTrack *imgTrack = imgBox->imgTracks; while(imgTrack != NULL) { if(imgTrack->slices == NULL) { slRemoveEl(&(imgBox->imgTracks),imgTrack); imgTrackFree(&imgTrack); imgTrack = imgBox->imgTracks; // start over continue; } imgTrack = imgTrack->next; } return slCount(imgBox->imgTracks); } boolean imgBoxIsComplete(struct imgBox *imgBox,boolean verbose) -/* Tests the completeness and consistency of an imgBox. */ +// Tests the completeness and consistency of an imgBox. { if (imgBox == NULL) { if (verbose) warn("No imgBox."); return FALSE; } if (imgBox->db == NULL) { if (verbose) warn("imgBox has no db."); return FALSE; } if (imgBox->db == NULL) { if (verbose) warn("imgBox has no chrom."); return FALSE; } if (imgBox->chromStart >= imgBox->chromEnd) { if (verbose) - warn("imgBox(%s.%s:%d-%d) has bad genome range.",imgBox->db,imgBox->chrom,imgBox->chromStart,imgBox->chromEnd); + warn("imgBox(%s.%s:%d-%d) has bad genome range.", + imgBox->db,imgBox->chrom,imgBox->chromStart,imgBox->chromEnd); return FALSE; } if (imgBox->portalStart >= imgBox->portalEnd || imgBox->portalStart < imgBox->chromStart || imgBox->portalEnd > imgBox->chromEnd ) { if (verbose) - warn("imgBox(%s.%s:%d-%d) has bad portal range: %d-%d",imgBox->db,imgBox->chrom,imgBox->chromStart,imgBox->chromEnd,imgBox->portalStart,imgBox->portalEnd); + warn("imgBox(%s.%s:%d-%d) has bad portal range: %d-%d", + imgBox->db,imgBox->chrom,imgBox->chromStart,imgBox->chromEnd, + imgBox->portalStart,imgBox->portalEnd); return FALSE; } // Must have images if (imgBox->images == NULL) { if (verbose) - warn("imgBox(%s.%s:%d-%d) has no images",imgBox->db,imgBox->chrom,imgBox->chromStart,imgBox->chromEnd); + warn("imgBox(%s.%s:%d-%d) has no images", + imgBox->db,imgBox->chrom,imgBox->chromStart,imgBox->chromEnd); return FALSE; } // Must have tracks if (imgBox->imgTracks == NULL) { if (verbose) - warn("imgBox(%s.%s:%d-%d) has no imgTracks",imgBox->db,imgBox->chrom,imgBox->chromStart,imgBox->chromEnd); + warn("imgBox(%s.%s:%d-%d) has no imgTracks", + imgBox->db,imgBox->chrom,imgBox->chromStart,imgBox->chromEnd); return FALSE; } struct imgTrack *imgTrack = imgBox->imgTracks; while(imgTrack != NULL) { if(!imgTrackIsComplete(imgTrack,verbose)) { if (verbose) - warn("imgBox(%s.%s:%d-%d) has bad track - being skipped.",imgBox->db,imgBox->chrom,imgBox->chromStart,imgBox->chromEnd); + warn("imgBox(%s.%s:%d-%d) has bad track - being skipped.", + imgBox->db,imgBox->chrom,imgBox->chromStart,imgBox->chromEnd); slRemoveEl(&(imgBox->imgTracks),imgTrack); imgTrackFree(&imgTrack); imgTrack = imgBox->imgTracks; // start over continue; //return FALSE; } if(differentWord(imgTrack->db, imgBox->db) || differentWord(imgTrack->chrom, imgBox->chrom) || imgTrack->chromStart != imgBox->chromStart || imgTrack->chromEnd != imgBox->chromEnd || imgTrack->plusStrand != imgBox->plusStrand) { if (verbose) warn("imgBox(%s.%s:%d-%d) has inconsistent imgTrack for %s.%s:%d-%d", imgBox->db, imgBox->chrom, imgBox->chromStart, imgBox->chromEnd, imgTrack->db,imgTrack->chrom,imgTrack->chromStart,imgTrack->chromEnd); return FALSE; } struct imgSlice *slice = NULL; for (slice = imgTrack->slices; slice != NULL; slice = slice->next ) { // Every slice that has an image must point to an image owned by the imgBox if(slice->parentImg && (slIxFromElement(imgBox->images,slice->parentImg) == -1)) { if (verbose) warn("imgBox(%s.%s:%d-%d) has slice(%s) for unknown image (%s)", imgBox->db,imgBox->chrom,imgBox->chromStart,imgBox->chromEnd, sliceTypeToString(slice->type),slice->parentImg->file); return FALSE; } } imgTrack = imgTrack->next; } return TRUE; } void imgBoxFree(struct imgBox **pImgBox) -/* frees all memory assocated with an imgBox (including images and imgTracks) */ +// frees all memory assocated with an imgBox (including images and imgTracks) { if(pImgBox != NULL && *pImgBox != NULL) { struct imgBox *imgBox = *pImgBox; struct imgTrack *imgTrack = NULL; while((imgTrack = slPopHead(&(imgBox->imgTracks))) != NULL ) imgTrackFree(&imgTrack); struct image *img = NULL; while((img = slPopHead(&(imgBox->images))) != NULL ) imgFree(&img); imgFree(&(imgBox->bgImg)); freeMem(imgBox->db); freeMem(imgBox->chrom); freeMem(imgBox); *pImgBox = NULL; } } /////////////////////// imageV2 UI API static boolean imageMapDraw(struct mapSet *map,char *name) -/* writes an image map as HTML */ +// writes an image map as HTML { -//warn("Drawing map_%s %s",name,(map == NULL?"map is NULL":map->items == NULL?"map->items is NULL":"Should draw!")); if(map == NULL || map->items == NULL) return FALSE; -slReverse(&(map->items)); // These must be reversed so that they are printed in the same order as created! - +slReverse(&(map->items)); // These must be reversed so that they are + // printed in the same order as created! hPrintf(" ", name); // map_ prefix is implicit struct mapItem *item = map->items; for(;item!=NULL;item=item->next) { hPrintf("\n topLeftX, item->topLeftY, item->bottomRightX, item->bottomRightY); // TODO: remove static portion of the link and handle in js if (sameString(TITLE_BUT_NO_LINK,item->linkVar)) { // map items could be for mouse-over titles only hPrintf(" class='area %s'",TITLE_BUT_NO_LINK); } else if(map->linkRoot != NULL) { if(skipToSpaces(item->linkVar)) hPrintf(" HREF=%s%s",map->linkRoot,(item->linkVar != NULL?item->linkVar:"")); else hPrintf(" HREF='%s%s'",map->linkRoot,(item->linkVar != NULL?item->linkVar:"")); hPrintf(" class='area'"); } else if(item->linkVar != NULL) { if(skipToSpaces(item->linkVar)) hPrintf(" HREF=%s",item->linkVar); else if(startsWith("/cgi-bin/hgGene", item->linkVar)) // redmine #4151 - hPrintf(" HREF='..%s'",item->linkVar); // FIXME: Chin should get rid of this special case! - else + hPrintf(" HREF='..%s'",item->linkVar); // FIXME: Chin should get rid + else // of this special case! hPrintf(" HREF='%s'",item->linkVar); hPrintf(" class='area'"); } else warn("map item has no url!"); if(item->title != NULL && strlen(item->title) > 0) hPrintf(" TITLE='%s'", attributeEncode(item->title) ); if(item->id != NULL) hPrintf(" id='%s'", item->id); hPrintf(">" ); } hPrintf("\n"); return TRUE; } -static void imageDraw(struct imgBox *imgBox,struct imgTrack *imgTrack,struct imgSlice *slice,char *name,int offsetX,int offsetY,boolean useMap) -/* writes an image as HTML */ +static void imageDraw(struct imgBox *imgBox,struct imgTrack *imgTrack,struct imgSlice *slice, + char *name,int offsetX,int offsetY,boolean useMap) +// writes an image as HTML { if(slice->parentImg && slice->parentImg->file != NULL) { hPrintf(" parentImg->file,offsetX,offsetY); // Problem: dragScroll beyond left shows ugly leftLabel! // Tried clip:rect() but this only works with position:absolute! // May need to split image betweeen side label and data!!! That is a big change. if(useMap) hPrintf(" usemap='#map_%s'",name); hPrintf(" class='sliceImg %s",sliceTypeToClass(slice->type)); if(slice->type==stData && imgBox->showPortal) hPrintf(" panImg'"); else hPrintf("'"); if(slice->title != NULL) hPrintf(" title='%s'", attributeEncode(slice->title) ); // Adds slice wide title else if(slice->parentImg->title != NULL) hPrintf("' title='%s'", attributeEncode(slice->parentImg->title) );// Adds image wide title if(slice->type==stData || slice->type==stCenter) hPrintf(" ondrag='{return false;}'"); hPrintf(">"); } else { int height = slice->height; // Adjustment for centerLabel Conditional if (imgTrack->centerLabelSeen == clNotSeen && (slice->type == stSide || slice->type == stButton)) { struct imgSlice *centerSlice = imgTrackSliceGetByType(imgTrack,stCenter); if (centerSlice != NULL) height -= centerSlice->height; } hPrintf(" ",trackName,(slice->link == NULL?"inset ":"")); + hPrintf(" width:9px; display:none;' class='%s %sbtn btnN'>

", + trackName,(slice->link == NULL ? "inset " : "")); } else hPrintf("width:%dpx;'>

",slice->width); } } // FF does not support newline code and '...' looks bad without newlines #define NEWLINE_ENCODED " " #define NEWLINE_NOT_SUPPORTED " - " #define NEWLINE_TO_USE(browser) ((browser) == btFF ? NEWLINE_NOT_SUPPORTED : NEWLINE_ENCODED) #define ELLIPSIS_TO_USE(browser) ((browser) == btFF ? "" : "...") -static void sliceAndMapDraw(struct imgBox *imgBox,struct imgTrack *imgTrack,enum sliceType sliceType,char *name,boolean scrollHandle) -/* writes a slice of an image and any assocated image map as HTML */ +static void sliceAndMapDraw(struct imgBox *imgBox,struct imgTrack *imgTrack, + enum sliceType sliceType,char *name,boolean scrollHandle) +// writes a slice of an image and any assocated image map as HTML { if(imgBox==NULL || imgTrack==NULL) return; struct imgSlice *slice = imgTrackSliceGetByType(imgTrack,sliceType); if(slice==NULL || slice->height == 0) return; boolean useMap=FALSE; int offsetX=slice->offsetX; int offsetY=slice->offsetY; int height = slice->height; int width=slice->width; if(slice->parentImg) { // Adjustment for centerLabel Conditional if (imgTrack->centerLabelSeen == clNotSeen && (sliceType == stSide || sliceType == stButton)) { struct imgSlice *centerSlice = imgTrackSliceGetByType(imgTrack,stCenter); if (centerSlice != NULL) { height -= centerSlice->height; offsetY += centerSlice->height; } } // Adjustment for portal if(imgBox->showPortal && imgBox->basesPerPixel > 0 && (sliceType==stData || sliceType==stCenter)) { offsetX += (imgBox->portalStart - imgBox->chromStart) / imgBox->basesPerPixel; width=imgBox->portalWidth; } hPrintf("
\n"); } struct mapSet *map = sliceGetMap(slice,FALSE); // Could be the image map or slice specific if(map) useMap = imageMapDraw(map,name); else if(slice->link != NULL) { if (sameString(TITLE_BUT_NO_LINK,slice->link)) { // This fake link ensures a mouse-over title is seen but not heard hPrintf("link) != NULL) hPrintf(" link); else hPrintf(" link); if (slice->title != NULL) { if (sliceType == stButton) { enum browserType browser = cgiClientBrowser(NULL,NULL,NULL); char *newLine = NEWLINE_TO_USE(browser); char *ellipsis = ELLIPSIS_TO_USE(browser); if(imgTrack->reorderable) - hPrintf(" TITLE='%s%sclick or right click to configure%s%sdrag to reorder%s'",attributeEncode(slice->title), newLine, - ellipsis, newLine,(tdbIsCompositeChild(imgTrack->tdb)?" highlighted subtracks":"") ); + hPrintf(" TITLE='%s%sclick or right click to configure%s%sdrag to reorder%s'", + attributeEncode(slice->title), newLine, ellipsis, newLine, + (tdbIsCompositeChild(imgTrack->tdb) ? " highlighted subtracks" : "") ); else - hPrintf(" TITLE='%s%sclick or right click to configure%s'",attributeEncode(slice->title), newLine, ellipsis); + hPrintf(" TITLE='%s%sclick or right click to configure%s'", + attributeEncode(slice->title), newLine, ellipsis); } else hPrintf(" TITLE='Click for: %s'", attributeEncode(slice->title) ); } hPrintf(">\n" ); } imageDraw(imgBox,imgTrack,slice,name,offsetX,offsetY,useMap); if(slice->link != NULL) hPrintf(""); if(slice->parentImg) hPrintf("
"); } void imageBoxDraw(struct imgBox *imgBox) -/* writes a entire imgBox including all tracksas HTML */ +// writes a entire imgBox including all tracksas HTML { if(imgBox->imgTracks == NULL) // Not an error to have an empty image return; imgBoxDropEmpties(imgBox); boolean verbose = (hIsPrivateHost()); // Warnings for hgwdev only if(!imgBoxIsComplete(imgBox,verbose)) // dorps empties as okay return; char name[256]; imgBoxTracksNormalizeOrder(imgBox); //if(verbose) // imgBoxShow(NULL,imgBox,0); -hPrintf("\n"); // DANGER FF interprets '--' as end of comment, not '-->' +hPrintf("\n"); + // DANGER FF interprets '--' as end of comment, not '-->' jsIncludeFile("jquery.tablednd.js", NULL); if(imgBox->bgImg) { int offset = 0; if(imgBox->showSideLabel && imgBox->plusStrand) { struct imgSlice *slice = imgTrackSliceGetByType(imgBox->imgTracks,stData); if(slice) offset = (slice->offsetX * -1); // This works because the ruler has a slice } hPrintf("\n"); } if(imgBox->showPortal) { // Let js code know what's up int chromSize = hChromSize(database, chromName); jsonObjectAdd(jsonForClient,"chromStart", newJsonNumber( 1)); jsonObjectAdd(jsonForClient,"chromEnd", newJsonNumber(chromSize)); jsonObjectAdd(jsonForClient,"imgBoxPortal", newJsonBoolean(TRUE)); jsonObjectAdd(jsonForClient,"imgBoxWidth", newJsonNumber(imgBox->width - imgBox->sideLabelWidth)); jsonObjectAdd(jsonForClient,"imgBoxPortalStart", newJsonNumber(imgBox->portalStart)); jsonObjectAdd(jsonForClient,"imgBoxPortalEnd", newJsonNumber(imgBox->portalEnd)); jsonObjectAdd(jsonForClient,"imgBoxPortalWidth", newJsonNumber(imgBox->portalWidth)); - jsonObjectAdd(jsonForClient,"imgBoxLeftLabel", newJsonNumber(imgBox->plusStrand ? imgBox->sideLabelWidth : 0)); - jsonObjectAdd(jsonForClient,"imgBoxPortalOffsetX", newJsonNumber((long) ((imgBox->portalStart - imgBox->chromStart) / imgBox->basesPerPixel))); + jsonObjectAdd(jsonForClient,"imgBoxLeftLabel", newJsonNumber(imgBox->plusStrand ? + imgBox->sideLabelWidth : 0)); + jsonObjectAdd(jsonForClient,"imgBoxPortalOffsetX", + newJsonNumber((long)( (imgBox->portalStart - imgBox->chromStart) + / imgBox->basesPerPixel))); jsonObjectAdd(jsonForClient,"imgBoxBasesPerPixel", newJsonDouble(imgBox->basesPerPixel)); } else jsonObjectAdd(jsonForClient,"imgBoxPortal", newJsonBoolean(FALSE)); -hPrintf("showPortal?(imgBox->portalWidth+imgBox->sideLabelWidth):imgBox->width); +hPrintf("
showPortal ? (imgBox->portalWidth+imgBox->sideLabelWidth) + : imgBox->width); hPrintf(" class='tableWithDragAndDrop'"); hPrintf(" style='border:1px solid blue;border-collapse:separate;'>\n"); struct jsonElement *jsonTdbVars = newJsonObject(newHash(8)); jsonTdbSettingsInit(jsonTdbVars); char *newLine = NEWLINE_TO_USE(cgiClientBrowser(NULL,NULL,NULL)); struct imgTrack *imgTrack = imgBox->imgTracks; for(;imgTrack!=NULL;imgTrack=imgTrack->next) { char *trackName = (imgTrack->name != NULL ? imgTrack->name : imgTrack->tdb->track ); struct track *track = hashFindVal(trackHash, trackName); if(track) jsonTdbSettingsBuild(jsonTdbVars, track, TRUE); hPrintf("\n",trackName,imgTrack->order, (imgTrack->reorderable?" trDraggable":" nodrop nodrag"), (imgTrack->centerLabelSeen != clAlways?" clOpt":""), (imgTrack->ajaxRetrieval ?" mustRetrieve":"")); if(imgBox->showSideLabel && imgBox->plusStrand) { // button safef(name, sizeof(name), "btn_%s", trackName); hPrintf(" \n"); // leftLabel safef(name,sizeof(name),"side_%s",trackName); if (imgTrack->reorderable) - hPrintf(" \n"); } // Main/Data image region - hPrintf(" \n"); if(imgBox->showSideLabel && !imgTrack->plusStrand) { // rightLabel safef(name, sizeof(name), "side_%s", trackName); if (imgTrack->reorderable) - hPrintf(" \n"); // button safef(name, sizeof(name), "btn_%s", trackName); hPrintf(" \n"); } hPrintf("\n"); } hPrintf("
\n",name,(imgTrack->reorderable?" class='dragHandle'":"")); sliceAndMapDraw(imgBox,imgTrack,stButton,name,FALSE); hPrintf("\n",name,attributeEncode(imgTrack->tdb->longLabel),newLine); + hPrintf(" \n", + name,attributeEncode(imgTrack->tdb->longLabel),newLine); else hPrintf(" \n",name); sliceAndMapDraw(imgBox,imgTrack,stSide,name,FALSE); hPrintf("\n", trackName, imgBox->width); + hPrintf(" \n", trackName, imgBox->width); // centerLabel if(imgTrack->hasCenterLabel) { safef(name, sizeof(name), "center_%s", trackName); sliceAndMapDraw(imgBox,imgTrack,stCenter,name,TRUE); hPrintf("\n"); } // data image safef(name, sizeof(name), "data_%s", trackName); sliceAndMapDraw(imgBox,imgTrack,stData,name,(imgTrack->order>0)); hPrintf("\n",name,attributeEncode(imgTrack->tdb->longLabel),newLine); + hPrintf(" \n", + name,attributeEncode(imgTrack->tdb->longLabel),newLine); else hPrintf(" \n",name); sliceAndMapDraw(imgBox,imgTrack,stSide,name,FALSE); hPrintf("\n",name,(imgTrack->reorderable?" class='dragHandle'":"")); sliceAndMapDraw(imgBox,imgTrack,stButton, name,FALSE); hPrintf("
\n"); -hPrintf("\n"); // DANGER FF interprets '--' as end of comment, not '-->' +hPrintf("\n"); jsonTdbSettingsUse(jsonTdbVars); }