src/hg/hgTracks/imageV2.c 1.21
1.21 2010/02/09 00:11:33 tdreszer
Changes that I have been sitting on awhile. More info on unexpected errors. Fixes to dragReorder. Support for simpler navigation links.
Index: src/hg/hgTracks/imageV2.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/hgTracks/imageV2.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -b -B -U 4 -r1.20 -r1.21
--- src/hg/hgTracks/imageV2.c 3 Feb 2010 18:43:37 -0000 1.20
+++ src/hg/hgTracks/imageV2.c 9 Feb 2010 00:11:33 -0000 1.21
@@ -223,8 +223,65 @@
}
return TRUE;
}
+static struct dyString *addIndent(struct dyString **dy,int indent)
+/* beginning indent for show functions */
+{
+struct dyString *myDy = (dy?*dy:NULL);
+if(dy == NULL || *dy == NULL)
+ myDy = newDyString(256);
+else
+ dyStringAppend(myDy,"<br>");
+dyStringAppend(myDy,"<code>");
+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 */
+{
+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 */
+{
+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) */
{
if (map == NULL)
@@ -321,8 +378,25 @@
{
return img->map;
}
+static void imgShow(struct dyString **dy,struct image *img,char *prefix,int indent)
+/* 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);
+ 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) */
{
if(pImg != NULL && *pImg != NULL)
@@ -352,8 +426,10 @@
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))
@@ -455,8 +531,32 @@
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 */
+{
+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 */
{
if (slice == NULL)
@@ -480,13 +580,13 @@
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 (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)
@@ -510,8 +610,11 @@
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;
@@ -618,10 +721,13 @@
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);
-slAddHead(&(imgTrack->slices),slice);
+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 */
@@ -714,8 +820,31 @@
// }
return count;
}
+static void imgTrackShow(struct dyString **dy,struct imgTrack *imgTrack,int indent)
+/* show the imgTrack */
+{
+if(imgTrack)
+ {
+ struct dyString *myDy = addIndent(dy,indent);
+ dyStringPrintf(myDy,"imgTrack: name:%s tdb:%s%s%s order:%d vis:%s",
+ (imgTrack->name?imgTrack->name:""),(imgTrack->tdb && imgTrack->tdb->tableName?imgTrack->tdb->tableName:""),
+ (imgTrack->showCenterLabel?" centerLabel":""),(imgTrack->reorderable?" reorderable":""),
+ 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) */
{
if (imgTrack == NULL)
@@ -726,63 +855,90 @@
}
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->tableName);
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;
// }
return TRUE;
@@ -1054,8 +1210,34 @@
slReverse(&(imgBox->imgTracks));
#endif//ndef IMAGEv2_DRAG_REORDER
}
+void imgBoxShow(struct dyString **dy,struct imgBox *imgBox,int indent)
+/* 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);
+ indent++;
+ imgShow(&myDy,imgBox->images,"data ",indent);
+ 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;
+ }
+}
+
boolean imgBoxIsComplete(struct imgBox *imgBox,boolean verbose)
/* Tests the completeness and consistency of an imgBox. */
{
if (imgBox == NULL)
@@ -1248,13 +1430,16 @@
{
hPrintf(" <p id='p_%s' style='height:%dpx;",name,slice->height);
if(slice->type==stButton)
{
- char *trackName = (imgTrack->name != NULL ?
- imgTrack->name :
- imgTrack->tdb->parent ?
- imgTrack->tdb->parent->tableName:
- imgTrack->tdb->tableName );
+ char *trackName = imgTrack->name;
+ if(trackName == NULL)
+ {
+ struct trackDb * tdb = imgTrack->tdb;
+ if(tdbIsCompositeChild(tdb))
+ tdb = trackDbCompositeParent(tdb);
+ trackName = tdb->tableName;
+ }
hPrintf(" width:9px; display:none;' class='%s btn btnN'></p>",trackName);
}
else
hPrintf("width:%dpx;'></p>",slice->width);
@@ -1319,8 +1504,10 @@
char name[256];
int bgOffset = NO_VALUE;
imgBoxTracksNormalizeOrder(imgBox);
+//if(verbose)
+// imgBoxShow(NULL,imgBox,0);
hPrintf("<!---------------vvv IMAGEv2 vvv---------------->\n");
//commonCssStyles();
#ifdef IMAGEv2_DRAG_REORDER
@@ -1367,8 +1554,10 @@
struct imgTrack *imgTrack = imgBox->imgTracks;
for(;imgTrack!=NULL;imgTrack=imgTrack->next)
{
char *trackName = (imgTrack->name != NULL ? imgTrack->name : imgTrack->tdb->tableName );
+ //if(verbose && imgTrack->order == 3)
+ // imgTrackShow(NULL,imgTrack,0);
hPrintf("<TR id='tr_%s'%s>\n",trackName,
(imgTrack->reorderable?" class='trDraggable'":" class='nodrop nodrag'"));
if(imgBox->showSideLabel && imgBox->plusStrand)