moved some Dg2 cmds here
[dyninst.git] / visiClients / barchart / barChartTcl.C
1 // barChartTcl.C
2
3 /* $Log: barChartTcl.C,v $
4 /* Revision 1.13  1996/04/30 20:45:24  tamches
5 /* moved some Dg2 cmds here
6 /* added functionality for phase label displayed in the tk window
7 /*
8  * Revision 1.12  1996/01/17 19:44:07  tamches
9  * shuffled colors a bit
10  *
11  * Revision 1.11  1996/01/11 01:53:42  tamches
12  * added long2shortFocusNameCommand to compute short focus names
13  *
14  * Revision 1.10  1996/01/10 19:36:12  tamches
15  * launchBarChart now takes 4 args instead of 7
16  *
17  * Revision 1.9  1996/01/10 02:24:25  tamches
18  * dataFormatHasChangedCommand now takes in an arg
19  * added getMetricColorNameCommand
20  * hardcoded barColorNames here
21  *
22  * Revision 1.8  1995/09/22 19:25:29  tamches
23  * removed warnings under g++ 2.7.0
24  *
25  * Revision 1.7  1994/11/06  10:24:59  tamches
26  * minor cleanups (especially comments)
27  *
28  * Revision 1.6  1994/10/14  10:29:33  tamches
29  * commented out diagnosted message when gracefully closing
30  *
31  * Revision 1.5  1994/10/13  00:52:38  tamches
32  * Minor additions to support a new command related to sorting
33  * of resources
34  *
35  * Revision 1.4  1994/10/10  23:08:44  tamches
36  * preliminary changes on the way to swapping the x and y axes
37  *
38  * Revision 1.3  1994/10/10  14:36:17  tamches
39  * fixed some resizing bugs
40  *
41  * Revision 1.2  1994/09/29  20:05:37  tamches
42  * minor cvs fixes
43  *
44  * Revision 1.1  1994/09/29  19:51:38  tamches
45  * initial implementation.
46  * Receiving point for visi lib callback routines.  Pretty much
47  * just calls the appropriate class member function in barChart.C
48  *
49 */
50
51 #include <iostream.h>
52
53 #include "Vector.h"
54 #include "String.h"
55
56 #include "tcl.h"
57 #include "tk.h"
58 #include "dg2.h" // for dataGrid[][]
59 #include "visi/h/visualization.h"
60 #include "barChart.h"
61
62 bool barChartIsValid = false;
63    // set to true ** after ** barChart::barChart
64    // until then, callbacks check this flag and do nothing
65
66 /* ************************************************************* */
67
68 void updatePhaseLabelIfFirstTime() {
69    static bool firstTime = true;
70
71    if (!firstTime)
72       return;
73
74    int phaseHandle = visi_GetMyPhaseHandle();
75    if (phaseHandle < -1)
76       return; // sorry, not yet defined
77
78    extern Tcl_Interp *MainInterp;
79    const char *phaseName = visi_GetMyPhaseName();
80    if (phaseName == NULL) {
81       // ugh; we have a current phase, but the name isn't yet known
82       myTclEval(MainInterp, string(".bargrph.phaseName config -text \"Phase: Current Phase\""));
83       return; // return w/o setting firstTime to false
84    }
85
86    // success
87    string commandStr = string(".bargrph.phaseName config -text \"Phase: ") + phaseName + "\"";
88    myTclEval(MainInterp, commandStr);
89
90    firstTime = false;
91 }
92
93 /* ************************************************************* */
94
95 int Dg2AddMetricsCallback(int) {
96    updatePhaseLabelIfFirstTime();
97    
98    myTclEval(MainInterp, "DgConfigCallback");
99
100    // if necessary, the tcl program will call xAxisHasChanged and/or
101    // yAxisHasChanged, which are commands we implement in barChart.C.
102    // We take action then.
103
104    return TCL_OK;
105 }
106
107 int Dg2Fold(int) {
108    myTclEval(MainInterp, "DgFoldCallback");
109    return TCL_OK;
110 }
111
112 int Dg2InvalidMetricsOrResources(int) {
113    myTclEval(MainInterp, "DgInvalidCallback");
114    return TCL_OK;
115 }
116
117 int Dg2PhaseNameCallback(int) {
118    myTclEval(MainInterp, "DgPhaseCallback");
119    return TCL_OK;
120 }
121
122 int Dg2NewDataCallback(int lastBucket) {
123    if (barChartIsValid) {
124       updatePhaseLabelIfFirstTime();
125       theBarChart->processNewData(lastBucket);
126       return TCL_OK;
127    }
128    else
129       return TCL_ERROR;
130 }
131
132 int resizeCallbackCommand(ClientData, Tcl_Interp *, int argc, char **argv) {
133    // called from barChart.tcl when it detects a resize; gives our C++ code
134    // a chance to process the resize, too.
135
136    // params: new width, new height
137    if (barChartIsValid && argc==3) {
138       theBarChart->processResizeWindow(atoi(argv[1]), atoi(argv[2]));
139       return TCL_OK;
140    }
141    else
142       return TCL_ERROR;
143 }
144
145 int exposeCallbackCommand(ClientData, Tcl_Interp *, int, char **) {
146    // called from barChart.tcl when it detects an expose; gives our C++ code
147    // a chance to process the expose, too.
148
149    if (barChartIsValid) {
150       theBarChart->processExposeWindow();
151       return TCL_OK;
152    }
153    else
154       return TCL_ERROR;
155 }
156
157 int resourcesAxisHasChangedCommand(ClientData, Tcl_Interp *, int argc, char **) {
158    // called from barChart.tcl when the x-axis layout has changed due to resize,
159    // insertion/deletion, etc; gives our C++ code a chance to update its
160    // internal structures.
161
162    // arg: new width
163
164    if (barChartIsValid && argc==2) {
165       theBarChart->RethinkMetricsAndResources();
166       return TCL_OK;
167    }
168    else
169       return TCL_ERROR;
170 }
171
172 int metricsAxisHasChangedCommand(ClientData, Tcl_Interp *, int argc, char **) {
173    // called from barChart.tcl when the y-axis layout has changed due to resize,
174    // insertion/deletion, etc; gives our C++ code a chance to update its
175    // internal structures.
176
177    // argument: new height (but currently unused)
178
179    if (barChartIsValid && argc==2) {
180       theBarChart->RethinkMetricsAndResources();
181       return TCL_OK;
182    }
183    else
184       return TCL_ERROR;
185 }
186
187 int newScrollPositionCommand(ClientData, Tcl_Interp *, int argc, char **argv) {
188    // called by tcl code when it's time to scroll the bars to a given value.
189    // argument: new first-visible-pixel.
190
191    if (barChartIsValid && argc==2) {
192       int newPos = atoi(argv[1]);
193       theBarChart->processNewScrollPosition(newPos);
194       return TCL_OK;
195    }
196    else
197       return TCL_ERROR;
198 }
199
200 int dataFormatHasChangedCommand(ClientData, Tcl_Interp *, int argc, char **argv) {
201    // rethink current vs. average vs. total
202    assert(argc == 2);
203    if (barChartIsValid) {
204       char *dataFormatString = argv[1];
205       if (0==strcmp(dataFormatString, "Instantaneous"))
206          theBarChart->rethinkDataFormat(BarChart::Current);
207       else if (0==strcmp(dataFormatString, "Average"))
208          theBarChart->rethinkDataFormat(BarChart::Average);
209       else if (0==strcmp(dataFormatString, "Sum"))
210          theBarChart->rethinkDataFormat(BarChart::Total);
211       else
212          panic("barChart dataFormatHasChangedCommand: unrecognized argument");
213       return TCL_OK;
214    }
215    else
216       return TCL_ERROR;
217 }
218
219 int rethinkIndirectResourcesCommand(ClientData, Tcl_Interp *, int, char **) {
220    // rethink how things are sorted
221    if (barChartIsValid) {
222       theBarChart->rethinkIndirectResources();
223       return TCL_OK;
224    }
225    else
226       return TCL_ERROR;
227 }
228
229 int getMetricColorNameCommand(ClientData, Tcl_Interp *interp,
230                               int argc, char **argv) {
231    // argument: metric index
232    assert(argc==2);
233    unsigned index = atoi(argv[1]);
234
235    const string &result = theBarChart->getMetricColorName(index);
236    strcpy(interp->result, result.string_of());
237    return TCL_OK;
238 }
239
240 int long2shortFocusNameCommand(ClientData, Tcl_Interp *interp, int argc, char **argv) {
241    assert(argc==2);
242    char *longName = argv[1];
243
244    // NOTE: most of this code is borrowed/stolen from tableVisi's tvFocus::tvFocus
245    //       routine.
246
247    if (0==strcmp(longName, "Whole Program")) {
248       // no change
249       strcpy(interp->result, longName);
250       return TCL_OK;
251    }
252
253    // Step 1: split up into components; 1 per resource hierarchy
254    vector<string> components;
255    const char *ptr = longName;
256
257    while (*ptr != '\0') {
258       // begin a new component; collect upto & including the first seen comma
259       char buffer[200];
260       char *bufferPtr = &buffer[0];
261       do {
262          *bufferPtr++ = *ptr++;
263       } while (*ptr != ',' && *ptr != '\0');
264
265       if (*ptr == ',')
266          *bufferPtr++ = *ptr++;
267
268       *bufferPtr = '\0';
269
270       components += string(buffer);
271    }
272
273    // Step 2: for each component, strip off all upto and including
274    //         the last '/'
275    for (unsigned componentlcv=0; componentlcv < components.size(); componentlcv++) {
276       const string &oldComponentString = components[componentlcv];
277
278       char *ptr = strrchr(oldComponentString.string_of(), '/');
279       if (ptr == NULL)
280          cerr << "tableVisi: could not find / in component " << oldComponentString << endl;
281       else if (ptr+1 == '\0')
282          cerr << "tableVisi: there was nothing after / in component " << oldComponentString << endl;
283       else
284          components[componentlcv] = string(ptr+1);
285    }
286
287    // Step 3: combine the components
288    string theShortName;
289    for (unsigned componentlcv=0; componentlcv < components.size(); componentlcv++)
290       theShortName += components[componentlcv];
291
292    // Step 4: pull it all together:
293    strcpy(interp->result, theShortName.string_of());
294    return TCL_OK;
295 }
296
297 int launchBarChartCommand(ClientData, Tcl_Interp *, int argc, char **argv) {
298    // called just once to fix some information needed by drawBarsCommand, especially
299    // the (sub-)window in which to draw.
300
301    // parameters:
302    // 1) window name (tk-style; e.g. ".top.middle.bar") of the area in which the bars
303    //    are drawn.
304    // 2) do you want double-buffering? ("doublebuffer" or "nodoublebuffer")
305    // 3) do you want no-flicker?       ("noflicker" or "flicker")
306    //       [you automatically get noflicker with doublebuffer]
307    // 4) initial numMetrics
308    // 5) initial numResources
309    // 6) flush flag (0 or 1); use 1 during debugging only
310
311    // cout << "Welcome to launchBarChartCommand()" << endl;
312    
313    if (argc != 4)
314       panic("launchBarChartCommand() -- cannot create barchart (incorrect #args)");
315
316    char *wname = argv[1];
317    const int iNumMetrics   = atoi(argv[2]);
318    const int iNumResources = atoi(argv[3]);
319
320    // bar colors: (see /usr/lib/X11/rgb.txt)
321    vector<string> barColorNames;
322 //   barColorNames += "cornflower blue";
323    barColorNames += "mediumslateblue";
324    barColorNames += "hotpink";
325 //   barColorNames += "chartreuse"; // too bright
326    barColorNames += "#3aa041"; // a type of green not far from mediumseagreen
327 //   barColorNames += "orange";
328 //   barColorNames += "lightsalmon"; // text part is too unreadable on grey
329    barColorNames += "salmon";
330    barColorNames += "chocolate";
331
332    theBarChart = new BarChart(wname, iNumMetrics, iNumResources, barColorNames);
333    assert(theBarChart);
334
335    barChartIsValid = true;
336    return TCL_OK;
337 }
338
339 void deleteLaunchBarChartCommand(ClientData) {
340    // cout << "Gracefully closing down barchart..." << endl;
341
342    barChartIsValid = false; // important!
343    delete theBarChart;
344 }
345
346 void deleteDummyProc(ClientData) { }
347    // do-nothing routine to be called when a command is deleted that
348    // doesn't require closing down...