/* * GTK plotting routines source file * * Copyright (c) 1999 Mark Taylor * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /* $Id: gpkplotting.c,v 1.9 2004/06/06 15:31:54 bouvigne Exp $ */ #ifdef HAVE_CONFIG_H # include <config.h> #endif #include "gpkplotting.h" #ifdef STDC_HEADERS # include <string.h> #else # ifndef HAVE_STRCHR # define strchr index # define strrchr rindex # endif char *strchr (), *strrchr (); # ifndef HAVE_MEMCPY # define memcpy(d, s, n) bcopy ((s), (d), (n)) # define memmove(d, s, n) bcopy ((s), (d), (n)) # endif #endif #ifdef WITH_DMALLOC #include <dmalloc.h> #endif static gint num_plotwindows = 0; static gint max_plotwindows = 10; static GdkPixmap *pixmaps[10]; static GtkWidget *pixmapboxes[10]; /* compute a gdkcolor */ void setcolor(GtkWidget *widget, GdkColor *color, gint red,gint green,gint blue) { /* colors in GdkColor are taken from 0 to 65535, not 0 to 255. */ color->red = red * (65535/255); color->green = green * (65535/255); color->blue = blue * (65535/255); color->pixel = (gulong)(color->red*65536 + color->green*256 + color->blue); /* find closest in colormap, if needed */ gdk_color_alloc(gtk_widget_get_colormap(widget),color); } void gpk_redraw(GdkPixmap *pixmap, GtkWidget *pixmapbox) { /* redraw the entire pixmap */ gdk_draw_pixmap(pixmapbox->window, pixmapbox->style->fg_gc[GTK_WIDGET_STATE (pixmapbox)], pixmap,0,0,0,0, pixmapbox->allocation.width, pixmapbox->allocation.height); } static GdkPixmap **findpixmap(GtkWidget *widget) { int i; for (i=0; i<num_plotwindows && widget != pixmapboxes[i] ; i++); if (i>=num_plotwindows) { g_print("findpixmap(): bad argument widget \n"); return NULL; } return &pixmaps[i]; } void gpk_graph_draw(GtkWidget *widget, /* plot on this widged */ int n, /* number of data points */ gdouble *xcord, gdouble *ycord, /* data */ gdouble xmn,gdouble ymn, /* coordinates of corners */ gdouble xmx,gdouble ymx, int clear, /* clear old plot first */ char *title, /* add a title (only if clear=1) */ GdkColor *color) { GdkPixmap **ppixmap; GdkPoint *points; int i; gint16 width,height; GdkFont *fixed_font; GdkGC *gc; gc = gdk_gc_new(widget->window); gdk_gc_set_foreground(gc, color); if ((ppixmap=findpixmap(widget))) { width = widget->allocation.width; height = widget->allocation.height; if (clear) { /* white background */ gdk_draw_rectangle (*ppixmap, widget->style->white_gc, TRUE,0, 0,width,height); /* title */ #ifdef _WIN32 fixed_font = gdk_font_load ("-misc-fixed-large-r-*-*-*-100-*-*-*-*-*-*"); #else fixed_font = gdk_font_load ("-misc-fixed-medium-r-*-*-*-100-*-*-*-*-iso8859-1"); #endif gdk_draw_text (*ppixmap,fixed_font, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], 0,10,title,strlen(title)); } points = g_malloc(n*sizeof(GdkPoint)); for (i=0; i<n ; i++) { points[i].x =.5+ ((xcord[i]-xmn)*(width-1)/(xmx-xmn)); points[i].y =.5+ ((ycord[i]-ymx)*(height-1)/(ymn-ymx)); } gdk_draw_lines(*ppixmap,gc,points,n); g_free(points); gpk_redraw(*ppixmap,widget); } gdk_gc_destroy(gc); } void gpk_rectangle_draw(GtkWidget *widget, /* plot on this widged */ gdouble *xcord, gdouble *ycord, /* corners */ gdouble xmn,gdouble ymn, /* coordinates of corners */ gdouble xmx,gdouble ymx, GdkColor *color) { GdkPixmap **ppixmap; GdkPoint points[2]; int i; gint16 width,height; GdkGC *gc; gc = gdk_gc_new(widget->window); gdk_gc_set_foreground(gc, color); if ((ppixmap=findpixmap(widget))) { width = widget->allocation.width; height = widget->allocation.height; for (i=0; i<2 ; i++) { points[i].x =.5+ ((xcord[i]-xmn)*(width-1)/(xmx-xmn)); points[i].y =.5+ ((ycord[i]-ymx)*(height-1)/(ymn-ymx)); } width=points[1].x-points[0].x + 1; height=points[1].y-points[0].y + 1; gdk_draw_rectangle(*ppixmap,gc,TRUE, points[0].x,points[0].y,width,height); gpk_redraw(*ppixmap,widget); } gdk_gc_destroy(gc); } void gpk_bargraph_draw(GtkWidget *widget, /* plot on this widged */ int n, /* number of data points */ gdouble *xcord, gdouble *ycord, /* data */ gdouble xmn,gdouble ymn, /* coordinates of corners */ gdouble xmx,gdouble ymx, int clear, /* clear old plot first */ char *title, /* add a title (only if clear=1) */ int barwidth, /* bar width. 0=compute based on window size */ GdkColor *color) { GdkPixmap **ppixmap; GdkPoint points[2]; int i; gint16 width,height,x,y,barheight; GdkFont *fixed_font; GdkGC *gc; int titleSplit; gc = gdk_gc_new(widget->window); gdk_gc_set_foreground(gc, color); if ((ppixmap=findpixmap(widget))) { width = widget->allocation.width; height = widget->allocation.height; if (clear) { /* white background */ gdk_draw_rectangle (*ppixmap, widget->style->white_gc, TRUE,0, 0,width,height); /* title */ #ifdef _WIN32 fixed_font = gdk_font_load ("-misc-fixed-large-r-*-*-*-100-*-*-*-*-*-*"); #else fixed_font = gdk_font_load ("-misc-fixed-medium-r-*-*-*-100-*-*-*-*-iso8859-1"); #endif titleSplit = strcspn(title, "\n"); if (titleSplit && (titleSplit != strlen(title))) { gdk_draw_text (*ppixmap,fixed_font, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], 0,10, title, titleSplit); gdk_draw_text (*ppixmap,fixed_font, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], 0,22, title+titleSplit+1, (strlen(title)-titleSplit)-1); } else { gdk_draw_text (*ppixmap,fixed_font, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], 0,10,title,strlen(title)); } } for (i=0; i<n ; i++) { points[1].x =.5+ ((xcord[i]-xmn)*(width-1)/(xmx-xmn)); points[1].y =.5+ ((ycord[i]-ymx)*(height-1)/(ymn-ymx)); points[0].x = points[1].x; points[0].y = height-1; x = .5+ ((xcord[i]-xmn)*(width-1)/(xmx-xmn)); y = .5+((ycord[i]-ymx)*(height-1)/(ymn-ymx)); if (!barwidth) barwidth = (width/(n+1))-1; barwidth = barwidth > 5 ? 5 : barwidth; barwidth = barwidth < 1 ? 1 : barwidth; barheight = height-1 - y; /* gdk_draw_lines(*ppixmap,gc,points,2); */ gdk_draw_rectangle(*ppixmap,gc,TRUE,x,y,barwidth,barheight); } gpk_redraw(*ppixmap,widget); } gdk_gc_destroy(gc); } /* Create a new backing pixmap of the appropriate size */ static gint configure_event (GtkWidget *widget, GdkEventConfigure *event, gpointer data) { GdkPixmap **ppixmap; if ((ppixmap=findpixmap(widget))){ if (*ppixmap) gdk_pixmap_unref(*ppixmap); *ppixmap = gdk_pixmap_new(widget->window, widget->allocation.width, widget->allocation.height, -1); gdk_draw_rectangle (*ppixmap, widget->style->white_gc, TRUE, 0, 0, widget->allocation.width, widget->allocation.height); } return TRUE; } /* Redraw the screen from the backing pixmap */ static gint expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer data) { GdkPixmap **ppixmap; if ((ppixmap=findpixmap(widget))){ gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], *ppixmap, event->area.x, event->area.y, event->area.x, event->area.y, event->area.width, event->area.height); } return FALSE; } GtkWidget *gpk_plot_new(int width, int height) { GtkWidget *pixmapbox; pixmapbox = gtk_drawing_area_new(); gtk_drawing_area_size(GTK_DRAWING_AREA(pixmapbox),width,height); gtk_signal_connect (GTK_OBJECT (pixmapbox), "expose_event", (GtkSignalFunc) expose_event, NULL); gtk_signal_connect (GTK_OBJECT(pixmapbox),"configure_event", (GtkSignalFunc) configure_event, NULL); gtk_widget_set_events (pixmapbox, GDK_EXPOSURE_MASK); if (num_plotwindows < max_plotwindows) { pixmapboxes[num_plotwindows] = pixmapbox; pixmaps[num_plotwindows] = NULL; num_plotwindows ++; } else { g_print("gtk_plotarea_new(): exceeded maximum of 10 plotarea windows\n"); } return pixmapbox; }