Logo Search packages:      
Sourcecode: scigraphica version File versions  Download package

sg_plot.c

/*  SciGraphica - Scientific graphics and data manipulation
 *  Copyright (C) 2001 Adrian E. Feiguin <feiguin@ifir.edu.ar>
 *
 *  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.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <stdio.h>
#include <gdk/gdk.h>
#include <gtk/gtk.h>
#include <gtkextra/gtkextra.h>
#include <gdk/gdkkeysyms.h>
#include "sg_plot.h"
#include "sg.h"
#include "sg_dialogs.h"
#include "sg_layer.h"
#include "gtkplotart.h"
#include "../pixmaps/plot_icon2.xpm"

#define EVENT_METHOD(i, x) GTK_WIDGET_CLASS(GTK_OBJECT(i)->klass)->x


static const gdouble unit_pt[]={ 1.0, 2.83, 28.35, 72.0, (72.0/SG_DPI)};


static void       sg_plot_class_init                  (SGplotClass *klass);
static void       sg_plot_init                        (SGplot *plot);
static void       sg_plot_init_gui              (SGplot *plot);
static void sg_plot_destroy                     (GtkObject *object); 
static void       sg_plot_realize                     (GtkWidget *widget);
static void       sg_plot_map                   (GtkWidget *widget);
static void     reorder_buttons                       (SGplot *plot);
static void     button_toggled                        (GtkWidget *widget, 
                                           gpointer data);
static gint     button_clicked                        (GtkWidget *widget, 
                                             GdkEventButton *event,
                                           gpointer data);

static gint       edit_text                     (GtkWidget *widget, 
                                           GdkEventButton *event,
                                           gpointer data);
static GtkWidget *open_text_dialog              (GtkPlotText *text); 
static gint       apply_dialog_text             (GtkWidget *widget,
                                           gpointer data);
static gint       click_on_item                       (GtkPlotCanvas *canvas,
                                           GdkEvent *event,
                                           GtkPlotCanvasChild *item,
                                           gpointer data);
static void       activate_layer                      (GtkPlotCanvas *canvas,
                                           gpointer data);
static gboolean resize_item                     (GtkPlotCanvas *canvas,
                                           GtkPlotCanvasChild *item,
                                           gdouble width, 
                                           gdouble height, 
                                           gpointer data);
static gboolean move_item                       (GtkPlotCanvas *canvas,
                                           GtkPlotCanvasChild *item,
                                           gdouble x, gdouble y, 
                                           gpointer data);

static gboolean key_press                       (GtkWidget *widget, 
                                           GdkEventKey *key,
                                           gpointer data);
static void update_ruler_expose_x               (GtkWidget *scroll, 
                                           gpointer data);
static void update_ruler_expose_y               (GtkWidget *scroll, 
                                           gpointer data);
static void sg_plot_motion                      (GtkWidget *widget, 
                                           GdkEventMotion *event,
                                           gpointer data);
static void canvas_changed                      (GtkPlotCanvas *canvas,
                                           gpointer data);

#ifdef WITH_GNOME
static GnomeAppClass *parent_class = NULL;
#else
static GtkWindowClass *parent_class = NULL;
#endif

GtkType
sg_plot_get_type (void)
{
  static GtkType sg_plot_type = 0;

  if (!sg_plot_type)
    {
      GtkTypeInfo sg_plot_info =
      {
        "SGplot",
        sizeof (SGplot),
        sizeof (SGplotClass),
        (GtkClassInitFunc) sg_plot_class_init,
        (GtkObjectInitFunc) sg_plot_init,
        /* reserved_1 */ NULL,
        /* reserved_2 */ NULL,
        (GtkClassInitFunc) NULL,
      };

#ifdef WITH_GNOME
      sg_plot_type = gtk_type_unique (gnome_app_get_type(), &sg_plot_info);
#else
      sg_plot_type = gtk_type_unique (gtk_window_get_type(), &sg_plot_info);
#endif
    }

  return sg_plot_type;
}

static void
sg_plot_class_init (SGplotClass *klass)
{
  GtkWidgetClass *widget_class;
  GtkObjectClass *object_class;

  widget_class = (GtkWidgetClass*) klass;
  object_class = (GtkObjectClass*) klass;

#ifdef WITH_GNOME
  parent_class = (GnomeAppClass *)gtk_type_class (gnome_app_get_type ());
#else
  parent_class = (GtkWindowClass *)gtk_type_class (gtk_window_get_type ());
#endif

  widget_class->realize = sg_plot_realize;
  widget_class->map = sg_plot_map;
  object_class->destroy = sg_plot_destroy;
}

static void
sg_plot_init (SGplot *plot)
{
   plot->tool = SG_TOOL_ARROW;
   plot->orientation = GTK_PLOT_PORTRAIT;
   plot->page_size = GTK_PLOT_LETTER;
   plot->scale = .65;
   plot->page_width = GTK_PLOT_LETTER_W;
   plot->page_height = GTK_PLOT_LETTER_H;
   plot->page_units = SG_UNIT_IN;

   plot->hruler = NULL;
   plot->vruler = NULL;

   plot->real_canvas = gtk_plot_canvas_new(GTK_PLOT_LETTER_W,
                                           GTK_PLOT_LETTER_H,
                                           plot->scale);

   plot->layers = NULL;
   plot->nlayers = 0;

   plot->sw = NULL;
   plot->toolbox = NULL;

   plot->x = 20;
   plot->y = 20;
   plot->width = 600;
   plot->height = 600;

   sg_plot_rescale(plot, .65);

   plot->antialias = FALSE;

   sg_plot_init_gui(plot);
}

#ifdef WITH_GNOME
void sg_plot_show_bands(GList *bandlist,gboolean show)
{ GnomeDockBand *dockband;
  GnomeDockBandChild *dockbandchild;
  GList *childlist;

  while (bandlist)
  { 
    dockband=(GnomeDockBand*)bandlist->data;
    childlist=dockband->children;
    while (childlist)
    { dockbandchild=(GnomeDockBandChild*)childlist->data;
      if (show)
        gtk_widget_show(dockbandchild->widget);
      else
        gtk_widget_hide(dockbandchild->widget);
      childlist=childlist->next;
    }
    childlist=dockband->floating_child;
    while (childlist)
    { dockbandchild=(GnomeDockBandChild*)childlist->data;
      if (show)
        gtk_widget_show(dockbandchild->widget);
      else
        gtk_widget_hide(dockbandchild->widget);
      childlist=childlist->next;
    }
    bandlist=bandlist->next;
  }
}

