src/hg/hgTracks/imageV2.c 1.2
1.2 2009/06/27 20:12:27 tdreszer
Drag reorder should now be persistent
Index: src/hg/hgTracks/imageV2.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/hgTracks/imageV2.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -b -B -U 4 -r1.1 -r1.2
--- src/hg/hgTracks/imageV2.c 26 Jun 2009 17:49:09 -0000 1.1
+++ src/hg/hgTracks/imageV2.c 27 Jun 2009 20:12:27 -0000 1.2
@@ -326,13 +326,13 @@
{
slice->type = type;
if(img != NULL && slice->parentImg != img)
slice->parentImg = img;
-if(title != NULL && differentStringNullOk(title,img->title))
+if(title != NULL && differentStringNullOk(title,slice->title))
{
- if(img->title != NULL)
- freeMem(img->title);
- img->title = cloneString(title);
+ if(slice->title != NULL)
+ freeMem(slice->title);
+ slice->title = cloneString(title);
}
slice->width = width;
slice->height = height;
slice->offsetX = offsetX;
@@ -416,9 +416,17 @@
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 || slice->height > slice->parentImg->height)
+if (slice->height == 0)
+ {
+ //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->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);
@@ -483,19 +491,20 @@
// boolean showCenterLabel; // Initially display center label? TODO: Isn't this redundent with vis?
// enum trackVisibility vis; // Current visibility of track image
// struct imgSlice *slices; // Currently there should be three slices for every track: data, centerLabel, sideLabel
// };
-struct imgTrack *imgTrackStart(struct trackDb *tdb,char *name,char *db,char *chrom,int chromStart,int chromEnd,boolean plusStrand,boolean showCenterLabel,enum trackVisibility vis,boolean reorderable)
+struct imgTrack *imgTrackStart(struct trackDb *tdb,char *name,char *db,char *chrom,int chromStart,int chromEnd,boolean plusStrand,boolean showCenterLabel,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);
-return imgTrackUpdate(imgTrack,tdb,name,db,chrom,chromStart,chromEnd,plusStrand,showCenterLabel,vis,reorderable);
+return imgTrackUpdate(imgTrack,tdb,name,db,chrom,chromStart,chromEnd,plusStrand,showCenterLabel,vis,order);
}
-struct imgTrack *imgTrackUpdate(struct imgTrack *imgTrack,struct trackDb *tdb,char *name,char *db,char *chrom,int chromStart,int chromEnd,boolean plusStrand,boolean showCenterLabel,enum trackVisibility vis,boolean reorderable)
+struct imgTrack *imgTrackUpdate(struct imgTrack *imgTrack,struct trackDb *tdb,char *name,char *db,char *chrom,int chromStart,int chromEnd,boolean plusStrand,boolean showCenterLabel,enum trackVisibility vis,int order)
/* Updates an already existing image track */
{
+static int lastOrder = 900; // keep track of the order these images get added
if(tdb != NULL && tdb != imgTrack->tdb)
imgTrack->tdb = tdb;
if(name != NULL && differentStringNullOk(imgTrack->name,name))
{
@@ -511,11 +520,36 @@
imgTrack->chromEnd = chromEnd;
imgTrack->plusStrand = plusStrand;
imgTrack->showCenterLabel = showCenterLabel;
imgTrack->vis = vis;
-imgTrack->reorderable = reorderable;
+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;
}
+int imgTrackOrderCmp(const void *va, const void *vb)
+/* Compare to sort on label. */
+{
+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: isData, isSide and isCenter */
{
struct imgSlice *slice = sliceCreate(type,img,title,width,height,offsetX,offsetY);
@@ -552,10 +586,9 @@
struct mapSet *imgTrackGetMapByType(struct imgTrack *imgTrack,enum sliceType type)
/* Gets the map assocated with a specific slice belonging to the imgTrack */
{
-struct imgSlice *slice = imgTrackSliceGetByType(imgTrack,type);
-if(slice == NULL)
+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
}
@@ -620,14 +653,15 @@
warn("imgTrack(%s) has bad slice",name);
return FALSE;
}
}
-if(!found[isData])
- {
- if (verbose)
- warn("imgTrack(%s) has no DATA slice.",name);
- return FALSE;
- }
+// This is not a requirement as the data portion could be empty (height==0)
+//if(!found[isData])
+// {
+// if (verbose)
+// warn("imgTrack(%s) has no DATA slice.",name);
+// return FALSE;
+// }
return TRUE;
}
void imgTrackFree(struct imgTrack **pImgTrack)
@@ -684,9 +718,9 @@
imgBox->portalEnd = chromEnd - oneThird;
imgBox->portalWidth = portalWidth;
// images are added with imgBoxImageAdd()
// imgTracks are added with imgBoxTrackAdd()
-// Plans for slices and maps: Fill in imgTracks with slices as the map is created.
+// Fill in imgTracks with slices as the map is created.
return imgBox;
}
struct image *imgBoxImageAdd(struct imgBox *imgBox,char *gif,char *title,int width,int height,boolean backGround)
@@ -721,12 +755,12 @@
//{
//return slRemoveEl(&(imgBox->images),img);
//}
-struct imgTrack *imgBoxTrackAdd(struct imgBox *imgBox,struct trackDb *tdb,char *name,enum trackVisibility vis,boolean showCenterLabel,boolean reorderable)
+struct imgTrack *imgBoxTrackAdd(struct imgBox *imgBox,struct trackDb *tdb,char *name,enum trackVisibility vis,boolean showCenterLabel,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,showCenterLabel,vis,reorderable);
+struct imgTrack *imgTrack = imgTrackStart(tdb,name,imgBox->db,imgBox->chrom,imgBox->chromStart,imgBox->chromEnd,imgBox->plusStrand,showCenterLabel,vis,order);
slAddHead(&(imgBox->imgTracks),imgTrack);
return imgBox->imgTracks;
}
struct imgTrack *imgBoxTrackFind(struct imgBox *imgBox,struct trackDb *tdb,char *name)
@@ -741,30 +775,42 @@
return imgTrack;
}
return NULL;
}
-struct imgTrack *imgBoxTrackFindOrAdd(struct imgBox *imgBox,struct trackDb *tdb,char *name,enum trackVisibility vis,boolean showCenterLabel,boolean reorderable)
+struct imgTrack *imgBoxTrackFindOrAdd(struct imgBox *imgBox,struct trackDb *tdb,char *name,enum trackVisibility vis,boolean showCenterLabel,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,showCenterLabel,reorderable);
+ imgTrack = imgBoxTrackAdd(imgBox,tdb,name,vis,showCenterLabel,order);
return imgTrack;
-}
-struct imgTrack *imgBoxTrackUpdateOrAdd(struct imgBox *imgBox,struct trackDb *tdb,char *name,enum trackVisibility vis,boolean showCenterLabel,boolean reorderable)
+} struct imgTrack *imgBoxTrackUpdateOrAdd(struct imgBox *imgBox,struct trackDb *tdb,char *name,enum trackVisibility vis,boolean showCenterLabel,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,showCenterLabel,reorderable);
+ return imgBoxTrackAdd(imgBox,tdb,name,vis,showCenterLabel,order);
-return imgTrackUpdate(imgTrack,tdb,name,imgBox->db,imgBox->chrom,imgBox->chromStart,imgBox->chromEnd,imgBox->plusStrand,showCenterLabel,vis,reorderable);
+return imgTrackUpdate(imgTrack,tdb,name,imgBox->db,imgBox->chrom,imgBox->chromStart,imgBox->chromEnd,imgBox->plusStrand,showCenterLabel,vis,order);
}
//boolean imgBoxTrackRemove(struct imgBox *imgBox,struct imgTrack *imgTrack)
//{
//return slRemoveEl(&(imgBox->imgTracks),imgTrack);
//}
+void imgBoxTracksNormalizeOrder(struct imgBox *imgBox)
+/* This routine sorts the imgTracks then forces tight ordering, so new tracks wil go to the end */
+{
+slSort(&(imgBox->imgTracks), imgTrackOrderCmp);
+struct imgTrack *imgTrack = NULL;
+int lastOrder = 0;
+for (imgTrack = imgBox->imgTracks; imgTrack != NULL; imgTrack = imgTrack->next )
+ {
+ if(imgTrack->reorderable)
+ imgTrack->order = ++lastOrder;
+ }
+}
+
boolean imgBoxIsComplete(struct imgBox *imgBox,boolean verbose)
/* Tests the completeness and consistency of an imgBox. */
{
if (imgBox == NULL)
@@ -819,10 +865,14 @@
{
if(!imgTrackIsComplete(imgTrack,verbose))
{
if (verbose)
- warn("imgBox(%s.%s:%d-%d) has bad track",imgBox->db,imgBox->chrom,imgBox->chromStart,imgBox->chromEnd);
- return FALSE;
+ 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
@@ -916,8 +966,10 @@
}
void sliceAndMapDraw(struct imgSlice *slice,char *name)
/* writes a slice of an image and any assocated image map as HTML */
{
+if(slice==NULL || slice->height == 0)
+ return;
hPrintf("<div style='width:%dpx; height:%dpx; overflow:hidden;'",slice->width,slice->height);
if(slice->type==isData)
hPrintf(" class='panDiv'");
hPrintf(">\n");
@@ -951,10 +1003,12 @@
return;
char name[128];
// TODO: Add in sorting
-if(differentStringNullOk(imgBox->imgTracks->name,RULER_TRACK_NAME))
- slReverse(&(imgBox->imgTracks));
+//if(differentStringNullOk(imgBox->imgTracks->name,RULER_TRACK_NAME))
+// slReverse(&(imgBox->imgTracks));
+imgBoxTracksNormalizeOrder(imgBox);
+
hPrintf("<!--------------- IMAGEv2 ---------------->\n");
//commonCssStyles();
jsIncludeFile("jquery.tablednd.js", NULL);
@@ -991,8 +1045,9 @@
hPrintf("</TD>");
}
// Main/Data image region
hPrintf("<TD id='td_data_%s' width=%d>\n", trackName, imgBox->portalWidth);
+ hPrintf("<input TYPE=HIDDEN name='%s_%s' value='%d'>\n",trackName,IMG_ORDER_VAR,imgTrack->order);
// centerLabel
if(imgTrack->showCenterLabel)
{
safef(name, sizeof(name), "center_%s", trackName);