- Changed to eliminate inline cvs logs -> cvs $Id$
[dyninst.git] / visiClients / barchart / src / barChartTcl.C
1 /*
2  * Copyright (c) 1996-1999 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 // barChartTcl.C
43
44 /* $Id: barChartTcl.C,v 1.17 1999/04/27 16:05:07 nash Exp $ */
45
46 #include <iostream.h>
47
48 #include "util/h/Vector.h"
49 #include "util/h/String.h"
50
51 #include "util/h/headers.h"
52 #include "util/h/pdsocket.h"
53
54 #include "tcl.h"
55 #include "tk.h"
56 #include "dg2.h" // for dataGrid[][]
57 #include "visi/h/visualization.h"
58 #include "barChart.h"
59 #include "barChartUtil.h"
60
61 bool barChartIsValid = false;
62    // set to true ** after ** barChart::barChart
63    // until then, callbacks check this flag and do nothing
64
65 /* ************************************************************* */
66
67 void updatePhaseLabelIfFirstTime() {
68    static bool firstTime = true;
69
70    if (!firstTime)
71       return;
72
73    int phaseHandle = visi_GetMyPhaseHandle();
74    if (phaseHandle < -1)
75       return; // sorry, not yet defined
76
77    extern Tcl_Interp *MainInterp;
78    const char *phaseName = visi_GetMyPhaseName();
79    if (phaseName == NULL) {
80       // ugh; we have a current phase, but the name isn't yet known
81       myTclEval(MainInterp, string(".bargrph.phaseName config -text \"Phase: Current Phase\""));
82       return; // return w/o setting firstTime to false
83    }
84
85    // success
86    string commandStr = string(".bargrph.phaseName config -text \"Phase: ") + phaseName + "\"";
87    myTclEval(MainInterp, commandStr);
88
89    firstTime = false;
90 }
91
92 /* ************************************************************* */
93
94 int Dg2AddMetricsCallback(int) {
95    updatePhaseLabelIfFirstTime();
96    
97    myTclEval(MainInterp, "DgConfigCallback");
98
99    // if necessary, the tcl program will call xAxisHasChanged and/or
100    // yAxisHasChanged, which are commands we implement in barChart.C.
101    // We take action then.
102
103    return TCL_OK;
104 }
105
106 int Dg2Fold(int) {
107    myTclEval(MainInterp, "DgFoldCallback");
108    return TCL_OK;
109 }
110
111 int Dg2InvalidMetricsOrResources(int) {
112    myTclEval(MainInterp, "DgInvalidCallback");
113    return TCL_OK;
114 }
115
116 int Dg2PhaseNameCallback(int) {
117    myTclEval(MainInterp, "DgPhaseCallback");
118    return TCL_OK;
119 }
120
121 int Dg2NewDataCallback(int lastBucket) {
122    if (barChartIsValid) {
123       updatePhaseLabelIfFirstTime();
124       theBarChart->processNewData(lastBucket);
125       return TCL_OK;
126    }
127    else
128       return TCL_ERROR;
129 }
130
131 int resizeCallbackCommand(ClientData, Tcl_Interp *, int argc, char **argv) {
132    // called from barChart.tcl when it detects a resize; gives our C++ code
133    // a chance to process the resize, too.
134
135    // params: new width, new height
136    if (barChartIsValid && argc==3) {
137       theBarChart->processResizeWindow(atoi(argv[1]), atoi(argv[2]));
138       return TCL_OK;
139    }
140    else
141       return TCL_ERROR;
142 }
143
144 int exposeCallbackCommand(ClientData, Tcl_Interp *, int, char **) {
145    // called from barChart.tcl when it detects an expose; gives our C++ code
146    // a chance to process the expose, too.
147
148    if (barChartIsValid) {
149       theBarChart->processExposeWindow();
150       return TCL_OK;
151    }
152    else
153       return TCL_ERROR;
154 }
155
156 int resourcesAxisHasChangedCommand(ClientData, Tcl_Interp *, int argc, char **) {
157    // called from barChart.tcl when the x-axis layout has changed due to resize,
158    // insertion/deletion, etc; gives our C++ code a chance to update its
159    // internal structures.
160
161    // arg: new width
162
163    if (barChartIsValid && argc==2) {
164       theBarChart->RethinkMetricsAndResources();
165       return TCL_OK;
166    }
167    else
168       return TCL_ERROR;
169 }
170
171 int metricsAxisHasChangedCommand(ClientData, Tcl_Interp *, int argc, char **) {
172    // called from barChart.tcl when the y-axis layout has changed due to resize,
173    // insertion/deletion, etc; gives our C++ code a chance to update its
174    // internal structures.
175
176    // argument: new height (but currently unused)
177
178    if (barChartIsValid && argc==2) {
179       theBarChart->RethinkMetricsAndResources();
180       return TCL_OK;
181    }
182    else
183       return TCL_ERROR;
184 }
185
186 int newScrollPositionCommand(ClientData, Tcl_Interp *, int argc, char **argv) {
187    // called by tcl code when it's time to scroll the bars to a given value.
188    // argument: new first-visible-pixel.
189
190    if (barChartIsValid && argc==2) {
191       int newPos = atoi(argv[1]);
192       theBarChart->processNewScrollPosition(newPos);
193       return TCL_OK;
194    }
195    else
196       return TCL_ERROR;
197 }
198
199 int dataFormatHasChangedCommand(ClientData, Tcl_Interp *, int argc, char **argv) {
200    // rethink current vs. average vs. total
201    assert(argc == 2);
202    if (barChartIsValid) {
203       char *dataFormatString = argv[1];
204       if (0==strcmp(dataFormatString, "Instantaneous"))
205          theBarChart->rethinkDataFormat(BarChart::Current);
206       else if (0==strcmp(dataFormatString, "Average"))
207          theBarChart->rethinkDataFormat(BarChart::Average);
208       else if (0==strcmp(dataFormatString, "Sum"))
209          theBarChart->rethinkDataFormat(BarChart::Total);
210       else
211          panic("barChart dataFormatHasChangedCommand: unrecognized argument");
212       return TCL_OK;
213    }
214    else
215       return TCL_ERROR;
216 }
217
218 int rethinkIndirectResourcesCommand(ClientData, Tcl_Interp *, int, char **) {
219    // rethink how things are sorted
220    if (barChartIsValid) {
221       theBarChart->rethinkIndirectResources();
222       return TCL_OK;
223    }
224    else
225       return TCL_ERROR;
226 }
227
228 int getMetricColorNameCommand(ClientData, Tcl_Interp *interp,
229                               int argc, char **argv) {
230    // argument: metric index
231    assert(argc==2);
232    unsigned index = atoi(argv[1]);
233
234    const string &result = theBarChart->getMetricColorName(index);
235    strcpy(interp->result, result.string_of());
236    return TCL_OK;
237 }
238
239 int long2shortFocusNameCommand(ClientData, Tcl_Interp *interp, int argc, char **argv) {
240         unsigned componentlcv;
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 (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 (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 newMetricMaxValCallbackCommand(ClientData, Tcl_Interp *, int argc, char **argv) {
298    assert(theBarChart);
299    assert(argc==3);
300    theBarChart->setMetricNewMaxLL(atoi(argv[1]), atof(argv[2]));
301    return TCL_OK;
302 }
303
304 int launchBarChartCommand(ClientData, Tcl_Interp *, int argc, char **argv) {
305    // called just once to fix some information needed by drawBarsCommand, especially
306    // the (sub-)window in which to draw.
307
308    // parameters:
309    // 1) window name (tk-style; e.g. ".top.middle.bar") of the area in which the bars
310    //    are drawn.
311    // 2) do you want double-buffering? ("doublebuffer" or "nodoublebuffer")
312    // 3) do you want no-flicker?       ("noflicker" or "flicker")
313    //       [you automatically get noflicker with doublebuffer]
314    // 4) initial numMetrics
315    // 5) initial numResources
316    // 6) flush flag (0 or 1); use 1 during debugging only
317
318    // cout << "Welcome to launchBarChartCommand()" << endl;
319    
320    if (argc != 4)
321       panic("launchBarChartCommand() -- cannot create barchart (incorrect #args)");
322
323    char *wname = argv[1];
324    const int iNumMetrics   = atoi(argv[2]);
325    const int iNumResources = atoi(argv[3]);
326
327    // bar colors: (see /usr/lib/X11/rgb.txt)
328    vector<string> barColorNames;
329 //   barColorNames += "cornflower blue";
330    barColorNames += "mediumslateblue";
331    barColorNames += "hotpink";
332 //   barColorNames += "chartreuse"; // too bright
333    barColorNames += "#3aa041"; // a type of green not far from mediumseagreen
334 //   barColorNames += "orange";
335 //   barColorNames += "lightsalmon"; // text part is too unreadable on grey
336    barColorNames += "salmon";
337    barColorNames += "chocolate";
338
339    theBarChart = new BarChart(wname, iNumMetrics, iNumResources, barColorNames);
340    assert(theBarChart);
341
342    barChartIsValid = true;
343    return TCL_OK;
344 }
345
346 void deleteLaunchBarChartCommand(ClientData) {
347    // cout << "Gracefully closing down barchart..." << endl;
348
349    barChartIsValid = false; // important!
350    delete theBarChart;
351 }
352
353 void deleteDummyProc(ClientData) { }
354    // do-nothing routine to be called when a command is deleted that
355    // doesn't require closing down...