void sg_plot_show_top_toolbar(SGplot *plot)
{ GnomeDock *dock;
  
  dock=gnome_app_get_dock (GNOME_APP(plot));
  sg_plot_show_bands(dock->top_bands,sg_show_plot_menubar);
  sg_plot_show_bands(dock->bottom_bands,sg_show_plot_menubar);
  sg_plot_show_bands(dock->left_bands,sg_show_plot_menubar);
  sg_plot_show_bands(dock->right_bands,sg_show_plot_menubar);
  gtk_widget_queue_resize(GTK_WIDGET(plot));
}  

#else
void sg_plot_show_top_toolbar(SGplot *plot)
{ GtkBox *box;
  GtkWidget *widget;
  box=GTK_BOX(GTK_BIN(plot)->child);
  widget=((GtkBoxChild*)box->children->data)->widget;; /* Assume the top toolbar is the first child */
  if (sg_show_plot_menubar)
    gtk_widget_show(widget);
  else
    gtk_widget_hide(widget);
}
#endif /* WITH_GNOME */

static void
sg_plot_init_gui(SGplot *plot)
{
 GtkWidget *table, *hbox, *hbox2, *vbox, *top_hruler, *left_vruler;
 GtkWidget *frame,*sbar_vert, *sbar_horiz;
 GtkStyle *style;
 GtkWidget *toolbar;

 vbox = gtk_vbox_new(FALSE, 0);
 plot->canvas_box = gtk_vbox_new(TRUE, 0);
 gtk_box_set_spacing(GTK_BOX(vbox), 5);
 hbox = gtk_hbox_new(FALSE, 0);
 hbox2 = gtk_hbox_new(FALSE, 0);
 table = gtk_table_new(4, 3, FALSE);

#ifdef WITH_GNOME
 gnome_app_construct(GNOME_APP(plot), PACKAGE, plot->name);
 gnome_app_set_contents(GNOME_APP(plot),vbox);
#else
 gtk_container_add(GTK_CONTAINER(plot), vbox);
#endif

 toolbar = sg_plot_build_toolbar(plot);

 gtk_window_set_title(GTK_WINDOW(plot), plot->name);
 gtk_window_set_policy(GTK_WINDOW(plot), TRUE, TRUE, FALSE);

 gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
 gtk_widget_show (hbox);
 plot->sw=gtk_viewport_new(NULL,NULL);
 sbar_vert=gtk_vscrollbar_new(gtk_viewport_get_vadjustment (GTK_VIEWPORT(plot->sw)));
 sbar_horiz=gtk_hscrollbar_new(gtk_viewport_get_hadjustment (GTK_VIEWPORT(plot->sw)));
 gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(sbar_vert), 3, 4, 1, 2,
                  (GtkAttachOptions)0,
                  (GtkAttachOptions)(GTK_FILL|GTK_SHRINK|GTK_EXPAND),0,0);
 gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(sbar_horiz), 2, 3, 2, 3,
                  (GtkAttachOptions)(GTK_FILL|GTK_SHRINK|GTK_EXPAND),
                  (GtkAttachOptions)0,0,0);

 plot->toolbox = sg_toolbox_new();
 
 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(plot->toolbox), FALSE, FALSE, 0);
 
 gtk_widget_realize(GTK_WIDGET(plot->toolbox));
 gtk_widget_show_all(plot->toolbox);
 if (!sg_show_plot_toolbar)
    gtk_widget_hide(plot->toolbox);


 gtk_box_pack_start(GTK_BOX(hbox), table, TRUE, TRUE, 0);

 gtk_container_add(GTK_CONTAINER(plot->sw),hbox2);
 gtk_box_pack_start(GTK_BOX(hbox2), GTK_WIDGET(plot->canvas_box), TRUE, FALSE, 0);
 gtk_box_pack_start(GTK_BOX(plot->canvas_box), GTK_WIDGET(plot->real_canvas), TRUE, FALSE, 0);
 gtk_widget_show(GTK_WIDGET(plot->real_canvas));
 gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(plot->sw), 2, 3, 1, 2,
                  (GtkAttachOptions)(GTK_FILL|GTK_SHRINK|GTK_EXPAND),
                  (GtkAttachOptions)(GTK_FILL|GTK_SHRINK|GTK_EXPAND), 0, 0);

/*-------------------------------------------------------------*/
 gtk_signal_connect(GTK_OBJECT(gtk_viewport_get_hadjustment (GTK_VIEWPORT(plot->sw))),
                    "changed",
                    (GtkSignalFunc)update_ruler_expose_x,(gpointer)plot);
 gtk_signal_connect(GTK_OBJECT(gtk_viewport_get_hadjustment (GTK_VIEWPORT(plot->sw))),
                    "value_changed",
                    (GtkSignalFunc)update_ruler_expose_x,(gpointer)plot);
 gtk_signal_connect(GTK_OBJECT(gtk_viewport_get_vadjustment (GTK_VIEWPORT(plot->sw))),
                    "changed",
                    (GtkSignalFunc)update_ruler_expose_y,(gpointer)plot);
 gtk_signal_connect(GTK_OBJECT(gtk_viewport_get_vadjustment (GTK_VIEWPORT(plot->sw))),
                    "value_changed",
                    (GtkSignalFunc)update_ruler_expose_y,(gpointer)plot);
