546e4b62f9c8abdda3576ce5b9bf8c4b82dc6b4e braney Tue Mar 21 14:42:01 2023 -0700 make squishyPack work nicely with Javascript track reorder diff --git src/hg/hgTracks/imageV2.h src/hg/hgTracks/imageV2.h index 0907ad6..292fe4b 100644 --- src/hg/hgTracks/imageV2.h +++ src/hg/hgTracks/imageV2.h @@ -1,472 +1,473 @@ // imageV2 - API for creating the image V2 features. /* Copyright (C) 2014 The Regents of the University of California * See kent/LICENSE or http://genome.ucsc.edu/license/ for licensing information. */ #ifndef IMAGEV2_H #define IMAGEV2_H // DRAG_SCROLL means dragging the image left-right to reposition the viewing window on the chrom. // NOTE: 1x works fine and is released. Set IMAGEv2_DRAG_SCROLL_SZ > 1 (3=3x) // to see hidden image while dragging. #ifndef IMAGEv2_DRAG_SCROLL_SZ #define IMAGEv2_DRAG_SCROLL_SZ 1 #endif #if defined(IMAGEv2_DRAG_SCROLL_SZ) && (IMAGEv2_DRAG_SCROLL_SZ > 1) #define IMAGEv2_SHORT_MAPITEMS //#define IMAGEv2_SHORT_TOGGLE //#define IMAGEv2_NO_LEFTLABEL_ON_FULL // Because the sideLabel clipping will leave a no longer needed label // aligned with the centerLabel, we will need to either: remove sideLabels // (which otherwise work) OR add a new side-slice to match the centerlabel #endif //defined(IMAGEv2_DRAG_SCROLL_SZ) && (IMAGEv2_DRAG_SCROLL_SZ > 1) // CURRENT PROBLEMS with dragScroll > 1X: // o Dynamic height for data/label based on image map currently works EXCEPT, // occasionally does not resize. Consider resize while dragging! // o next item feature '>>' arrows should check if items are in the wings // o next exon feature '>>' arrows are only seen in the wings and only look beyond the wings // UNCOMMENT USE_NAVIGATION_LINKS for so far experimental UI changes to replace buttons at top // with more streamlined links //#define USE_NAVIGATION_LINKS extern struct imgBox *theImgBox; // Make this global for now to avoid huge rewrite extern struct imgTrack *curImgTrack; // 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 independent of imageV2 // These should probably be moved to hgTracks.h ///////////////////////// struct flatTracks // List of tracks in image, flattened to promote subtracks { struct flatTracks *next; // Next on list. struct track *track; // Track (the track list is still heirarchical int order; // Image order: This keeps track of dragReorder int maxHeight; // largest height among all windows in image. }; void flatTracksAdd(struct flatTracks **flatTracks,struct track *track,struct cart *cart, struct slName *orderedWiggles); // Adds one track into the flatTracks list int flatTracksCmp(const void *va, const void *vb); // Compare to sort on flatTrack->order void flatTracksSort(struct flatTracks **flatTracks); // This routine sorts the imgTracks then forces tight ordering, so new tracks wil go to the end void flatTracksFree(struct flatTracks **flatTracks); // Frees all memory used to support flatTracks (underlying tracks are untouched) ///////////////////////// // JSON support. Eventually the whole imgTbl could be written out as JSON void jsonTdbSettingsBuild(struct jsonElement *settings, struct track *track, boolean configurable); // Creates then successively adds trackDb settings to the jsonTdbSettingsString // Initially pass in NULL pointer to a dyString to properly begin building void jsonTdbSettingsUse(struct jsonElement *settings); // Closes and returns the contents of the jsonTdbSettingsString ///////////////////////// // IMAGEv2 // The new way to do images // Terms: // "image box": The new version of the image on the html page. It is a table with rows that // contain tracks which are made up of parts of images. // "imgBox": This C struct contains all information to render the image box on the html page. // "imgTbl": The HTML structure that contains individual track images. // The javascript client controls the imgTbl. // Thus cgi knows imgBox while html/js knows imgTbl. // "image": A single png. An image may contain mutilple tracks. // Even as a single track and image may contain a data image, centerLabel, sideLabel and button. // "map": (or "mapSet") The image map for providing links to items in a data image. // An image and map are a 1 to 1 pair and pixel coordinates are always image relative. // "slice": (or "imgSlice") The cgi concept of the portion of an image that is sent to the // html/js side. If we are sending a 3X sized image, the "slice" spans the entire 3X. // Almost always a subset of an image, but possibly the whole image. // Even if the image is of a single track, it will still be cut into data image, // sideLabel and centerLabel slices. // "sliceMap": The portion of a map that belongs to a slice. The pixel coordinates are always // image relative, not slice relative. // "portal": (or "imgPortal") The html/js concept of the portion of a data slice that is visible in // the browser. Thus, if we are sending a 3X sized data image slice, the "portal" seen // in the browser spans only 1X. // "imgTrack": (or track image) The cgi side whole shabang for rendering one track. It contains // track specific information and four slices: data, centerLabel, sideLabel and button // The imgBox contains N imgTracks. Typically an ajax/JSON request gets a single // imgTrack returned, which then is updated in the imgTbl containing multiple tracks. // image box support: This can contain all the support variables that are global to the image box // (like font size, box width, etc.). At this point, lets not talk structure // or cgi vs. html/js but leave this container as a concept that we know // needs filling. // imgBox is the top level and contains all info to draw the image in HTML // - contains slList of all imgTrack structs shown // imgTrack contains all info to display one track/subtrack in the imgBox // - contains 4 imgSlice structs (data, centerLabel, sideLabel, button) // imgSlice contains all info to display a portion of an image file // - contains 1 image struct // image contains all information about an image file and associated map box ///////////////////////// /////////////////////// Maps struct mapItem // IMAGEv2: single map item in an image map. { struct mapItem *next; // slList char *linkVar; // the get variables associated with the map link char *title; // item title int topLeftX; // in pixels relative to image int topLeftY; // in pixels relative to image int bottomRightX; // in pixels relative to image int bottomRightY; // in pixels relative to image char *id; // id; used by js right-click code to figure out what to do with // a map item (usually mapName) }; struct mapSet // IMAGEv2: full map for image OR partial map for slice { char *name; // to point an image to a map in HTML struct image *parentImg; // points to the image this map belongs to char *linkRoot; // the common or static portion of the link for the entire image struct mapItem *items; // list of items }; // To create map items which have mouse-over titles but no link, fill link with: #define TITLE_BUT_NO_LINK "noLink" 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() struct mapSet *mapSetUpdate(struct mapSet *map,char *name,struct image *img,char *linkRoot); // Updates an existing map (aka mapSet) 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 *mapSetItemUpdate(struct mapSet *map,struct mapItem *item,char *link,char *title, int topLeftX,int topLeftY,int bottomRightX,int bottomRightY, char *id); // Update an already existing mapItem 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 *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 *mapSetItemFindOrAdd(struct mapSet *map,char *link,char *title, int topLeftX,int topLeftY,int bottomRightX,int bottomRightY, char *id); // Finds or adds the map item void mapItemFree(struct mapItem **pItem); // frees all memory assocated with a single mapItem 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 boolean mapSetIsComplete(struct mapSet *map,boolean verbose); // Tests the completeness and consistency of this map (mapSet) void mapSetFree(struct mapSet **pMap); // frees all memory (including items) assocated with a single mapSet /////////////////////// Images struct image // IMAGEv2: single image which may have multiple imgSlices focused on it { struct image *next; // slList (Not yet used) char *file; // name of file that hold the image char *title; // image wide title int width; // in pixels int height; // in pixels struct mapSet *map; // map assocated with this image (may be NULL) }; struct image *imgCreate(char *png,char *title,int width,int height); // Creates a single image container. // A map map be added with imgMapStart(),mapSetItemAdd() 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() struct mapSet *imgGetMap(struct image *img); // Gets the map associated with this image. // Map items can then be added to the map with mapSetItemAdd() void imgFree(struct image **pImg); // frees all memory assocated with an image (including a map) /////////////////////// Slices enum sliceType { stUnknown=0, // Invalid stData=1, // Data or track slice of an image stCenter=2, // Top or centerLabel slice of an image stButton=3, // Config button (by separating from side label, can have // separate image which is colored/zipped by javascript) stSide=4, // Side or leftLabel slice of an image stInvalid=5 // Invalid }; #define stMaxSliceTypes stInvalid struct imgSlice // IMAGEv2: the portion of an image that is displayable for one track { struct imgSlice *next; // slList enum sliceType type; // Type of slice (currently only 3) struct image *parentImg; // the actual image/png char *title; // slice wide title struct mapSet *map; // A slice specific map. It contains a subset of the img->map. // Coordinates must be img relative NOT slice relative! char *link; // If a slice has no map, it may have a whole slice link int width; // in pixels (differs from img->width if img contains sideLabel) int height; // in pixels (differs from img->height if // img contains centerLabel and/or multiple tracks) int offsetX; // offset from left (when img->width > slice->width) int offsetY; // offset from top (when img->height > slice->height) }; 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 *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 char *sliceTypeToString(enum sliceType type); // Translate enum slice type to string struct imgSlice *sliceAddLink(struct imgSlice *slice,char *link,char *title); // Adds a slice wide link. The link and map are mutually exclusive 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() struct mapSet *sliceGetMap(struct imgSlice *slice,boolean sliceSpecific); // Gets the map associate with a slice which may be sliceSpecific or it may belong to the // slices' image. Map items can then be added to the map returned with mapSetItemAdd(). struct mapSet *sliceMapFindOrStart(struct imgSlice *slice,char *name,char *linkRoot); // Finds the slice specific map or starts it struct mapSet *sliceMapUpdateOrStart(struct imgSlice *slice,char *name,char *linkRoot); // Updates the slice specific map or starts it boolean sliceIsConsistent(struct imgSlice *slice,boolean verbose); // Test whether the slice and it's associated image and map are consistent with each other void sliceFree(struct imgSlice **pSlice); // frees all memory assocated with a slice // (not including the image or a map belonging to the image) /////////////////////// imgTracks enum centerLabelSeen { clUnknown=0, // Invalid clAlways=1, // Default is always seen clNowSeen=2, // Conditionally and currently seen clNotSeen=3 // Conditionally and currently unseen }; struct imgTrack // IMAGEv2: imageBox contains list of displayed imageTracks { struct imgTrack *next; // slList struct trackDb *tdb; // trackDb entry (should this be struct track* entry?) char *name; // It is possible to have an imgTrack without a tdb, // but then it must have a name char *db; // Image for db (species) (assert imgTrack matches imgBox) char *chrom; // Image for chrom (assert imgTrack matches imgBox) long chromStart; // Image start (absolute, not portal position) long chromEnd; // Image end (absolute, not portal position) boolean plusStrand; // Image covers plus strand, not minus strand boolean hasCenterLabel; // A track may have a center label but not show it enum centerLabelSeen centerLabelSeen; // Conditionally displayed center labels are always // there but sometimes hidden boolean reorderable; // Is this track reorderable (by drag and drop) ? boolean ajaxRetrieval; // This track needs to be retrieved via ajax int order; // Image order: This keeps track of dragReorder enum trackVisibility vis; // Current visibility of track image struct imgSlice *slices; // Currently there should be four slices for every track: // data, centerLabel, sideLabel, button + boolean linked; // is this track linked to another track (like squishyPack) }; #define IMG_ANYORDER -2 #define IMG_FIXEDPOS -1 #define IMG_ORDERTOP 10000 #define IMG_ORDEREND 20000 #define IMG_ORDER_VAR "imgOrd" struct imgTrack *imgTrackStart(struct trackDb *tdb,char *name,char *db, char *chrom, long chromStart, long 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 *imgTrackUpdate(struct imgTrack *imgTrack,struct trackDb *tdb,char *name, char *db,char *chrom, long chromStart, long chromEnd, boolean plusStrand, boolean hasCenterLabel, enum trackVisibility vis, int order); // Updates an already existing image track void imgTrackMarkForAjaxRetrieval(struct imgTrack *imgTrack,boolean ajaxRetrieval); // Updates the imgTrack to trigger an ajax callback from the html client to get this track #define imgTrackMarkedForAjaxRetrieval(imgTrack) ((imgTrack)->ajaxRetrieval) // Is this imgTrack marked for Ajax retrieval #define imgTrackUpdateCenterLabelSeen(slice,seen) { (slice)->centerLabelSeen = (seen); } // Center slices are occasionally unseen int imgTrackOrderCmp(const void *va, const void *vb); // Compare to sort on label. 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 *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 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 *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 int imgTrackCoordinates(struct imgTrack *imgTrack, int *leftX,int *topY,int *rightX,int *bottomY); // Fills in topLeft x,y and bottomRight x,y coordinates, returning topY. #define imgTrackTopY(imgTrack) imgTrackCoordinates(imgTrack,NULL,NULL,NULL,NULL) // Returns the Y coordinate of the top of the track. int imgTrackBottomY(struct imgTrack *imgTrack); // Returns the Y coordinate of the bottom of the track. struct mapSet *imgTrackGetMapByType(struct imgTrack *imgTrack,enum sliceType type); // Gets the map assocated with a specific slice belonging to the imgTrack int imgTrackAddMapItem(struct imgTrack *imgTrack,char *link,char *title,int topLeftX,int topLeftY, int bottomRightX,int bottomRightY, char *id); // Will add a map item it 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! boolean imgTrackIsComplete(struct imgTrack *imgTrack,boolean verbose); // Tests the completeness and consistency of this imgTrack (including slices) void imgTrackFree(struct imgTrack **pImgTrack); // frees all memory assocated with an imgTrack (including slices) /////////////////////// Image Box struct imgBox // IMAGEv2: imageBox conatins all the definitions to draw an image in hgTracks { char *db; // database (species) char *chrom; // chrom long chromStart; // Image start (absolute, not portal position) long chromEnd; // Image end (absolute, not portal position) boolean plusStrand; // imgBox currently shows plus strand, not minus strand struct image *images; // Contains all images for the imgBox. TEMPORARY: hgTracks creates // it's current one image and I'll store it here struct image *bgImg; // When track images are transparent, bgImage contains blue lines // that are db coordinate granularity. int width; // in pixels (note that portalWidth in visible position within // image position in db coodinates) boolean showSideLabel; // Initially display side label? (use 'plusStrand' for left/right) int sideLabelWidth; // in pixels (note this is needed when setting up a portal // and dragScrolling) boolean showPortal; // Rather than showing the entire data range, only show a portion, // and allow dragScrolling double basesPerPixel; // number of bases covered by a single pixel long portalStart; // initial visible portal within html image table (db coodinates) // [May be obsoleted by js client] long portalEnd; // initial visible portal within html image table (db coodinates) // [May be obsoleted by js client] int portalWidth; // in pixels (should be equal to the visible position of data slice) struct imgTrack *imgTracks; // slList of all images to display }; struct imgBox *imgBoxStart(char *db, char *chrom, long chromStart, long 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() boolean imgBoxPortalDefine(struct imgBox *imgBox, long *chromStart, long *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 imgBoxPortalRemove(struct imgBox *imgBox, long *chromStart, long *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 boolean imgBoxPortalDimensions(struct imgBox *imgBox, long *chromStart, long *chromEnd, int *imgWidth, int *sideLabelWidth, long *portalStart, long *portalEnd, int *portalWidth, double *basesPerPixel); // returns the imgBox portal dimensions in the OUTs returns TRUE if portal defined struct image *imgBoxImageAdd(struct imgBox *imgBox,char *png,char *title,int width,int height, boolean backGround); // Adds an image to an imgBox. The image may be extended with imgMapStart(),mapSetItemAdd() struct image *imgBoxImageFind(struct imgBox *imgBox,char *png); // Finds a specific image already added to this imgBox 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 *imgBoxTrackFind(struct imgBox *imgBox,struct trackDb *tdb,char *name); // Finds a specific imgTrack already added to this imgBox 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 *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 void imgBoxTracksNormalizeOrder(struct imgBox *imgBox); // This routine sorts the imgTracks int imgBoxDropEmpties(struct imgBox *imgBox); // Empty imageTracks (without slices) is not an error but they should be dropped. // returns remaining current track count boolean imgBoxIsComplete(struct imgBox *imgBox,boolean verbose); // Tests the completeness and consistency of an imgBox. void imgBoxFree(struct imgBox **pImgBox); // frees all memory assocated with an imgBox (including images and imgTracks) /////////////////////// imageV2 UI API void imageBoxDraw(struct imgBox *imgBox); // writes a entire imgBox including all tracks as HTML #endif//ndef IMAGEV2_H