diff options
author | Remco Treffkorn <remco@rvt.com> | 1999-07-17 23:03:47 +0000 |
---|---|---|
committer | Remco Treffkorn <remco@rvt.com> | 1999-07-17 23:03:47 +0000 |
commit | f632377e259aa6656057e238e73051121e2d2478 (patch) | |
tree | 564da23d7331d6cb90ecea5c37ab1550080d71a4 /Tachometer.c | |
parent | 6ac8d7649f528969ce98a8067bcf6aaa749b8b10 (diff) | |
download | gpsd-f632377e259aa6656057e238e73051121e2d2478.tar.gz |
*** empty log message ***
Diffstat (limited to 'Tachometer.c')
-rw-r--r-- | Tachometer.c | 741 |
1 files changed, 741 insertions, 0 deletions
diff --git a/Tachometer.c b/Tachometer.c new file mode 100644 index 00000000..9c952892 --- /dev/null +++ b/Tachometer.c @@ -0,0 +1,741 @@ +/* + * Tachometer Widget Implementation + * + * Author: Kazuhiko Shutoh, 1989. + * Revised by Shinji Sumimoto, 1989/9 (xtachos) + * + * Permission to use, copy, modify and distribute without charge this software, + * documentation, images, etc. is granted, provided that this comment and the + * author's name is retained. The author assumes no responsibility for lost + * sleep as a consequence of use of this software. + * + * Send any comments, bug reports, etc. to shutoh@isl.yamaha.JUNET + * + * + * Modifications : ilham@mit.edu (July 10 '90) + */ + + +#define XtStrlen(s) ((s) ? strlen(s) : 0) + +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <TachometerP.h> +#include <math.h> + +/**************************************************************** + * + * Full class record constant + * + ****************************************************************/ + +/* Private Data */ + +#define PI 3.1415927 + +typedef struct { + unsigned char digit[7]; + } DigitRec; + +typedef struct { + int nofline; + XPoint point_list[5]; + } StringRec; + +/* Number's character database - like as "LED" */ + +DigitRec num_segment[] = { + {1,1,1,1,1,1,0}, + {0,1,1,0,0,0,0}, + {1,1,0,1,1,0,1}, + {1,1,1,1,0,0,1}, + {0,1,1,0,0,1,1}, + {1,0,1,1,0,1,1}, + {1,0,1,1,1,1,1}, + {1,1,1,0,0,0,0}, + {1,1,1,1,1,1,1}, + {1,1,1,1,0,1,1}}; + +XSegment offset[] = { + {-10,-10, 10,-10}, + { 10,-10, 10, 0}, + { 10, 0, 10, 10}, + { 10, 10,-10, 10}, + {-10, 10,-10, 0}, + {-10, 0,-10,-10}, + {-10, 0, 10, 0}}; + + +/* " X 10 %" character database */ + +StringRec char_data[] = { + { 2, /* "X" */ + {{-17, -5}, + {-7, 5}}}, + { 2, + {{-7, -5}, + {-17, 5}}}, + { 2, /* "1" */ + {{-2, -5}, + {-2, 5}}}, + { 5, /* "0" */ + {{2, -5}, + {12, -5}, + {12, 5}, + {2, 5}, + {2, -5}}}}; +#if 0 +{{{{ {2, -5}}}, + { 5, /* "%" */ + {{17, -5}, + {20, -5}, + {20, -2}, + {17, -2}, + {17, -5}}}, + { 2, + {{27, -5}, + {17, 5}}}, + {5, + {{24, 2}, + {27, 2}, + {27, 5}, + {24, 5}, + {24, 2}}}}; +#endif + + + +#define offst(field) XtOffset(TachometerWidget, field) +static XtResource resources[] = { + {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), + offst(tachometer.scale), XtRString, "XtDefaultForeground"}, + {XtNtachometerCircleColor, XtCBorderColor, XtRPixel, sizeof(Pixel), + offst(tachometer.circle), XtRString, "XtDefaultForeground"}, + {XtNtachometerNeedleColor, XtCBorderColor, XtRPixel, sizeof(Pixel), + offst(tachometer.needle), XtRString, "XtDefaultForeground"}, + {XtNtachometerNeedleSpeed, XtCtachometerNeedleSpeed, XtRInt, + sizeof(int), offst(tachometer.speed), XtRImmediate, (caddr_t) 1}, + {XtNvalue, XtCValue, XtRInt, sizeof(int), + offst(tachometer.value), XtRImmediate, (caddr_t) 0}, + {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension), + offst(core.height), XtRImmediate, (caddr_t) 100}, + {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension), + offst(core.width), XtRImmediate, (caddr_t) 100}, + {XtNborderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension), + offst(core.border_width), XtRImmediate, (caddr_t) 0}, + {XtNinternalBorderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension), + offst(tachometer.internal_border), XtRImmediate, (caddr_t) 0}, +}; + +static void Initialize(); +static void Realize(); +static void Resize(); +static void Redisplay(); +static Boolean SetValues(); +static void Destroy(); + +TachometerClassRec tachometerClassRec = { + { +/* core_class fields */ +#define superclass (&simpleClassRec) + /* superclass */ (WidgetClass) superclass, + /* class_name */ "Tachometer", + /* widget_size */ sizeof(TachometerRec), + /* class_initialize */ NULL, + /* class_part_initialize */ NULL, + /* class_inited */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* realize */ Realize, + /* actions */ NULL, + /* num_actions */ 0, + /* resources */ resources, + /* num_resources */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* compress_motion */ TRUE, + /* compress_exposure */ TRUE, + /* compress_enterleave */ TRUE, + /* visible_interest */ FALSE, + /* destroy */ Destroy, + /* resize */ Resize, + /* expose */ Redisplay, + /* set_values */ SetValues, + /* set_values_hook */ NULL, + /* set_values_almost */ XtInheritSetValuesAlmost, + /* get_values_hook */ NULL, + /* accept_focus */ NULL, + /* version */ XtVersion, + /* callback_private */ NULL, + /* tm_table */ NULL, + /* query_geometry */ NULL, + /* display_accelerator */ XtInheritDisplayAccelerator, + /* extension */ NULL + }, +/* Simple class fields initialization */ + { + /* change_sensitive */ XtInheritChangeSensitive + } + +}; +WidgetClass tachometerWidgetClass = (WidgetClass)&tachometerClassRec; +/**************************************************************** + * + * Private Procedures + * + ****************************************************************/ + + +static void DrawTachometer(); +static void FastFillCircle(); +static void GetneedleGC(); +static void GetscaleGC(); +static void GetcSingleircleGC(); +static void GetbackgroundGC(); +static void DrawGauge(); +static void DrawNeedle(); +static void DrawNumbers(); +static void DrawSingleNumber(); +static void DrawLabelString(); +static void MoveNeedle(); + + + +static void DrawTachometer(w) +TachometerWidget w; +{ + Cardinal center_x, center_y; + Cardinal radius_x, radius_y; + + center_x = w->core.width / 2; + center_y = w->core.height / 2; + + radius_x = center_x - w->tachometer.internal_border; + radius_y = center_y - w->tachometer.internal_border; + + if ((center_x == 0) || (center_y == 0) || + (radius_x <= 0) || (radius_y <= 0)) + /* Can't draw anything -- no room */ + return; + + /* Draw meter shape */ + + /* Big circle */ + + FastFillCircle(XtDisplay(w), XtWindow(w), w->tachometer.circle_GC, + center_x, center_y, radius_x, radius_y); + + /* Inner circle same color as the background */ + + FastFillCircle(XtDisplay(w), XtWindow(w), w->tachometer.background_GC, + center_x, center_y, (Cardinal) (radius_x * 0.95), + (Cardinal) (radius_y * 0.95)); + + /* Small circle */ + + FastFillCircle(XtDisplay(w), XtWindow(w), w->tachometer.circle_GC, + center_x, center_y, (Cardinal) (radius_x * 0.1), + (Cardinal) (radius_y * 0.1)); + + /* Draw the details */ + + DrawGauge(w); + DrawNeedle(w, w->tachometer.value); +} + + + +static void FastFillCircle(d, w, gc, center_x, center_y, radius_x, radius_y) +Display *d; +Drawable w; +GC gc; +Cardinal center_x; +Cardinal center_y; +Cardinal radius_x; +Cardinal radius_y; +{ + XPoint points[360]; + Cardinal angle; + + for (angle = 0; angle < 360; angle++) { + points[angle].x = (short) (sin((double) angle * PI / 180.0) * + (double) radius_x + (double) center_x); + points[angle].y = (short) (cos((double) angle * PI / 180.0) * + (double) radius_y + (double) center_y); + } + + XFillPolygon(d, w, gc, points, 360, Complex, + CoordModeOrigin); + +} + + + + +static void DrawGauge(w) +TachometerWidget w; +{ + XPoint points[4]; + double step; + Cardinal in_gauge_x, in_gauge_y; + Cardinal out_gauge_x, out_gauge_y; + Cardinal number_x, number_y; + Cardinal center_x, center_y; + Cardinal radius_x, radius_y; + GC gc; + double jump = 1.0; + + center_x = w->core.width / 2; + center_y = w->core.height / 2; + + radius_x = center_x - w->tachometer.internal_border; + radius_y = center_y - w->tachometer.internal_border; + + if ((center_x == 0) || (center_y == 0) || (radius_x <= 0) || + (radius_y <= 0)) + /* Can't draw anything */ + return; + + gc = w->tachometer.scale_GC; + + for (step = 330.0; step >= 30.0; step -= jump) { + if ((Cardinal) (step) % 30 == 0) { + points[0].x = sin((step + 1.0) * PI / 180.0) * radius_x * 0.75 + + center_x; + points[0].y = cos((step + 1.0) * PI / 180.0) * radius_y * 0.75 + + center_y; + points[1].x = sin((step - 1.0) * PI / 180.0) * radius_x * 0.75 + + center_x; + points[1].y = cos((step - 1.0) * PI / 180.0) * radius_y * 0.75 + + center_y; + points[2].x = sin((step - 1.0) * PI / 180.0) * radius_x * 0.85 + + center_x; + points[2].y = cos((step - 1.0) * PI / 180.0) * radius_y * 0.85 + + center_y; + points[3].x = sin((step + 1.0) * PI / 180.0) * radius_x * 0.85 + + center_x; + points[3].y = cos((step + 1.0) * PI / 180.0) * radius_y * 0.85 + + center_y; + + XFillPolygon(XtDisplay(w), XtWindow(w), gc, points, 4, + Complex, CoordModeOrigin); + + number_x = sin((step + 1.0) * PI / 180.0) * radius_x * 0.65 + + center_x; + number_y = cos((step + 1.0) * PI / 180.0) * radius_y * 0.65 + + center_y; + + if ((int)((330.0 - step) / 30.0) == 1) + jump = 3.0; + + DrawNumbers(w, (unsigned char) ((330.0 - step) / 30.0), + number_x, number_y); + + } else { + in_gauge_x = sin(step * PI / 180.0) * radius_x * 0.8 + center_x; + in_gauge_y = cos(step * PI / 180.0) * radius_y * 0.8 + center_y; + out_gauge_x = sin(step * PI / 180.0) * radius_x * 0.85 + + center_x; + out_gauge_y = cos(step * PI / 180.0) * radius_y * 0.85 + + center_y; + + XDrawLine(XtDisplay(w), XtWindow(w), gc, in_gauge_x, + in_gauge_y, out_gauge_x, out_gauge_y); + } + } + + DrawLabelString(w); +} + +static void DrawNeedle(w, load) +TachometerWidget w; +int load; +{ + XPoint points[6]; + double cur_theta1, cur_theta2, cur_theta3; + double cur_theta4, cur_theta5; + Cardinal center_x, center_y; + Cardinal radius_x, radius_y; + GC gc; + + center_x = w->core.width / 2; + center_y = w->core.height / 2; + + radius_x = center_x - w->tachometer.internal_border; + radius_y = center_y - w->tachometer.internal_border; + + if ((center_x == 0) || (center_y == 0) || (radius_x <= 0) || + (radius_y <= 0)) + /* can't draw anything */ + return; + + gc = w->tachometer.needle_GC; + + cur_theta1 = (double) (330 - (load * 3)) * PI / 180.0; + cur_theta2 = (double) (330 - (load * 3) + 1) * PI / 180.0; + cur_theta3 = (double) (330 - (load * 3) - 1) * PI / 180.0; + cur_theta4 = (330.0 - ((double) load * 3.0) + 7.0) * PI / 180.0; + cur_theta5 = (330.0 - ((double) load * 3.0) - 7.0) * PI / 180.0; + + points[0].x = sin(cur_theta1) * radius_x * 0.75 + center_x; + points[0].y = cos(cur_theta1) * radius_y * 0.75 + center_y; + points[1].x = sin(cur_theta2) * radius_x * 0.7 + center_x; + points[1].y = cos(cur_theta2) * radius_y * 0.7 + center_y; + points[2].x = sin(cur_theta4) * radius_x * 0.1 + center_x; + points[2].y = cos(cur_theta4) * radius_y * 0.1 + center_y; + points[3].x = sin(cur_theta5) * radius_x * 0.1 + center_x; + points[3].y = cos(cur_theta5) * radius_y * 0.1 + center_y; + points[4].x = sin(cur_theta3) * radius_x * 0.7 + center_x; + points[4].y = cos(cur_theta3) * radius_y * 0.7 + center_y; + points[5].x = points[0].x; + points[5].y = points[0].y; + + XDrawLines(XtDisplay(w), XtWindow(w), gc, points, 6, CoordModeOrigin); +} + + +static void DrawNumbers(w, which, x, y) +TachometerWidget w; +unsigned char which; +Cardinal x, y; +{ + /* Draw Numbers */ + + if (which == 10) { + DrawSingleNumber(w, 1, (Cardinal) ((double) x * 0.9), y); + DrawSingleNumber(w, 0, x, y); + } else + DrawSingleNumber(w, which, x, y); +} + + + +static void DrawSingleNumber(w, which, x, y) +TachometerWidget w; +Cardinal x, y; +{ + + XSegment segments[7]; + Cardinal nsegments; + unsigned char count; + Cardinal width, height; + GC gc; + + width = (w->core.width / 2) - w->tachometer.internal_border; + height = (w->core.height / 2) - w->tachometer.internal_border; + + if ((width <= 0) || (height <= 0)) + return; + + gc = w->tachometer.scale_GC; + + for (count = 0, nsegments = 0; count < 7; count++) { + if (num_segment[which].digit[count] == 1) { + segments[nsegments].x1 = (short) + (x + ((double) offset[count].x1 * + ((double) width / 200.0))); + segments[nsegments].y1 = (short) + (y + ((double) offset[count].y1 * + ((double) height / 200.0))); + segments[nsegments].x2 = (short) + (x + ((double) offset[count].x2 * + ((double) width / 200.0))); + segments[nsegments].y2 = (short) + (y + ((double) offset[count].y2 * + ((double) height / 200.0))); + nsegments++; + } + } + + XDrawSegments(XtDisplay(w), XtWindow(w), gc, segments, nsegments); + +} + + + +static void DrawLabelString(w) +TachometerWidget w; +{ + XPoint points[5]; + Cardinal ry; + unsigned char char_count; + unsigned char data_count; + Cardinal center_x, center_y; + Cardinal radius_x, radius_y; + GC gc; + + gc = w->tachometer.scale_GC; + + center_x = w->core.width / 2; + center_y = w->core.height / 2; + radius_x = center_x - w->tachometer.internal_border; + radius_y = center_y - w->tachometer.internal_border; + + if (! (center_x && center_y && (radius_x > 0) && (radius_y > 0))) + return; + + ry = (double) radius_y * 0.35 + center_y; + + for (char_count = 0; char_count < 4; char_count++) { + for (data_count = 0; data_count < char_data[char_count].nofline + ; data_count++) { + points[data_count].x = (double) + (char_data[char_count].point_list[data_count].x) * + (double) radius_x * 0.01 + center_x; + points[data_count].y = (double) + (char_data[char_count].point_list[data_count].y) * + (double) radius_y * 0.01 + ry; + } + XDrawLines(XtDisplay(w), XtWindow(w), gc, points, + char_data[char_count].nofline, CoordModeOrigin); + } +} + + + +static void MoveNeedle(w, new) +TachometerWidget w; +int new; +{ + int step; + int old, loop; + + old = w->tachometer.value; + if (new > 100) + new = 100; + + if (old == new) + return; + else if (old < new) + step = (w->tachometer.speed ? w->tachometer.speed : new - old); + else + step = (w->tachometer.speed ? - w->tachometer.speed : new - old); + + if (old < new) { + for (loop = old; loop < new; loop += step) + DrawNeedle(w, loop); + for (loop = old + step; loop <= new; loop += step) + DrawNeedle(w, loop); + } + else { + for (loop = old; loop > new; loop += step) + DrawNeedle(w, loop); + for (loop = old + step; loop >= new; loop += step) + DrawNeedle(w, loop); + } + + if (loop != new + step) /* The final needle wasn't printed */ + DrawNeedle(w, new); + + w->tachometer.value = new; +} + +static void GetneedleGC(ta) +TachometerWidget ta; +{ + XGCValues values; + + values.background = ta->core.background_pixel; + values.foreground = ta->tachometer.needle ^ ta->core.background_pixel; + values.function = GXxor; + + ta->tachometer.needle_GC = XtGetGC( + (Widget)ta, + (unsigned) GCFunction | GCBackground | GCForeground, + &values); +} + +static void GetscaleGC(ta) +TachometerWidget ta; +{ + XGCValues values; + + values.foreground = ta->tachometer.scale; + values.background = ta->core.background_pixel; + + ta->tachometer.scale_GC = XtGetGC( + (Widget)ta, + (unsigned) GCForeground | GCBackground, + &values); +} + +static void GetcircleGC(ta) +TachometerWidget ta; +{ + XGCValues values; + + values.foreground = ta->tachometer.circle; + values.background = ta->core.background_pixel; + + ta->tachometer.circle_GC = XtGetGC( + (Widget)ta, + (unsigned) GCForeground | GCBackground, + &values); +} + + +static void GetbackgroundGC(ta) +TachometerWidget ta; +{ + XGCValues values; + + values.foreground = ta->core.background_pixel; + values.background = ta->core.background_pixel; + + ta->tachometer.background_GC = XtGetGC( + (Widget)ta, + (unsigned) GCForeground | GCBackground, + &values); +} + +/* ARGSUSED */ +static void Initialize(request, new) + Widget request, new; +{ + TachometerWidget ta = (TachometerWidget) new; + + GetneedleGC(ta); + GetcircleGC(ta); + GetscaleGC(ta); + GetbackgroundGC(ta); + ta->tachometer.width = ta->tachometer.height = 0; +} /* Initialize */ + + +static void Realize(w, valueMask, attributes) + register Widget w; + Mask *valueMask; + XSetWindowAttributes *attributes; +{ + *valueMask |= CWBitGravity; + attributes->bit_gravity = NorthWestGravity; + (*superclass->core_class.realize) (w, valueMask, attributes); + +} /* Realize */ + + + +/* + * Repaint the widget window + */ + +/* ARGSUSED */ +static void Redisplay(w, event, region) + Widget w; + XEvent *event; + Region region; +{ + TachometerWidget ta = (TachometerWidget) w; + + if (event->xexpose.count == 0) + DrawTachometer(ta); +} + +static void Resize(w) + Widget w; +{ + TachometerWidget ta = (TachometerWidget) w; + + if ((ta->core.width == ta->tachometer.width) && + (ta->core.height == ta->tachometer.height)) + /* What resize? We don't see a resize! */ + return; + + XClearWindow(XtDisplay(w), XtWindow(w)); + + if ((ta->core.width <= ta->tachometer.width) && + (ta->core.height <= ta->tachometer.height)) + /* Only redraw here if no expose events are going to be */ + /* generated, i.e. if the window has not grown horizontally */ + /* or vertically. */ + DrawTachometer(ta); + + ta->tachometer.width = ta->core.width; + ta->tachometer.height = ta->core.height; +} + +/* + * Set specified arguments into widget + */ + +/* ARGSUSED */ +static Boolean SetValues(current, request, new) + Widget current, request, new; +{ + Boolean back; + Boolean changed = False; + + TachometerWidget curta = (TachometerWidget) current; + TachometerWidget newta = (TachometerWidget) new; + + back = (curta->core.background_pixel != newta->core.background_pixel); + + if (back || (curta->tachometer.needle != newta->tachometer.needle)) { + XtReleaseGC(new, newta->tachometer.needle_GC); + GetneedleGC(newta); + changed = True; + } + if (back || (curta->tachometer.scale != newta->tachometer.scale)) { + XtReleaseGC(new, newta->tachometer.scale_GC); + GetscaleGC(newta); + changed = True; + } + if (back || (curta->tachometer.circle != newta->tachometer.circle)) { + XtReleaseGC(new, newta->tachometer.circle_GC); + GetcircleGC(newta); + changed = True; + } + if (back) { + XtReleaseGC(new, newta->tachometer.background_GC); + GetbackgroundGC(newta); + changed = True; + } + + if (curta->tachometer.value != newta->tachometer.value) { + MoveNeedle(newta, newta->tachometer.value); + changed = True; + } + + return(changed); +} + +static void Destroy(w) + Widget w; +{ + TachometerWidget ta = (TachometerWidget) w; + + XtReleaseGC( w, ta->tachometer.needle_GC ); + XtReleaseGC( w, ta->tachometer.circle_GC ); + XtReleaseGC( w, ta->tachometer.scale_GC ); + XtReleaseGC( w, ta->tachometer.background_GC ); +} + + + +/*************************************************************** + * + * Exported Procedures + * + ***************************************************************/ + +int TachometerGetValue(w) +Widget w; +{ + TachometerWidget ta = (TachometerWidget) w; + + return(ta->tachometer.value); +} + + +int TachometerSetValue(w, i) +Widget w; +int i; +{ + int old; + TachometerWidget ta = (TachometerWidget) w; + + old = ta->tachometer.value; + + MoveNeedle(ta, i); + + return(old); +} |