/*---------------------------------------------------------------*/
 plot->hruler = top_hruler = gtk_hruler_new();
 gtk_ruler_set_range(GTK_RULER(top_hruler), 0,
                     plot->page_width, 0, plot->page_width);

 gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(top_hruler), 2,3,0,1,
                  (GtkAttachOptions)(GTK_SHRINK|GTK_FILL|GTK_EXPAND),
              (GtkAttachOptions)0,0,0);
 gtk_widget_show(top_hruler);


 plot->vruler = left_vruler = gtk_vruler_new();
 gtk_ruler_set_range(GTK_RULER(left_vruler), 0,
                     plot->page_height, 0, plot->page_height);


 gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(left_vruler),1,2,1,2,
                  (GtkAttachOptions)0,
              (GtkAttachOptions)(GTK_SHRINK|GTK_FILL|GTK_EXPAND),0,0);
 gtk_widget_show(left_vruler);
 
 style=gtk_style_copy(GTK_WIDGET(plot)->style);

 if (style && style->font){
  gtk_widget_set_style(top_hruler,style);
  gtk_widget_set_style(left_vruler,style);
 }

 gtk_signal_connect(GTK_OBJECT(plot->hruler),
                    "map",
                    (GtkSignalFunc)update_ruler_expose_x,(gpointer)plot);
 gtk_signal_connect(GTK_OBJECT(plot->vruler),
                    "map",
                    (GtkSignalFunc)update_ruler_expose_y,(gpointer)plot);

 gtk_widget_show (left_vruler);

 gtk_signal_connect(GTK_OBJECT(plot->real_canvas),"motion_notify_event",
                    GTK_SIGNAL_FUNC(sg_plot_motion), plot);
/*-------------------------------------------------------------*/

 frame = gtk_frame_new(NULL);
 gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
 gtk_box_pack_end(GTK_BOX(vbox), frame, FALSE, FALSE, 0);
 gtk_widget_show(frame);

 plot->label = gtk_label_new("");
 gtk_misc_set_alignment(GTK_MISC(plot->label), 0., .5);
 gtk_container_add(GTK_CONTAINER(frame), plot->label);
 gtk_widget_show(plot->label);

/*-------------------------------------------------------------*/
 gtk_plot_canvas_set_size(GTK_PLOT_CANVAS(plot->real_canvas),
                          GTK_PLOT_CANVAS(plot->real_canvas)->width,
                          GTK_PLOT_CANVAS(plot->real_canvas)->height);

 gtk_widget_ensure_style(plot->real_canvas);
 gtk_plot_canvas_paint(GTK_PLOT_CANVAS(plot->real_canvas));
 gtk_plot_canvas_refresh(GTK_PLOT_CANVAS(plot->real_canvas));
 
 gtk_widget_show_all(table);
 gtk_widget_show(vbox);
 
 /* Signals */
 gtk_signal_connect(GTK_OBJECT(plot->real_canvas), "changed",
                    (GtkSignalFunc)canvas_changed, plot);

 gtk_signal_connect(GTK_OBJECT(plot->real_canvas), "select_item",
                    (GtkSignalFunc)click_on_item, plot);

 gtk_signal_connect(GTK_OBJECT(plot->real_canvas), "button_press_event",
                    (GtkSignalFunc)edit_text, plot);

 gtk_signal_connect(GTK_OBJECT(plot->real_canvas), "key_press_event",
                    (GtkSignalFunc)key_press, plot);

 gtk_signal_connect(GTK_OBJECT(plot->real_canvas), "move_item",
                    (GtkSignalFunc)move_item, plot);

 gtk_signal_connect(GTK_OBJECT(plot->real_canvas), "resize_item",
                    (GtkSignalFunc)resize_item, plot);


}

static void
sg_plot_realize(GtkWidget *widget)
{
 SGplot *plot;
 GdkPixmap *plot_icon_pixmap;
 GdkBitmap *plot_icon_mask;

 plot = SG_PLOT(widget);

 if(plot->width > 0 && plot->height > 0){
          gtk_widget_set_uposition(GTK_WIDGET(plot),
                                   plot->x, plot->y);
          gtk_widget_set_usize(GTK_WIDGET(plot),
                               plot->width,
                               plot->height);
 }else{
          gtk_widget_set_usize(GTK_WIDGET(plot),
                               600,
                               600);
 }

 GTK_WIDGET_CLASS(parent_class)->realize(widget);

 plot_icon_pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL,
                                                gdk_colormap_get_system(),
                                                &plot_icon_mask, NULL, plot_icon2_xpm);

 gdk_window_set_icon(GTK_WIDGET(plot)->window, NULL, plot_icon_pixmap, plot_icon_mask);
}

static void
sg_plot_map(GtkWidget *widget)
{
 SGplot *plot;
 GdkPixmap *plot_icon_pixmap;
 GdkBitmap *plot_icon_mask;

 plot = SG_PLOT(widget);

 GTK_WIDGET_CLASS(parent_class)->map(widget);
 sg_plot_show_top_toolbar(plot);
 sg_plot_toolbox_init(plot);

}

SGplot *
sg_plot_new(gchar *name)
{
   SGplot *plot;

   plot = SG_PLOT(gtk_widget_new(sg_plot_get_type(), NULL));

   plot->name = g_strdup(name);
   gtk_window_set_title(GTK_WINDOW(plot), plot->name);
  
   return plot;
}   

SGplot *
sg_plot_new_with_layer(SGlayerType layer_type, gchar *name)
{
   SGplot *plot;
   SGlayer *default_layer;

   plot = sg_plot_new(name);

   if(layer_type != SG_LAYER_POLAR)
     default_layer = sg_layer_new(layer_type, .65, .45);
   else
     default_layer = sg_layer_new(layer_type, .75, .45);

   sg_plot_add_layer(plot, default_layer, .175, .15);

   return plot;
}


void
sg_plot_add_layer(SGplot *plot, SGlayer *layer, gdouble x, gdouble y)
{
   gint nlayers;

   layer->parent = plot;

   nlayers = plot->nlayers;

   gtk_fixed_put(GTK_FIXED(plot->real_canvas), 
                 layer->button,
                 nlayers * 24, 0);
   gtk_widget_show(layer->button);
   sg_layer_button_set_label(layer, nlayers + 1);

   gtk_plot_canvas_add_plot(GTK_PLOT_CANVAS(plot->real_canvas), 
                            GTK_PLOT(layer->real_plot), x, y);

   gtk_widget_show(GTK_WIDGET(layer->real_plot));
   plot->layers = g_list_append(plot->layers, layer);

   sg_plot_set_active_layer(plot, layer);
   plot->nlayers++;

   gtk_signal_connect(GTK_OBJECT(layer->button), "toggled",
                      GTK_SIGNAL_FUNC(button_toggled), layer);
   gtk_signal_connect(GTK_OBJECT(layer->button), "button_press_event",
                      GTK_SIGNAL_FUNC(button_clicked), layer);

   sg_layer_control_refresh(plot->name);
}

