Hi

>  > > For sure.  As I said, I do not see the X Drawable extension to the
>  > > xcairo device as a replacement for memcairo.  They are both
>  > > addressing different problem spaces IMHO.
>  > >
>  > > Besides this, the X Drawable extension doesn't really add a lot of
>  > > additional code to the xcairo driver while making plplot directly
>  > > accessible to almost all Xwindows developers.  This is why I am keen
>  > > to see it merged.
>  > 
>  > I agree that having both is a reasonable proposal and I think it  
>  > should be possible to merge something like this before the next release.
>  > 
>  > Does anyone know if the current xwin driver supports a X Drawable? If  
>  > it does then it might be a good idea to try and keep the interfaces  
>  > consistent. If it does not are their any objections to Jonathan's  
>  > proposed interface?
> :
> Any plans to make available a test/demo program for showing this off?

A small-ish demo is attached.  It uses GTK since that's what I was using
when developing the code but it trivially generalises to any framework so
long as an X Display and an X Drawable are accessible (including, obviously,
a "pure" libX11 application).

The attached program can be compiled so plot via a pixmap or directly to
an X Window.

This program compiles and runs against plplot patched as per the patch I
posted.  The only change to a production version would be that the structure
used for xinfo in setup_plot_drawable() would have a type of
PLXcairoDrawableInfo once its declaration was moved to plplot.h.

Under bash compile with:
  gcc -Wall $(pkg-config --cflags --libs plplotd gtk+-2.0) \
    -o plplot_xdrawable_demo plplot_xdrawable_demo.c

Regards
  jonathan

/*
 * A simple GTK application demonstrating the use of the X Drawable
 * functionality of plplot's xcairo driver.
 *
 * Copyright (C) 2008 Jonathan Woithe <[EMAIL PROTECTED]>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 */

/* Set to 0 to draw direct to an X Window, 1 to draw via a pixmap */
#define TO_PIXMAP 1
 
#include <stdio.h>
#include <plplot.h>
#include <gtk/gtk.h>

/* Needed for GDK_WINDOW_XID */
#include <gdk/gdkx.h>

/* Main menu structure */
static GtkItemFactoryEntry menu_items[] = {
  { "/_File",      NULL,         NULL,          0, "<Branch>" },
  { "/File/_Quit", "<control>Q", gtk_main_quit, 0, NULL },
};

#define APP_INITIAL_WIDTH  320
#define APP_INITIAL_HEIGHT 200

typedef struct App {
  GtkWidget *rootwindow;
  GtkWidget *plotwindow;
  GdkPixmap *plotwindow_pixmap;
} App;

App app;

/* ======================================================================== */

void setup_plot_drawable(App *app) {

struct {
  Display *display;
  Drawable drawable;
} xinfo;

PLFLT x[3] = {1,3,4};
PLFLT y[3] = {3,2,5};

  plsdev("xcairo");
  plsetopt("drvopt", "external_drawable");
  plinit();

  #if TO_PIXMAP==1
    /* Here we set up to draw to a pixmap */
    xinfo.display = GDK_PIXMAP_XDISPLAY(app->plotwindow_pixmap);
    xinfo.drawable = GDK_PIXMAP_XID(app->plotwindow_pixmap);
  #else
    /* Alternatively, we can do direct to a visible X Window */
    xinfo.display = GDK_WINDOW_XDISPLAY(app->plotwindow->window);
    xinfo.drawable = GDK_WINDOW_XID(app->plotwindow->window);
  #endif

  pl_cmd(PLESC_DEVINIT, &xinfo);
  plenv(0,5,0,5,0,0);

  plline(3, x, y);
  plend();  
}
/* ======================================================================== */

static gint ev_plotwindow_conf(GtkWidget *widget, GdkEventConfigure *ev, 
gpointer *data) {

  #if TO_PIXMAP==1
    /* Allocate pixmap */
    if (app.plotwindow_pixmap)
      gdk_pixmap_unref(app.plotwindow_pixmap);
    app.plotwindow_pixmap = gdk_pixmap_new(widget->window,
      widget->allocation.width,widget->allocation.height,-1);

    /* Clear the pixmap to a sensible background colour */
    gdk_draw_rectangle(app.plotwindow_pixmap,
      widget->style->black_gc, TRUE, 0, 0,
      widget->allocation.width, widget->allocation.height);

    /* If drawing to a pixmap we can do a plot from the conf handler since
     * the pixmap is now realised (the window widget isn't).
     */
    setup_plot_drawable(&app);
  #endif

  return(TRUE);
}

