Chapter 17. Embedding Plots in Graphical User Interfaces

This chapter describes how to embed plots in graphical user interfaces.

The PlplotCanvas Widget for Gnome/GTK Applications

Plots can be embedded into Gnome/GTK applications by using the PlplotCanvas widget. Information on the GTK toolkit is provided at http://www.gtk.org/. PlplotCanvas is a subclass of the GnomeCanvas (see http://developer.gnome.org/doc/API/2.0/libgnomecanvas/index.html), and so includes all of its functionality. The specialized C API for PlplotCanvas is described in the Section called PlplotCanvas API, and bindings to other languages are described in *** NEEDS DOCUMENTATION ***.

PlplotCanvas Basics

The method declarations and data structures are defined in plplotcanvas.h. Programs using the PlplotCanvas widget must be linked against the libplplotgnome2d library rather than libplplotd. This is most easily accomplished using pkg-config; i.e.,


	  gcc plplotcanvas_demo.c -o plplotcanvas_demo `pkg-config --cflags --libs plplotd-gnome2`
	
You may need to remind pkg-config where to look for the plplotd-gnome2.pc file installed by PLplot; e.g.,

	  gcc plplotcanvas_demo.c -o plplotcanvas_demo `PKG_CONFIG_PATH=/usr/local/lib/pkgconfig pkg-config --cflags --libs plplotd-gnome2`
	

A specialized API is provided for PlplotCanvas and is described in the Section called PlplotCanvas API. The API provides methods to create and manipulate PlplotCanvas widgets, in addition to object-oriented analogues for each of the PLplot functions.

Example programs are provided that demonstrate the use of the PlplotCanvas widget in the Section called PlplotCanvas Examples.

PlplotCanvas API

The PlplotCanvas methods are as follows. Because PlplotCanvas is a GTK widget, GLib types (gint, gdouble, gboolean, etc) are sometimes used rather than PLplot types (PLINT, PLFLT, etc). See http://developer.gnome.org/doc/API/2.0/glib/index.html for more information on GLib and GLib types.

plplot_canvas_new: Creates a new PlplotCanvas.

PlplotCanvas* plplot_canvas_new (void);

Returns a pointer to a new PlplotCanvas widget. Methods that apply to a PlplotCanvas are given next.

void

There are no arguments for this method.

plplot_canvas_plfunc: PLplot function analogues.

void plplot_canvas_plfunc(canvas, ...);

The PLplot functions have analogue methods named like plplot_canvas_plfunc. For example, the PLplot function plline maps to plplot_canvas_plline. The plplot_canvas_plfunc methods should be used rather than the standard PLplot API when the PlplotCanvas is used.

Lines drawn to the canvas are not shown until the page is advanced using plplot_canvas_pladv. The plot will remain on the canvas until the next page advance.

The PLplot plinit and plgstrm functions are not used with PlplotCanvas because the plplot_canvas_new function does the necessary initialization and returns an object with a unique stream number.

canvas (PlplotCanvas*, input)

The canvas on which to operate.

...

The list of arguments from the PLplot function analogue. The same types used in the PLplot function are used here.

plplot_canvas_dispose: Disposes the canvas.

void plplot_canvas_dispose(canvas);

Disposes the Canvas.

canvas (PlplotCanvas*, input)

The canvas to dispose.

plplot_canvas_set_size: Sets the canvas size.

void plplot_canvas_set_size (canvas, width, height);

Sets the PlplotCanvas widget width and height.

canvas (PlplotCanvas*, input)

The PlplotCanvas to size.

width (gint, input)

The width, in pixels.

height (gint, input)

The height, in pixels.

plplot_canvas_use_text: Sets text handling.

void plplot_canvas_use_text(canvas, use_text);

Sets whether TrueType text or Hershey fonts are used by the PlplotCanvas widget.

canvas (PlplotCanvas*, input)

The PlplotCanvas to set.

use_text (gboolean, input)

TRUE for TrueType fonts (default), FALSE for Hershey fonts.

plplot_canvas_use_pixmap: Sets pixmap usage.

void plplot_canvas_use_pixmap(canvas, use_pixmap);

Sets whether lines and shades are drawn to a pixmap, or instead as vector graphics.

Lines and shade drawn to the pixmap are not anti-aliased, and so may appear pixelated. Vector graphics are fully anti-aliased, but are rendered at a slower speed.

canvas (PlplotCanvas*, input)

The PlplotCanvas to set.

use_pixmap (gboolean, input)

TRUE to use pixmap (default), FALSE for vector graphics instead.

plplot_canvas_use_persistence: Sets persistence of subsequent drawing operations.

void plplot_canvas_use_persistence (canvas, use_persistence);

Sets whether the subsequent drawing commands are persistent, or refreshed when the PLplot page is advanced. This feature is useful for plot animations, because the axes can be persistent rather than redrawn for each frame.

