gnome-canvas scrolling



I am trying to use the gnome canvas. My application has several
image maps and correlated (point) feature data. I display the
maps using GdkPixbufs and the point features using text, and
the canvas is awesome.

However, I would like to be able to pan around the image.

at all zooms, i would like
1. the left-most scroll to have the right edge of the image in the middle
   of the window
2. the right-most scroll position to have the left edge of the image
   in the middle of the window.

(and the same for up-down)
The exact details of this panning aren't so important, but the general
idea that the pannable area should be a function of zoomed image size
and screen size is.

I have tried many different things, but it seems that the meaning
of (0,0) changes based on the zoom of the image. If the image is
smaller than the window, then (0,0) seems to nearly center the image,
but if zooming has made the size of the image larger than the screen,
then (0,0) places the upper left corner of the full size image in the
upper left corner of the window.

I can think of several ways to work around this.
1. check if image width > window width
2. set_scroll_region to be very large

but both seem to be hacks.

what is a good way to overcome this problem?

I am attaching a very stripped down c file that clearly indicates the
problem. Use b1 to pan, Sb1 to zoom in, and Sb3 to zoom out.

At z==1, and a "big" window, it works properly, allowing any pixel
in the rectangle to be placed in the center of the window,
but when zoomed in, things break down.

I have similarly had methods that worked so long as the image was
big, but that broke when the image fit inside the window.

Any suggestions would be much appreciated.
Thanks,
Seth
#include <gtk/gtk.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <gnome.h>

typedef struct { GnomeCanvas *canvas; GtkAdjustment *zadj; } mystuff;



static void destroy(GtkWidget *widget, gpointer data) { gtk_main_quit(); }

static gint my_events (GtkWidget *w,GdkEvent *event,mystuff *z) {
  GdkEventButton *bevent;
  GdkEventMotion *mevent;
  gint tx, ty;
  gint x, y, width, height;
  gfloat zo,z1,z2;
  int b1;
  GnomeCanvas *canvas;
  int m2=(GDK_CONTROL_MASK|GDK_MOD1_MASK|GDK_MOD2_MASK|GDK_BUTTON2_MASK|GDK_BUTTON3_MASK);
  int m1=(GDK_SHIFT_MASK|m2);
  GtkAdjustment *adj;
  float y1,y2;
  double xc1,xc2,yc1,yc2;

  canvas=GNOME_CANVAS(w);
  gdk_window_get_size(w->window,&width,&height);
  gdk_window_get_pointer (w->window, &tx, &ty, NULL);
  x = CLAMP (tx, 0, width-1);
  y = CLAMP (ty, 0, height-1);
  gnome_canvas_get_scroll_region(canvas,&xc1,&yc1,&xc2,&yc2);
  b1=0;

  if (event->type==GDK_BUTTON_PRESS) {
    gtk_grab_add (w); bevent=(GdkEventButton *)event;
    if (bevent->button==1 && !(bevent->state & m1)) { b1=1; }
    else if (bevent->button==1 && (bevent->state & GDK_SHIFT_MASK) && !(bevent->state & m2)) { b1=2; }
    else if (bevent->button==3 && (bevent->state & GDK_SHIFT_MASK) && !(bevent->state & m2)) { b1=3; }
  }
  else if (event->type==GDK_BUTTON_RELEASE) {
    gtk_grab_remove(w); bevent=(GdkEventButton *)event; 
    if (bevent->button==1 && !(bevent->state & m1)) { b1=1; }
  }
  else if (event->type==GDK_MOTION_NOTIFY) {
    mevent = (GdkEventMotion *) event; 
    if ((mevent->state & GDK_BUTTON1_MASK) && !(mevent->state & m1)) { b1=1; }
  }

  if (b1==1) {
    adj=GTK_LAYOUT(w)->hadjustment; 
    if (adj && width>0) { 
      adj->value=y1=0.5*(xc2-xc1)+(xc1-xc2)*x/width;
      gtk_adjustment_value_changed(adj);
    }
    adj=GTK_LAYOUT(w)->vadjustment;
    if (adj && height>0) {
      adj->value=y2=0.5*(yc2-yc1)+(yc1-yc2)*y/height;
      gtk_adjustment_value_changed(adj);
    }
  }
  else if (b1==2 || b1==3) {
    adj=z->zadj;
    zo=adj->value;
    z1=adj->lower;
    z2=adj->upper;

    if (b1==2) (adj->value) *= 2;
    else if (b1==3) (adj->value) /= 2;
    if (adj->value<z1) adj->value=z1;
    if (adj->value>=z2) adj->value=z2;
    if (adj->value != zo)   gnome_canvas_set_pixels_per_unit(GNOME_CANVAS(canvas),adj->value);
  }

  if (1) printf("event: %5d %5d | %7.3f %7.3f | %7.3f %7.3f \n",width,height,1.0*x/(width-1),1.0*y/(height-1),y1,y2);
  return(0);
}


int main( int argc, char *argv[] ) {
  GtkWidget *window,*canvas;
  GnomeCanvasGroup *root;
  mystuff *z;

  gnome_init ("testGNOME", "1.2", argc, argv);
  gdk_rgb_set_verbose (TRUE);
  gdk_rgb_init ();
  gtk_widget_set_default_colormap (gdk_rgb_get_cmap ());
  gtk_widget_set_default_visual (gdk_rgb_get_visual ());

  window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
  gtk_signal_connect (GTK_OBJECT (window), "destroy",(GtkSignalFunc) destroy, NULL);
  gtk_widget_show( window );


  canvas = gnome_canvas_new ();
  root = gnome_canvas_root (GNOME_CANVAS (canvas));

  gnome_canvas_item_new(root,
			gnome_canvas_rect_get_type(),
			"x1",0.0,"x2",100.0,
			"y1",0.0,"y2",100.0,
			"fill_color", "red",
			"outline_color", "black",
			NULL);


  z=(mystuff *)calloc(1,sizeof(mystuff));
  z->canvas=GNOME_CANVAS(canvas);
  z->zadj=GTK_ADJUSTMENT(gtk_adjustment_new (1.00, 0.0625,256, 0.05, 0.50, 0.50));
  gnome_canvas_set_pixels_per_unit(GNOME_CANVAS(canvas),z->zadj->value);

  gnome_canvas_set_scroll_region (GNOME_CANVAS (canvas),-1,-1,101,101);
  gtk_container_add (GTK_CONTAINER (window), canvas);
  gtk_widget_show (canvas);
  gtk_signal_connect_after (GTK_OBJECT (canvas),"event",(GtkSignalFunc) my_events,z);

  
  GTK_WIDGET_SET_FLAGS (canvas, GTK_CAN_FOCUS);
  gtk_widget_grab_focus (canvas);
  

  gtk_widget_show_all (window);


  /* show the window */
  gtk_main ();
  return 0;
}
/* example-end */


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