void
sg_plot_move_layer(SGplot *plot, SGlayer *layer, gdouble x, gdouble y)
{
   gint nlayers;

   layer->parent = plot;

   gtk_plot_move(GTK_PLOT(layer->real_plot), x, y);

   gtk_plot_canvas_paint(GTK_PLOT_CANVAS(plot->real_canvas));
   gtk_plot_canvas_refresh(GTK_PLOT_CANVAS(plot->real_canvas));
}

void
sg_plot_resize_layer(SGplot *plot, SGlayer *layer, gdouble w, gdouble h)
{
   gtk_plot_resize(GTK_PLOT(layer->real_plot), w, h);

   gtk_plot_canvas_paint(GTK_PLOT_CANVAS(plot->real_canvas));
   gtk_plot_canvas_refresh(GTK_PLOT_CANVAS(plot->real_canvas));
}

void
sg_plot_remove_layer(SGplot *plot, SGlayer *layer)
{
  GList *layers = NULL;

  if(plot->nlayers == 0) return;

  gtk_container_remove(GTK_CONTAINER(plot->real_canvas), layer->real_plot); 
  gtk_container_remove(GTK_CONTAINER(plot->real_canvas), layer->button); 

  layers = plot->layers;
  while(layers) {
     if(layers->data == layer){
         plot->layers = g_list_remove_link(plot->layers, layers);
         if(layer && GTK_IS_OBJECT(layer)) gtk_object_destroy(GTK_OBJECT(layer));
         g_list_free_1(layers);
         plot->nlayers--;
         break;
     }
     layers = layers->next;
  }

  if(layer) g_free(layer);

  reorder_buttons(plot);

  if(plot->nlayers > 0) 
      activate_layer(GTK_PLOT_CANVAS(plot->real_canvas), plot); 
  else{
      plot->layers = NULL;
      plot->active_layer = NULL;
  }

  sg_layer_control_refresh(plot->name);
}

static void
reorder_buttons(SGplot *plot)
{
  GList *layers = NULL;
  SGlayer *layer;
  gint nlayers = 0;

  layers = plot->layers;

  while(layers) {
     layer = (SGlayer *)layers->data;

     gtk_fixed_move(GTK_FIXED(plot->real_canvas), 
                   layer->button,
                   nlayers * 24, 0);
     gtk_widget_show(layer->button);
     sg_layer_button_set_label(layer, nlayers + 1);

     nlayers++;
     layers = layers->next;
  }

}


static void
button_toggled(GtkWidget *widget, gpointer data)
{
  SGlayer *layer;

  layer = SG_LAYER(data);
  sg_plot_set_active_layer(SG_PLOT(layer->parent), layer);
}

static gint
button_clicked(GtkWidget* widget, GdkEventButton *event, gpointer data)
{
  SGlayer *layer;
  SGplot *plot;
  GList *llink;
  GdkModifierType mods;
  gchar path[1000];

  gdk_window_get_pointer(widget->window, NULL, NULL, &mods);
  if(!(mods & GDK_BUTTON1_MASK)) return FALSE;
  if(event->type != GDK_2BUTTON_PRESS) return FALSE;

  layer = SG_LAYER(data);
  plot = SG_PLOT(layer->parent);
  llink = g_list_find(plot->layers, layer);
  sprintf(path, "%s:%d:dataset", plot->name,
          g_list_position(plot->layers, llink)+1);
  sg_layer_control(path);

  gtk_grab_remove(widget);
  return FALSE;
}
   
void
sg_plot_set_active_layer(SGplot *plot, SGlayer *layer)
{
  SGlayer *child = NULL;
  GList *list;

  plot->active_layer = layer;

  list = plot->layers;
  while(list){
    child = (SGlayer *)list->data;
    GTK_BUTTON(child->button)->button_down = FALSE;
    GTK_TOGGLE_BUTTON(child->button)->active = FALSE;
    gtk_widget_set_state(child->button, GTK_STATE_NORMAL);
    gtk_widget_draw(child->button, NULL);
    list = list->next;
  }

  if(!layer) return;

  gtk_plot_canvas_set_active_plot(GTK_PLOT_CANVAS(plot->real_canvas),
                                  GTK_PLOT(layer->real_plot));

  GTK_BUTTON(layer->button)->button_down = TRUE;
  GTK_TOGGLE_BUTTON(layer->button)->active = TRUE;
  gtk_widget_set_state(layer->button, GTK_STATE_ACTIVE);
  gtk_widget_draw(child->button, NULL);
}


gint
sg_plot_rename(SGplot *plot, gchar *name)
{
  if(strcmp(plot->name, name) == 0) return FALSE;

  if(plot->name){
     g_free(plot->name);
     plot->name = NULL;
  }
 
  plot->name = g_strdup(name);

  gtk_window_set_title(GTK_WINDOW(plot),name);

  if(gui_iconlist){
    if(plot->icon->label){
       g_free(plot->icon->label);
       plot->icon->label = NULL;
    }
 
    plot->icon->label = g_strdup(name);

    if(plot->icon->entry_label){
       g_free(plot->icon->entry_label);
       plot->icon->entry_label = NULL;
    }
 
    plot->icon->entry_label = g_strdup(name);

    gtk_entry_set_text(GTK_ENTRY(plot->icon->entry), name);
  }

  return TRUE;
}


SGplot *
sg_plot_get_from_canvas(GtkWidget *canvas)
{
  GList *w;
  SGplot *plot = NULL;
  GtkWidget *data;

  w = plots;
  while(w){
    plot = (SGplot *)w->data;
    data = plot->real_canvas;
    if(data && data == canvas) break;
    w = w->next;
  }
 
  if(w)
   return (SGplot *)w->data;

  return NULL;
}