static gint ev_plotwindow_expose(GtkWidget *widget, GdkEventExpose *ev, 
gpointer *data) {

  #if TO_PIXMAP==1
    /* Dump the cached plot (created in the conf handler) to the window from 
     * the pixmap.  We don't need to recreate the plot on each expose.
     */
    gdk_draw_pixmap(widget->window,
      widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
      app.plotwindow_pixmap, ev->area.x, ev->area.y, ev->area.x, ev->area.y,
      ev->area.width, ev->area.height);
  #else
  /* If drawing direct to an X Window, ensure GTK's double buffering 
   * is turned off for that window or else the plot will be overridden
   * when the buffer is dumped to the screen.
   */
   setup_plot_drawable(&app);
  #endif

  return(TRUE);
}

/* ======================================================================== */

void init_app(App *app) {

GtkWidget *menubar;
GtkItemFactory *item_factory;
GtkAccelGroup  *accel_group = gtk_accel_group_new();
signed int nitems = sizeof(menu_items) / sizeof(menu_items[0]);

GtkWidget *vbox, *hbox;

  /* Create the top-level root window */
  app->rootwindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_signal_connect(GTK_OBJECT(app->rootwindow), "delete_event", gtk_main_quit,
     NULL);

  /* A toplevel box to hold things */
  vbox = gtk_vbox_new(FALSE,0);
  gtk_container_add(GTK_CONTAINER(app->rootwindow), vbox);

  /* Construct the main menu structure */
  item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR,"<main>",accel_group);
  gtk_item_factory_create_items(item_factory, nitems, menu_items, NULL);
  gtk_window_add_accel_group(GTK_WINDOW(app->rootwindow), accel_group);
  menubar = gtk_item_factory_get_widget(item_factory,"<main>");
  gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
  gtk_widget_show(menubar);

  /* Fiddle with boxes to effect an indent from the edges of the root window */
  hbox = gtk_hbox_new(FALSE,0);
  gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 10);
  vbox = gtk_vbox_new(FALSE,10);
  gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 10);

  /* Add an area to plot into */  
  app->plotwindow = gtk_drawing_area_new();
  app->plotwindow_pixmap = NULL;

  #if TO_PIXMAP!=1
    /* Turn off double buffering if we are plotting direct to the plotwindow
     * in setup_plot_drawable().
     */
   GTK_WIDGET_UNSET_FLAGS(app->plotwindow, GTK_DOUBLE_BUFFERED);
  #endif

  /* By experiment, 3x3 seems to be the smallest size plplot can cope with.
   * Here we utilise the side effect that gtk_widget_set_size_request()
   * effectively sets the minimum size of the widget.
   */
  gtk_widget_set_size_request(app->plotwindow,3,3);
  gtk_box_pack_start(GTK_BOX(vbox), app->plotwindow, TRUE, TRUE, 0);

  // Set the initial size of the application
  gtk_window_set_default_size(GTK_WINDOW(app->rootwindow), 
APP_INITIAL_WIDTH,APP_INITIAL_HEIGHT);

  g_signal_connect(G_OBJECT(app->plotwindow), "configure_event",
    G_CALLBACK(ev_plotwindow_conf), NULL);
  g_signal_connect(G_OBJECT(app->plotwindow), "expose_event",
    G_CALLBACK(ev_plotwindow_expose), NULL);

  gtk_widget_show_all(app->rootwindow);
}
/* ======================================================================== */

int main(int argc, char *argv[]) {
  gtk_init(&argc, &argv);
  init_app(&app);
  gtk_main();
  return 0;
}
/* ======================================================================== */

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Plplot-devel mailing list
Plplot-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/plplot-devel

Reply via email to