00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 # include <config.h>
00026 #endif
00027
00028 #include "gpkplotting.h"
00029
00030 #ifdef STDC_HEADERS
00031 # include <string.h>
00032 #else
00033 # ifndef HAVE_STRCHR
00034 # define strchr index
00035 # define strrchr rindex
00036 # endif
00037 char *strchr(), *strrchr();
00038 # ifndef HAVE_MEMCPY
00039 # define memcpy(d, s, n) bcopy ((s), (d), (n))
00040 # define memmove(d, s, n) bcopy ((s), (d), (n))
00041 # endif
00042 #endif
00043
00044 #ifdef WITH_DMALLOC
00045 #include <dmalloc.h>
00046 #endif
00047
00048 static gint num_plotwindows = 0;
00049 static gint max_plotwindows = 10;
00050 static GdkPixmap *pixmaps[10];
00051 static GtkWidget *pixmapboxes[10];
00052
00053
00054
00055
00056
00057 void
00058 setcolor(GtkWidget * widget, GdkColor * color, gint red, gint green, gint blue)
00059 {
00060
00061
00062 color->red = red * (65535 / 255);
00063 color->green = green * (65535 / 255);
00064 color->blue = blue * (65535 / 255);
00065 color->pixel = (gulong) (color->red * 65536 + color->green * 256 + color->blue);
00066
00067 gdk_color_alloc(gtk_widget_get_colormap(widget), color);
00068 }
00069
00070
00071 void
00072 gpk_redraw(GdkPixmap * pixmap, GtkWidget * pixmapbox)
00073 {
00074
00075 gdk_draw_pixmap(pixmapbox->window,
00076 pixmapbox->style->fg_gc[GTK_WIDGET_STATE(pixmapbox)],
00077 pixmap, 0, 0, 0, 0, pixmapbox->allocation.width, pixmapbox->allocation.height);
00078 }
00079
00080
00081 static GdkPixmap **
00082 findpixmap(GtkWidget * widget)
00083 {
00084 int i;
00085 for (i = 0; i < num_plotwindows && widget != pixmapboxes[i]; i++);
00086 if (i >= num_plotwindows) {
00087 g_print("findpixmap(): bad argument widget \n");
00088 return NULL;
00089 }
00090 return &pixmaps[i];
00091 }
00092
00093 void
00094 gpk_graph_draw(GtkWidget * widget,
00095 int n,
00096 gdouble * xcord, gdouble * ycord,
00097 gdouble xmn, gdouble ymn,
00098 gdouble xmx, gdouble ymx, int clear,
00099 char *title,
00100 GdkColor * color)
00101 {
00102 GdkPixmap **ppixmap;
00103 GdkPoint *points;
00104 int i;
00105 gint16 width, height;
00106 GdkFont *fixed_font;
00107 GdkGC *gc;
00108
00109 gc = gdk_gc_new(widget->window);
00110 gdk_gc_set_foreground(gc, color);
00111
00112
00113
00114 if ((ppixmap = findpixmap(widget))) {
00115 width = widget->allocation.width;
00116 height = widget->allocation.height;
00117
00118
00119 if (clear) {
00120
00121 gdk_draw_rectangle(*ppixmap, widget->style->white_gc, TRUE, 0, 0, width, height);
00122
00123 #ifdef _WIN32
00124 fixed_font = gdk_font_load("-misc-fixed-large-r-*-*-*-100-*-*-*-*-*-*");
00125 #else
00126 fixed_font = gdk_font_load("-misc-fixed-medium-r-*-*-*-100-*-*-*-*-iso8859-1");
00127 #endif
00128
00129 gdk_draw_text(*ppixmap, fixed_font,
00130 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
00131 0, 10, title, strlen(title));
00132 }
00133
00134
00135 points = g_malloc(n * sizeof(GdkPoint));
00136 for (i = 0; i < n; i++) {
00137 points[i].x = .5 + ((xcord[i] - xmn) * (width - 1) / (xmx - xmn));
00138 points[i].y = .5 + ((ycord[i] - ymx) * (height - 1) / (ymn - ymx));
00139 }
00140 gdk_draw_lines(*ppixmap, gc, points, n);
00141 g_free(points);
00142 gpk_redraw(*ppixmap, widget);
00143 }
00144 gdk_gc_destroy(gc);
00145 }
00146
00147
00148
00149 void
00150 gpk_rectangle_draw(GtkWidget * widget,
00151 gdouble * xcord, gdouble * ycord,
00152 gdouble xmn, gdouble ymn,
00153 gdouble xmx, gdouble ymx, GdkColor * color)
00154 {
00155 GdkPixmap **ppixmap;
00156 GdkPoint points[2];
00157 int i;
00158 gint16 width, height;
00159 GdkGC *gc;
00160
00161
00162 gc = gdk_gc_new(widget->window);
00163 gdk_gc_set_foreground(gc, color);
00164
00165
00166 if ((ppixmap = findpixmap(widget))) {
00167 width = widget->allocation.width;
00168 height = widget->allocation.height;
00169
00170
00171 for (i = 0; i < 2; i++) {
00172 points[i].x = .5 + ((xcord[i] - xmn) * (width - 1) / (xmx - xmn));
00173 points[i].y = .5 + ((ycord[i] - ymx) * (height - 1) / (ymn - ymx));
00174 }
00175 width = points[1].x - points[0].x + 1;
00176 height = points[1].y - points[0].y + 1;
00177 gdk_draw_rectangle(*ppixmap, gc, TRUE, points[0].x, points[0].y, width, height);
00178 gpk_redraw(*ppixmap, widget);
00179 }
00180 gdk_gc_destroy(gc);
00181 }
00182
00183
00184
00185 void
00186 gpk_bargraph_draw(GtkWidget * widget,
00187 int n,
00188 gdouble * xcord, gdouble * ycord,
00189 gdouble xmn, gdouble ymn,
00190 gdouble xmx, gdouble ymx, int clear,
00191 char *title,
00192 int barwidth,
00193 GdkColor * color)
00194 {
00195 GdkPixmap **ppixmap;
00196 GdkPoint points[2];
00197 int i;
00198 gint16 width, height, x, y, barheight;
00199 GdkFont *fixed_font;
00200 GdkGC *gc;
00201 int titleSplit;
00202
00203
00204 gc = gdk_gc_new(widget->window);
00205 gdk_gc_set_foreground(gc, color);
00206
00207
00208 if ((ppixmap = findpixmap(widget))) {
00209 width = widget->allocation.width;
00210 height = widget->allocation.height;
00211
00212
00213 if (clear) {
00214
00215 gdk_draw_rectangle(*ppixmap, widget->style->white_gc, TRUE, 0, 0, width, height);
00216
00217 #ifdef _WIN32
00218 fixed_font = gdk_font_load("-misc-fixed-large-r-*-*-*-100-*-*-*-*-*-*");
00219 #else
00220 fixed_font = gdk_font_load("-misc-fixed-medium-r-*-*-*-100-*-*-*-*-iso8859-1");
00221 #endif
00222
00223 titleSplit = strcspn(title, "\n");
00224
00225 if (titleSplit && (titleSplit != strlen(title))) {
00226 gdk_draw_text(*ppixmap, fixed_font,
00227 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
00228 0, 10, title, titleSplit);
00229
00230 gdk_draw_text(*ppixmap, fixed_font,
00231 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
00232 0, 22, title + titleSplit + 1, (strlen(title) - titleSplit) - 1);
00233
00234
00235 }
00236 else {
00237 gdk_draw_text(*ppixmap, fixed_font,
00238 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
00239 0, 10, title, strlen(title));
00240 }
00241 }
00242
00243
00244 for (i = 0; i < n; i++) {
00245 points[1].x = .5 + ((xcord[i] - xmn) * (width - 1) / (xmx - xmn));
00246 points[1].y = .5 + ((ycord[i] - ymx) * (height - 1) / (ymn - ymx));
00247 points[0].x = points[1].x;
00248 points[0].y = height - 1;
00249
00250 x = .5 + ((xcord[i] - xmn) * (width - 1) / (xmx - xmn));
00251 y = .5 + ((ycord[i] - ymx) * (height - 1) / (ymn - ymx));
00252 if (!barwidth)
00253 barwidth = (width / (n + 1)) - 1;
00254 barwidth = barwidth > 5 ? 5 : barwidth;
00255 barwidth = barwidth < 1 ? 1 : barwidth;
00256 barheight = height - 1 - y;
00257
00258 gdk_draw_rectangle(*ppixmap, gc, TRUE, x, y, barwidth, barheight);
00259
00260 }
00261 gpk_redraw(*ppixmap, widget);
00262 }
00263 gdk_gc_destroy(gc);
00264 }
00265
00266
00267
00268
00269
00270
00271 static gint
00272 configure_event(GtkWidget * widget, GdkEventConfigure * event, gpointer data)
00273 {
00274 GdkPixmap **ppixmap;
00275 if ((ppixmap = findpixmap(widget))) {
00276 if (*ppixmap)
00277 gdk_pixmap_unref(*ppixmap);
00278 *ppixmap = gdk_pixmap_new(widget->window,
00279 widget->allocation.width, widget->allocation.height, -1);
00280 gdk_draw_rectangle(*ppixmap,
00281 widget->style->white_gc,
00282 TRUE, 0, 0, widget->allocation.width, widget->allocation.height);
00283 }
00284 return TRUE;
00285 }
00286
00287
00288
00289
00290 static gint
00291 expose_event(GtkWidget * widget, GdkEventExpose * event, gpointer data)
00292 {
00293 GdkPixmap **ppixmap;
00294 if ((ppixmap = findpixmap(widget))) {
00295 gdk_draw_pixmap(widget->window,
00296 widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
00297 *ppixmap,
00298 event->area.x, event->area.y,
00299 event->area.x, event->area.y, event->area.width, event->area.height);
00300 }
00301
00302 return FALSE;
00303 }
00304
00305
00306
00307
00308
00309 GtkWidget *
00310 gpk_plot_new(int width, int height)
00311 {
00312 GtkWidget *pixmapbox;
00313
00314 pixmapbox = gtk_drawing_area_new();
00315 gtk_drawing_area_size(GTK_DRAWING_AREA(pixmapbox), width, height);
00316 gtk_signal_connect(GTK_OBJECT(pixmapbox), "expose_event", (GtkSignalFunc) expose_event, NULL);
00317 gtk_signal_connect(GTK_OBJECT(pixmapbox), "configure_event",
00318 (GtkSignalFunc) configure_event, NULL);
00319 gtk_widget_set_events(pixmapbox, GDK_EXPOSURE_MASK);
00320
00321 if (num_plotwindows < max_plotwindows) {
00322 pixmapboxes[num_plotwindows] = pixmapbox;
00323 pixmaps[num_plotwindows] = NULL;
00324 num_plotwindows++;
00325 }
00326 else {
00327 g_print("gtk_plotarea_new(): exceeded maximum of 10 plotarea windows\n");
00328 }
00329
00330 return pixmapbox;
00331 }