void
sg_plot_rescale(SGplot *plot, gdouble scale)
{
  if(scale < .15) return;

  plot->scale = scale;
  gtk_plot_canvas_set_magnification(GTK_PLOT_CANVAS(plot->real_canvas),
                                    plot->scale);

  if(plot->hruler) update_ruler_expose_x(NULL, plot);
  if(plot->vruler) update_ruler_expose_y(NULL, plot);
}

void
sg_plot_fit_page(SGplot *plot)
{
  gdouble width, height;
  gdouble w_width, w_height;
  GtkBin *bin;
  gdouble scale,scalex,scaley;

  w_width=(gdouble)plot->sw->allocation.width;
  w_height=(gdouble)plot->sw->allocation.height;
  width = (gdouble)GTK_PLOT_CANVAS(plot->real_canvas)->pixmap_width;
  height = (gdouble)GTK_PLOT_CANVAS(plot->real_canvas)->pixmap_height;

  scalex=w_width/width;
  scaley=w_height/height;

  if(scalex<scaley)   sg_plot_rescale(plot, scalex*plot->scale);
  else   sg_plot_rescale(plot, scaley*plot->scale);

}

void
sg_plot_fit_page_h(SGplot *plot)
{
  gdouble width;
  gdouble w_width;
  GtkBin *bin;
  gdouble scalex;

  w_width=(gdouble)plot->sw->allocation.width;
  width = (gdouble)GTK_PLOT_CANVAS(plot->real_canvas)->pixmap_width;

  scalex=w_width/width;

  sg_plot_rescale(plot, scalex*plot->scale);
}

void
sg_plot_fit_page_v(SGplot *plot)
{
  gdouble height;
  gdouble w_height;
  GtkBin *bin;
  gdouble scaley;

  w_height=(gdouble)plot->sw->allocation.height;
  height = (gdouble)GTK_PLOT_CANVAS(plot->real_canvas)->pixmap_height;

  scaley=w_height/height;

  sg_plot_rescale(plot, scaley*plot->scale);

}

void
sg_plot_set_size(SGplot *plot, gint page_size, 
                 gint width, gint height, gint orientation)
{
  gint real_width, real_height;

  if(orientation == GTK_PLOT_PORTRAIT){
    real_width = width;
    real_height = height;
  }else{
    real_width = height;
    real_height = width;
  }

  plot->page_size = page_size;
  plot->page_width = real_width;
  plot->page_height = real_height;
  plot->orientation = orientation;

  GTK_PLOT_CANVAS(plot->real_canvas)->pixmap_width = real_width;
  GTK_PLOT_CANVAS(plot->real_canvas)->pixmap_height = real_height;

  gtk_plot_canvas_set_size(GTK_PLOT_CANVAS(plot->real_canvas), 
                           real_width, real_height);

  if(plot->hruler) update_ruler_expose_x(NULL, plot);
  if(plot->vruler) update_ruler_expose_y(NULL, plot);

} 

void
sg_plot_clear(SGplot *plot)
{
  GList *list;

  list = plot->layers;
  while(list){
    SGlayer *layer;
 
    layer = SG_LAYER(list->data); 
    sg_plot_remove_layer(plot, layer);

    list = plot->layers;
  }  
  
  plot->layers = NULL;  
}

