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