00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 #include <stdio.h>
00052 #include <X11/IntrinsicP.h>
00053 #include <X11/StringDefs.h>
00054 #include <X11/Xaw3d/XawInit.h>
00055 #include <X11/Xaw3d/StripCharP.h>
00056 #include <X11/Xfuncs.h>
00057
00058 #define MS_PER_SEC 1000
00059
00060
00061
00062 #define offset(field) XtOffsetOf(StripChartRec, field)
00063
00064 static XtResource resources[] = {
00065 {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
00066 offset(core.width), XtRImmediate, (XtPointer) 120},
00067 {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
00068 offset(core.height), XtRImmediate, (XtPointer) 120},
00069 {XtNupdate, XtCInterval, XtRInt, sizeof(int),
00070 offset(strip_chart.update), XtRImmediate, (XtPointer) 10},
00071 {XtNminScale, XtCScale, XtRInt, sizeof(int),
00072 offset(strip_chart.min_scale), XtRImmediate, (XtPointer) 1},
00073 {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
00074 offset(strip_chart.fgpixel), XtRString, XtDefaultForeground},
00075 {XtNhighlight, XtCForeground, XtRPixel, sizeof(Pixel),
00076 offset(strip_chart.hipixel), XtRString, XtDefaultForeground},
00077 {XtNgetValue, XtCCallback, XtRCallback, sizeof(XtPointer),
00078 offset(strip_chart.get_value), XtRImmediate, (XtPointer) NULL},
00079 {XtNjumpScroll, XtCJumpScroll, XtRInt, sizeof(int),
00080 offset(strip_chart.jump_val), XtRImmediate, (XtPointer) DEFAULT_JUMP},
00081 };
00082
00083 #undef offset
00084
00085 static void Initialize(), Destroy(), Redisplay(), MoveChart(), SetPoints();
00086 static Boolean SetValues();
00087 static int repaint_window();
00088
00089 StripChartClassRec stripChartClassRec = {
00090 {
00091 (WidgetClass) &threeDClassRec,
00092 "StripChart",
00093 sizeof(StripChartRec),
00094 XawInitializeWidgetSet,
00095 NULL,
00096 FALSE,
00097 Initialize,
00098 NULL,
00099 XtInheritRealize,
00100 NULL,
00101 0,
00102 resources,
00103 XtNumber(resources),
00104 NULLQUARK,
00105 TRUE,
00106 XtExposeCompressMultiple |
00107 XtExposeGraphicsExposeMerged,
00108 TRUE,
00109 FALSE,
00110 Destroy,
00111 SetPoints,
00112 Redisplay,
00113 SetValues,
00114 NULL,
00115 NULL,
00116 NULL,
00117 NULL,
00118 XtVersion,
00119 NULL,
00120 NULL,
00121 XtInheritQueryGeometry,
00122 XtInheritDisplayAccelerator,
00123 NULL
00124 },
00125 {
00126 XtInheritChangeSensitive
00127 },
00128 {
00129 XtInheritXaw3dShadowDraw
00130 },
00131 {
00132 0
00133 }
00134 };
00135
00136 WidgetClass stripChartWidgetClass = (WidgetClass) &stripChartClassRec;
00137
00138
00139
00140
00141
00142
00143
00144 static void draw_it();
00145
00146
00147
00148
00149
00150
00151
00152
00153 static void
00154 CreateGC(w, which)
00155 StripChartWidget w;
00156 unsigned int which;
00157 {
00158 XGCValues myXGCV;
00159
00160 if (which & FOREGROUND) {
00161 myXGCV.foreground = w->strip_chart.fgpixel;
00162 w->strip_chart.fgGC = XtGetGC((Widget) w, GCForeground, &myXGCV);
00163 }
00164
00165 if (which & HIGHLIGHT) {
00166 myXGCV.foreground = w->strip_chart.hipixel;
00167 w->strip_chart.hiGC = XtGetGC((Widget) w, GCForeground, &myXGCV);
00168 }
00169 }
00170
00171
00172
00173
00174
00175
00176
00177
00178 static void
00179 DestroyGC(w, which)
00180 StripChartWidget w;
00181 unsigned int which;
00182 {
00183 if (which & FOREGROUND)
00184 XtReleaseGC((Widget) w, w->strip_chart.fgGC);
00185
00186 if (which & HIGHLIGHT)
00187 XtReleaseGC((Widget) w, w->strip_chart.hiGC);
00188 }
00189
00190
00191 static void Initialize (greq, gnew, args, num_args)
00192 Widget greq, gnew;
00193 ArgList args;
00194 Cardinal *num_args;
00195 {
00196 StripChartWidget w = (StripChartWidget)gnew;
00197
00198 if (w->strip_chart.update > 0)
00199 w->strip_chart.interval_id =
00200 XtAppAddTimeOut( XtWidgetToApplicationContext(gnew),
00201 (unsigned long) w->strip_chart.update * MS_PER_SEC,
00202 draw_it, (XtPointer) gnew);
00203 CreateGC(w, (unsigned int) ALL_GCS);
00204
00205 w->strip_chart.scale = w->strip_chart.min_scale;
00206 w->strip_chart.interval = 0;
00207 w->strip_chart.max_value = 0.0;
00208 w->strip_chart.points = NULL;
00209 SetPoints((Widget)w);
00210 }
00211
00212 static void Destroy (gw)
00213 Widget gw;
00214 {
00215 StripChartWidget w = (StripChartWidget)gw;
00216
00217 if (w->strip_chart.update > 0)
00218 XtRemoveTimeOut (w->strip_chart.interval_id);
00219 if (w->strip_chart.points)
00220 XtFree((char *) w->strip_chart.points);
00221 DestroyGC(w, (unsigned int) ALL_GCS);
00222 }
00223
00224
00225
00226
00227
00228
00229
00230
00231 static void Redisplay(gw, event, region)
00232 Widget gw;
00233 XEvent *event;
00234 Region region;
00235 {
00236
00237 StripChartWidget w = (StripChartWidget)gw;
00238 StripChartWidgetClass swclass = (StripChartWidgetClass) XtClass (gw);
00239 Dimension x, width, s = w->threeD.shadow_width;
00240
00241 (*swclass->threeD_class.shadowdraw) (gw, event, region, FALSE);
00242
00243 if (event->type == GraphicsExpose) {
00244 x = event->xgraphicsexpose.x;
00245 width = event->xgraphicsexpose.width;
00246 } else {
00247 x = event->xexpose.x;
00248 width = event->xexpose.width;
00249 }
00250 if (x > s) x -= s;
00251 else x = 0;
00252 if (x + width > w->core.width - 2 * s)
00253 width = w->core.width - 2 * s - x;
00254
00255 (void) repaint_window (gw, x, width);
00256 }
00257
00258
00259 static void
00260 draw_it(client_data, id)
00261 XtPointer client_data;
00262 XtIntervalId *id;
00263 {
00264 StripChartWidget w = (StripChartWidget)client_data;
00265 StripChartWidgetClass swclass = (StripChartWidgetClass) XtClass ((Widget) w);
00266 Dimension s = w->threeD.shadow_width;
00267 double value;
00268
00269 if (w->strip_chart.update > 0)
00270 w->strip_chart.interval_id =
00271 XtAppAddTimeOut(XtWidgetToApplicationContext( (Widget) w),
00272 (unsigned long) w->strip_chart.update * MS_PER_SEC,
00273 draw_it, client_data);
00274
00275 if (w->strip_chart.interval >= (int)( w->core.width - 2 * s))
00276 MoveChart( (StripChartWidget) w, TRUE);
00277
00278
00279
00280 if (w->strip_chart.get_value == NULL)
00281 return;
00282
00283 XtCallCallbacks( (Widget)w, XtNgetValue, (XtPointer)&value );
00284
00285
00286
00287
00288
00289
00290 if (value > w->strip_chart.max_value) {
00291 w->strip_chart.max_value = value;
00292 if (XtIsRealized((Widget)w) &&
00293 w->strip_chart.max_value > w->strip_chart.scale) {
00294 XClearWindow(XtDisplay ((Widget) w), XtWindow ((Widget) w));
00295 w->strip_chart.interval = repaint_window((Widget)w, 0, (int) w->core.width - 2 * s);
00296 (*swclass->threeD_class.shadowdraw) ((Widget) w,
00297 (XEvent *)0, (Region)0,
00298 FALSE);
00299 }
00300 }
00301
00302 w->strip_chart.valuedata[w->strip_chart.interval] = value;
00303 if (XtIsRealized((Widget)w)) {
00304 int y = (int) (( w->core.height - 2 * s)
00305 - (int)(( w->core.height - 2 * s) * value) / w->strip_chart.scale);
00306
00307 XFillRectangle(XtDisplay((Widget) w), XtWindow((Widget) w), w->strip_chart.fgGC,
00308 w->strip_chart.interval + s,
00309 y + s, (unsigned int) 1,
00310 (w->core.height - 2 * s) - y);
00311
00312
00313
00314
00315 if (w->strip_chart.points != NULL) {
00316 w->strip_chart.points[0].x = w->strip_chart.interval + s;
00317 XDrawPoints(XtDisplay(w), XtWindow(w), w->strip_chart.hiGC,
00318 w->strip_chart.points, w->strip_chart.scale,
00319 CoordModePrevious);
00320 }
00321
00322 XFlush(XtDisplay(w));
00323 }
00324 w->strip_chart.interval++;
00325 }
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337 static int
00338 repaint_window(gw, left, width)
00339 Widget gw;
00340 int left, width;
00341 {
00342 StripChartWidget w = (StripChartWidget) gw;
00343 Dimension s = w->threeD.shadow_width;
00344 StripChartWidgetClass swclass = (StripChartWidgetClass) XtClass ((Widget) w);
00345 int i, j;
00346 int next = w->strip_chart.interval;
00347 int scale = w->strip_chart.scale;
00348 int scalewidth = 0;
00349
00350
00351
00352 if (w->strip_chart.interval != 0 || scale <= (int)w->strip_chart.max_value)
00353 scale = ((int) (w->strip_chart.max_value)) + 1;
00354 if (scale < w->strip_chart.min_scale)
00355 scale = w->strip_chart.min_scale;
00356
00357 if (scale != w->strip_chart.scale) {
00358 w->strip_chart.scale = scale;
00359 left = 0;
00360 width = next;
00361 scalewidth = w->core.width - 2 * s;
00362
00363 SetPoints(gw);
00364
00365 if (XtIsRealized (gw)) {
00366 XClearWindow (XtDisplay (gw), XtWindow (gw));
00367 (*swclass->threeD_class.shadowdraw) (gw, (XEvent *)0, (Region)0, FALSE);
00368 }
00369
00370 }
00371
00372 if (XtIsRealized(gw)) {
00373 Display *dpy = XtDisplay(gw);
00374 Window win = XtWindow(gw);
00375
00376 width += left - 1;
00377 if (!scalewidth) scalewidth = width;
00378
00379 if (next < (++width - s)) width = next + s;
00380
00381
00382 for (i = left; i < width; i++) {
00383 int y = (int) (( w->core.height - 2 * s) -
00384 (int)(( w->core.height - 2 * s) * w->strip_chart.valuedata[i]) /
00385 w->strip_chart.scale);
00386
00387 XFillRectangle(dpy, win, w->strip_chart.fgGC,
00388 i + s, y + s, (unsigned int) 1,
00389 (unsigned int) (w->core.height - 2 * s - y ));
00390 }
00391
00392
00393 for (i = 1; i < w->strip_chart.scale; i++) {
00394 j = i * ((w->core.height - 2 * s) / w->strip_chart.scale);
00395 XDrawLine(dpy, win, w->strip_chart.hiGC,
00396 left + s, j + s, scalewidth + s, j + s);
00397 }
00398 }
00399 return(next);
00400 }
00401
00402
00403
00404
00405
00406
00407
00408
00409 static void
00410 MoveChart(w, blit)
00411 StripChartWidget w;
00412 Boolean blit;
00413 {
00414 Dimension s = w->threeD.shadow_width;
00415 double old_max;
00416 int left, i, j;
00417 int next = w->strip_chart.interval;
00418
00419 if (!XtIsRealized((Widget) w)) return;
00420
00421 if (w->strip_chart.jump_val < 0) w->strip_chart.jump_val = DEFAULT_JUMP;
00422 if (w->strip_chart.jump_val == DEFAULT_JUMP)
00423 j = ( w->core.width - 2 * s) / 2;
00424 else {
00425 j = ( w->core.width - 2 * s) - w->strip_chart.jump_val;
00426 if (j < 0) j = 0;
00427 }
00428
00429 (void) memmove((char *)(w->strip_chart.valuedata),
00430 (char *)(w->strip_chart.valuedata + next - j),
00431 j * sizeof(double));
00432 next = w->strip_chart.interval = j;
00433
00434
00435
00436
00437
00438
00439 old_max = w->strip_chart.max_value;
00440 w->strip_chart.max_value = 0.0;
00441 for (i = 0; i < next; i++) {
00442 if (w->strip_chart.valuedata[i] > w->strip_chart.max_value)
00443 w->strip_chart.max_value = w->strip_chart.valuedata[i];
00444 }
00445
00446 if (!blit) return;
00447
00448 if ( ((int) old_max) != ( (int) w->strip_chart.max_value) ) {
00449 XClearWindow(XtDisplay(w), XtWindow(w));
00450 repaint_window((Widget)w, 0, w->core.width - 2 * s);
00451 return;
00452 }
00453
00454 XCopyArea(XtDisplay((Widget)w), XtWindow((Widget)w), XtWindow((Widget)w),
00455 w->strip_chart.hiGC,
00456 (int) ((w->strip_chart.jump_val == DEFAULT_JUMP) ?
00457 (j + s) : (w->strip_chart.jump_val + s)), s,
00458 (unsigned int) j, (unsigned int) ( w->core.height - 2 * s),
00459 s, s);
00460
00461 XClearArea(XtDisplay((Widget)w), XtWindow((Widget)w),
00462 (int) j + s, s,
00463 (unsigned int) ((w->strip_chart.jump_val == DEFAULT_JUMP) ?
00464 j : w->strip_chart.jump_val),
00465 (unsigned int) ( w->core.height - 2 * s),
00466 FALSE);
00467
00468
00469 left = j;
00470 for (i = 1; i < w->strip_chart.scale; i++) {
00471 j = i * ((w->core.height - 2 * s) / w->strip_chart.scale);
00472 XDrawLine(XtDisplay((Widget) w), XtWindow( (Widget) w),
00473 w->strip_chart.hiGC,
00474 left, j + s, ((int)w->core.width - s - 1), j + s);
00475 }
00476 return;
00477 }
00478
00479
00480 static Boolean SetValues (current, request, new, args, num_args)
00481 Widget current, request, new;
00482 ArgList args;
00483 Cardinal *num_args;
00484 {
00485 StripChartWidget old = (StripChartWidget)current;
00486 StripChartWidget w = (StripChartWidget)new;
00487 Boolean ret_val = FALSE;
00488 unsigned int new_gc = NO_GCS;
00489
00490 if (w->strip_chart.update != old->strip_chart.update) {
00491 if (old->strip_chart.update > 0)
00492 XtRemoveTimeOut (old->strip_chart.interval_id);
00493 if (w->strip_chart.update > 0)
00494 w->strip_chart.interval_id =
00495 XtAppAddTimeOut(XtWidgetToApplicationContext(new),
00496 (unsigned long) w->strip_chart.update * MS_PER_SEC,
00497 draw_it, (XtPointer)w);
00498 }
00499
00500 if ( w->strip_chart.min_scale > (int) ((w->strip_chart.max_value) + 1) )
00501 ret_val = TRUE;
00502
00503 if ( w->strip_chart.fgpixel != old->strip_chart.fgpixel ) {
00504 new_gc |= FOREGROUND;
00505 ret_val = True;
00506 }
00507
00508 if ( w->strip_chart.hipixel != old->strip_chart.hipixel ) {
00509 new_gc |= HIGHLIGHT;
00510 ret_val = True;
00511 }
00512
00513 DestroyGC(old, new_gc);
00514 CreateGC(w, new_gc);
00515
00516 return( ret_val );
00517 }
00518
00519
00520
00521
00522
00523
00524
00525
00526 #define HEIGHT ( (unsigned int) w->core.height)
00527
00528 static void
00529 SetPoints(widget)
00530 Widget widget;
00531 {
00532 StripChartWidget w = (StripChartWidget) widget;
00533 Dimension s = w->threeD.shadow_width;
00534 XPoint * points;
00535 Cardinal size;
00536 int i;
00537
00538 if (w->strip_chart.scale <= 1) {
00539 XtFree ((char *) w->strip_chart.points);
00540 w->strip_chart.points = NULL;
00541 return;
00542 }
00543
00544 size = sizeof(XPoint) * (w->strip_chart.scale - 1);
00545
00546 points = (XPoint *) XtRealloc( (XtPointer) w->strip_chart.points, size);
00547 w->strip_chart.points = points;
00548
00549
00550
00551 for (i = 1; i < w->strip_chart.scale; i++) {
00552 points[i - 1].x = 0;
00553 points[i - 1].y = ( short)(((double)w->core.height - 2.0 * (double) s) / (double) w->strip_chart.scale );
00554 }
00555 points[0].y += (short)s;
00556 }