static void
sg_plot_destroy(GtkObject *object)
{
  SGplot *plot;

  plot = SG_PLOT(object);

  sg_plot_clear(plot); 

  gtk_widget_destroy(plot->real_canvas);

  g_free(plot->name);

  if (GTK_OBJECT_CLASS (parent_class)->destroy)
    (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
}

/* Events */

static gint
dialog_quit (GtkWidget *widget)
{
  sg_dialog_kill(widget);

  gtk_main_quit();

  return FALSE;
}

static gint
click_on_item(GtkPlotCanvas *canvas, GdkEvent *event, 
              GtkPlotCanvasChild *item, gpointer data)
{
  GtkPlotCanvasChild *child = NULL;
  SGplot *plot;
  GList *llink;
  gchar path[255];
  gboolean double_click;
  gboolean return_value = TRUE;

  double_click = (event->type == GDK_2BUTTON_PRESS);

  plot = SG_PLOT(data);
  activate_layer(canvas, plot);

  llink = g_list_find(plot->layers, plot->active_layer);

  if(plot->tool == SG_TOOL_ZOOM ||
     plot->tool == SG_TOOL_LINE ||
     plot->tool == SG_TOOL_LINE_ARROW ||
     plot->tool == SG_TOOL_RECTANGLE ||
     plot->tool == SG_TOOL_ELLIPSE)
    return TRUE;

  switch(item->type){
    case GTK_PLOT_CANVAS_PLOT:
       sprintf(path, "%s:%d", plot->name,
               g_list_position(plot->layers, llink)+1);
       if(double_click && plot->tool == SG_TOOL_ARROW){
            sg_layer_control(path);
            return_value = FALSE;
       }
       break;
    case GTK_PLOT_CANVAS_TEXT:
       if(double_click && plot->tool == SG_TOOL_ARROW){
         GtkPlotCanvasChild *child;
         GtkPlotText *real_text;
         GtkWidget *dialog;

         child = (GtkPlotCanvasChild *)item->data;
         real_text = (GtkPlotText *)child->data;

         dialog = open_text_dialog(real_text);
         gtk_signal_connect (GTK_OBJECT(SG_TEXT_DIALOG(dialog)->apply_button), 
                             "clicked",
                             GTK_SIGNAL_FUNC (apply_dialog_text), 
                             plot);
         gtk_main();

         gtk_plot_canvas_paint(GTK_PLOT_CANVAS(canvas));
         gtk_plot_canvas_refresh(GTK_PLOT_CANVAS(canvas));
         return_value = FALSE;
       }
       break;
    case GTK_PLOT_CANVAS_TITLE:
       sprintf(path, "%s:%d:axis:title", plot->name,
               g_list_position(plot->layers, llink)+1);
       if(double_click && plot->tool == SG_TOOL_ARROW){
            sg_layer_control(path);
            return_value = FALSE;
       }
       break;
    case GTK_PLOT_CANVAS_DATA:
       sprintf(path, "%s:%d:dataset:style", plot->name,
               g_list_position(plot->layers, llink)+1);
       if(double_click && plot->tool == SG_TOOL_ARROW){
            sg_layer_control(path);
            return_value = FALSE;
       }
       if(plot->tool == SG_TOOL_POINTER){
            if(GTK_IS_PLOT_POLAR(canvas->active_plot))
                g_snprintf(path, 200, "  (R, Angle) = (%f,%f)",
                        GTK_PLOT_CANVAS(canvas)->active_x,
                        GTK_PLOT_CANVAS(canvas)->active_y);
            else
                g_snprintf(path, 200, "  (X,Y) = (%f,%f)", 
                        GTK_PLOT_CANVAS(canvas)->active_x,
                        GTK_PLOT_CANVAS(canvas)->active_y);
            gtk_label_set_text(GTK_LABEL(plot->label), path);
            return_value = TRUE;
       }
       if(plot->tool == SG_TOOL_MARKERS){
            GtkPlotData *active_data;
            GtkPlotMarker *marker = NULL;
            GList *markers;
            gint nmarkers = 0;
             
            active_data = plot->active_layer->active_data;
            if(active_data){
              markers = active_data->markers;
              while(markers){
                nmarkers++;
                markers = markers->next;
              }
            }

            if(nmarkers == 2) sg_layer_remove_markers(plot->active_layer);

            if(nmarkers <= 2){ 
              active_data = GTK_PLOT_CANVAS(canvas)->active_data;
              if(GTK_IS_PLOT_POLAR(canvas->active_plot))
                  g_snprintf(path, 200, "  (R, Angle) = (%f,%f)",
                          GTK_PLOT_CANVAS(canvas)->active_x,
                          GTK_PLOT_CANVAS(canvas)->active_y);
              else
                  g_snprintf(path, 200, "  (X,Y) = (%f,%f)", 
                          GTK_PLOT_CANVAS(canvas)->active_x,
                          GTK_PLOT_CANVAS(canvas)->active_y);
              gtk_label_set_text(GTK_LABEL(plot->label), path);
              gtk_plot_data_add_marker(active_data,
                               GTK_PLOT_CANVAS(canvas)->active_point);
              gtk_plot_canvas_paint(GTK_PLOT_CANVAS(canvas));
              gtk_plot_canvas_refresh(GTK_PLOT_CANVAS(canvas));
              plot->active_layer->active_data = active_data; 
            }
            return_value = FALSE;
       }
       break;
    case GTK_PLOT_CANVAS_AXIS:
       sprintf(path, "%s:%d:axis", plot->name,
               g_list_position(plot->layers, llink)+1);
       if(double_click && plot->tool == SG_TOOL_ARROW){
            sg_layer_control(path);
            return_value = FALSE;
       }
       break;
    case GTK_PLOT_CANVAS_LEGENDS:
       sprintf(path, "%s:%d:legends", plot->name,
               g_list_position(plot->layers, llink)+1);
       if(double_click && plot->tool == SG_TOOL_ARROW){
            sg_layer_control(path);
            return_value = FALSE;
       }
       break;
    case GTK_PLOT_CANVAS_LINE:
       child = (GtkPlotCanvasChild *)item->data;
       if(double_click && plot->tool == SG_TOOL_ARROW){
         sg_line_dialog(canvas, (GtkPlotCanvasLine *)child->data);
         return_value = FALSE;
       }
       break;
    case GTK_PLOT_CANVAS_RECTANGLE:
       child = (GtkPlotCanvasChild *)item->data;
       if(double_click && plot->tool == SG_TOOL_ARROW){
         sg_rectangle_dialog(canvas, (GtkPlotCanvasRectangle *)child->data);
         return_value = FALSE;
       }
       break;
    case GTK_PLOT_CANVAS_ELLIPSE:
       child = (GtkPlotCanvasChild *)item->data;
       if(double_click && plot->tool == SG_TOOL_ARROW){
         sg_ellipse_dialog(canvas, (GtkPlotCanvasEllipse *)child->data);
         return_value = FALSE;
       }
       break;
    case GTK_PLOT_CANVAS_MARKER:
       return_value = TRUE;
       break;
   }

  return return_value;
}

static gint 
edit_text(GtkWidget *widget, GdkEventButton *event, gpointer data)
{
  GtkPlotCanvasChild *child;
  GdkModifierType mods;
  GtkPlotText text;
  SGplot *plot;
  GtkWidget *dialog;
  GtkPlotText *real_text;
  gint x, y;

  plot = SG_PLOT(data);
  if(plot->tool != SG_TOOL_TEXT) return FALSE;

  gdk_window_get_pointer(widget->window, &x, &y, &mods);
  if(!(mods & GDK_BUTTON1_MASK)) return FALSE;
  activate_layer(GTK_PLOT_CANVAS(widget), plot);

  text.text = g_strdup("Enter text here");
  gdk_color_black(gdk_colormap_get_system(), &text.fg);
  gdk_color_white(gdk_colormap_get_system(), &text.bg);
  text.angle = 0;
  text.height = 16;
  text.transparent = TRUE;
  text.border = (GtkPlotBorderStyle)0;
  text.border_width = 0;
  text.border_space = 2;
  text.shadow_width = 3;
  text.justification = GTK_JUSTIFY_LEFT;
  text.font = g_strdup("Helvetica");

  gtk_plot_canvas_get_position(GTK_PLOT_CANVAS(widget), x, y,
                               &text.x, &text.y);

  child = gtk_plot_canvas_put_text(GTK_PLOT_CANVAS(plot->real_canvas),
                                   text.x, text.y,
                                   text.font, text.height,
                                   text.angle,
                                   &text.fg, &text.bg,
                                   text.transparent,
                                   text.justification,
                                   text.text);

  real_text = (GtkPlotText *)child->data; 
  real_text->border_space = 2;
  real_text->shadow_width = 3;

  dialog = open_text_dialog(real_text);
  gtk_signal_connect (GTK_OBJECT(SG_TEXT_DIALOG(dialog)->apply_button), 
                      "clicked",
                      GTK_SIGNAL_FUNC (apply_dialog_text), 
                      plot);
  gtk_main();

  if(!real_text->text || strlen(real_text->text) == 0){
    gtk_plot_canvas_remove_child(GTK_PLOT_CANVAS(plot->real_canvas), child);
  } 
  gtk_plot_canvas_paint(GTK_PLOT_CANVAS(plot->real_canvas));
  gtk_plot_canvas_refresh(GTK_PLOT_CANVAS(plot->real_canvas));

  return TRUE;
}

static gint
apply_dialog_text(GtkWidget *widget, gpointer data)
{
  SGplot *plot = SG_PLOT(data);

  gtk_plot_canvas_paint(GTK_PLOT_CANVAS(plot->real_canvas));
  gtk_plot_canvas_refresh(GTK_PLOT_CANVAS(plot->real_canvas));
}

static GtkWidget *
open_text_dialog(GtkPlotText *text)
{
  GtkWidget *dialog;

  dialog = sg_text_dialog_new(text);

  gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);

  gtk_widget_show(dialog);
  sg_dialog_new(dialog);

  gtk_signal_connect(GTK_OBJECT(dialog), "destroy",
                     GTK_SIGNAL_FUNC(dialog_quit), NULL);

  gtk_signal_connect (GTK_OBJECT(SG_TEXT_DIALOG(dialog)->ok_button), 
                      "clicked",
                      GTK_SIGNAL_FUNC (gtk_widget_destroy), 
                      GTK_OBJECT(dialog));

  gtk_signal_connect_object (GTK_OBJECT(SG_TEXT_DIALOG(dialog)->cancel_button),
                             "clicked",
                             GTK_SIGNAL_FUNC (gtk_widget_destroy), 
                             GTK_OBJECT(dialog));

  return dialog;
}

