/******************************************************************************* * dispTree.c Display a Standard HEP event tree. * * This is based on the Constraint Tree Widget , from Douglas Young. * * * * Copyright (c) 1991 Universities Research Association, Inc. * * All rights reserved. * * * * This material resulted from work developed under a Government Contract and * * is subject to the following license: The Government retains a paid-up, * * nonexclusive, irrevocable worldwide license to reproduce, prepare derivative * * works, perform publicly and display publicly by or for the Government, * * including the right to distribute to other Government contractors. Neither * * the United States nor the United States Department of Energy, nor any of * * their employees, makes any warrenty, express or implied, or assumes any * * legal liability or responsibility for the accuracy, completeness, or * * usefulness of any information, apparatus, product, or process disclosed, or * * represents that its use would not infringe privately owned rights. * * * * Fermilab Nirvana GUI Library * * March 18, 1991 * * * * Written by Paul Lebrun * * * *******************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include "spin/Spin.h" #include "tree.h" #include "phase.h" #include "space.h" #include "phaseP.h" #include "dispTree.h" #include "pick.h" #include "drawEvent.h" #include "listNodeHep.h" #include "util/stringUtils.h" /* #define DEBUG */ /* * Function declarations */ static nodehep *hepevt_tree(StdHepWindow *window); static nodehep *make_node(StdHepWindow *window, int *list, int nn ); static void drawNodehep(nodehep *ptr); static void listnodeCB(Widget w, nodehep *ptr, caddr_t callData); static void closeCB(Widget w, StdHepWindow *window); static void closecolorCB(Widget w, StdHepWindow *window); void DispTree(Widget w, StdHepWindow *window) { Widget treediag, sw, tree; int i, nn; int idum = 0; nodehep *head = NULL; int ac,digit; Arg wargs[10]; char title[40]; if ((window->modetreedisp != TREEDISPREAL) && (window->modetreedisp != TREEDISPCODE)) { printf (" Internal error, don't know which tree to set \n"); return; } /* * First create an application shell to hold the scrollable window. */ if (window->modetreedisp == TREEDISPREAL) { if (window->dtree == NULL) { sprintf(title," Tree for StdHep event %d ",window->event.userData); treediag = XmCreateDialogShell(w, title, wargs,0); AddMotifCloseCallback(treediag, closeCB, (void *) window); window->dtree = treediag; /* * Put the tree in a scrolled window, to handle * large trees. */ ac = 0; XtSetArg(wargs[ac], XmNscrollingPolicy, XmAUTOMATIC); ac++; XtSetArg(wargs[ac], XmNwidth, 300); ac++; XtSetArg(wargs[ac], XmNheight, 500); ac++; sw = XtCreateManagedWidget("swindow", xmScrolledWindowWidgetClass, treediag, wargs, ac); window->stree = sw; } else { sprintf(title," Tree for StdHep event %d ",window->event.userData); XtVaSetValues(window->dtree, XmNtitle, title, XmNiconName, "Tree", 0); treediag = window->dtree; sw = window->stree; } /* * Always recreate the tree.. */ if (window->tree != NULL) XtDestroyWidget(window->tree); /* * Create the tree widget. */ tree = XtCreateManagedWidget("tree", XstreeWidgetClass, sw, NULL, 0); window->tree = tree; /* * Create the HEP tree from the STD HEP structure. */ if (window->treehead == NULL) { head = hepevt_tree(window); window->treehead = (int *) head; } else head = (nodehep *) window->treehead; } else { /* Color code.. Make it also scrollable window */ if (window->dtreecolorcode == NULL) { sprintf(title," Color Code Table for Phase and Tree Display "); treediag = XmCreateDialogShell(w, title, wargs,0); AddMotifCloseCallback(treediag, closecolorCB, (void *) window); window->dtreecolorcode = treediag; ac = 0; XtSetArg(wargs[ac], XmNscrollingPolicy, XmAUTOMATIC); ac++; XtSetArg(wargs[ac], XmNwidth, 500); ac++; XtSetArg(wargs[ac], XmNheight, 600); ac++; sw = XtCreateManagedWidget("ColorsParticles", xmScrolledWindowWidgetClass, treediag, wargs, ac); window->streecolorcode = sw; } else { treediag = window->dtreecolorcode; sw = window->streecolorcode; } if (window->treecolorcode != NULL) XtDestroyWidget(window->treecolorcode); tree = XtCreateManagedWidget("tree", XstreeWidgetClass, sw, NULL, 0); window->treecolorcode = tree; if (window->treeheadcolorcode == NULL) { head = hepevt_tree(window); window->treeheadcolorcode = (int *) head; } else head = (nodehep *) window->treeheadcolorcode; } /* * Create the widgets representing the tree. */ ShowTree(window, head, NULL); return; } static nodehep *hepevt_tree(StdHepWindow *window) { int index, indexm, nn, create; int i, j, k, ndone, nprev, imo; int *nlist, *nl1; PhaseParticle *p1, *p2; PhaseEvent *evt; nodehep *top, *cur, *mother, *backcur; /* * At the top of the tree, we place a dummy key */ nn = -1; top = make_node(window, NULL,nn); top->stdid = window->event.eventNum; /* * Now all the particles nodes. */ if (window->modetreedisp == TREEDISPREAL) evt = &(window->event); else evt = &(window->colorcode); create= -1; while (create) { p1 = evt->particles; for(i=0; i < evt->nParticles ; i++, p1++){ create = 0; /* * Look if this node has been already defined... If not defined, do it * In addition, the mother better be created... */ imo = p1->mother - 1; if (p1->mother == 0) mother = top; else { mother = SearchNodes(top, imo); #ifdef DEBUG printf(" make tree... Part %d has mother %d , at node %x \n", i, imo, mother); #endif } if ((SearchNodes(top,i) == NULL) & (mother != NULL)) { /* * We will create a node for this particle.. * Collect all the particles belonging to this node. Conditions * are (i) the particle is off the same type. (ii) the particle * have the same mother (iii) the particles have no daughters */ nn = 1; p2 = evt->particles; for(j=0; j < evt->nParticles ; j++, p2++){ if ( (i != j) && (p1->id == p2->id) && (p1->mother == p2->mother)) { if (p1->firstdaughter == 0) nn++; } } nlist = (int *) XtMalloc(sizeof(int) * nn); *nlist = i; nl1 = nlist; nlist++; p2 = evt->particles; if (nn > 1) { for(j=0; j < evt->nParticles ; j++, p2++ ){ if ( (i != j) && (p1->id == p2->id) && (p1->mother == p2->mother)) { if (p1->firstdaughter == 0) { *nlist = j; nlist++; } } } } /* * Make a node and connect it... */ cur = make_node(window, nl1,nn); cur->mother = mother; create = -1; if(mother->daughter != NULL) { #ifdef DEBUG printf(" make tree.. daughter %x becomes sister of %x \n", mother->daughter, cur); #endif cur->sister = mother->daughter; backcur = cur->sister; backcur->backsister = cur; } mother->daughter = cur; #ifdef DEBUG printf(" make tree.. mother %x has daughter %x \n \n", mother, cur); #endif } } } return (top); } static nodehep *make_node(StdHepWindow *window, int *list, int nn) { int index; int nnp, j, k; int *l, *jid; PhaseParticle *p1; PhaseEvent *evt; nodehep *ptr = (nodehep *) malloc(sizeof(nodehep)); if (window->modetreedisp == TREEDISPREAL) evt = &(window->event); else evt = & (window->colorcode); if (list != NULL) { index = *list; p1 = evt->particles; for(k=0; k< index; k++, p1++); ptr->stdid = p1->id; ptr->stdIndex = list; } else ptr->stdIndex = NULL; ptr->multiplicity = nn; ptr->daughter = ptr->sister = ptr->mother = NULL; ptr->backsister = NULL; ptr->stwidget = NULL; ptr->window = window; #ifdef DEBUG printf (" make_node... multiplicity \%d id. %d ",nn, ptr->stdid); #endif nnp = nn; if (nnp > 10) nnp=10; if (nnp >0 ) { #ifdef DEBUG printf(" Hepevt Indices.."); #endif l = list; for ( j=0; j multiplicity; l = node->stdIndex; for (i=0; i daughter != NULL) { next = SearchNodes(node->daughter,stdi); if (next != NULL) return(next); } if (node->sister != NULL) { next = SearchNodes(node->sister,stdi); if (next != NULL) return(next); } return(NULL); } void FreeTree(nodehep *node) { nodehep *mother, *cur, *sister, *next; int *l; /* * If point to null, assume we are done... */ if (node == NULL) return; /* * Make sure node has no daughter, and if it has, move to * the last granddaughter in the family.. */ cur = node; while (cur->daughter != NULL) { cur = cur->daughter; } /* * reassing the sister to be the first daughter ( if any), * and set the next node to be free to that daughter. if no * such daughter, then set next to be the mother. */ mother = cur->mother; sister = cur->sister; if (sister == NULL) { if (mother != NULL) mother->daughter = NULL; next = mother; } else { mother->daughter = sister; next = sister; } #ifdef DEBUG printf(" freeing tree at %x \n", cur); #endif /* * Now free the node at cur... */ l = cur->stdIndex; if (l != NULL) free(l); free(cur); /* * and get going to the next one .. */ FreeTree(next); } void ShowTree(StdHepWindow *window, nodehep *mother, Widget super_node) { Widget w, sw, parent; Arg wargs[3]; int nm, i, j; int n = 0; int backup; nodehep *lastsister, *curtmp, *cursister, *newmother; Widget *mw; if (window->modetreedisp == TREEDISPREAL) parent = window->tree; else parent = window->treecolorcode; /* * We draw the daughter and her sisters of the mother nodehep * We assume that the mother has already been drawn.. First ensure * we have a real mother... */ if (!mother) return; /* * first time around : if the super node is null, there is no mother * to mother, we assume that we have to draw the top of the tree... */ if(!super_node){ n = 0; XtSetArg(wargs[n], XtNsuperNode, super_node); n++; w = XtCreateManagedWidget("node", xmPushButtonWidgetClass, parent, wargs, n); mother->stwidget = (int *) w; drawNodehep(mother); sw = w; } else { sw = super_node; } cursister = mother->daughter; /* * Find the last sister... For esthetique reasons, we want to * to draw the tree backwards, since it was created backwards for * reason of convenience... */ lastsister = cursister; if (cursister != NULL) { while ( cursister->sister != NULL) { cursister = cursister->sister; } lastsister = cursister; while ( cursister != NULL) { /* * Create a widget for the node, specifying the * given super_node constraint. */ n = 0; XtSetArg(wargs[n], XtNsuperNode, sw); n++; w = XtCreateManagedWidget("node", xmPushButtonWidgetClass, parent, wargs, n); cursister->stwidget = (int *) w; drawNodehep(cursister); cursister = cursister->backsister; } /* cursister = mother->daughter; */ cursister = lastsister; } /* * Now find the next mother, to set the recurrence. * */ if (cursister == NULL) { backup = -1; curtmp = mother; while (backup == -1) { newmother = curtmp->backsister; if (newmother != NULL) backup = 0; else { if (curtmp->mother == NULL) { /* * end backing up, we are at the top of the tree... */ newmother = NULL; backup = 0; } else { /* * backup one level... */ curtmp = curtmp->mother; } } } } else { /* * Look for the most backward daughter */ newmother = lastsister; } if ( newmother != NULL) sw = ((Widget) newmother->stwidget); else sw = NULL; ShowTree(window, newmother, sw); } static void drawNodehep( nodehep *ptr){ char strnum[20], nampart[30]; XmString xstrnum, xnampart, xminfo; Arg wargs[10]; int i, n, lnp, icol, id, selected, itrsel; int *list; Widget w; StdHepWindow *window; Pixel black, white; Display *display; Screen *screen; XVisualInfo info; XmFontList fontList; w = ( Widget) ptr->stwidget; display = XtDisplay(w); screen = XtScreen(w); /* * Check that first if this is a selected node.. */ window = ptr->window; selected = 0; itrsel = 0; if (window->selectedTrack != NO_TRACK) { list = ptr->stdIndex; for (i=0; imultiplicity; i++, list++) if (*list == window->selectedTrack) { selected = 1; break; } } /* * Place the number of particles, first part the Label.. Then convert * the particle id to a the multifont name, then to Xm muilt font string.. * Complete the label */ if ( ptr->multiplicity == -1){ sprintf(strnum, "Top"); xminfo = XmStringLtoRCreate(strnum, XmSTRING_DEFAULT_CHARSET); icol = 11; id = 0; } else { sprintf(strnum, " %d ", ptr->multiplicity); xstrnum = XmStringLtoRCreate(strnum, XmSTRING_DEFAULT_CHARSET); hepnam_(&ptr->stdid,nampart ); /* If greek font is available, use greek letters in particle name */ GET_ONE_RSRC(w, XmNfontList, &fontList); if (CharsetAvailable("greek", fontList)) { hepnmg_(&ptr->stdid, nampart); } else { hepnam_(&ptr->stdid,nampart ); *(char *)strchr(nampart, ' ') = '\0'; } xnampart = MultiFontString(nampart); xminfo = XmStringConcat(xstrnum, xnampart); XmStringFree (xnampart); XmStringFree (xstrnum); /* * Set the color of the button... */ id = ptr->stdid; icol = ParticleColorIndex(id); } /* * Load this crap... */ n = 0; if (selected == 1) { window->selectedNode = (int *) ptr; XtSetArg(wargs[n], XmNshadowThickness, 5); n++; } XtSetArg(wargs[n], XmNlabelString, xminfo); n++; if (XMatchVisualInfo(display, XScreenNumberOfScreen(screen), DefaultDepthOfScreen(screen), PseudoColor, &info)) { XtSetArg(wargs[n], XmNbackground, ParticleColors[icol] ); n++; black = BlackPixelOfScreen(screen); if (ParticleColors[icol] == black) { white = WhitePixelOfScreen(screen); XtSetArg(wargs[n], XmNforeground, white); n++; } } XtSetValues(w, wargs, n); XmStringFree (xminfo); /* * Now add the pointer to the node to the argument forthe call back routine. */ XtAddCallback(w, XmNactivateCallback, (XtCallbackProc) listnodeCB, ptr); } static void listnodeCB(Widget w, nodehep *ptr, caddr_t callData) { StdHepWindow *wim; int i, j, im, *l, *lp; PhaseParticle *p, *pm; int nn, takeit; /* Do nothin if the user click on the tree top.. */ wim = ptr->window; if ((nodehep *) wim->treehead == ptr) return; if (wim->modetreedisp == TREEDISPREAL) { if (wim->selnodeTracks != NULL) XtFree((char *) wim->selnodeTracks); lp = ptr->stdIndex; if (wim->highlightTrackMode == TRACK_NODE) { l = (int *) XtMalloc(sizeof(int) * ptr->multiplicity); wim->selnodeTracks = l; for (i=0; i < ptr->multiplicity; i++, l++, lp++) *l = *lp; wim->selnodeNumTrack = ptr->multiplicity; } else if (wim->highlightTrackMode == TRACK_DESCENDANTS) { /* This is a bit wasteful in memory usage, but faster.. */ l = (int *) XtMalloc(sizeof(int) * wim->event.nParticles); wim->selnodeTracks = l; p = wim->event.particles; nn = 0; for (i=0; i < wim->event.nParticles; i++, p++) { takeit = False; pm = p; while ((!takeit) && (pm->mother != 0)) { if ((pm->mother - 1) == *lp) takeit = True; im = (pm->mother) - 1; pm = wim->event.particles; pm += im; } if (takeit) { nn++; *l = i; l++; } } wim->selnodeNumTrack = nn; } else if (wim->highlightTrackMode == TRACK_DAUGHTERS) { /* This is a bit wasteful in memory usage, but faster.. */ l = (int *) XtMalloc(sizeof(int) * wim->event.nParticles); wim->selnodeTracks = l; p = wim->event.particles; nn = 0; for (i=0; i < wim->event.nParticles; i++, p++) { if (( p->mother - 1) == *lp ) { nn++; *l = i; l++; } } wim->selnodeNumTrack = nn; } else if (wim->highlightTrackMode == TRACK_ANCESTORS) { /* This is a bit wasteful in memory usage, but faster.. */ l = (int *) XtMalloc(sizeof(int) * wim->event.nParticles); wim->selnodeTracks = l; nn = 0; p = wim->event.particles; p += *lp; pm = p; while (pm->mother != NULL) { im = (pm->mother) - 1; pm = wim->event.particles; pm += im; nn++; *l = im; l++; } wim->selnodeNumTrack = nn; } else if (wim->highlightTrackMode == TRACK_MOTHER) { p = wim->event.particles; p += *lp; if (p->mother == NULL) { wim->selnodeTracks = NULL; wim->selnodeNumTrack = 0; } else { im = (p->mother) -1; wim->selnodeTracks = (int *) XtMalloc(sizeof(int)); *wim->selnodeTracks = im; wim->selnodeNumTrack = 1; } } DrawEvent(wim, FALSE); ListNodeHep(wim->dtree, ptr); } else ListNodeHep(wim->dtreecolorcode, ptr); } static void closeCB(Widget w, StdHepWindow *window) { CloseHepTreeWindow(w, window); } void CloseHepTreeWindow(Widget w, StdHepWindow *window) { nodehep *head; /* Set the selected Node to null and redraw the event to remore the possible highlights..*/ window->selectedNode = NULL; window->selnodeNumTrack = 0; if (window->selnodeTracks != NULL) XtFree((char *) window->selnodeTracks); window->selnodeTracks = NULL; DrawEvent(window, FALSE); head = (nodehep *) window->treehead; if (head != NULL) { FreeTree(head); window->treehead = NULL; } window->selectedNode = NULL; if (window->dtree != NULL) XtDestroyWidget(window->dtree); window->nodeWindowShell = NULL; window->dtree = NULL; window->stree = NULL; window->tree = NULL; return; } static void closecolorCB(Widget w, StdHepWindow *window) { XtDestroyWidget(window->dtreecolorcode); window->dtreecolorcode = NULL; window->streecolorcode = NULL; window->treecolorcode = NULL; return; }