1159b3361Sopenharmony_ci/* 2159b3361Sopenharmony_ci * GTK plotting routines source file 3159b3361Sopenharmony_ci * 4159b3361Sopenharmony_ci * Copyright (c) 1999 Mark Taylor 5159b3361Sopenharmony_ci * 6159b3361Sopenharmony_ci * This library is free software; you can redistribute it and/or 7159b3361Sopenharmony_ci * modify it under the terms of the GNU Library General Public 8159b3361Sopenharmony_ci * License as published by the Free Software Foundation; either 9159b3361Sopenharmony_ci * version 2 of the License, or (at your option) any later version. 10159b3361Sopenharmony_ci * 11159b3361Sopenharmony_ci * This library is distributed in the hope that it will be useful, 12159b3361Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 13159b3361Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14159b3361Sopenharmony_ci * Library General Public License for more details. 15159b3361Sopenharmony_ci * 16159b3361Sopenharmony_ci * You should have received a copy of the GNU Library General Public 17159b3361Sopenharmony_ci * License along with this library; if not, write to the 18159b3361Sopenharmony_ci * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19159b3361Sopenharmony_ci * Boston, MA 02111-1307, USA. 20159b3361Sopenharmony_ci */ 21159b3361Sopenharmony_ci 22159b3361Sopenharmony_ci/* $Id$ */ 23159b3361Sopenharmony_ci 24159b3361Sopenharmony_ci#ifdef HAVE_CONFIG_H 25159b3361Sopenharmony_ci# include <config.h> 26159b3361Sopenharmony_ci#endif 27159b3361Sopenharmony_ci 28159b3361Sopenharmony_ci#include "gpkplotting.h" 29159b3361Sopenharmony_ci 30159b3361Sopenharmony_ci#ifdef STDC_HEADERS 31159b3361Sopenharmony_ci# include <string.h> 32159b3361Sopenharmony_ci#else 33159b3361Sopenharmony_ci# ifndef HAVE_STRCHR 34159b3361Sopenharmony_ci# define strchr index 35159b3361Sopenharmony_ci# define strrchr rindex 36159b3361Sopenharmony_ci# endif 37159b3361Sopenharmony_cichar *strchr(), *strrchr(); 38159b3361Sopenharmony_ci# ifndef HAVE_MEMCPY 39159b3361Sopenharmony_ci# define memcpy(d, s, n) bcopy ((s), (d), (n)) 40159b3361Sopenharmony_ci# define memmove(d, s, n) bcopy ((s), (d), (n)) 41159b3361Sopenharmony_ci# endif 42159b3361Sopenharmony_ci#endif 43159b3361Sopenharmony_ci 44159b3361Sopenharmony_ci#ifdef WITH_DMALLOC 45159b3361Sopenharmony_ci#include <dmalloc.h> 46159b3361Sopenharmony_ci#endif 47159b3361Sopenharmony_ci 48159b3361Sopenharmony_cistatic gint num_plotwindows = 0; 49159b3361Sopenharmony_cistatic gint max_plotwindows = 10; 50159b3361Sopenharmony_cistatic GdkPixmap *pixmaps[10]; 51159b3361Sopenharmony_cistatic GtkWidget *pixmapboxes[10]; 52159b3361Sopenharmony_ci 53159b3361Sopenharmony_ci 54159b3361Sopenharmony_ci 55159b3361Sopenharmony_ci 56159b3361Sopenharmony_ci/* compute a gdkcolor */ 57159b3361Sopenharmony_civoid 58159b3361Sopenharmony_cisetcolor(GtkWidget * widget, GdkColor * color, gint red, gint green, gint blue) 59159b3361Sopenharmony_ci{ 60159b3361Sopenharmony_ci 61159b3361Sopenharmony_ci /* colors in GdkColor are taken from 0 to 65535, not 0 to 255. */ 62159b3361Sopenharmony_ci color->red = red * (65535 / 255); 63159b3361Sopenharmony_ci color->green = green * (65535 / 255); 64159b3361Sopenharmony_ci color->blue = blue * (65535 / 255); 65159b3361Sopenharmony_ci color->pixel = (gulong) (color->red * 65536 + color->green * 256 + color->blue); 66159b3361Sopenharmony_ci /* find closest in colormap, if needed */ 67159b3361Sopenharmony_ci gdk_color_alloc(gtk_widget_get_colormap(widget), color); 68159b3361Sopenharmony_ci} 69159b3361Sopenharmony_ci 70159b3361Sopenharmony_ci 71159b3361Sopenharmony_civoid 72159b3361Sopenharmony_cigpk_redraw(GdkPixmap * pixmap, GtkWidget * pixmapbox) 73159b3361Sopenharmony_ci{ 74159b3361Sopenharmony_ci /* redraw the entire pixmap */ 75159b3361Sopenharmony_ci gdk_draw_pixmap(pixmapbox->window, 76159b3361Sopenharmony_ci pixmapbox->style->fg_gc[GTK_WIDGET_STATE(pixmapbox)], 77159b3361Sopenharmony_ci pixmap, 0, 0, 0, 0, pixmapbox->allocation.width, pixmapbox->allocation.height); 78159b3361Sopenharmony_ci} 79159b3361Sopenharmony_ci 80159b3361Sopenharmony_ci 81159b3361Sopenharmony_cistatic GdkPixmap ** 82159b3361Sopenharmony_cifindpixmap(GtkWidget * widget) 83159b3361Sopenharmony_ci{ 84159b3361Sopenharmony_ci int i; 85159b3361Sopenharmony_ci for (i = 0; i < num_plotwindows && widget != pixmapboxes[i]; i++); 86159b3361Sopenharmony_ci if (i >= num_plotwindows) { 87159b3361Sopenharmony_ci g_print("findpixmap(): bad argument widget \n"); 88159b3361Sopenharmony_ci return NULL; 89159b3361Sopenharmony_ci } 90159b3361Sopenharmony_ci return &pixmaps[i]; 91159b3361Sopenharmony_ci} 92159b3361Sopenharmony_ci 93159b3361Sopenharmony_civoid 94159b3361Sopenharmony_cigpk_graph_draw(GtkWidget * widget, /* plot on this widged */ 95159b3361Sopenharmony_ci int n, /* number of data points */ 96159b3361Sopenharmony_ci gdouble * xcord, gdouble * ycord, /* data */ 97159b3361Sopenharmony_ci gdouble xmn, gdouble ymn, /* coordinates of corners */ 98159b3361Sopenharmony_ci gdouble xmx, gdouble ymx, int clear, /* clear old plot first */ 99159b3361Sopenharmony_ci char *title, /* add a title (only if clear=1) */ 100159b3361Sopenharmony_ci GdkColor * color) 101159b3361Sopenharmony_ci{ 102159b3361Sopenharmony_ci GdkPixmap **ppixmap; 103159b3361Sopenharmony_ci GdkPoint *points; 104159b3361Sopenharmony_ci int i; 105159b3361Sopenharmony_ci gint16 width, height; 106159b3361Sopenharmony_ci GdkFont *fixed_font; 107159b3361Sopenharmony_ci GdkGC *gc; 108159b3361Sopenharmony_ci 109159b3361Sopenharmony_ci gc = gdk_gc_new(widget->window); 110159b3361Sopenharmony_ci gdk_gc_set_foreground(gc, color); 111159b3361Sopenharmony_ci 112159b3361Sopenharmony_ci 113159b3361Sopenharmony_ci 114159b3361Sopenharmony_ci if ((ppixmap = findpixmap(widget))) { 115159b3361Sopenharmony_ci width = widget->allocation.width; 116159b3361Sopenharmony_ci height = widget->allocation.height; 117159b3361Sopenharmony_ci 118159b3361Sopenharmony_ci 119159b3361Sopenharmony_ci if (clear) { 120159b3361Sopenharmony_ci /* white background */ 121159b3361Sopenharmony_ci gdk_draw_rectangle(*ppixmap, widget->style->white_gc, TRUE, 0, 0, width, height); 122159b3361Sopenharmony_ci /* title */ 123159b3361Sopenharmony_ci#ifdef _WIN32 124159b3361Sopenharmony_ci fixed_font = gdk_font_load("-misc-fixed-large-r-*-*-*-100-*-*-*-*-*-*"); 125159b3361Sopenharmony_ci#else 126159b3361Sopenharmony_ci fixed_font = gdk_font_load("-misc-fixed-medium-r-*-*-*-100-*-*-*-*-iso8859-1"); 127159b3361Sopenharmony_ci#endif 128159b3361Sopenharmony_ci 129159b3361Sopenharmony_ci gdk_draw_text(*ppixmap, fixed_font, 130159b3361Sopenharmony_ci widget->style->fg_gc[GTK_WIDGET_STATE(widget)], 131159b3361Sopenharmony_ci 0, 10, title, strlen(title)); 132159b3361Sopenharmony_ci } 133159b3361Sopenharmony_ci 134159b3361Sopenharmony_ci 135159b3361Sopenharmony_ci points = g_malloc(n * sizeof(GdkPoint)); 136159b3361Sopenharmony_ci for (i = 0; i < n; i++) { 137159b3361Sopenharmony_ci points[i].x = .5 + ((xcord[i] - xmn) * (width - 1) / (xmx - xmn)); 138159b3361Sopenharmony_ci points[i].y = .5 + ((ycord[i] - ymx) * (height - 1) / (ymn - ymx)); 139159b3361Sopenharmony_ci } 140159b3361Sopenharmony_ci gdk_draw_lines(*ppixmap, gc, points, n); 141159b3361Sopenharmony_ci g_free(points); 142159b3361Sopenharmony_ci gpk_redraw(*ppixmap, widget); 143159b3361Sopenharmony_ci } 144159b3361Sopenharmony_ci gdk_gc_destroy(gc); 145159b3361Sopenharmony_ci} 146159b3361Sopenharmony_ci 147159b3361Sopenharmony_ci 148159b3361Sopenharmony_ci 149159b3361Sopenharmony_civoid 150159b3361Sopenharmony_cigpk_rectangle_draw(GtkWidget * widget, /* plot on this widged */ 151159b3361Sopenharmony_ci gdouble * xcord, gdouble * ycord, /* corners */ 152159b3361Sopenharmony_ci gdouble xmn, gdouble ymn, /* coordinates of corners */ 153159b3361Sopenharmony_ci gdouble xmx, gdouble ymx, GdkColor * color) 154159b3361Sopenharmony_ci{ 155159b3361Sopenharmony_ci GdkPixmap **ppixmap; 156159b3361Sopenharmony_ci GdkPoint points[2]; 157159b3361Sopenharmony_ci int i; 158159b3361Sopenharmony_ci gint16 width, height; 159159b3361Sopenharmony_ci GdkGC *gc; 160159b3361Sopenharmony_ci 161159b3361Sopenharmony_ci 162159b3361Sopenharmony_ci gc = gdk_gc_new(widget->window); 163159b3361Sopenharmony_ci gdk_gc_set_foreground(gc, color); 164159b3361Sopenharmony_ci 165159b3361Sopenharmony_ci 166159b3361Sopenharmony_ci if ((ppixmap = findpixmap(widget))) { 167159b3361Sopenharmony_ci width = widget->allocation.width; 168159b3361Sopenharmony_ci height = widget->allocation.height; 169159b3361Sopenharmony_ci 170159b3361Sopenharmony_ci 171159b3361Sopenharmony_ci for (i = 0; i < 2; i++) { 172159b3361Sopenharmony_ci points[i].x = .5 + ((xcord[i] - xmn) * (width - 1) / (xmx - xmn)); 173159b3361Sopenharmony_ci points[i].y = .5 + ((ycord[i] - ymx) * (height - 1) / (ymn - ymx)); 174159b3361Sopenharmony_ci } 175159b3361Sopenharmony_ci width = points[1].x - points[0].x + 1; 176159b3361Sopenharmony_ci height = points[1].y - points[0].y + 1; 177159b3361Sopenharmony_ci gdk_draw_rectangle(*ppixmap, gc, TRUE, points[0].x, points[0].y, width, height); 178159b3361Sopenharmony_ci gpk_redraw(*ppixmap, widget); 179159b3361Sopenharmony_ci } 180159b3361Sopenharmony_ci gdk_gc_destroy(gc); 181159b3361Sopenharmony_ci} 182159b3361Sopenharmony_ci 183159b3361Sopenharmony_ci 184159b3361Sopenharmony_ci 185159b3361Sopenharmony_civoid 186159b3361Sopenharmony_cigpk_bargraph_draw(GtkWidget * widget, /* plot on this widged */ 187159b3361Sopenharmony_ci int n, /* number of data points */ 188159b3361Sopenharmony_ci gdouble * xcord, gdouble * ycord, /* data */ 189159b3361Sopenharmony_ci gdouble xmn, gdouble ymn, /* coordinates of corners */ 190159b3361Sopenharmony_ci gdouble xmx, gdouble ymx, int clear, /* clear old plot first */ 191159b3361Sopenharmony_ci char *title, /* add a title (only if clear=1) */ 192159b3361Sopenharmony_ci int barwidth, /* bar width. 0=compute based on window size */ 193159b3361Sopenharmony_ci GdkColor * color) 194159b3361Sopenharmony_ci{ 195159b3361Sopenharmony_ci GdkPixmap **ppixmap; 196159b3361Sopenharmony_ci GdkPoint points[2]; 197159b3361Sopenharmony_ci int i; 198159b3361Sopenharmony_ci gint16 width, height, x, y, barheight; 199159b3361Sopenharmony_ci GdkFont *fixed_font; 200159b3361Sopenharmony_ci GdkGC *gc; 201159b3361Sopenharmony_ci int titleSplit; 202159b3361Sopenharmony_ci 203159b3361Sopenharmony_ci 204159b3361Sopenharmony_ci gc = gdk_gc_new(widget->window); 205159b3361Sopenharmony_ci gdk_gc_set_foreground(gc, color); 206159b3361Sopenharmony_ci 207159b3361Sopenharmony_ci 208159b3361Sopenharmony_ci if ((ppixmap = findpixmap(widget))) { 209159b3361Sopenharmony_ci width = widget->allocation.width; 210159b3361Sopenharmony_ci height = widget->allocation.height; 211159b3361Sopenharmony_ci 212159b3361Sopenharmony_ci 213159b3361Sopenharmony_ci if (clear) { 214159b3361Sopenharmony_ci /* white background */ 215159b3361Sopenharmony_ci gdk_draw_rectangle(*ppixmap, widget->style->white_gc, TRUE, 0, 0, width, height); 216159b3361Sopenharmony_ci /* title */ 217159b3361Sopenharmony_ci#ifdef _WIN32 218159b3361Sopenharmony_ci fixed_font = gdk_font_load("-misc-fixed-large-r-*-*-*-100-*-*-*-*-*-*"); 219159b3361Sopenharmony_ci#else 220159b3361Sopenharmony_ci fixed_font = gdk_font_load("-misc-fixed-medium-r-*-*-*-100-*-*-*-*-iso8859-1"); 221159b3361Sopenharmony_ci#endif 222159b3361Sopenharmony_ci 223159b3361Sopenharmony_ci titleSplit = strcspn(title, "\n"); 224159b3361Sopenharmony_ci 225159b3361Sopenharmony_ci if (titleSplit && (titleSplit != strlen(title))) { 226159b3361Sopenharmony_ci gdk_draw_text(*ppixmap, fixed_font, 227159b3361Sopenharmony_ci widget->style->fg_gc[GTK_WIDGET_STATE(widget)], 228159b3361Sopenharmony_ci 0, 10, title, titleSplit); 229159b3361Sopenharmony_ci 230159b3361Sopenharmony_ci gdk_draw_text(*ppixmap, fixed_font, 231159b3361Sopenharmony_ci widget->style->fg_gc[GTK_WIDGET_STATE(widget)], 232159b3361Sopenharmony_ci 0, 22, title + titleSplit + 1, (strlen(title) - titleSplit) - 1); 233159b3361Sopenharmony_ci 234159b3361Sopenharmony_ci 235159b3361Sopenharmony_ci } 236159b3361Sopenharmony_ci else { 237159b3361Sopenharmony_ci gdk_draw_text(*ppixmap, fixed_font, 238159b3361Sopenharmony_ci widget->style->fg_gc[GTK_WIDGET_STATE(widget)], 239159b3361Sopenharmony_ci 0, 10, title, strlen(title)); 240159b3361Sopenharmony_ci } 241159b3361Sopenharmony_ci } 242159b3361Sopenharmony_ci 243159b3361Sopenharmony_ci 244159b3361Sopenharmony_ci for (i = 0; i < n; i++) { 245159b3361Sopenharmony_ci points[1].x = .5 + ((xcord[i] - xmn) * (width - 1) / (xmx - xmn)); 246159b3361Sopenharmony_ci points[1].y = .5 + ((ycord[i] - ymx) * (height - 1) / (ymn - ymx)); 247159b3361Sopenharmony_ci points[0].x = points[1].x; 248159b3361Sopenharmony_ci points[0].y = height - 1; 249159b3361Sopenharmony_ci 250159b3361Sopenharmony_ci x = .5 + ((xcord[i] - xmn) * (width - 1) / (xmx - xmn)); 251159b3361Sopenharmony_ci y = .5 + ((ycord[i] - ymx) * (height - 1) / (ymn - ymx)); 252159b3361Sopenharmony_ci if (!barwidth) 253159b3361Sopenharmony_ci barwidth = (width / (n + 1)) - 1; 254159b3361Sopenharmony_ci barwidth = barwidth > 5 ? 5 : barwidth; 255159b3361Sopenharmony_ci barwidth = barwidth < 1 ? 1 : barwidth; 256159b3361Sopenharmony_ci barheight = height - 1 - y; 257159b3361Sopenharmony_ci /* gdk_draw_lines(*ppixmap,gc,points,2); */ 258159b3361Sopenharmony_ci gdk_draw_rectangle(*ppixmap, gc, TRUE, x, y, barwidth, barheight); 259159b3361Sopenharmony_ci 260159b3361Sopenharmony_ci } 261159b3361Sopenharmony_ci gpk_redraw(*ppixmap, widget); 262159b3361Sopenharmony_ci } 263159b3361Sopenharmony_ci gdk_gc_destroy(gc); 264159b3361Sopenharmony_ci} 265159b3361Sopenharmony_ci 266159b3361Sopenharmony_ci 267159b3361Sopenharmony_ci 268159b3361Sopenharmony_ci 269159b3361Sopenharmony_ci 270159b3361Sopenharmony_ci/* Create a new backing pixmap of the appropriate size */ 271159b3361Sopenharmony_cistatic gint 272159b3361Sopenharmony_ciconfigure_event(GtkWidget * widget, GdkEventConfigure * event, gpointer data) 273159b3361Sopenharmony_ci{ 274159b3361Sopenharmony_ci GdkPixmap **ppixmap; 275159b3361Sopenharmony_ci if ((ppixmap = findpixmap(widget))) { 276159b3361Sopenharmony_ci if (*ppixmap) 277159b3361Sopenharmony_ci gdk_pixmap_unref(*ppixmap); 278159b3361Sopenharmony_ci *ppixmap = gdk_pixmap_new(widget->window, 279159b3361Sopenharmony_ci widget->allocation.width, widget->allocation.height, -1); 280159b3361Sopenharmony_ci gdk_draw_rectangle(*ppixmap, 281159b3361Sopenharmony_ci widget->style->white_gc, 282159b3361Sopenharmony_ci TRUE, 0, 0, widget->allocation.width, widget->allocation.height); 283159b3361Sopenharmony_ci } 284159b3361Sopenharmony_ci return TRUE; 285159b3361Sopenharmony_ci} 286159b3361Sopenharmony_ci 287159b3361Sopenharmony_ci 288159b3361Sopenharmony_ci 289159b3361Sopenharmony_ci/* Redraw the screen from the backing pixmap */ 290159b3361Sopenharmony_cistatic gint 291159b3361Sopenharmony_ciexpose_event(GtkWidget * widget, GdkEventExpose * event, gpointer data) 292159b3361Sopenharmony_ci{ 293159b3361Sopenharmony_ci GdkPixmap **ppixmap; 294159b3361Sopenharmony_ci if ((ppixmap = findpixmap(widget))) { 295159b3361Sopenharmony_ci gdk_draw_pixmap(widget->window, 296159b3361Sopenharmony_ci widget->style->fg_gc[GTK_WIDGET_STATE(widget)], 297159b3361Sopenharmony_ci *ppixmap, 298159b3361Sopenharmony_ci event->area.x, event->area.y, 299159b3361Sopenharmony_ci event->area.x, event->area.y, event->area.width, event->area.height); 300159b3361Sopenharmony_ci } 301159b3361Sopenharmony_ci 302159b3361Sopenharmony_ci return FALSE; 303159b3361Sopenharmony_ci} 304159b3361Sopenharmony_ci 305159b3361Sopenharmony_ci 306159b3361Sopenharmony_ci 307159b3361Sopenharmony_ci 308159b3361Sopenharmony_ci 309159b3361Sopenharmony_ciGtkWidget * 310159b3361Sopenharmony_cigpk_plot_new(int width, int height) 311159b3361Sopenharmony_ci{ 312159b3361Sopenharmony_ci GtkWidget *pixmapbox; 313159b3361Sopenharmony_ci 314159b3361Sopenharmony_ci pixmapbox = gtk_drawing_area_new(); 315159b3361Sopenharmony_ci gtk_drawing_area_size(GTK_DRAWING_AREA(pixmapbox), width, height); 316159b3361Sopenharmony_ci gtk_signal_connect(GTK_OBJECT(pixmapbox), "expose_event", (GtkSignalFunc) expose_event, NULL); 317159b3361Sopenharmony_ci gtk_signal_connect(GTK_OBJECT(pixmapbox), "configure_event", 318159b3361Sopenharmony_ci (GtkSignalFunc) configure_event, NULL); 319159b3361Sopenharmony_ci gtk_widget_set_events(pixmapbox, GDK_EXPOSURE_MASK); 320159b3361Sopenharmony_ci 321159b3361Sopenharmony_ci if (num_plotwindows < max_plotwindows) { 322159b3361Sopenharmony_ci pixmapboxes[num_plotwindows] = pixmapbox; 323159b3361Sopenharmony_ci pixmaps[num_plotwindows] = NULL; 324159b3361Sopenharmony_ci num_plotwindows++; 325159b3361Sopenharmony_ci } 326159b3361Sopenharmony_ci else { 327159b3361Sopenharmony_ci g_print("gtk_plotarea_new(): exceeded maximum of 10 plotarea windows\n"); 328159b3361Sopenharmony_ci } 329159b3361Sopenharmony_ci 330159b3361Sopenharmony_ci return pixmapbox; 331159b3361Sopenharmony_ci} 332