Note that lines that are persistent are always anti-aliased and drawn at the front.

canvas (PlplotCanvas*, input)

The PlplotCanvas to set.

use_persistence (gboolean, input)

TRUE for persistence, FALSE for erasing at new page (default).

plplot_canvas_get_stream_number: Retrieves the PLplot stream number.

PLINT plplot_canvas_get_stream_number (canvas);

Returns the stream number for the given Canvas. Although the concept of streams that exists in the standard PLplot API is not used here, the stream number provides a unique ID number for the given PlplotCanvas widget.

canvas (PlplotCanvas*, input)

The canvas to retrieve the stream number from.

PlplotCanvas Examples

Two example programs are provided that demonstrate the use of the PlplotCanvas widget. They are:

  • plplotcanvas_demo: Demonstrates the basic usage of the PlplotCanvas to embed a plot in a Gnome application.

  • plplotcanvas_animation: Demonstrates advanced multi-threaded dual-stream usage of the PlplotCanvas.

The code from plplotcanvas_demo.c is given below, and is explained in what follows.


	#include <plplotcanvas.h>
	#include <gtk/gtk.h>

	/* The width and height of the plplot canvas widget */
	#define WIDTH 1000 /* 500 */
	#define HEIGHT 600 /* 300 */

	/* Delete event callback */
	gint delete_event( GtkWidget *widget,GdkEvent *event,gpointer data ) {
	return FALSE;
	}

	/* Destroy event calback */
	void destroy(GtkWidget *widget,gpointer data) {
	gtk_main_quit ();
	}


	int main(int argc,char *argv[] )
	{

	PlplotCanvas* canvas;
	GtkWidget *window;

	/* Parse the options */
	plparseopts(&argc, argv, PL_PARSE_FULL);

	/* The data to plot */
	double x[11] = {0,1,2,3,4,5,6,7,8,9,10};
	double y[11] = {0,0.1,0.4,0.9,1.6,2.6,3.6,4.9,6.4,8.1,10};

	/* Initialize gtk and the glib type system */
	gtk_init(&argc, &argv);
	g_type_init();

	/* Create the canvas and set its size; during the creation process,
	* the gcw driver is loaded into plplot, and plinit() is invoked.
	*/
	canvas=plplot_canvas_new(TRUE);
	plplot_canvas_set_size(canvas,WIDTH,HEIGHT);

	/* Create a new window and stuff the canvas into it */
	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_container_set_border_width(GTK_CONTAINER(window),10);
	gtk_container_add(GTK_CONTAINER(window),GTK_WIDGET(canvas));

	/* Connect the signal handlers to the window decorations */
	g_signal_connect(G_OBJECT(window),"delete_event",
	G_CALLBACK(delete_event),NULL);
	g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(destroy),NULL);

	/* Display everything */
	gtk_widget_show_all(window);

	/* Draw on the canvas with Plplot */
	plplot_canvas_pladv(canvas,0); /* Advance to first page */
	plplot_canvas_plcol0(canvas,15); /* Set color to black */
	plplot_canvas_plwid(canvas,2); /* Set the pen width */
	plplot_canvas_plvsta(canvas); /* Set the viewport */
	plplot_canvas_plwind(canvas,0.,10.,0.,10.); /* Set the window */
	plplot_canvas_plbox(canvas,"bcnst",0.,0,"bcnstv",0.,0); /* Set the box */
	plplot_canvas_pllab(canvas,"x-axis","y-axis","A Simple Plot"); /* Draw some labels */

	/* Draw the line */
	plplot_canvas_plcol0(canvas,1); /* Set the pen color */
	plplot_canvas_plline(canvas,11,x,y);

	/* Advancing the page finalizes this plot */
	plplot_canvas_pladv(canvas,0);

	/* Start the gtk main loop */
	gtk_main();
	}
      

So, what's going on here? After the preliminaries, the GTK and the GLib type system are initialized by calls to gtk_init and g_type_init. A PlplotCanvas is created using plplot_canvas_new, and it's size is set using plplot_canvas_set_size.

Next, a window is created (gtk_window_new), the border is set (gtk_set_border_width), and the canvas is stuffed into the window (gtk_container_add).

Callback functions are installed using g_signal_connect so that the window decorations respond. The window is set to display everything using gtk_widget_show_all.

Now come the PLplot analogue commands. First, the page using is advanced using plplot_canvas_pladv. The pen color and width are set with plplot_canvas_plcol0 and plplot_canvas_plwid,respectively. The PLplot viewport, window, box and labels are created using plplot_canvas_plvpor, plplot_canvas_plwind, plplot_canvas_plbox and plplot_canvas_pllab, respectively. A line is drawn on the canvas using plplot_canvas_plline, the page is advanced with plplot_canvas_pladv.

Finally, the GTK main loop is entered using gtk_main, where it resides until the program is exited.