4c4b980ed5f0d298107bab2261384f8bfe0e304c tdreszer Thu Sep 23 16:20:55 2010 -0700 Lots of rework to the cartTdbTree and Visibility cleanup routines. This code should be passive until findTracks or rightClick are released. diff --git src/hg/lib/cart.c src/hg/lib/cart.c index 7662879..04da163 100644 --- src/hg/lib/cart.c +++ src/hg/lib/cart.c @@ -1819,7 +1819,7 @@ char parentVar[512]; char *parentVal = NULL; char *stView; -if(subgroupFind(tdb,"view",&stView)) +if (tdbIsView(viewTdb,&stView)) { safef(parentVar,sizeof parentVar,"%s.%s.%s",tdb->parent->track,stView,suffix); parentVal = hashFindVal(cart->hash, parentVar); @@ -1980,6 +1980,16 @@ return atof(a); } +// These macros allow toggling warn messages to NOOPS when no longer debugging +//#define DEBUG_WITH_WARN +#ifdef DEBUG_WITH_WARN + #define WARN warn + #define ASSERT assert +#else///ifndef DEBUG_WITH_WARN + #define WARN(...) + #define ASSERT(...) +#endif///ndef DEBUG_WITH_WARN + boolean cartValueHasChanged(struct cart *newCart,struct hash *oldVars,char *setting,boolean ignoreRemoved,boolean ignoreCreated) /* Returns TRUE if new cart setting has changed from old cart setting */ @@ -2020,7 +2030,7 @@ struct slPair *oneName = NULL; while ((oneName = slPopHead(&oldList)) != NULL) { - boolean thisOneChanged = cartValueHasChanged(newCart,oldVars,oneName->val,ignoreRemoved,TRUE); + boolean thisOneChanged = cartValueHasChanged(newCart,oldVars,oneName->name,ignoreRemoved,TRUE); if (unChanged != thisOneChanged) slAddHead(&newList,oneName); else @@ -2054,19 +2064,78 @@ return removed; } +static boolean cartTdbOverrideSuperTracks(struct cart *cart,struct trackDb *tdb,boolean ifJustSelected) +/* When when the child of a hidden supertrack is foudn and selected, then shape the supertrack accordingly + Returns TRUE if any cart changes are made */ +{ +// This is only pertinent to supertrack children just turned on +if (!tdbIsSuperTrackChild(tdb)) + return FALSE; + +char setting[512]; + +// Must be from having just selected the track in findTracks. This will carry with it the "_sel" setting. +if (ifJustSelected) + { + safef(setting,sizeof(setting),"%s_sel",tdb->track); + if (!cartVarExists(cart,setting)) + return FALSE; + cartRemove(cart,setting); // Unlike composite subtracks, supertrack children keep the "_sel" setting only for detecting this moment + } + +// if parent is not hidden then nothing to do +ASSERT(tdb->parent != NULL && tdbIsSuperTrack(tdb->parent)); +enum trackVisibility vis = tdbVisLimitedByAncestry(cart, tdb->parent, FALSE); +if (vis != tvHide) + return FALSE; + +// Now turn all other supertrack children to hide and the supertrack to visible +struct slRef *childRef; +for(childRef = tdb->parent->children;childRef != NULL; childRef = childRef->next) + { + struct trackDb *child = childRef->val; + if (child == tdb) + continue; + + // Make sure this child hasn't also just been turned on! + safef(setting,sizeof(setting),"%s_sel",child->track); + if (cartVarExists(cart,setting)) + { + cartRemove(cart,setting); // Unlike composite subtracks, supertrack children keep the "_sel" setting only for detecting this moment + continue; + } + + // hide this sibling if not already hidden + char *cartVis = cartOptionalString(cart,child->track); + if (cartVis != NULL) + { + if (child->visibility == tvHide) + cartRemove(cart,child->track); + else if (hTvFromString(cartVis) != tvHide) + cartSetString(cart,child->track,"hide"); + } + else if (child->visibility != tvHide) + cartSetString(cart,child->track,"hide"); + } +// and finally show the parent +cartSetString(cart,tdb->parent->track,"show"); +WARN("Set %s to 'show'",tdb->parent->track); +return TRUE; +} + // Shaping composite vis by subtrack specific vis comes in 3 flavors: // Simple) No shaping. Subtrack specific vis overrides composite/view level but does not alter it // Plan A) When composite is in default settings only, then composite/vis is shaped to reflect current subtrack vis // Plan B) Whenever there is subtrack level vis, the composite and view vis are shaped to show maximum subtrack vis, // while subtracks with inherited vis may be given subtrack specific vis to return them to that state #define COMPOSITE_VIS_SHAPING_PLAN_A -//#define COMPOSITE_VIS_SHAPING_PLAN_B +#define COMPOSITE_VIS_SHAPING_PLAN_B #if defined(COMPOSITE_VIS_SHAPING_PLAN_A) || defined(COMPOSITE_VIS_SHAPING_PLAN_B) -static int cartTdbParentShapeVis(struct cart *cart,struct trackDb *parent,char *view,struct slRef *refSubtracks,struct hash *subVisHash,boolean compositeAtDefault) +static int cartTdbParentShapeVis(struct cart *cart,struct trackDb *parent,char *view,struct hash *subVisHash,boolean reshapeFully) // This shapes one level of vis (view or composite) based upon subtrack specific visibility. Returns count of subtracks affected { -int count=0; +ASSERT(view || (tdbIsComposite(parent) && tdbIsCompositeChild(parent->subtracks))); struct trackDb *subtrack = NULL; char setting[512]; if (view != NULL) @@ -2074,65 +2143,84 @@ else safef(setting,sizeof(setting),"%s",parent->track); -enum trackVisibility vis = tvHide; // Looking for max vis of child subtracks -enum trackVisibility visOrig = hTvFromString(cartUsualString(cart,setting,hStringFromTv(parent->visibility))); +enum trackVisibility visMax = tvHide; +//enum trackVisibility visOrig = hTvFromString(cartUsualString(cart,setting,hStringFromTv(parent->visibility))); +enum trackVisibility visOrig = tdbVisLimitedByAncestry(cart, parent, FALSE); -// Should walk through children and check for subtrackVis override -struct slRef *refSub; -for(refSub = refSubtracks;refSub != NULL;refSub = refSub->next) +// Should walk through children to get max new vis for this parent +for(subtrack = parent->subtracks;subtrack != NULL;subtrack = subtrack->next) { - subtrack = refSub->val; - if (parent != subtrack->parent) // This should work whether at view level or composite level, - continue; // since composite level call only happens if composite has no views - char *foundVis = hashFindVal(subVisHash, subtrack->track); // if the subtrack doesn't have individual vis AND... if (foundVis != NULL) { enum trackVisibility visSub = hTvFromString(foundVis); - if (tvCompare(vis, visSub) >= 0) - vis = visSub; + if (tvCompare(visMax, visSub) >= 0) + visMax = visSub; } - else + else if (!reshapeFully && visOrig != tvHide) { - enum trackVisibility visSub = tdbVisLimitedByAncestry(NULL, subtrack, FALSE); - if (tvCompare(vis, visSub) >= 0) - vis = visSub; + int fourState = subtrackFourStateChecked(subtrack,cart); + if (fourStateVisible(fourState)) // subtrack must be visible + { + enum trackVisibility visSub = tdbVisLimitedByAncestry(cart, subtrack, FALSE); + if (tvCompare(visMax, visSub) >= 0) + visMax = visSub; + } } } // Now we need to update non-subtrack specific vis/sel in cart -if (vis != visOrig) +int countUnchecked=0; +int countExplicitVis=0; +if (visMax != visOrig || reshapeFully) { - //warn("%s vis old:%d new:%d",parent->track,visOrig,vis); - cartSetString(cart,setting,hStringFromTv(vis)); + cartSetString(cart,setting,hStringFromTv(visMax)); // Set this explicitly. The visOrig may be inherited! + if (visOrig == tvHide && tdbIsSuperTrackChild(parent)) + cartTdbOverrideSuperTracks(cart,parent,FALSE); // deal with superTrack vis! cleanup // Now set all subtracks that inherit vis back to visOrig - for(refSub = refSubtracks;refSub != NULL;refSub = refSub->next) + for(subtrack = parent->subtracks;subtrack != NULL;subtrack = subtrack->next) + { + int fourState = subtrackFourStateChecked(subtrack,cart); + if (fourStateChecked(fourState)) // subtrack is checked (should include subtrack level vis) { - subtrack = refSub->val; - if (parent != subtrack->parent) // This should work whether at view level or composite level, - continue; // since composite level call only happens composite has no views - if (!hashFindVal(subVisHash, subtrack->track)) // if the subtrack doesn't have individual vis AND... { - int fourState = subtrackFourStateChecked(subtrack,cart); - if (fourStateChecked(fourState)) // subtrack is checked + if (reshapeFully || visMax == tvHide) + { + subtrackFourStateCheckedSet(subtrack, cart,FALSE,fourStateEnabled(fourState)); // uncheck + cartRemove(cart,subtrack->track); // Remove it if it exists, just in case + countUnchecked++; + } + else if (visOrig != tvHide) { - if (compositeAtDefault || visOrig == tvHide) - subtrackFourStateCheckedSet(subtrack, cart,FALSE,fourStateEnabled(fourState)); - else cartSetString(cart,subtrack->track,hStringFromTv(visOrig)); - count++; + countExplicitVis++; + } } } + else if (reshapeFully) + { + cartRemove(cart,subtrack->track); // Remove it if it exists, just in case + countUnchecked++; + } } if (tdbIsCompositeView(parent)) + { + visOrig = tdbVisLimitedByAncestry(cart, parent->parent, FALSE); cartSetString(cart,parent->parent->track,"full"); // Now set composite to full. + if (visOrig == tvHide && tdbIsSuperTrackChild(parent->parent)) + cartTdbOverrideSuperTracks(cart,parent->parent,FALSE); // deal with superTrack vis! cleanup } -return count; + + WARN("%s visOrig:%d visMax:%d unchecked:%d explicitVis:%d",parent->track,visOrig,visMax,countUnchecked,countExplicitVis); } +return (countUnchecked + countExplicitVis); +} +#endif/// defined(COMPOSITE_VIS_SHAPING_PLAN_A) || defined(COMPOSITE_VIS_SHAPING_PLAN_B) +#ifndef COMPOSITE_VIS_SHAPING_PLAN_B static boolean cartVarsNoneFoundForTdb(struct cart *cart,struct hash *subVisHash,struct trackDb *tdb) { struct slPair *cartVar,*cartVars = cartVarsWithPrefix(cart,tdb->track); @@ -2161,8 +2249,8 @@ struct trackDb *viewTdb; for (viewTdb=tdb->subtracks; viewTdb!=NULL; viewTdb=viewTdb->next) { - char *viewOfTdb = trackDbLocalSetting(viewTdb,"view"); - if (viewOfTdb && sameString(viewOfTdb,viewFound)) + char *viewOfTdb = NULL; + if (tdbIsView(viewTdb,&viewOfTdb) && sameString(viewOfTdb,viewFound)) { if(sameString((char *)cartVar->val,hStringFromTv(viewTdb->visibility)) ) continue; @@ -2171,7 +2259,7 @@ } } } - //warn("cartVarsNoneFoundForTdb: %s=%s",cartVar->name,(char *)cartVar->val); + WARN("cartVarsNoneFoundForTdb: %s=%s",cartVar->name,(char *)cartVar->val); slFreeList(&cartVars); return FALSE; // Any view cart vars means non-default so do not "shape" composite } @@ -2180,7 +2268,7 @@ } return TRUE; } -#endif/// defined(COMPOSITE_VIS_SHAPING_PLAN_A) || defined(COMPOSITE_VIS_SHAPING_PLAN_B) +#endif///ndef COMPOSITE_VIS_SHAPING_PLAN_B boolean cartTdbTreeMatchSubtrackVis(struct cart *cart,struct trackDb *tdbComposite) /* When subtrack vis is set via findTracks, and composite has no cart settings, @@ -2193,7 +2281,8 @@ // First look for subtrack level vis char setting[512]; struct trackDb *subtrack = NULL; -struct hash *subVisHash = newHash(8); +struct trackDb *tdbView = NULL; +struct hash *subVisHash = newHash(0); struct slRef *tdbRef, *tdbRefList = trackDbListGetRefsToDescendantLeaves(tdbComposite->subtracks); for (tdbRef = tdbRefList; tdbRef != NULL; tdbRef = tdbRef->next) { @@ -2201,35 +2290,49 @@ char *val=cartOptionalString(cart,subtrack->track); if (val && differentString(val,"hide")) // NOTE should we include hide? { + int fourState = subtrackFourStateChecked(subtrack,cart); + //if (cartUsualInt(cart,setting,0) != 0) // FIXME: sub level vis is not getting cleared out!!!! + if (fourStateVisible(fourState)) // subtrack is checked too + { + WARN("Subtrack level vis %s=%s",subtrack->track,val); hashAdd(subVisHash,subtrack->track,val); - // Add the "_sel" setting which should also exist. Point it to subtrack safef(setting,sizeof(setting),"%s_sel",subtrack->track); - hashAdd(subVisHash,setting,subtrack); + hashAdd(subVisHash,setting,subtrack); // Add the "_sel" setting which should also exist. Point it to subtrack + } } } +slFreeList(&tdbRefList); + if (hashNumEntries(subVisHash) == 0) { - slFreeList(&tdbRefList); + WARN("No subtrack level vis"); return FALSE; } // Next look for any cart settings other than subtrack vis/sel -boolean compositeAtDefault = TRUE; -compositeAtDefault = cartVarsNoneFoundForTdb(cart,subVisHash,tdbComposite); + // FIXME: New directive means that if composite is hidden, then ignore previous and don't bother checking cart. +#ifdef COMPOSITE_VIS_SHAPING_PLAN_B +boolean reshapeFully = (tdbVisLimitedByAncestry(cart, tdbComposite, FALSE) == tvHide); +#else///ifndef COMPOSITE_VIS_SHAPING_PLAN_B +boolean reshapeFully = cartVarsNoneFoundForTdb(cart,subVisHash,tdbComposite); +#endif///ndef COMPOSITE_VIS_SHAPING_PLAN_B // What about view level settings? -struct trackDb *tdbView = tdbComposite->subtracks; +#ifdef COMPOSITE_VIS_SHAPING_PLAN_B +boolean hasViews = tdbIsCompositeView(tdbComposite->subtracks); +#else///ifndef COMPOSITE_VIS_SHAPING_PLAN_B boolean hasViews = FALSE; +tdbView = tdbComposite->subtracks; if (tdbIsCompositeView(tdbView)) { hasViews = TRUE; - if (compositeAtDefault) + if (reshapeFully) { for( ;tdbView != NULL; tdbView = tdbView->next ) { if(!cartVarsNoneFoundForTdb(cart,subVisHash,tdbView)) { - compositeAtDefault = FALSE; + reshapeFully = FALSE; break; } } @@ -2237,26 +2340,24 @@ } // How about subtrack level settings? Assume that compositePrefix caught them? If views then YES -if (compositeAtDefault && !hasViews) +if (reshapeFully && !hasViews) { - for(tdbRef = tdbRefList;tdbRef != NULL; tdbRef = tdbRef->next ) + for(subtrack = tdbComposite->subtracks;subtrack != NULL; subtrack = subtrack->next ) { if (!cartVarsNoneFoundForTdb(cart,subVisHash,subtrack)); { - compositeAtDefault = FALSE; + reshapeFully = FALSE; break; } } } -//warn("compositeAtDefault:%s",compositeAtDefault?"TRUE":"FALSE"); - #ifndef COMPOSITE_VIS_SHAPING_PLAN_B - if (!compositeAtDefault) +if (!reshapeFully) { - slFreeList(&tdbRefList); hashFree(&subVisHash); return FALSE; // Any view cart vars means non-default so do not "shape" composite } #endif///ndef COMPOSITE_VIS_SHAPING_PLAN_B +WARN("reshapeFully:%s",reshapeFully?"TRUE":"FALSE"); // Now shape views and composite to match subtrack specific visibility int count = 0; @@ -2264,83 +2365,40 @@ { for(tdbView = tdbComposite->subtracks;tdbView != NULL; tdbView = tdbView->next ) { - char *view = trackDbSetting(tdbView,"view"); - assert(view != NULL); - count += cartTdbParentShapeVis(cart,tdbView,view,tdbRefList,subVisHash,compositeAtDefault); + char *view = NULL; + if (tdbIsView(tdbView,&view) ) + count += cartTdbParentShapeVis(cart,tdbView,view,subVisHash,reshapeFully); } } else // If no views then composite is not set to fuul but to max of subtracks - count = cartTdbParentShapeVis(cart,tdbComposite,NULL,tdbRefList,subVisHash,compositeAtDefault); + count = cartTdbParentShapeVis(cart,tdbComposite,NULL,subVisHash,reshapeFully); -slFreeList(&tdbRefList); hashFree(&subVisHash); return TRUE; #endif/// defined(COMPOSITE_VIS_SHAPING_PLAN_A) || defined(COMPOSITE_VIS_SHAPING_PLAN_B) } -static boolean cartTdbOverrideSuperTracks(struct trackDb *tdb,struct cart *cart) -/* When when the child of a hidden supertrack is foudn and selected, then shape the supertrack accordingly - Returns TRUE if any cart changes are made */ -{ -// This is only pertinent to supertrack children just turned on -if (!tdbIsSuperTrackChild(tdb)) - return FALSE; - -// Must be from having just selected the track in findTracks. This will carry with it the "_sel" setting. -char setting[512]; -safef(setting,sizeof(setting),"%s_sel",tdb->track); -if (!cartVarExists(cart,setting)) - return FALSE; -cartRemove(cart,setting); // Unlike composite subtracks, supertrack children keep the "_sel" setting only for detecting this moment - -// if parent is not hidden then nothing to do -assert(tdb->parent != NULL && tdbIsSuperTrack(tdb->parent)); -enum trackVisibility vis = tdbVisLimitedByAncestry(cart, tdb->parent, FALSE); -if (vis != tvHide) - return FALSE; - -// Now turn all other supertrack children to hide and the supertrack to visible -struct slRef *childRef; -for(childRef = tdb->parent->children;childRef != NULL; childRef = childRef->next) - { - struct trackDb *child = childRef->val; - if (child == tdb) - continue; - - // Make sure this chile hasn't also just been turned on! - safef(setting,sizeof(setting),"%s_sel",child->track); - if (cartVarExists(cart,setting)) - { - cartRemove(cart,setting); // Unlike composite subtracks, supertrack children keep the "_sel" setting only for detecting this moment - continue; - } - - // hide this sibling if not already hidden - vis = child->visibility; - char *cartVis = cartOptionalString(cart,child->track); - if (cartVis != NULL) - vis = hTvFromString(cartVis); - if (vis != tvHide) - cartSetString(cart,child->track,"hide"); - } -// and finally show the parent -cartSetString(cart,tdb->parent->track,"show"); -return TRUE; -} - boolean cartTdbTreeCleanupOverrides(struct trackDb *tdb,struct cart *newCart,struct hash *oldVars) /* When composite/view settings changes, remove subtrack specific settings Returns TRUE if any cart vars are removed */ { -boolean anythingChanged = cartTdbOverrideSuperTracks(tdb,newCart); +boolean anythingChanged = cartTdbOverrideSuperTracks(newCart,tdb,TRUE); if (!tdbIsComposite(tdb)) return anythingChanged; // vis is a special additive case! composite or view level changes then remove subtrack vis -boolean compositeVisChanged = cartValueHasChanged(newCart,oldVars,tdb->track,TRUE,TRUE); +boolean compositeVisChanged = cartValueHasChanged(newCart,oldVars,tdb->track,TRUE,FALSE); +if (compositeVisChanged) + { + // If just created and if vis is the same as tdb default then vis has not changed + char *cartVis = cartOptionalString(newCart,tdb->track); + char *oldValue = hashFindVal(oldVars,tdb->track); + if (cartVis && oldValue == NULL && hTvFromString(cartVis) == tdb->visibility) + compositeVisChanged = FALSE; + } struct trackDb *tdbView = NULL; struct slPair *oneName = NULL; -char * var = NULL; +char *suffix = NULL; int clensed = 0; // Build list of current settings for composite and views @@ -2354,7 +2412,8 @@ if (!tdbIsView(tdbView,&view)) break; hasViews = TRUE; - safef(setting,sizeof(setting),"%s.",tdbView->track); + safef(setting,sizeof(setting),"%s.",tdbView->track); // unfortunatly setting name could be wgEncodeBroadHistoneViewSig.??? + //safef(setting, sizeof(setting),"%s.%s.",tdb->track,view); // or wgEncodeBroadHistone.Sig.??? HOWEVER: this are picked up by composite prefix struct slPair *changeViewSettings = cartVarsWithPrefix(newCart, setting); changedSettings = slCat(changedSettings, changeViewSettings); } @@ -2378,6 +2437,13 @@ if (!tdbIsView(tdbView,&view)) break; + // If just created and if vis is the same as tdb default then vis has not changed + safef(setting,sizeof(setting),"%s.%s.vis",tdb->track,view); + char *cartVis = cartOptionalString(newCart,setting); + char *oldValue = hashFindVal(oldVars,setting); + if (cartVis && oldValue == NULL && hTvFromString(cartVis) != tdbView->visibility) + viewVisChanged = FALSE; + safef(setting, sizeof(setting),"%s.%s.",tdb->track,view); // unfortunatly setting name could be wgEncodeBroadHistone.Sig.???r char settingAlt[512]; safef(settingAlt,sizeof(settingAlt),"%s.",tdbView->track); // or wgEncodeBroadHistoneViewSig.??? @@ -2385,27 +2451,28 @@ // Walk through settings that match this view while ((oneName = slPopHead(&changedSettings)) != NULL) { - if(startsWith(setting,oneName->val)) - var = oneName->val + strlen(setting); - else if(startsWith(settingAlt,oneName->val)) - var = oneName->val + strlen(settingAlt); + if(startsWith(setting,oneName->name)) + suffix = oneName->name + strlen(setting); + else if(startsWith(settingAlt,oneName->name)) + suffix = oneName->name + strlen(settingAlt); else { slAddHead(&leftOvers,oneName); continue; } - if (sameString(var,"vis")) + if (sameString(suffix,"vis")) { viewVisChanged = TRUE; } - else if (cartRemoveFromTdbTree(newCart,tdbView,var,TRUE) > 0) + else if (cartRemoveFromTdbTree(newCart,tdbView,suffix,TRUE) > 0) clensed++; freeMem(oneName); } if (compositeVisChanged || viewVisChanged) { // vis is a special additive case! + WARN("Removing subtrack vis for %s.%s",tdb->track,view); if (cartRemoveFromTdbTree(newCart,tdbView,NULL,TRUE) > 0) clensed++; } @@ -2416,8 +2483,8 @@ // Now deal with anything remaining at the composite level while ((oneName = slPopHead(&changedSettings)) != NULL) { - var = oneName->val + strlen(tdb->track) + 1; - if(cartRemoveFromTdbTree(newCart,tdb,var,TRUE) > 0) + suffix = oneName->name + strlen(tdb->track) + 1; + if(cartRemoveFromTdbTree(newCart,tdb,suffix,TRUE) > 0) clensed++; freeMem(oneName); }