// barChartTcl.C /* $Log: barChartTcl.C,v $ /* Revision 1.14 1996/05/15 18:03:48 tamches /* added newMetricMaxValCallbackCommand /* * Revision 1.13 1996/04/30 20:45:24 tamches * moved some Dg2 cmds here * added functionality for phase label displayed in the tk window * * Revision 1.12 1996/01/17 19:44:07 tamches * shuffled colors a bit * * Revision 1.11 1996/01/11 01:53:42 tamches * added long2shortFocusNameCommand to compute short focus names * * Revision 1.10 1996/01/10 19:36:12 tamches * launchBarChart now takes 4 args instead of 7 * * Revision 1.9 1996/01/10 02:24:25 tamches * dataFormatHasChangedCommand now takes in an arg * added getMetricColorNameCommand * hardcoded barColorNames here * * Revision 1.8 1995/09/22 19:25:29 tamches * removed warnings under g++ 2.7.0 * * Revision 1.7 1994/11/06 10:24:59 tamches * minor cleanups (especially comments) * * Revision 1.6 1994/10/14 10:29:33 tamches * commented out diagnosted message when gracefully closing * * Revision 1.5 1994/10/13 00:52:38 tamches * Minor additions to support a new command related to sorting * of resources * * Revision 1.4 1994/10/10 23:08:44 tamches * preliminary changes on the way to swapping the x and y axes * * Revision 1.3 1994/10/10 14:36:17 tamches * fixed some resizing bugs * * Revision 1.2 1994/09/29 20:05:37 tamches * minor cvs fixes * * Revision 1.1 1994/09/29 19:51:38 tamches * initial implementation. * Receiving point for visi lib callback routines. Pretty much * just calls the appropriate class member function in barChart.C * */ #include #include "Vector.h" #include "String.h" #include "tcl.h" #include "tk.h" #include "dg2.h" // for dataGrid[][] #include "visi/h/visualization.h" #include "barChart.h" bool barChartIsValid = false; // set to true ** after ** barChart::barChart // until then, callbacks check this flag and do nothing /* ************************************************************* */ void updatePhaseLabelIfFirstTime() { static bool firstTime = true; if (!firstTime) return; int phaseHandle = visi_GetMyPhaseHandle(); if (phaseHandle < -1) return; // sorry, not yet defined extern Tcl_Interp *MainInterp; const char *phaseName = visi_GetMyPhaseName(); if (phaseName == NULL) { // ugh; we have a current phase, but the name isn't yet known myTclEval(MainInterp, string(".bargrph.phaseName config -text \"Phase: Current Phase\"")); return; // return w/o setting firstTime to false } // success string commandStr = string(".bargrph.phaseName config -text \"Phase: ") + phaseName + "\""; myTclEval(MainInterp, commandStr); firstTime = false; } /* ************************************************************* */ int Dg2AddMetricsCallback(int) { updatePhaseLabelIfFirstTime(); myTclEval(MainInterp, "DgConfigCallback"); // if necessary, the tcl program will call xAxisHasChanged and/or // yAxisHasChanged, which are commands we implement in barChart.C. // We take action then. return TCL_OK; } int Dg2Fold(int) { myTclEval(MainInterp, "DgFoldCallback"); return TCL_OK; } int Dg2InvalidMetricsOrResources(int) { myTclEval(MainInterp, "DgInvalidCallback"); return TCL_OK; } int Dg2PhaseNameCallback(int) { myTclEval(MainInterp, "DgPhaseCallback"); return TCL_OK; } int Dg2NewDataCallback(int lastBucket) { if (barChartIsValid) { updatePhaseLabelIfFirstTime(); theBarChart->processNewData(lastBucket); return TCL_OK; } else return TCL_ERROR; } int resizeCallbackCommand(ClientData, Tcl_Interp *, int argc, char **argv) { // called from barChart.tcl when it detects a resize; gives our C++ code // a chance to process the resize, too. // params: new width, new height if (barChartIsValid && argc==3) { theBarChart->processResizeWindow(atoi(argv[1]), atoi(argv[2])); return TCL_OK; } else return TCL_ERROR; } int exposeCallbackCommand(ClientData, Tcl_Interp *, int, char **) { // called from barChart.tcl when it detects an expose; gives our C++ code // a chance to process the expose, too. if (barChartIsValid) { theBarChart->processExposeWindow(); return TCL_OK; } else return TCL_ERROR; } int resourcesAxisHasChangedCommand(ClientData, Tcl_Interp *, int argc, char **) { // called from barChart.tcl when the x-axis layout has changed due to resize, // insertion/deletion, etc; gives our C++ code a chance to update its // internal structures. // arg: new width if (barChartIsValid && argc==2) { theBarChart->RethinkMetricsAndResources(); return TCL_OK; } else return TCL_ERROR; } int metricsAxisHasChangedCommand(ClientData, Tcl_Interp *, int argc, char **) { // called from barChart.tcl when the y-axis layout has changed due to resize, // insertion/deletion, etc; gives our C++ code a chance to update its // internal structures. // argument: new height (but currently unused) if (barChartIsValid && argc==2) { theBarChart->RethinkMetricsAndResources(); return TCL_OK; } else return TCL_ERROR; } int newScrollPositionCommand(ClientData, Tcl_Interp *, int argc, char **argv) { // called by tcl code when it's time to scroll the bars to a given value. // argument: new first-visible-pixel. if (barChartIsValid && argc==2) { int newPos = atoi(argv[1]); theBarChart->processNewScrollPosition(newPos); return TCL_OK; } else return TCL_ERROR; } int dataFormatHasChangedCommand(ClientData, Tcl_Interp *, int argc, char **argv) { // rethink current vs. average vs. total assert(argc == 2); if (barChartIsValid) { char *dataFormatString = argv[1]; if (0==strcmp(dataFormatString, "Instantaneous")) theBarChart->rethinkDataFormat(BarChart::Current); else if (0==strcmp(dataFormatString, "Average")) theBarChart->rethinkDataFormat(BarChart::Average); else if (0==strcmp(dataFormatString, "Sum")) theBarChart->rethinkDataFormat(BarChart::Total); else panic("barChart dataFormatHasChangedCommand: unrecognized argument"); return TCL_OK; } else return TCL_ERROR; } int rethinkIndirectResourcesCommand(ClientData, Tcl_Interp *, int, char **) { // rethink how things are sorted if (barChartIsValid) { theBarChart->rethinkIndirectResources(); return TCL_OK; } else return TCL_ERROR; } int getMetricColorNameCommand(ClientData, Tcl_Interp *interp, int argc, char **argv) { // argument: metric index assert(argc==2); unsigned index = atoi(argv[1]); const string &result = theBarChart->getMetricColorName(index); strcpy(interp->result, result.string_of()); return TCL_OK; } int long2shortFocusNameCommand(ClientData, Tcl_Interp *interp, int argc, char **argv) { assert(argc==2); char *longName = argv[1]; // NOTE: most of this code is borrowed/stolen from tableVisi's tvFocus::tvFocus // routine. if (0==strcmp(longName, "Whole Program")) { // no change strcpy(interp->result, longName); return TCL_OK; } // Step 1: split up into components; 1 per resource hierarchy vector components; const char *ptr = longName; while (*ptr != '\0') { // begin a new component; collect upto & including the first seen comma char buffer[200]; char *bufferPtr = &buffer[0]; do { *bufferPtr++ = *ptr++; } while (*ptr != ',' && *ptr != '\0'); if (*ptr == ',') *bufferPtr++ = *ptr++; *bufferPtr = '\0'; components += string(buffer); } // Step 2: for each component, strip off all upto and including // the last '/' for (unsigned componentlcv=0; componentlcv < components.size(); componentlcv++) { const string &oldComponentString = components[componentlcv]; char *ptr = strrchr(oldComponentString.string_of(), '/'); if (ptr == NULL) cerr << "tableVisi: could not find / in component " << oldComponentString << endl; else if (ptr+1 == '\0') cerr << "tableVisi: there was nothing after / in component " << oldComponentString << endl; else components[componentlcv] = string(ptr+1); } // Step 3: combine the components string theShortName; for (unsigned componentlcv=0; componentlcv < components.size(); componentlcv++) theShortName += components[componentlcv]; // Step 4: pull it all together: strcpy(interp->result, theShortName.string_of()); return TCL_OK; } int newMetricMaxValCallbackCommand(ClientData, Tcl_Interp *, int argc, char **argv) { assert(theBarChart); assert(argc==3); theBarChart->setMetricNewMaxLL(atoi(argv[1]), atof(argv[2])); return TCL_OK; } int launchBarChartCommand(ClientData, Tcl_Interp *, int argc, char **argv) { // called just once to fix some information needed by drawBarsCommand, especially // the (sub-)window in which to draw. // parameters: // 1) window name (tk-style; e.g. ".top.middle.bar") of the area in which the bars // are drawn. // 2) do you want double-buffering? ("doublebuffer" or "nodoublebuffer") // 3) do you want no-flicker? ("noflicker" or "flicker") // [you automatically get noflicker with doublebuffer] // 4) initial numMetrics // 5) initial numResources // 6) flush flag (0 or 1); use 1 during debugging only // cout << "Welcome to launchBarChartCommand()" << endl; if (argc != 4) panic("launchBarChartCommand() -- cannot create barchart (incorrect #args)"); char *wname = argv[1]; const int iNumMetrics = atoi(argv[2]); const int iNumResources = atoi(argv[3]); // bar colors: (see /usr/lib/X11/rgb.txt) vector barColorNames; // barColorNames += "cornflower blue"; barColorNames += "mediumslateblue"; barColorNames += "hotpink"; // barColorNames += "chartreuse"; // too bright barColorNames += "#3aa041"; // a type of green not far from mediumseagreen // barColorNames += "orange"; // barColorNames += "lightsalmon"; // text part is too unreadable on grey barColorNames += "salmon"; barColorNames += "chocolate"; theBarChart = new BarChart(wname, iNumMetrics, iNumResources, barColorNames); assert(theBarChart); barChartIsValid = true; return TCL_OK; } void deleteLaunchBarChartCommand(ClientData) { // cout << "Gracefully closing down barchart..." << endl; barChartIsValid = false; // important! delete theBarChart; } void deleteDummyProc(ClientData) { } // do-nothing routine to be called when a command is deleted that // doesn't require closing down...