static void
activate_layer(GtkPlotCanvas *canvas, gpointer data)
{
  GList *list;
  SGlayer *layer;
  SGplot *plot;

  if(!canvas) return;
  plot = SG_PLOT(data);

  list = plot->layers;
  while(list)
   {
     layer = (SGlayer *)list->data;

     if(GTK_PLOT(layer->real_plot) == canvas->active_plot){
        sg_plot_set_active_layer(plot, layer);
        break;
     }

     list = list->next;
   }

}

static gboolean
resize_item(GtkPlotCanvas *canvas, GtkPlotCanvasChild *item,
            gdouble new_width, gdouble new_height, gpointer data)
{
  return TRUE;
}

static gboolean
move_item(GtkPlotCanvas *canvas, GtkPlotCanvasChild *item,
          gdouble x, gdouble y, gpointer data)
{
  switch(item->type){
    case GTK_PLOT_CANVAS_PLOT:
        return TRUE;
        break;
    case GTK_PLOT_CANVAS_LEGENDS:
        return TRUE;
        break;
    case GTK_PLOT_CANVAS_TITLE:
        return TRUE;
        break;
    case GTK_PLOT_CANVAS_TEXT:
        return TRUE;
        break;
    default:
        return TRUE;
        break;
  }
     
  gtk_plot_canvas_paint(canvas);
  gtk_plot_canvas_refresh(canvas);
  return FALSE;
}


static gboolean
key_press(GtkWidget *widget, GdkEventKey *key, gpointer data)
{
  GtkPlotCanvas *canvas = GTK_PLOT_CANVAS(active_plot->real_canvas);
  GtkPlotCanvasChild *child = NULL;
  GtkPlotAxis *axis = NULL;
  SGplot *plot = SG_PLOT(data);
  gint i = 0;
  gint the_axis = -1;


  switch(key->keyval){
    case GDK_Escape:
      if(canvas->action != GTK_PLOT_CANVAS_ACTION_INACTIVE)
         gtk_plot_canvas_cancel_action(canvas);
      break;
    case GDK_Delete: case GDK_KP_Delete:
      if(canvas->state == GTK_STATE_SELECTED)
        switch(canvas->active_item.type){
         case GTK_PLOT_CANVAS_PLOT:
          gtk_plot_canvas_cancel_action(canvas);
          if(canvas->num_plots  > 1 && sg_accept_dialog("Remove layer?", 1) == YES_CLICKED)
             sg_plot_remove_layer(plot, plot->active_layer);
          return TRUE;
         case GTK_PLOT_CANVAS_LEGENDS:
          gtk_plot_canvas_cancel_action(canvas);
          gtk_plot_hide_legends(GTK_PLOT(canvas->active_plot));
          gtk_plot_canvas_paint(canvas);
          gtk_plot_canvas_refresh(canvas);
          return TRUE;
          break;
         case GTK_PLOT_CANVAS_TITLE:
          for(i = 0; i < 4; i++){
             axis = gtk_plot_get_axis(GTK_PLOT(canvas->active_plot), (GtkPlotAxisPos)i);
             if(axis == canvas->active_item.data){
                the_axis = i;
                break;
             }
          }

          gtk_plot_canvas_cancel_action(canvas);
          if(the_axis != -1)
              gtk_plot_axis_hide_title(GTK_PLOT(canvas->active_plot), (GtkPlotAxisPos)the_axis);
          
          gtk_plot_canvas_paint(canvas);
          gtk_plot_canvas_refresh(canvas);
          return TRUE;
         case GTK_PLOT_CANVAS_AXIS:
          return TRUE;
         default:
          child = (GtkPlotCanvasChild *)canvas->active_item.data;
          gtk_plot_canvas_cancel_action(canvas);
          gtk_plot_canvas_remove_child(canvas, child); 
          gtk_plot_canvas_paint(canvas);
          gtk_plot_canvas_refresh(canvas);
          return TRUE;
       }
     break;
    default:
     break;
  }

  return FALSE;
}

