XORing of GC



I'm testing out Gtk+ on the VMS environment.  The source code was
recently ported to VMS and I've been messing around with the example
programs.  I took the simple-scribble.c program and modified it to
perform rubberbanding, however I'm having trouble with XORing the
results. I want to eliminate the artifacts that result from negating the
old line with the background color.  Rather, I'd like to flip it back to
whatever it was originally.

My basic problem is -- "I don't know when and where to XOR the
"Graphical Context".  Do I do it globally in the main routine or locally
when I configure the drawable.  Also, the syntax is giving me trouble. 
I'm using Havoc Pennington's book "GTK+/Gnome Application Development"
as a reference.

Thanks,

Donald G Plugge

Notice the main routine where I play with GtkGC.  The XOR does nothing
at this point, but the code works to rubberband.
Code is as follows:


#include <gtk/gtk.h>

/* Current rubber line coordinates */
  struct {
    gint orig_x;
    gint orig_y;
    gint base_x;
    gint base_y;
    gint dyn_x;
    gint dyn_y;
  } update_line;

/* Phase of selection process*/
  gint phase = 0;

/* Backing pixmap for drawing area */
static GdkPixmap *pixmap = NULL;

/* Create a new backing pixmap of the appropriate size */
static gint configure_event( GtkWidget         *widget,
                             GdkEventConfigure *event )
{
  g_print ("configure_event\n");
  if (pixmap)
    gdk_pixmap_unref(pixmap);

  pixmap = gdk_pixmap_new(widget->window,
                          widget->allocation.width,
                          widget->allocation.height,
                          -1);

  gdk_draw_rectangle (pixmap,
                      widget->style-bg_gc[GTK_WIDGET_STATE (widget)],
                      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 )
{
  g_print ("expose_event\n");
  gdk_draw_pixmap(widget->window,
                  widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
                  pixmap,
                  event->area.x, event->area.y,
                  event->area.x, event->area.y,
                  event->area.width, event->area.height);

  return FALSE;
}

/* Draw a rubber line on the screen using a base position */
static gint rubber_line( GtkWidget *widget,
                        gdouble    x,
                        gdouble    y)
{
  gdk_draw_line (widget->window,
                      widget->style->bg_gc[GTK_WIDGET_STATE (widget)],
                      update_line.base_x, update_line.base_y,
                      update_line.dyn_x, update_line.dyn_y);
  update_line.dyn_x = x;
  update_line.dyn_y = y;
  gdk_draw_line (widget->window,
                      widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
                      update_line.base_x, update_line.base_y,
                      update_line.dyn_x, update_line.dyn_y);

  return FALSE;
}

static gint button_press_event( GtkWidget      *widget,
                                GdkEventButton *event )
{
  g_print ("button_press_event\n");
  if (event->button == 1 && pixmap != NULL) {
    if (phase == 0) {
      update_line.orig_x = event->x;
      update_line.orig_y = event->y;
    }
    update_line.base_x = event->x;
    update_line.base_y = event->y;
    phase = 1;
  }
  if (event->button == 3 && pixmap != NULL) {
    update_line.base_x = update_line.orig_x;
    update_line.base_y = update_line.orig_y;
    phase = 2;
  }
  return TRUE;
}

static gint motion_notify_event( GtkWidget *widget,
                                 GdkEventMotion *event )
{
  int x, y;
  GdkModifierType state;

  if (event->is_hint) 
    {
    gdk_window_get_pointer (event->window, &x, &y, &state);
    }
  else
    {
      x = event->x;
      y = event->y;
      state = event->state;
    }
    
  if (phase == 1 && pixmap != NULL)
    rubber_line (widget, x, y);
  
  return TRUE;
}

void quit ()
{
  gtk_exit (0);
}

int main( int   argc, 
          char *argv[] )
{
  GtkWidget *window;
  GtkWidget *drawing_area;
  GtkWidget *vbox;
  GdkGC     *gc;

  GtkWidget *button;

  gtk_init (&argc, &argv);

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_widget_set_name (window, "Test Input");

  vbox = gtk_vbox_new (FALSE, 0);
  gtk_container_add (GTK_CONTAINER (window), vbox);
  gtk_widget_show (vbox);

  gtk_signal_connect (GTK_OBJECT (window), "destroy",
                      GTK_SIGNAL_FUNC (quit), NULL);

  /* Create the drawing area */

  drawing_area = gtk_drawing_area_new ();
  gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area), 200, 200);

  GdkGCValues values;
  values.foreground = window->style->white.pixel ?
    window->style->white : window->style->black;
  values.function = GDK_XOR;
  gc = gdk_gc_new_with_values (GTK_LAYOUT (window),
                               &values,
                               GDK_GC_FOREGROUND | GDK_GC_FUNCTION);

  gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);

  gtk_widget_show (drawing_area);

  /* Signals used to handle backing pixmap */

  gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
                      (GtkSignalFunc) expose_event, NULL);
  gtk_signal_connect (GTK_OBJECT(drawing_area),"configure_event",
                      (GtkSignalFunc) configure_event, NULL);

  /* Event signals */

  gtk_signal_connect (GTK_OBJECT (drawing_area), "motion_notify_event",
                      (GtkSignalFunc) motion_notify_event, NULL);
  gtk_signal_connect (GTK_OBJECT (drawing_area), "button_press_event",
                      (GtkSignalFunc) button_press_event, NULL);

  gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
                         | GDK_LEAVE_NOTIFY_MASK
                         | GDK_BUTTON_PRESS_MASK
                         | GDK_POINTER_MOTION_MASK
                         | GDK_POINTER_MOTION_HINT_MASK);

  /* .. And a quit button */
  button = gtk_button_new_with_label ("Quit");
  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);

  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
                             GTK_SIGNAL_FUNC (gtk_widget_destroy),
                             GTK_OBJECT (window));
  gtk_widget_show (button);

  gtk_widget_show (window);

  gtk_main ();

  return 0;
}
/* example-end */




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]