src/hg/lib/hui.c 1.259
1.259 2010/02/08 22:10:48 tdreszer
Big changes to move matrix CB normalizeAll code from js to C. These changes should make the large composites less sluggish
Index: src/hg/lib/hui.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/lib/hui.c,v
retrieving revision 1.258
retrieving revision 1.259
diff -b -B -U 4 -r1.258 -r1.259
--- src/hg/lib/hui.c 6 Feb 2010 21:43:01 -0000 1.258
+++ src/hg/lib/hui.c 8 Feb 2010 22:10:48 -0000 1.259
@@ -2106,42 +2106,141 @@
}
return members;
}
-static members_t *subgroupMembersGetByDimension(struct trackDb *parentTdb, char dimension)
-/* Finds the dimension requested and return its associated
- * subgroupMembership, returning the count of members or 0 */
+// No longer used, but it could come back!
+//static members_t *subgroupMembersGetByDimension(struct trackDb *parentTdb, char dimension)
+///* Finds the dimension requested and return its associated
+// * subgroupMembership, returning the count of members or 0 */
+//{
+//int ix;
+//dimensions_t *dimensions = dimensionSettingsGet(parentTdb);
+//if(dimensions!=NULL)
+// {
+// for(ix=0;ix<dimensions->count;ix++)
+// {
+// if(lastChar(dimensions->names[ix]) != dimension)
+// continue;
+// if((strlen(dimensions->names[ix]) == 10 && startsWith("dimension",dimensions->names[ix]))
+// || (strlen(dimensions->names[ix]) == 4 && startsWith("dim",dimensions->names[ix])))
+// {
+// members_t *members = subgroupMembersGet(parentTdb, dimensions->subgroups[ix]);
+// dimensionsFree(&dimensions);
+// return members;
+// }
+// }
+// dimensionsFree(&dimensions);
+// }
+//return NULL;
+//}
+
+static void subgroupMembersFree(members_t **members)
+/* frees memory for subgroupMembers lists */
{
-int ix;
-dimensions_t *dimensions = dimensionSettingsGet(parentTdb);
-if(dimensions!=NULL)
+if(members && *members)
{
- for(ix=0;ix<dimensions->count;ix++)
+ freeMem((*members)->setting);
+ freeMem((*members)->names);
+ freeMem((*members)->values);
+ freez(members);
+ }
+}
+
+enum
+{
+ dimV=0, // View first
+ dimX=1, // X & Y next
+ dimY=2,
+ dimA=3, // dimA is start of first of the optional non-matrix, non-view dimensions
+};
+
+typedef struct _membersForAll {
+ int abcCount;
+ int dimMax;
+ dimensions_t *dimensions;
+ members_t* members[27];
+ char* checkedTags[27];
+} membersForAll_t;
+
+static char* abcMembersChecked(struct trackDb *parentTdb, struct cart *cart, members_t* members, char letter)
+/* returns a string of subGroup tags which are currently checked */
+{
+struct dyString *currentlyCheckedTags = NULL;
+char settingName[SMALLBUF];
+// Need a string of subGroup tags which are currently checked
+safef(settingName,sizeof(settingName),"dimension%cchecked",letter);
+char *dimCheckedDefaults = trackDbSettingOrDefault(parentTdb,settingName,"");
+boolean currentlySet=FALSE;
+int mIx;
+for(mIx=0;mIx<members->count;mIx++)
{
- if(lastChar(dimensions->names[ix]) != dimension)
- continue;
- if((strlen(dimensions->names[ix]) == 10 && startsWith("dimension",dimensions->names[ix]))
- || (strlen(dimensions->names[ix]) == 4 && startsWith("dim",dimensions->names[ix])))
+ char objName[SMALLBUF];
+ safef(objName, sizeof(objName), "%s.mat_%s_dim%c_cb",parentTdb->tableName,members->names[mIx],letter);
+ currentlySet=(NULL!=findWordByDelimiter(members->names[mIx],',',dimCheckedDefaults));
+ currentlySet=cartUsualBoolean(cart,objName,currentlySet);
+ if(currentlySet)
+ {
+ if(currentlyCheckedTags == NULL)
+ currentlyCheckedTags = dyStringCreate(members->names[mIx]);
+ else
{
- members_t *members = subgroupMembersGet(parentTdb, dimensions->subgroups[ix]);
- dimensionsFree(&dimensions);
- return members;
+ dyStringAppendC(currentlyCheckedTags,',');
+ dyStringAppend(currentlyCheckedTags,members->names[mIx]);
}
}
- dimensionsFree(&dimensions);
}
+if(currentlyCheckedTags)
+ return dyStringCannibalize(¤tlyCheckedTags);
return NULL;
}
-static void subgroupMembersFree(members_t **members)
-/* frees memory for subgroupMembers lists */
+static membersForAll_t* membersForAllSubGroupsGet(struct trackDb *parentTdb, struct cart *cart)
+/* Returns all the parents subGroups and members */
{
-if(members && *members)
+membersForAll_t *membersForAll = needMem(sizeof(membersForAll_t));
+membersForAll->members[dimV]=subgroupMembersGet(parentTdb,"view");
+membersForAll->dimMax=dimA; // This can expand, depending upon ABC dimensions
+membersForAll->dimensions = dimensionSettingsGet(parentTdb);
+int ix;
+for(ix=0;ix<membersForAll->dimensions->count;ix++)
{
- freeMem((*members)->setting);
- freeMem((*members)->names);
- freeMem((*members)->values);
- freez(members);
+ char letter = lastChar(membersForAll->dimensions->names[ix]);
+ if(letter != 'X' && letter != 'Y')
+ {
+ membersForAll->members[membersForAll->dimMax]=subgroupMembersGet(parentTdb, membersForAll->dimensions->subgroups[ix]);
+ if(cart != NULL)
+ membersForAll->checkedTags[membersForAll->dimMax] = abcMembersChecked(parentTdb,cart,membersForAll->members[membersForAll->dimMax],letter);
+ membersForAll->dimMax++;
+ }
+ else if(letter == 'X')
+ membersForAll->members[dimX]=subgroupMembersGet(parentTdb, membersForAll->dimensions->subgroups[ix]);
+ else
+ membersForAll->members[dimY]=subgroupMembersGet(parentTdb, membersForAll->dimensions->subgroups[ix]);
+ }
+membersForAll->abcCount = membersForAll->dimMax - dimA;
+
+return membersForAll;
+}
+
+static void membersForAllSubGroupsFree(membersForAll_t** membersForAllPtr)
+/* frees memory for membersForAllSubGroups struct */
+{
+if(membersForAllPtr && *membersForAllPtr)
+ {
+ membersForAll_t* membersForAll = *membersForAllPtr;
+ subgroupMembersFree(&(membersForAll->members[dimX]));
+ subgroupMembersFree(&(membersForAll->members[dimY]));
+ subgroupMembersFree(&(membersForAll->members[dimV]));
+ int ix;
+ for(ix=dimA;ix<membersForAll->dimMax;ix++)
+ {
+ //ASSERT(membersForAll->members[ix] != NULL);
+ subgroupMembersFree(&(membersForAll->members[ix]));
+ if(membersForAll->checkedTags[ix])
+ freeMem(membersForAll->checkedTags[ix]);
+ }
+ dimensionsFree(&(membersForAll->dimensions));
+ freez(membersForAllPtr);
}
}
int multViewCount(struct trackDb *parentTdb)
@@ -2226,8 +2325,32 @@
}
}
return membership;
}
+
+static boolean membershipInAllCurrentABCs(membership_t *membership,membersForAll_t*membersForAll)
+/* looks for a match between a membership set and ABC dimensions currently checked */
+{
+int mIx,aIx;
+for (aIx = dimA; aIx <membersForAll->dimMax;aIx++)
+ {
+ if(membersForAll->checkedTags[aIx] == NULL) // None checked
+ return FALSE;
+ int found = FALSE;
+ for (mIx = 0; mIx <membership->count;mIx++)
+ {
+ if(findWordByDelimiter(membership->membership[mIx],',',membersForAll->checkedTags[aIx]))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ if(!found)
+ return FALSE; // Not in one of the ABC dims
+ }
+return TRUE; // passed all tests so must be on all
+}
+
static void subgroupMembershipFree(membership_t **membership)
/* frees subgroupMembership memory */
{
if(membership && *membership)
@@ -2241,8 +2364,20 @@
freez(membership);
}
}
+boolean subtrackInAllCurrentABCs(struct trackDb *childTdb,membersForAll_t*membersForAll)
+/* looks for a match between a membership set and ABC dimensions currently checked */
+{
+membership_t *membership = subgroupMembershipGet(childTdb);
+if(membership == NULL)
+ return FALSE;
+boolean found = membershipInAllCurrentABCs(membership,membersForAll);
+subgroupMembershipFree(&membership);
+return found;
+}
+
+
boolean subgroupFind(struct trackDb *childTdb, char *name,char **value)
/* looks for a single tag in a child track's subGroups setting */
{
if(value != NULL)
@@ -3046,8 +3181,25 @@
if(tdbIsComposite(tdb))
printf("<script type='text/javascript'>compositeCfgRegisterOnchangeAction(\"%s\")</script>\n",prefix);
}
+static int subtrackFourStateChecked(struct trackDb *subtrack, struct cart *cart)
+/* Returns the four state checked state of the subtrack */
+{
+char * setting = NULL;
+char objName[SMALLBUF];
+int fourState = 0;
+if ((setting = trackDbLocalSetting(subtrack, "parent")) != NULL)
+ {
+ if(findWordByDelimiter("off",' ',setting) == NULL)
+ fourState = 1;
+ }
+safef(objName, sizeof(objName), "%s_sel", subtrack->tableName);
+return cartCgiUsualInt(cart, objName, fourState);
+}
+#define fourStateChecked(fourState) ((fourState) == 1 || (fourState) == -1)
+#define fourStateEnabled(fourState) ((fourState) >= 0)
+
static void compositeUiSubtracks(char *db, struct cart *cart, struct trackDb *parentTdb,
boolean selectedOnly, char *primarySubtrack)
/* Display list of subtracks and descriptions with checkboxes to control visibility and possibly other
* nice things including links to schema and metadata and a release date. */
@@ -3055,9 +3207,8 @@
struct trackDb *subtrack;
char *primaryType = getPrimaryType(primarySubtrack, parentTdb);
char htmlIdentifier[SMALLBUF];
struct dyString *dyHtml = newDyString(SMALLBUF);
-char *words[5];
char *colors[2] = { COLOR_BG_DEFAULT,
COLOR_BG_ALTDEFAULT };
int colorIx = COLOR_BG_DEFAULT_IX; // Start with non-default allows alternation
boolean dependentCfgsNeedBinding = FALSE;
@@ -3071,40 +3222,11 @@
if(dividers)
lastDivide = needMem(sizeof(char*)*dividers->count);
hierarchy_t *hierarchy = hierarchySettingGet(parentTdb);
-enum
-{
- dimV=0, // View first
- dimX=1, // X & Y next
- dimY=2,
- dimA=3, // dimA is start of first of the optional non-matrix, non-view dimensions
-};
-int dimMax=dimA; // This can expand, depending upon ABC dimensions
-members_t* dimensions[27]; // Just pointers, so make a bunch!
-memset((char *)dimensions,0,sizeof(dimensions));
-dimensions_t *dims = dimensionSettingsGet(parentTdb);
-if(dims != NULL)
- {
- int ix;
- for(ix=0;ix<dims->count;ix++)
- {
- char letter = lastChar(dims->names[ix]);
- if(letter != 'X' && letter != 'Y')
- {
- dimensions[dimMax]=subgroupMembersGet(parentTdb, dims->subgroups[ix]);
- dimMax++;
- }
- else if(letter == 'X')
- dimensions[dimX]=subgroupMembersGet(parentTdb, dims->subgroups[ix]);
- else
- dimensions[dimY]=subgroupMembersGet(parentTdb, dims->subgroups[ix]);
- }
- dimensionsFree(&dims);
- }
-dimensions[dimV]=subgroupMembersGet(parentTdb,"view");
+membersForAll_t* membersForAll = membersForAllSubGroupsGet(parentTdb,NULL);
int dimCount=0,di;
-for(di=0;di<dimMax;di++) { if(dimensions[di]) dimCount++; }
+for(di=0;di<membersForAll->dimMax;di++) { if(membersForAll->members[di]) dimCount++; }
sortOrder_t* sortOrder = sortOrderGet(cart,parentTdb);
boolean preSorted = FALSE;
boolean useDragAndDrop = sameOk("subTracks",trackDbSetting(parentTdb, "dragAndDrop"));
@@ -3205,28 +3327,17 @@
for (subtrackRef = subtrackRefList; subtrackRef != NULL; subtrackRef = subtrackRef->next)
{
subtrack = subtrackRef->val;
- boolean checkedCB = TRUE;
- boolean enabledCB = TRUE;
boolean isPrimary = FALSE;
- char *setting;
int ix;
- if ((setting = trackDbLocalSetting(subtrack, "parent")) != NULL)
- {
- if (chopLine(cloneString(setting), words) >= 2)
- checkedCB = differentString(words[1], "off");
- }
- safef(htmlIdentifier, sizeof(htmlIdentifier), "%s_sel", subtrack->tableName);
- setting = cartOptionalString(cart, htmlIdentifier);
- if(setting != NULL)
- {
- int state = atoi(setting);
- checkedCB = (state == 1 || state == -1); // checked/eanbled:1 unchecked/enabled:0 checked/disabled:-1 unchecked/disabled:-2
- enabledCB = (state >= 0);
- }
+ int fourState = subtrackFourStateChecked(subtrack,cart);
+ boolean checkedCB = fourStateChecked(fourState);
+ boolean enabledCB = fourStateEnabled(fourState);
isPrimary = (primarySubtrack &&
sameString(subtrack->tableName, primarySubtrack));
+ safef(htmlIdentifier, sizeof(htmlIdentifier), "%s_sel", subtrack->tableName);
+
if (primarySubtrack)
{
if (isPrimary)
@@ -3256,26 +3367,27 @@
if( divisionIfNeeded(lastDivide,dividers,membership) )
colorIx = (colorIx == COLOR_BG_DEFAULT_IX ? COLOR_BG_ALTDEFAULT_IX : COLOR_BG_DEFAULT_IX);
}
- char *id = checkBoxIdMakeForTrack(subtrack,dimensions,dimMax,membership); // view is known tag
+ char *id = checkBoxIdMakeForTrack(subtrack,membersForAll->members,membersForAll->dimMax,membership); // view is known tag
printf("<TR valign='top' BGCOLOR=\"%s\"",colors[colorIx]);
if(useDragAndDrop)
printf(" class='trDraggable' title='Drag to Reorder'");
- printf(" id=\"tr_%s\" nowrap%s>\n<TD>",id,(selectedOnly?" style='display:none'":""));
+ printf(" id=\"tr_%s\" nowrap%s>\n",id,(selectedOnly?" style='display:none'":""));
+ printf("<TD%s>",(enabledCB?"":" title='view is hidden' style='cursor: pointer;'"));
dyStringClear(dyHtml);
- dyStringPrintf(dyHtml, "onclick='matSubCbClick(this);' onmouseover=\"this.style.cursor='default';\" class=\"subCB");
- for(di=dimX;di<dimMax;di++)
+ dyStringAppend(dyHtml, "subCB");
+ for(di=dimX;di<membersForAll->dimMax;di++)
{
- if(dimensions[di] && -1 != (ix = stringArrayIx(dimensions[di]->tag, membership->subgroups, membership->count)))
- dyStringPrintf(dyHtml, " %s",membership->membership[ix]);
+ if(membersForAll->members[di] && -1 != (ix = stringArrayIx(membersForAll->members[di]->tag, membership->subgroups, membership->count)))
+ dyStringPrintf(dyHtml," %s",membership->membership[ix]);
}
// Save view for last
- if(dimensions[dimV] && -1 != (ix = stringArrayIx(dimensions[dimV]->tag, membership->subgroups, membership->count)))
+ if(membersForAll->members[dimV] && -1 != (ix = stringArrayIx(membersForAll->members[dimV]->tag, membership->subgroups, membership->count)))
dyStringPrintf(dyHtml, " %s",membership->membership[ix]);
- dyStringAppendC(dyHtml,'"');
- cgiMakeCheckBox2BoolWithIdAndJS(htmlIdentifier,checkedCB,enabledCB,id,dyStringContents(dyHtml));
+ cgiMakeCheckBoxFourWay(htmlIdentifier,checkedCB,enabledCB,id,dyStringContents(dyHtml),"onclick='matSubCbClick(this);' onmouseover=\"this.style.cursor='default';\"");
+
if(sortOrder != NULL || useDragAndDrop)
{
safef(htmlIdentifier, sizeof(htmlIdentifier), "%s.priority", subtrack->tableName);
float priority = (float)cartUsualDouble(cart, htmlIdentifier, subtrack->priority);
@@ -3354,10 +3466,9 @@
if (!primarySubtrack)
puts("<script type='text/javascript'>matInitializeMatrix();</script>");
if(dependentCfgsNeedBinding)
cfgLinkToDependentCfgs(parentTdb,parentTdb->tableName);
-for(di=0;di<dimMax;di++)
- subgroupMembersFree(&dimensions[di]);
+membersForAllSubGroupsFree(&membersForAll);
dyStringFree(&dyHtml)
sortOrderFree(&sortOrder);
dividersFree(÷rs);
hierarchyFree(&hierarchy);
@@ -5112,79 +5223,62 @@
else if (left && dimensionY && childTdb != NULL)
printf("<TH ALIGN=RIGHT nowrap>%s</TH>\n",labelWithVocabLink(parentTdb,childTdb,dimensionY->tag,dimensionY->values[ixY]));
}
-static int displayABCdimensions(struct cart *cart, struct trackDb *parentTdb, struct slRef *subtrackRefList, int expected)
+static int displayABCdimensions(struct cart *cart, struct trackDb *parentTdb, struct slRef *subtrackRefList, membersForAll_t* membersForAll)
/* This will walk through all declared nonX&Y dimensions (X and Y is the 2D matrix of CBs.
NOTE: ABC dims are only supported if there are X & Y both. Also expected number should be passed in */
{
int count=0,ix;
-for(ix=0;ix<26;ix++)
+for(ix=dimA;ix<membersForAll->dimMax;ix++)
{
- char dimLetter = 'A' + ix;
- if(dimLetter == 'X' || dimLetter == 'Y')
- continue;
-
- members_t *dim = subgroupMembersGetByDimension(parentTdb,dimLetter);
- if(dim==NULL)
+ if(membersForAll->members[ix]==NULL)
continue;
- if(dim->count<1)
- {
- subgroupMembersFree(&dim);
+ if(membersForAll->members[ix]->count<1)
continue;
- }
count++;
- int cells[dim->count]; // The Z dimension is a separate 1D matrix
- struct trackDb *tdbs[dim->count];
+ int cells[membersForAll->members[ix]->count];
+ struct trackDb *tdbs[membersForAll->members[ix]->count];
memset(cells, 0, sizeof(cells));
memset(tdbs, 0, sizeof(tdbs));
+ // Are there subtracks for each member of the subGroup?
int aIx;
struct slRef *subtrackRef;
for (subtrackRef = subtrackRefList; subtrackRef != NULL; subtrackRef = subtrackRef->next)
{
struct trackDb *subtrack = subtrackRef->val;
char *value;
- if(subgroupFind(subtrack,dim->tag,&value))
+ if(subgroupFind(subtrack,membersForAll->members[ix]->tag,&value))
{
- aIx = stringArrayIx(value,dim->names,dim->count);
+ aIx = stringArrayIx(value,membersForAll->members[ix]->names,membersForAll->members[ix]->count);
cells[aIx]++;
tdbs[aIx] = subtrack;
subgroupFree(&value);
}
}
if(count==1) // First time set up a table
puts("<BR><TABLE>");
- printf("<TR><TH valign=top align='right'> <B><EM>%s</EM></B>:</TH>",dim->title);
- char settingName[32];
- safef(settingName,sizeof(settingName),"dimension%cchecked",dimLetter);
- char *dimCheckedDefaults = trackDbSettingOrDefault(parentTdb,settingName,"");
- boolean alreadySet=FALSE;
- for(aIx=0;aIx<dim->count;aIx++)
+ printf("<TR><TH valign=top align='right'> <B><EM>%s</EM></B>:</TH>",membersForAll->members[ix]->title);
+ for(aIx=0;aIx<membersForAll->members[ix]->count;aIx++)
{
if(tdbs[aIx] != NULL && cells[aIx]>0)
{
printf("<TH align=left nowrap>");
char objName[SMALLBUF];
char javascript[JBUFSIZE];
- safef(objName, sizeof(objName), "%s.mat_%s_dim%c_cb",parentTdb->tableName,dim->names[aIx],dimLetter);
- alreadySet=(NULL!=findWordByDelimiter(dim->names[aIx],',',dimCheckedDefaults));
- alreadySet=cartUsualBoolean(cart,objName,alreadySet);
- safef(javascript,sizeof(javascript),"onclick='matCbClick(this);' class=\"matCB abc %s\"",dim->names[aIx]);
- // TODO Set classes properly (if needed!!!) The classes could be
- // a) matCB to keep the list of all
- // b) dimZ or some other designator but the current dimZ would work
- // c) a new one (subgroup tag?) to break dimZs into subsets. But how to recognize the subsets? Will js need to pick by name?
+ boolean alreadySet=FALSE;
+ if(membersForAll->checkedTags[ix] != NULL)
+ alreadySet=(NULL!=findWordByDelimiter(membersForAll->members[ix]->names[aIx],',',membersForAll->checkedTags[ix]));
+ safef(javascript,sizeof(javascript),"onclick='matCbClick(this);' class=\"matCB abc %s\"",membersForAll->members[ix]->names[aIx]);
+ // TODO Set classes properly (if needed!!!) The class abc works but what about a b or c?
cgiMakeCheckBoxJS(objName,alreadySet,javascript);
- printf("%s",labelWithVocabLink(parentTdb,tdbs[aIx],dim->tag,dim->values[aIx]));
+ printf("%s",labelWithVocabLink(parentTdb,tdbs[aIx],membersForAll->members[ix]->tag,membersForAll->members[ix]->values[aIx]));
puts("</TH>");
}
}
puts("</TR>");
- subgroupMembersFree(&dim);
- if(count==expected)
- break;
}
if(count>0)
puts("</TABLE>");
return count;
@@ -5209,60 +5303,80 @@
//int ix;
char objName[SMALLBUF];
char javascript[JBUFSIZE];
-dimensions_t *dims = dimensionSettingsGet(parentTdb);
-if(dims == NULL)
+membersForAll_t* membersForAll = membersForAllSubGroupsGet(parentTdb,cart);
+if(membersForAll == NULL)
+ return FALSE;
+if(membersForAll->dimensions == NULL)
+ {
+ membersForAllSubGroupsFree(&membersForAll);
return FALSE;
+ }
int ixX,ixY;
-members_t *dimensionX = subgroupMembersGetByDimension(parentTdb,'X');
-members_t *dimensionY = subgroupMembersGetByDimension(parentTdb,'Y');
-if(dimensionX == NULL && dimensionY == NULL) // Must be an X or Y dimension
+if(membersForAll->members[dimX] == NULL && membersForAll->members[dimY] == NULL) // Must be an X or Y dimension
return FALSE;
// Get list of leaf subtracks to work with
struct slRef *subtrackRef, *subtrackRefList = trackDbListGetRefsToDescendantLeaves(parentTdb->subtracks);
struct trackDb *subtrack;
// use array of char determine all the cells (in X,Y,Z dimensions) that are actually populated
char *value;
-int sizeOfX = dimensionX?dimensionX->count:1;
-int sizeOfY = dimensionY?dimensionY->count:1;
+int sizeOfX = membersForAll->members[dimX]?membersForAll->members[dimX]->count:1;
+int sizeOfY = membersForAll->members[dimY]?membersForAll->members[dimY]->count:1;
int cells[sizeOfX][sizeOfY]; // There needs to be atleast one element in dimension
+int chked[sizeOfX][sizeOfY]; // How many subCBs are checked per matCB?
+int enabd[sizeOfX][sizeOfY]; // How many subCBs are enabled per matCB?
struct trackDb *tdbsX[sizeOfX]; // Representative subtracks
struct trackDb *tdbsY[sizeOfY];
memset(cells, 0, sizeof(cells));
+memset(chked, 0, sizeof(chked));
+memset(enabd, 0, sizeof(chked));
memset(tdbsX, 0, sizeof(tdbsX));
memset(tdbsY, 0, sizeof(tdbsY));
for (subtrackRef = subtrackRefList; subtrackRef != NULL; subtrackRef = subtrackRef->next)
{
subtrack = subtrackRef->val;
- ixX = (dimensionX ? -1 : 0 );
- ixY = (dimensionY ? -1 : 0 );
- if(dimensionX && subgroupFind(subtrack,dimensionX->tag,&value))
+ ixX = (membersForAll->members[dimX] ? -1 : 0 );
+ ixY = (membersForAll->members[dimY] ? -1 : 0 );
+ if(membersForAll->members[dimX] && subgroupFind(subtrack,membersForAll->members[dimX]->tag,&value))
{
- ixX = stringArrayIx(value,dimensionX->names,dimensionX->count);
+ ixX = stringArrayIx(value,membersForAll->members[dimX]->names,membersForAll->members[dimX]->count);
tdbsX[ixX] = subtrack;
subgroupFree(&value);
}
- if(dimensionY && subgroupFind(subtrack,dimensionY->tag,&value))
+ if(membersForAll->members[dimY] && subgroupFind(subtrack,membersForAll->members[dimY]->tag,&value))
{
- ixY = stringArrayIx(value,dimensionY->names,dimensionY->count);
+ ixY = stringArrayIx(value,membersForAll->members[dimY]->names,membersForAll->members[dimY]->count);
tdbsY[ixY] = subtrack;
subgroupFree(&value);
}
if(ixX > -1 && ixY > -1)
+ {
cells[ixX][ixY]++;
+ // FIXME This mess should be done once per subtrack, stored in the struct, then reused when subCBs are written out.
+ int fourState = subtrackFourStateChecked(subtrack,cart);
+ if(fourStateEnabled(fourState) >= 0) // hidden views are handled by 4-way CBs: only count enabled
+ {
+ if(subtrackInAllCurrentABCs(subtrack,membersForAll)) // Only bother if the subtrack is found in all ABC dims checked
+ {
+ enabd[ixX][ixY]++;
+ if(fourStateChecked(fourState) == 1)
+ chked[ixX][ixY]++;
+ }
+ }
+ }
}
//puts("<B>Select subtracks by characterization:</B><BR>");
printf("<B>Select subtracks by ");
-if(dimensionX && !dimensionY)
- safef(javascript, sizeof(javascript), "%s:</B>",dimensionX->title);
-else if(!dimensionX && dimensionY)
- safef(javascript, sizeof(javascript), "%s:</B>",dimensionY->title);
-else if(dims->count == 2)
- safef(javascript, sizeof(javascript), "%s and %s:</B>",dimensionX->title,dimensionY->title);
+if(membersForAll->members[dimX] && !membersForAll->members[dimY])
+ safef(javascript, sizeof(javascript), "%s:</B>",membersForAll->members[dimX]->title);
+else if(!membersForAll->members[dimX] && membersForAll->members[dimY])
+ safef(javascript, sizeof(javascript), "%s:</B>",membersForAll->members[dimY]->title);
+else if(membersForAll->dimensions->count == 2)
+ safef(javascript, sizeof(javascript), "%s and %s:</B>",membersForAll->members[dimX]->title,membersForAll->members[dimY]->title);
else
safef(javascript, sizeof(javascript), "multiple variables:</B>");
puts(strLower(javascript));
@@ -5270,81 +5384,87 @@
puts("(<A HREF=\"../goldenPath/help/multiView.html\" title='Help on views' TARGET=_BLANK>help</A>)\n");
puts("<BR>\n");
-if(dims->count > 2)
+if(membersForAll->dimensions->count > 2)
{
- displayABCdimensions(cart,parentTdb,subtrackRefList, dims->count - 2); // No dimABCs without X & Y both
+ displayABCdimensions(cart,parentTdb,subtrackRefList,membersForAll); // No dimABCs without X & Y both
}
-dimensionsFree(&dims);
printf("<TABLE class='greenBox' bgcolor='%s' borderColor='%s'>\n",COLOR_BG_DEFAULT,COLOR_BG_DEFAULT);
-matrixXheadings(parentTdb,dimensionX,dimensionY,tdbsX,TRUE);
+matrixXheadings(parentTdb,membersForAll->members[dimX],membersForAll->members[dimY],tdbsX,TRUE);
// Now the Y by X matrix
int cntX=0,cntY=0;
for (ixY = 0; ixY < sizeOfY; ixY++)
{
- if(tdbsY[ixY] != NULL || dimensionY == NULL)
+ if(tdbsY[ixY] != NULL || membersForAll->members[dimY] == NULL)
{
cntY++;
- assert(!dimensionY || ixY < dimensionY->count);
+ assert(!membersForAll->members[dimY] || ixY < membersForAll->members[dimY]->count);
printf("<TR ALIGN=CENTER BGCOLOR=\"#FFF9D2\">");
- matrixYheadings(parentTdb, dimensionX,dimensionY,ixY,tdbsY[ixY],TRUE);
+ matrixYheadings(parentTdb, membersForAll->members[dimX],membersForAll->members[dimY],ixY,tdbsY[ixY],TRUE);
#define MAT_CB_SETUP "<INPUT TYPE=CHECKBOX NAME='%s' VALUE=on %s>"
#define MAT_CB(name,js) printf(MAT_CB_SETUP,(name),(js));
for (ixX = 0; ixX < sizeOfX; ixX++)
{
- if(tdbsX[ixX] != NULL || dimensionX == NULL)
+ if(tdbsX[ixX] != NULL || membersForAll->members[dimX] == NULL)
{
- assert(!dimensionX || ixX < dimensionX->count);
+ assert(!membersForAll->members[dimX] || ixX < membersForAll->members[dimX]->count);
if(cntY==1) // Only do this on the first good Y
cntX++;
- if(dimensionX && ixX == dimensionX->count)
+ if(membersForAll->members[dimX] && ixX == membersForAll->members[dimX]->count)
break;
if(cells[ixX][ixY] > 0)
{
+ boolean halfChecked = (chked[ixX][ixY] > 0 && chked[ixX][ixY] != enabd[ixX][ixY]);
struct dyString *dyJS = dyStringCreate("onclick='matCbClick(this);'");
- if(dimensionX && dimensionY)
+ if(membersForAll->members[dimX] && membersForAll->members[dimY])
{
- safef(objName, sizeof(objName), "mat_%s_%s_cb", dimensionX->names[ixX],dimensionY->names[ixY]);
+ safef(objName, sizeof(objName), "mat_%s_%s_cb", membersForAll->members[dimX]->names[ixX],membersForAll->members[dimY]->names[ixY]);
}
else
{
- safef(objName, sizeof(objName), "mat_%s_cb", (dimensionX ? dimensionX->names[ixX] : dimensionY->names[ixY]));
+ safef(objName, sizeof(objName), "mat_%s_cb", (membersForAll->members[dimX] ? membersForAll->members[dimX]->names[ixX] : membersForAll->members[dimY]->names[ixY]));
}
- puts("<TD>");
+ //printf("<TD title='subCBs:%d checked:%d enabled:%d'>\n",cells[ixX][ixY],chked[ixX][ixY],enabd[ixX][ixY]);
+ printf("<TD%s>\n",(halfChecked?" title='Not all associated subtracks have been selected'":""));
dyStringPrintf(dyJS, " class=\"matCB");
- if(dimensionX)
- dyStringPrintf(dyJS, " %s",dimensionX->names[ixX]);
- if(dimensionY)
- dyStringPrintf(dyJS, " %s",dimensionY->names[ixY]);
+ if(halfChecked)
+ dyStringPrintf(dyJS, " halfVis"); // needed for later js identification!
+ if(membersForAll->members[dimX])
+ dyStringPrintf(dyJS, " %s",membersForAll->members[dimX]->names[ixX]);
+ if(membersForAll->members[dimY])
+ dyStringPrintf(dyJS, " %s",membersForAll->members[dimY]->names[ixY]);
dyStringAppendC(dyJS,'"');
+ if(chked[ixX][ixY] > 0)
+ dyStringAppend(dyJS," CHECKED");
+ if(halfChecked)
+ dyStringAppend(dyJS," style='filter:alpha(opacity=50)'"); // overkill with class=halfVis but IE doesn't cooperate!
MAT_CB(objName,dyStringCannibalize(&dyJS)); // X&Y are set by javascript page load
puts("</TD>");
}
else
puts("<TD> </TD>");
}
}
- if(dimensionX && cntX>MATRIX_RIGHT_BUTTONS_AFTER)
- matrixYheadings(parentTdb, dimensionX,dimensionY,ixY,tdbsY[ixY],FALSE);
+ if(membersForAll->members[dimX] && cntX>MATRIX_RIGHT_BUTTONS_AFTER)
+ matrixYheadings(parentTdb, membersForAll->members[dimX],membersForAll->members[dimY],ixY,tdbsY[ixY],FALSE);
puts("</TR>\n");
}
}
-if(dimensionY && cntY>MATRIX_BOTTOM_BUTTONS_AFTER)
- matrixXheadings(parentTdb,dimensionX,dimensionY,tdbsX,FALSE);
+if(membersForAll->members[dimY] && cntY>MATRIX_BOTTOM_BUTTONS_AFTER)
+ matrixXheadings(parentTdb,membersForAll->members[dimX],membersForAll->members[dimY],tdbsX,FALSE);
puts("</TD></TR></TABLE>");
-subgroupMembersFree(&dimensionX);
-subgroupMembersFree(&dimensionY);
puts("<BR>\n");
+membersForAllSubGroupsFree(&membersForAll);
return TRUE;
}
static boolean hCompositeUiAllButtons(char *db, struct cart *cart, struct trackDb *parentTdb, char *formName)