static void
update_ruler_expose_x(GtkWidget *scroll, gpointer data)
{
    GtkAdjustment *adj;
    SGplot *plot;
    gdouble start, end, fac, fac2,p_size;
    gint width,s_width,height;
    GtkAllocation allocation;

    if (!data) return;

    plot=(SGplot *)data;

    allocation = plot->real_canvas->allocation;

    /* width of vscrollbar*/
    s_width=plot->sw->allocation.width;
          
    p_size = GTK_PLOT_CANVAS(plot->real_canvas)->width * GTK_PLOT_CANVAS(plot->real_canvas)->magnification;

    adj=gtk_viewport_get_hadjustment (GTK_VIEWPORT(plot->sw));

    /* Conversion factor from pixels to real physical unit */
    fac=plot->page_width/unit_pt[plot->page_units];
    if (p_size<s_width)
    {  
        start=-((s_width-p_size)/2)/p_size*fac;
        end=((s_width-p_size)/2+p_size)/p_size*fac;
        allocation.x = (gint16)( (s_width - p_size)/2 );
        gtk_widget_size_allocate(plot->canvas_box, &allocation);
    }
    else
    { 
        start=adj->value/adj->upper*fac;
        end=(adj->value+adj->page_size)/adj->upper*fac;
        allocation.x = 0;
        gtk_widget_size_allocate(plot->canvas_box, &allocation);
    }
    gtk_ruler_set_range(GTK_RULER(plot->hruler), start,
                        end, start, end);

    fac = (gdouble)GTK_PLOT_CANVAS(plot->real_canvas)->pixmap_width / (gdouble)plot->page_width * unit_pt[plot->page_units]; 
    switch(plot->page_units){
      case SG_UNIT_PT:
      case SG_UNIT_PIXEL:
        GTK_PLOT_CANVAS(plot->real_canvas)->grid_step = 20. * fac; 
        break;
      case SG_UNIT_MM:
        GTK_PLOT_CANVAS(plot->real_canvas)->grid_step = 10. * fac; 
        break;
      case SG_UNIT_CM:
        GTK_PLOT_CANVAS(plot->real_canvas)->grid_step = 1. * fac; 
        break;
      case SG_UNIT_IN:
        GTK_PLOT_CANVAS(plot->real_canvas)->grid_step = .2 * fac; 
        break;
     }
}

static void
update_ruler_expose_y(GtkWidget *scroll, gpointer data)
{
    GtkAdjustment *adj;
    SGplot *plot;
    gdouble start, end, fac, p_size;
    gint height,s_height;
    GtkAllocation allocation;

    if (!data) return;

    plot=(SGplot *)data;

    allocation = plot->real_canvas->allocation;

    /* height of hscrollbar*/
    s_height=plot->sw->allocation.height;

    p_size = GTK_PLOT_CANVAS(plot->real_canvas)->height * GTK_PLOT_CANVAS(plot->real_canvas)->magnification;

    adj=gtk_viewport_get_vadjustment (GTK_VIEWPORT(plot->sw));

    /* Conversion factor from pixels to real physical unit */
    fac=plot->page_height/unit_pt[plot->page_units];

    if (p_size<s_height)
    {  
        start=-((s_height-p_size)/2)/p_size*fac;
        end=((s_height-p_size)/2+p_size)/p_size*fac;
        allocation.y = (gint16)( (s_height - p_size)/2 );
        gtk_widget_size_allocate(plot->canvas_box, &allocation);
    }
    else
    { 
        start=adj->value/adj->upper*fac;
        end=(adj->value+adj->page_size)/adj->upper*fac;
        allocation.y = 0;
        gtk_widget_size_allocate(plot->canvas_box, &allocation);
    }
    gtk_ruler_set_range(GTK_RULER(plot->vruler), start,
                        end, start, end);
}

static void
sg_plot_motion(GtkWidget *widget, GdkEventMotion *event, gpointer data)
{
  SGplot *plot;
  GtkPlotCanvas *canvas;

  plot = SG_PLOT(data);
  canvas = GTK_PLOT_CANVAS(widget);

  if(!plot->layers || !canvas->active_plot) return;

  if(!GTK_IS_PLOT3D(canvas->active_plot) && plot->tool == SG_TOOL_ARROW){
    gint x, y;
    gdouble px, py;
    gchar text[200];

    gtk_widget_get_pointer(widget, &x, &y);
    gtk_plot_get_point(GTK_PLOT(canvas->active_plot),
                   x, y, &px, &py);
    if(GTK_IS_PLOT_POLAR(canvas->active_plot))
      g_snprintf(text, 200, "  (R,Angle) = (%f,%f)", px, py);
    else
      g_snprintf(text, 200, "  (X,Y) = (%f,%f)", px, py);
    gtk_label_set(GTK_LABEL(plot->label), text);
  }

  gtk_widget_event(plot->hruler, (GdkEvent *)event);
  gtk_widget_event(plot->vruler, (GdkEvent *)event);
}

static void
canvas_changed (GtkPlotCanvas *canvas, gpointer data)
{
  sg_project_changed(TRUE);
}

void
sg_plot_put_pixmap(SGplot *plot, GdkPixmap *pixmap)
{
  GtkPlotCanvas *canvas;
  GtkPlotCanvasChild *child;
  gint width, height;

  canvas = GTK_PLOT_CANVAS(plot->real_canvas);

  gdk_window_get_size(pixmap, &width, &height);

  child = gtk_plot_canvas_put_pixmap(canvas,
                                     pixmap,
                                     0., 0.);

  gtk_plot_canvas_refresh(canvas);
}

void
sg_plot_antialias(SGplot *plot, gboolean do_art)
{
  if(do_art && !plot->antialias){
    plot->antialias = TRUE;
#ifdef WITH_LIBART
    gtk_plot_canvas_set_pc(GTK_PLOT_CANVAS(plot->real_canvas), 
                           GTK_PLOT_PC(gtk_plot_art_new(NULL)));
#endif /* WITH_LIBART */
  }
  if(!do_art && plot->antialias){
    plot->antialias = FALSE;
    gtk_plot_canvas_set_pc(GTK_PLOT_CANVAS(plot->real_canvas), 
                           GTK_PLOT_PC(gtk_plot_gdk_new(NULL)));
  }
}

void
sg_plot_refresh_datasets(SGplot *plot)
{
  GList *aux_layers;

  aux_layers = plot->layers;
  while(aux_layers){
      SGlayer *layer;

      layer = (SGlayer *)aux_layers->data;

      sg_layer_refresh_datasets(layer);
      aux_layers = aux_layers->next;
  }
}

Generated by  Doxygen 1.6.0   Back to index