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

sg_worksheet.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 <string.h>
#include <gdk/gdk.h>
#include <gtk/gtk.h>
#include <gtkextra/gtkextra.h>
#include <gdk/gdkkeysyms.h>
#include "sg_worksheet.h"
#include "sg.h"
#include "sg_worksheet_tools.h"
#include "sg_formula_dialog.h"
#include "../pixmaps/sheet_icon2.xpm"
#include "python/python_main.h"
#define DEFAULT_PRECISION 3
#define DEFAULT_ROWS 20 
#define DEFAULT_COLUMNS 5 

static void     sg_worksheet_class_init               (SGworksheetClass *klass);
static void     sg_worksheet_init                     (SGworksheet *worksheet);
static void     sg_worksheet_init_gui             (SGworksheet *worksheet);

static void sg_worksheet_destroy                (GtkObject *object); 
static void       sg_worksheet_realize                (GtkWidget *widget); 

static gboolean activate_cell                   (GtkSheet *sheet, 
                                           gint row, gint col,
                                           gpointer data);
static gboolean deactivate_cell                         (GtkSheet *sheet,
                                                         gint row, gint col,
                                                         gpointer data);

static gboolean click_on_column                       (GtkWidget *widget, 
                                           GdkEventButton *event,
                                           gpointer data);
static void clear_cell                                (GtkSheet *sheet,
                                                         gint row, gint col,
                                                         gpointer data);
static void sheet_changed                       (GtkSheet *sheet,
                                           gpointer data);


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

GtkType
sg_worksheet_get_type (void)
{
  static GtkType sg_worksheet_type = 0;

  if (!sg_worksheet_type)
    {
      GtkTypeInfo sg_worksheet_info =
      {
        "SGworksheet",
        sizeof (SGworksheet),
        sizeof (SGworksheetClass),
        (GtkClassInitFunc) sg_worksheet_class_init,
        (GtkObjectInitFunc) sg_worksheet_init,
        /* reserved_1 */ NULL,
        /* reserved_2 */ NULL,
        (GtkClassInitFunc) NULL,
      };

#ifdef WITH_GNOME
      sg_worksheet_type = gtk_type_unique (gnome_app_get_type(), &sg_worksheet_info);
#else
      sg_worksheet_type = gtk_type_unique (gtk_window_get_type(), &sg_worksheet_info);
#endif
    }

  return sg_worksheet_type;
}

static void
sg_worksheet_class_init (SGworksheetClass *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_worksheet_realize;
  object_class->destroy = sg_worksheet_destroy;
}

static void
sg_worksheet_init (SGworksheet *worksheet)
{
  GtkSheet *sheet;
  gint c;
  gint nrows, ncols;

  worksheet->mode = SG_MODE_WORKSHEET;

  worksheet->cell_save=NULL;
  worksheet->is_frozen = FALSE;

  worksheet->sheet = gtk_sheet_new(DEFAULT_ROWS, DEFAULT_COLUMNS, "Data");
  nrows = 20;
  ncols = 5;

  worksheet->last_column = ncols-1;

  sheet = GTK_SHEET(worksheet->sheet);
  gtk_sheet_set_row_titles_width(sheet, 60);
  GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_JUSTIFY_ENTRY);
  GTK_SHEET_SET_FLAGS(sheet, GTK_SHEET_ROW_FROZEN);

  worksheet->column = g_new(SGcolumn, ncols);

  for(c = 0; c < ncols; c++){
     gchar label[4];
     gint max = 'Z'-'A'+1;
     gint n;

     n = 0;
     if(c >= max*max){
        label[0] = c/(max*max)+'A'-1;
        label[1] = '\0';
        n = 1;
        c -= (c/(max*max))*max*max;
     }
     if(c >= max){
        label[n] = c/max+'A'-1;
        label[n+1] = '\0';
        n++ ;
        c -= (c/max)*max;
     }
     if(c < max){
        label[n] = c+'A';
        label[n+1] = '\0';
     }

    gtk_sheet_column_button_add_label(sheet, c, label);
    gtk_sheet_set_column_title(sheet, c, label);
    sg_worksheet_column_set_format(worksheet, c, 
                                   SG_TYPE_NUMBER,
                                   SG_FORMAT_DECIMAL,
                                   SG_INTERNAL_DOUBLE,
                                   DEFAULT_PRECISION);
    worksheet->column[c].exp = NULL;
  }

  sg_worksheet_matrix_set_format(worksheet, 
                                   SG_TYPE_NUMBER,
                                   SG_FORMAT_DECIMAL,
                                   SG_INTERNAL_DOUBLE,
                                   DEFAULT_PRECISION);

  worksheet->matrix.exp = NULL;
  worksheet->sw = NULL;

  worksheet->x = 0;
  worksheet->y = 0;
  worksheet->width = 500;
  worksheet->height = 350;

  worksheet->begin = -1;
  worksheet->end = -1;

  worksheet->xmin = 0.;
  worksheet->xmax = 10.;
  worksheet->ymin = 0.;
  worksheet->ymax = 10.;

  gtk_signal_connect(GTK_OBJECT(worksheet->sheet), "activate",
                     GTK_SIGNAL_FUNC(activate_cell), worksheet);

  gtk_signal_connect(GTK_OBJECT(worksheet->sheet), "deactivate",
                     GTK_SIGNAL_FUNC(deactivate_cell), worksheet);

  gtk_signal_connect(GTK_OBJECT(worksheet->sheet), "clear_cell",
                     GTK_SIGNAL_FUNC(clear_cell), worksheet);

  gtk_signal_connect(GTK_OBJECT(worksheet->sheet), "changed",
                     GTK_SIGNAL_FUNC(sheet_changed), NULL);

  gtk_signal_connect(GTK_OBJECT(worksheet->sheet), "button_press_event",
                     GTK_SIGNAL_FUNC(click_on_column), worksheet);

  sg_worksheet_init_gui(worksheet);
}   

SGworksheet *
sg_worksheet_new(gchar *name, gint nrows, gint ncols)
{
  SGworksheet *worksheet;

  worksheet = SG_WORKSHEET(gtk_widget_new(sg_worksheet_get_type(), NULL));

  worksheet->name = g_strdup(name);
  gtk_sheet_set_title(GTK_SHEET(worksheet->sheet), (const gchar *)name);
  gtk_window_set_title(GTK_WINDOW(worksheet),name);
  sg_worksheet_add_rows(worksheet, nrows - DEFAULT_ROWS);
  sg_worksheet_add_columns(worksheet, ncols - DEFAULT_COLUMNS);

  return worksheet;
}  

gint
sg_worksheet_get_column(SGworksheet *worksheet, gchar *col_name)
{
  GtkSheet *sheet;
  gint i;

  sheet = GTK_SHEET(worksheet->sheet);

  for(i = 0; i <= sheet->maxcol; i++)
    if(strcmp(sheet->column[i].name, col_name) == 0) return i;

  return -1;
}

void
sg_worksheet_column_set_format(SGworksheet *worksheet,
                               gint column, 
                               SGcolumntype type,
                               SGcolumnformat format,
                               SGcolumninternal internal,
                               gint precision)
{
  GtkSheet *sheet;
  gint row;

  sheet = GTK_SHEET(worksheet->sheet);

  worksheet->column[column].type = type; 
  worksheet->column[column].format = format; 
  worksheet->column[column].internal = internal; 
  worksheet->column[column].precision = precision;

  switch(worksheet->column[column].type){
    case SG_TYPE_NUMBER:
       gtk_sheet_column_set_justification(sheet, column, GTK_JUSTIFY_RIGHT);
       break;
    case SG_TYPE_DATE:
    case SG_TYPE_TIME:
       gtk_sheet_column_set_justification(sheet, column, GTK_JUSTIFY_CENTER);
       break;
    case SG_TYPE_TEXT:
    default:
       gtk_sheet_column_set_justification(sheet, column, GTK_JUSTIFY_LEFT);
  }

  gtk_sheet_freeze(sheet);
  for(row = 0; row <= sheet->maxallocrow; row++)
    sg_worksheet_cell_update_format(worksheet, row, column);
  gtk_sheet_thaw(sheet);
}

void
sg_worksheet_matrix_set_format(SGworksheet *worksheet,
                               SGcolumntype type,
                               SGcolumnformat format,
                               SGcolumninternal internal,
                               gint precision)
{
  GtkSheet *sheet;
  gint row,col;

  sheet = GTK_SHEET(worksheet->sheet);

  worksheet->matrix.type = type; 
  worksheet->matrix.format = format; 
  worksheet->matrix.internal = internal; 
  worksheet->matrix.precision = precision;

  switch(worksheet->matrix.type){
    case SG_TYPE_NUMBER:
      for(col = 0; col <= sheet->maxalloccol; col++)
       gtk_sheet_column_set_justification(sheet, col, GTK_JUSTIFY_RIGHT);
       break;
    case SG_TYPE_DATE:
    case SG_TYPE_TIME:
      for(col = 0; col <= sheet->maxalloccol; col++)
       gtk_sheet_column_set_justification(sheet, col, GTK_JUSTIFY_CENTER);
       break;
    case SG_TYPE_TEXT:
    default:
      for(col = 0; col <= sheet->maxalloccol; col++)
       gtk_sheet_column_set_justification(sheet, col, GTK_JUSTIFY_LEFT);
  }

  gtk_sheet_freeze(sheet);
  for(col = 0; col <= sheet->maxalloccol; col++)
    for(row = 0; row <= sheet->maxallocrow; row++)
      sg_worksheet_cell_update_format(worksheet, row, col);
  gtk_sheet_thaw(sheet);
}


void 
sg_worksheet_hidden_cell_clear(SGworksheet *sheet, gint row, gint col)
{
  SGhiddencell *hidden;
  hidden = (SGhiddencell *)gtk_sheet_get_link(GTK_SHEET(sheet->sheet), row, col);
  if(hidden)
  { 
    if (hidden->formula){
      g_free(hidden->formula);
      hidden->formula = NULL;
    }
    switch(hidden->type){
      case SG_TYPE_DATE:
      case SG_TYPE_TIME:
      case SG_TYPE_TEXT:
        if (hidden->value.val_char){
          g_free(hidden->value.val_char);
          hidden->value.val_char = NULL;
        }
        break;
      default: 
        break;
    }
    g_free(hidden);
    gtk_sheet_link_cell(GTK_SHEET(sheet->sheet), row, col, NULL);
  }
}

void 
sg_worksheet_cell_clear(SGworksheet *sheet, gint row, gint col)
{ 
  sg_worksheet_hidden_cell_clear(sheet, row, col);
  gtk_sheet_cell_clear(GTK_SHEET(sheet->sheet), row, col);
}

static gboolean
click_on_column(GtkWidget *widget, GdkEventButton *event, gpointer data)
{
  SGworksheet *worksheet;
  GtkSheet *sheet;
  GdkModifierType mods;
  gint x, y;
  gint r, c;

  worksheet = SG_WORKSHEET(data);
  sheet = GTK_SHEET(worksheet->sheet);

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

  GTK_SHEET_UNSET_FLAGS(sheet, GTK_SHEET_IN_SELECTION|GTK_SHEET_IN_XDRAG|GTK_SHEET_IN_YDRAG);
  gdk_pointer_ungrab(event->time);
  gtk_grab_remove(widget);

  gtk_sheet_get_pixel_info(sheet, x, y, &r, &c);

  if(c >= 0)
     sg_formula_dialog(worksheet, c);

  return FALSE;
}

static void 
clear_cell(GtkSheet *sheet, gint row, gint col, gpointer data)
{
  SGhiddencell *hidden;

  hidden = (SGhiddencell *)gtk_sheet_get_link(sheet, row, col);
  if(hidden)
    { 
      if (hidden->formula){
        g_free(hidden->formula);
        hidden->formula = NULL;
      }
      switch(hidden->type){
        case SG_TYPE_DATE:
        case SG_TYPE_TIME:
        case SG_TYPE_TEXT:
          if (hidden->value.val_char){
            g_free(hidden->value.val_char);
            hidden->value.val_char = NULL;
          }
          break;
        default: break;
      }
      g_free(hidden);
      gtk_sheet_link_cell(sheet, row, col, NULL);
    }
}

static gboolean
activate_cell(GtkSheet *sheet, gint row, gint col, gpointer data)
{
  SGworksheet *worksheet;
  GtkEntry *entry;
  gchar *text=NULL,fpnum[40];
  gchar label[100];
  SGhiddencell *link = NULL;
  PyObject *floato;

  entry = GTK_ENTRY(sheet->sheet_entry);
  worksheet = (SGworksheet *)data;

  worksheet->cell_save = g_strdup(gtk_entry_get_text(entry));
  if(worksheet->column[col].type == SG_TYPE_TEXT) return TRUE;

  link=(SGhiddencell *)gtk_sheet_get_link(GTK_SHEET(worksheet->sheet),row,col);

  fpnum[0]='\0';

  if (link)
   {  
      if (link->formula){
        text = link->formula;
      }
      else if(link->type == SG_TYPE_NUMBER){
        if(link->internal == SG_INTERNAL_INTEGER){
          switch(link->format){
            case SG_FORMAT_DECIMAL:
              g_snprintf(fpnum,40,"%l",link->value.val_long);
              text=fpnum;
              break;
            case SG_FORMAT_SCIENTIFIC:
              floato=PyObject_Repr(PyFloat_FromDouble((double)link->value.val_long));
              text=PyString_AsString(floato);
              break;
          }
        } else {
          switch(link->format){
            case SG_FORMAT_DECIMAL:
              floato=PyObject_Repr(PyFloat_FromDouble(link->value.val_double));
              text=PyString_AsString(floato);
              break;
            case SG_FORMAT_SCIENTIFIC:
              g_snprintf(fpnum,40,"%2.20e",link->value.val_double);
              text=fpnum;
              break;
          }
        }
      } else {
          text=link->value.val_char;
      }
      if(!worksheet->is_frozen) gtk_entry_set_text(entry,text);
   }
  else
   { 
      text = NULL;
      gtk_entry_set_text(entry,"");
   }

  if(text && strlen(text)){
    gtk_entry_select_region(entry, 0, strlen(text));
    gtk_entry_set_position(entry, 0);
  }

  sprintf(label, "  %s:%d", sheet->column[col].name, row);
  gtk_label_set(GTK_LABEL(worksheet->label), label);

  return TRUE;
}


static gboolean
deactivate_cell(GtkSheet *sheet, gint row, gint col, gpointer data)
{
  SGworksheet *worksheet;
  gchar *text;
  gint arow,acol;

  worksheet = (SGworksheet *)data;
  text = gtk_sheet_cell_get_text(sheet, row, col);

  if(text && strlen(text) > 0)
    sg_worksheet_cell_set(worksheet, row, col, text, TRUE, TRUE);

  return TRUE;
}

void sg_worksheet_cell_set_text(SGworksheet *worksheet, gint row, gint col, gchar *text)
{ 
  gint arow,acol;

  gtk_sheet_set_cell_text(GTK_SHEET(worksheet->sheet), row, col, text);

  gtk_sheet_get_active_cell(GTK_SHEET(worksheet->sheet), &arow, &acol);

  if (arow==row && acol==col)
   {  
      gtk_entry_set_text(GTK_ENTRY(GTK_SHEET(worksheet->sheet)->sheet_entry),text);
   }

}

                      

void
sg_worksheet_cell_set(SGworksheet *worksheet, gint row, gint col,
                      gchar *text, gboolean formula, gboolean eval)
{
  gchar *save;
  SGhiddencell *link = NULL;
  GtkSheet *sheet;
  gboolean myformula=formula, myeval=eval;

  sheet = GTK_SHEET(worksheet->sheet);
  link = (SGhiddencell *)gtk_sheet_get_link(GTK_SHEET(worksheet->sheet), row, col);

  if (text && strlen(text))
  { if (!link)
     {
            myformula=formula;
            myeval=eval;
            link = (SGhiddencell *)g_new0(SGhiddencell, 1);
            link->formula = NULL;
            link->updated = FALSE;
            link->format =  worksheet->column[col].format;
            link->type =  worksheet->column[col].type;
            link->internal =  worksheet->column[col].internal;
            link->precision = worksheet->column[col].precision;
            gtk_sheet_link_cell(GTK_SHEET(worksheet->sheet), row, col, link);
     }

     save = g_strdup(text);
     if (!myformula)
     {  
        sg_worksheet_cell_set_text(worksheet,row, col, save);
     }
     else
     {  
       link->updated=FALSE;
       switch(link->type){
      case SG_TYPE_DATE:
      case SG_TYPE_TIME:
      case SG_TYPE_TEXT:
        if (link->value.val_char){
          g_free(link->value.val_char);
          link->value.val_char = NULL;
        }
          myeval = FALSE;
        break;
       }
       if (myeval){
            worksheet->is_frozen = TRUE;  
            if (python_sheet(worksheet, row, col, save, GTK_ORIENTATION_VERTICAL)){
                link->updated=TRUE;
                link->formula=g_strdup(save);
            }
            worksheet->is_frozen = FALSE;
       }
       else /* currently used for dates, text, and time */
       {          
               sg_worksheet_cell_set_text(worksheet, row, col, (save?save:text));
       }

       if (link->formula)
          g_free(link->formula);
       link->formula = save;
     }
   }
  else /* We were passed an empty cell */
   { 
     if (link) sg_worksheet_cell_clear(worksheet, row, col);
     else
     {  
        if (worksheet->cell_save && strlen(worksheet->cell_save))
          sg_worksheet_cell_set_text(worksheet,
                                row, col, g_strdup(worksheet->cell_save));
        else
          gtk_sheet_cell_clear(GTK_SHEET(worksheet->sheet), row, col);
     }
   }


  if(worksheet->cell_save) g_free(worksheet->cell_save);
  worksheet->cell_save = NULL;

}

gboolean
sg_worksheet_cell_update_format(SGworksheet *worksheet, gint row, gint col)
{
  GtkSheet *sheet;
  gchar *string,fpnum[40],pspec[20];
  gint freemem=FALSE;
  SGhiddencell *hidden;

  sheet = GTK_SHEET(worksheet->sheet);
  hidden = (SGhiddencell *)gtk_sheet_get_link(sheet, row, col);
  if (!hidden) return FALSE;
  fpnum[0]='\0';
  pspec[0]='\0';

  hidden->type = worksheet->column[col].type;
  hidden->format = worksheet->column[col].format;
  hidden->internal = worksheet->column[col].internal;
  hidden->precision = worksheet->column[col].precision;

  if(hidden->type == SG_TYPE_NUMBER){
    if(hidden->internal == SG_INTERNAL_INTEGER){
      switch(hidden->format){
        case SG_FORMAT_DECIMAL:
          g_snprintf(pspec,20,"%%ld");
          g_snprintf(fpnum,40,pspec,hidden->value.val_long);
          string=fpnum;
          break;
        case SG_FORMAT_SCIENTIFIC:
          g_snprintf(pspec,20,"%%1.%de",hidden->precision);
          g_snprintf(fpnum,40,pspec,(double)hidden->value.val_long);
          string=fpnum;
          break;
      }
    } else {
      switch(hidden->format){
        case SG_FORMAT_DECIMAL:
          g_snprintf(pspec,20,"%%1.%df",hidden->precision);
          g_snprintf(fpnum,40,pspec,hidden->value.val_double);
          string=fpnum;
          break;
        case SG_FORMAT_SCIENTIFIC:
          g_snprintf(pspec,20,"%%1.%de",hidden->precision);
          g_snprintf(fpnum,40,pspec,hidden->value.val_double);
          string=fpnum;
          break;
      }
    }
  } else {
      string=hidden->value.val_char;
  }
  sg_worksheet_cell_set_text(worksheet,row, col, string);

  return TRUE;
}


gchar *
sg_worksheet_cell_get_text(SGworksheet *worksheet, gint row, gint col)
{ gint arow,acol;
  gchar *text;

  gtk_sheet_get_active_cell(GTK_SHEET(worksheet->sheet), &arow, &acol);
  
  if (GTK_SHEET(worksheet->sheet)->state == GTK_STATE_NORMAL && 
      arow==row && acol==col && worksheet->cell_save){
   text=worksheet->cell_save;
  }else{
   text = gtk_sheet_cell_get_text(GTK_SHEET(worksheet->sheet), row, col);
  }
  return text;
}

gchar *
sg_worksheet_cell_get_formula(SGworksheet *worksheet, gint row, gint col)
{
  gchar *text=NULL;
  SGhiddencell *link;

  link = (SGhiddencell *)gtk_sheet_get_link(GTK_SHEET(worksheet->sheet),
                                            row, col);

  if(link) text = link->formula;

  return text;
}

gdouble
sg_worksheet_cell_get_double(SGworksheet *worksheet, gint row, gint col, gboolean *error)
{
  gchar *text=NULL;
  SGhiddencell *link;

  *error = FALSE;

  if(!worksheet) {
      *error=TRUE;
      return 0.0;
  }

  link = (SGhiddencell *)gtk_sheet_get_link(GTK_SHEET(worksheet->sheet),
                                            row, col);
  if(!link) {
      *error=TRUE;
      return 0.0;
  }

  switch(link->type){
      case SG_TYPE_NUMBER:
      switch (link->internal){
          case SG_INTERNAL_INTEGER: return (gdouble)link->value.val_long;
          case SG_INTERNAL_DOUBLE:  return (gdouble)link->value.val_double;
          default: return 0.0;
      }
      case SG_TYPE_TEXT:        
      case SG_TYPE_TIME:        
      case SG_TYPE_DATE:        
      default:
          return 0.0;
  }


}

gint
sg_worksheet_cell_get_int(SGworksheet *worksheet, gint row, gint col, gboolean *error)
{
  gchar *text=NULL;
  SGhiddencell *link;

  *error = FALSE;

  if(!worksheet) {
      *error=TRUE;
      return 0;
  }


  link = (SGhiddencell *)gtk_sheet_get_link(GTK_SHEET(worksheet->sheet),
                                            row, col);
  if(!link) {
      *error=TRUE;
      return 0;
  }

  switch(link->type){
      case SG_TYPE_NUMBER:
      switch (link->internal){
          case SG_INTERNAL_INTEGER: return (gint)link->value.val_long;
          case SG_INTERNAL_DOUBLE:  return (gint)link->value.val_double;
          default: return 0;
      }
      case SG_TYPE_TEXT:        
      case SG_TYPE_TIME:        
      case SG_TYPE_DATE:        
      default:
          return 0;
  }
}


static void
sg_worksheet_init_gui(SGworksheet *worksheet)
{
  gchar msg[80];
  GtkWidget *vbox;
  GtkWidget *frame;
  GtkWidget *toolbar;

  gtk_window_set_title(GTK_WINDOW(worksheet), worksheet->name);
  gtk_window_set_policy(GTK_WINDOW(worksheet), TRUE, TRUE, FALSE);
 
  vbox = gtk_vbox_new(FALSE, 5);

#ifdef WITH_GNOME
  gnome_app_construct(GNOME_APP(worksheet), PACKAGE, worksheet->name);
  gnome_app_set_contents(GNOME_APP(worksheet),vbox);
#else
  gtk_container_add(GTK_CONTAINER(worksheet),vbox);
#endif
  toolbar = sg_worksheet_build_toolbar(worksheet);

  frame = gtk_frame_new(NULL);
  gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
  worksheet->label = gtk_label_new(" ");
  gtk_misc_set_alignment(GTK_MISC(worksheet->label), 0., .5);
  gtk_container_add(GTK_CONTAINER(frame), worksheet->label);
 
  worksheet->sw = gtk_scrolled_window_new(NULL, NULL);
 
  gtk_container_add(GTK_CONTAINER(worksheet->sw), worksheet->sheet);
  gtk_box_pack_start(GTK_BOX(vbox), worksheet->sw, TRUE, TRUE, 0);
  gtk_box_pack_end(GTK_BOX(vbox), frame, FALSE, FALSE, 0);
  
  gtk_widget_ensure_style(worksheet->sheet);

  gtk_widget_show(worksheet->sw);
  gtk_widget_show(worksheet->sheet);
  gtk_widget_show(worksheet->label);
  gtk_widget_show(frame);
  gtk_widget_show(vbox);

  if(worksheet->x > 0 && worksheet->y > 0){
           gtk_widget_set_uposition(GTK_WIDGET(worksheet), 
                                    worksheet->x, worksheet->y);
           gtk_widget_set_usize(GTK_WIDGET(worksheet),
                                worksheet->width,
                                worksheet->height);
  }else{
           gtk_widget_set_usize(GTK_WIDGET(worksheet),
                                500,
                                350);
  }
}

static void
sg_worksheet_realize(GtkWidget *widget)
{
  GdkPixmap *sheet_icon_pixmap;
  GdkBitmap *sheet_icon_mask;
  SGworksheet *worksheet;
  
  worksheet = SG_WORKSHEET(widget);

  GTK_WIDGET_CLASS(parent_class)->realize(widget);

  sheet_icon_pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL,
                                                gdk_colormap_get_system(),
                                                &sheet_icon_mask, NULL, sheet_icon2_xpm);


  gdk_window_set_icon(GTK_WIDGET(worksheet)->window, NULL,
                      sheet_icon_pixmap, sheet_icon_mask);


}

gint
sg_worksheet_rename(SGworksheet *worksheet, gchar *name)
{
  if(strcmp(worksheet->name, name) == 0) return FALSE;

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

  gtk_window_set_title(GTK_WINDOW(worksheet),name);

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

    if(worksheet->icon->entry_label){
       g_free(worksheet->icon->label);
       worksheet->icon->label = NULL;
    }
  
    worksheet->icon->label = g_strdup(name);
    gtk_entry_set_text(GTK_ENTRY(worksheet->icon->entry), name);
  }

  return TRUE;
}

void
sg_worksheet_set_begin(SGworksheet *worksheet, gint row)
{
  GtkSheet *sheet;
  GdkColor bg;
  GtkSheetRange range;
  gchar label[100];

  sheet = GTK_SHEET(worksheet->sheet);

  if(row > worksheet->end &&
     worksheet->end != -1) return;

  gtk_sheet_freeze(sheet);

  if(worksheet->begin != -1){
    range.col0 = 0;
    range.coli = sheet->maxcol;
    range.row0 = worksheet->begin;
    range.rowi = worksheet->begin;
    gdk_color_white(gdk_colormap_get_system(), &bg);
    gtk_sheet_row_button_add_label(sheet, worksheet->begin, NULL);
    gtk_sheet_range_set_background(sheet, &range, &bg);
  }

  gdk_color_parse("light blue", &bg);
  gdk_color_alloc(gdk_colormap_get_system(), &bg);
  worksheet->begin = row;
  range.col0 = 0;
  range.coli = sheet->maxcol;
  range.row0 = row;
  range.rowi = row;

  sprintf(label, "(Begin)");

  if(row > -1){
    gtk_sheet_row_button_add_label(sheet, row, label);
    gtk_sheet_range_set_background(sheet, &range, &bg);
  }
  gtk_sheet_thaw(sheet);
}

void
sg_worksheet_set_end(SGworksheet *worksheet, gint row)
{
  GtkSheet *sheet;
  GdkColor bg;
  GtkSheetRange range;
  gchar label[100];


  sheet = GTK_SHEET(worksheet->sheet);

  if(row != -1 && row < worksheet->begin) return;

  gtk_sheet_freeze(sheet);

  if(worksheet->end != -1){
    range.col0 = 0;
    range.coli = sheet->maxcol;
    range.row0 = worksheet->end;
    range.rowi = worksheet->end;
    gdk_color_white(gdk_colormap_get_system(), &bg);
    gtk_sheet_row_button_add_label(sheet, worksheet->end, NULL);
    gtk_sheet_range_set_background(sheet, &range, &bg);
  }

  gdk_color_parse("light blue", &bg);
  gdk_color_alloc(gdk_colormap_get_system(), &bg);
  worksheet->end = row;
  range.col0 = 0;
  range.coli = sheet->maxcol;
  range.row0 = row;
  range.rowi = row;

  sprintf(label, "(End)");

  if(row > -1){
    gtk_sheet_row_button_add_label(sheet, row, label);
    gtk_sheet_range_set_background(sheet, &range, &bg);
  }

  gtk_sheet_thaw(sheet);
}


void
sg_worksheet_reset(SGworksheet *worksheet)
{
  sg_worksheet_set_begin(worksheet, -1);
  sg_worksheet_set_end(worksheet, -1);
}

void
sg_worksheet_destroy(GtkObject *object)
{
  SGworksheet *worksheet;

  worksheet = SG_WORKSHEET(object);

  g_free(worksheet->name);
  g_free(worksheet->column);

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

void
sg_worksheet_add_rows(SGworksheet *worksheet, gint nrows)
{
  GtkSheet *sheet;

  sheet = GTK_SHEET(worksheet->sheet);

  if(nrows < 0){
    sg_worksheet_delete_rows(worksheet, sheet->maxrow+nrows+1, -nrows);
    return;
  } 

  gtk_sheet_freeze(sheet);

  gtk_sheet_add_row(sheet, nrows);

  sg_worksheet_set_begin(worksheet, worksheet->begin);
  sg_worksheet_set_end(worksheet, worksheet->end);

  gtk_sheet_thaw(sheet);
}

void
sg_worksheet_add_columns(SGworksheet *worksheet, gint ncols)
{
  GtkSheet *sheet;
  gint i, c, n = 0, max;
  gchar label[4];

  sheet = GTK_SHEET(worksheet->sheet);

  if(ncols < 0){
    sg_worksheet_delete_columns(worksheet, sheet->maxcol+ncols+1, -ncols);
    return;
  } 

  gtk_sheet_freeze(sheet);

  max = 'Z'-'A'+1;

  gtk_sheet_add_column(sheet, ncols);

  worksheet->column = g_renew(SGcolumn, worksheet->column, (sheet->maxcol + 1));

  for(i = sheet->maxcol - ncols + 1; i <= sheet->maxcol ; i++){
      worksheet->last_column++;
      c = worksheet->last_column;
      n = 0;
      if(c >= max*max){
         label[0] = c/(max*max)+'A'-1;
         label[1] = '\0';
         n = 1;
         c -= (c/(max*max))*max*max;
      }
      if(c >= max){
         label[n] = c/max+'A'-1;
         label[n+1] = '\0';
         n++ ;
         c -= (c/max)*max;
      }
      if(c < max){
         label[n] = c+'A';
         label[n+1] = '\0';
      }
      gtk_sheet_column_button_add_label(sheet, i, label);
      gtk_sheet_set_column_title(sheet, i, label);
      gtk_sheet_column_set_justification(sheet, i, GTK_JUSTIFY_RIGHT);
      sg_worksheet_column_set_format(worksheet, i, 
                                     SG_TYPE_NUMBER,
                                     SG_FORMAT_DECIMAL,
                                     SG_INTERNAL_DOUBLE,
                                     DEFAULT_PRECISION);
      worksheet->column[i].exp = NULL;
  }

  sg_worksheet_set_begin(worksheet, worksheet->begin);
  sg_worksheet_set_end(worksheet, worksheet->end);

  gtk_sheet_thaw(sheet);

}

void
sg_worksheet_set_column_name(SGworksheet *worksheet, gint col, gchar *name)
{
  GtkSheet *sheet;

  sheet = GTK_SHEET(worksheet->sheet);

  gtk_sheet_column_button_add_label(sheet, col, name);
  gtk_sheet_set_column_title(sheet, col, name);
}


void
sg_worksheet_insert_rows(SGworksheet *worksheet, 
                         gint row,
                         gint nrows)
{
  GtkSheet *sheet;

  sheet = GTK_SHEET(worksheet->sheet);

  gtk_sheet_insert_rows(sheet, row, nrows);

  if(worksheet->end >= row)
      sg_worksheet_set_end(worksheet, worksheet->end + nrows);

  if(worksheet->begin >= row)
      sg_worksheet_set_begin(worksheet, worksheet->begin + nrows);

}

void
sg_worksheet_insert_columns(SGworksheet *worksheet, 
                            gint col,
                            gint ncols)
{
  GtkSheet *sheet;
  gint i, c, n, max;
  gchar label[4];
  SGcolumn auxcol;

  sheet = GTK_SHEET(worksheet->sheet);

  gtk_sheet_freeze(sheet);

  gtk_sheet_insert_columns(sheet, col, ncols);

  worksheet->column = g_renew(SGcolumn, worksheet->column, (sheet->maxcol + 1));

  for(i=sheet->maxcol; i>=col+ncols; i--){
    auxcol = worksheet->column[i];
    worksheet->column[i]=worksheet->column[i-ncols];
    worksheet->column[i-ncols]=auxcol;
  }

  max = 'Z'-'A'+1;
  for(i = col; i < col+ncols; i++){
      worksheet->last_column++;
      c = worksheet->last_column;

      n = 0;
      if(c >= max*max){
         label[0] = c/(max*max)+'A'-1;
         label[1] = '\0';
         n = 1;
         c -= (c/(max*max))*max*max;
      }
      if(c >= max){
         label[n] = c/max+'A'-1;
         label[n+1] = '\0';
         n++ ;
         c -= (c/max)*max;
      }
      if(c < max){
         label[n] = c+'A';
         label[n+1] = '\0';
      }

      gtk_sheet_column_button_add_label(sheet, i, label);
      gtk_sheet_set_column_title(sheet, i, label);
      gtk_sheet_column_set_justification(sheet, i, GTK_JUSTIFY_RIGHT);
      sg_worksheet_column_set_format(worksheet, i, 
                                     SG_TYPE_NUMBER,
                                     SG_FORMAT_DECIMAL,
                                     SG_INTERNAL_DOUBLE,
                                     DEFAULT_PRECISION);
      worksheet->column[i].exp = NULL;
    }

  gtk_sheet_thaw(sheet);

}

void
sg_worksheet_delete_rows(SGworksheet *worksheet, gint row, gint nrows)
{
  GtkSheet *sheet;

  sheet = GTK_SHEET(worksheet->sheet);

  gtk_sheet_delete_rows(sheet, row,
                        nrows);

  if(worksheet->begin >= row &&
     worksheet->begin <= row+nrows)
          sg_worksheet_set_begin(worksheet, -1);

  if(worksheet->begin > row+nrows)
          sg_worksheet_set_begin(worksheet,
                                 worksheet->begin - nrows);

  if(worksheet->end >= row &&
     worksheet->end <= row+nrows)
          sg_worksheet_set_end(worksheet, -1);

  if(worksheet->end > row+nrows)
          sg_worksheet_set_end(worksheet,
                               worksheet->end - nrows);
}

void
sg_worksheet_delete_columns(SGworksheet *worksheet, gint col, gint ncols)
{
  GtkSheet *sheet;
  gint i;

  sheet = GTK_SHEET(worksheet->sheet);

  gtk_sheet_delete_columns(sheet, 
                           col,
                           ncols);


  for(i = col; i <= sheet->maxcol-ncols; i++){
    sg_worksheet_column_set_exp(worksheet, i, NULL);
    worksheet->column[i]=worksheet->column[i+ncols];
  }

}

void
sg_worksheet_column_set_exp(SGworksheet *worksheet, gint col, gchar *exp)
{ gchar *new_exp;
  
  if (exp && strlen(exp)>0)
     new_exp=g_strdup(exp);
  
  if(worksheet->column[col].exp)
     g_free(worksheet->column[col].exp);

  worksheet->column[col].exp = NULL;

  if(exp && strlen(exp) > 0)
     worksheet->column[col].exp = new_exp;;
}

void
sg_worksheet_update_column_exp (SGworksheet *worksheet, 
                                gchar *exp, gint column,
                                gint from, gint to)
{ 
  PyObject *object;
  gint i;

  object = (PyObject *)python_eval_expr(exp);
  if (object)
  {
      if (PyArray_Check(object))
       { gtk_sheet_freeze(GTK_SHEET(worksheet->sheet));
         python_array(worksheet,0,column,(PyArrayObject *)object,
                      GTK_ORIENTATION_VERTICAL,TRUE);
         gtk_sheet_thaw(GTK_SHEET(worksheet->sheet));
       }
      else if (PySequence_Check(object))
       { gtk_sheet_freeze(GTK_SHEET(worksheet->sheet));
         python_sequence(worksheet,0,column,object,
                         GTK_ORIENTATION_VERTICAL,TRUE,FALSE);
         gtk_sheet_thaw(GTK_SHEET(worksheet->sheet));
       }
      else if (object!=Py_None)
       { gtk_sheet_freeze(GTK_SHEET(worksheet->sheet));
         for (i=from;i<=to;i++) /* inclusive */
             python_singleton(worksheet,i,column,object,TRUE,TRUE);
         gtk_sheet_thaw(GTK_SHEET(worksheet->sheet));
       }
      else
       { gtk_sheet_freeze(GTK_SHEET(worksheet->sheet));
         for (i=from;i<=to;i++) /* inclusive */
          sg_worksheet_cell_set(worksheet, i, column, exp, TRUE, TRUE);
         gtk_sheet_thaw(GTK_SHEET(worksheet->sheet));
       }
       Py_XDECREF(object);
   }

}

void
sg_worksheet_matrix_set_exp(SGworksheet *worksheet, gchar *exp)
{
  if(worksheet->matrix.exp)
     g_free(worksheet->matrix.exp);

  worksheet->matrix.exp = NULL;

  if(exp && strlen(exp) > 0)
     worksheet->matrix.exp = g_strdup(exp);
}


void
sg_worksheet_update_matrix_exp (SGworksheet *worksheet, gchar *exp,
                                gint from_col, gint to_col,
                                gint from_row, gint to_row)
{ 
  PyObject *object;
  gint i,j;
  gdouble x, y, dx, dy, z;
  gboolean TwoD=FALSE, OneD=FALSE;

  if (exp!=worksheet->matrix.exp)
    sg_worksheet_matrix_set_exp(worksheet,  exp);
  if (!worksheet->matrix.exp) return;
  dx=(worksheet->xmax-worksheet->xmin)/gtk_sheet_get_columns_count(GTK_SHEET(worksheet->sheet));
  dy=(worksheet->ymax-worksheet->ymin)/gtk_sheet_get_rows_count(GTK_SHEET(worksheet->sheet));
  gtk_sheet_freeze(GTK_SHEET(worksheet->sheet));

  for (j=from_col;j<=to_col;j++) /* inclusive */
  { x=(gdouble)j*dx + worksheet->xmin;
    OneD=FALSE;
     for (i=from_row;i<=to_row;i++) /* inclusive */
     { y= worksheet->ymin+i*dy;
       object = sg_eval_func_xy(exp, x, y, &z);
       if (object)
       {   if (PyArray_Check(object))
           { PyArrayObject *array;
             array=(PyArrayObject *)object;
             if (array->nd>2)   /*No more than 2 dimensions */
             {  
                gtk_sheet_thaw(GTK_SHEET(worksheet->sheet));
                return;
             }
             if (array->nd==2) TwoD=TRUE;
             if (array->nd==1) OneD=TRUE;
             python_array(worksheet,i,j,(PyArrayObject *)array,
                          GTK_ORIENTATION_VERTICAL,TRUE);
           }
           else if (PySequence_Check(object))
           { 
             python_sequence(worksheet,0,0,object,
                             GTK_ORIENTATION_VERTICAL,TRUE,FALSE);
             OneD=TRUE;
           }
           else if (object!=Py_None)
              python_singleton(worksheet,i,j,object,FALSE,TRUE);
          else
            sg_worksheet_cell_set(worksheet, i, j, exp, TRUE, TRUE);
           Py_XDECREF(object);
        }
        if (OneD || TwoD) break;
     }
     if (TwoD) break;
  }
  gtk_sheet_thaw(GTK_SHEET(worksheet->sheet));
}


/* Mark all formulas in a range as not updated */
gint sg_worksheet_unupdate_exp_range(SGworksheet *worksheet,
                                   gint row0, gint rowi,
                                   gint col0, gint coli)
{ SGcolumn *column;
  gint col,row;
  gchar *exp;
  SGhiddencell *link = NULL;


  link = (SGhiddencell *)gtk_sheet_get_link(GTK_SHEET(worksheet->sheet),
                                            row, col);

  for(row=row0;row<=rowi;row++)
      for (col=col0;col<=coli;col++)
      {   
          exp=sg_worksheet_cell_get_formula(worksheet, row, col);
          if (!exp) continue;
          link = (SGhiddencell *)gtk_sheet_get_link(GTK_SHEET(worksheet->sheet), row, col);
          if (link) link->updated=FALSE;
      }
  return TRUE;
}

/* Mark all formulas in cells as not updated */
gint sg_worksheet_unupdate_exp_all(SGworksheet *worksheet)
{
  return sg_worksheet_unupdate_exp_range(worksheet, 
           0, GTK_SHEET(worksheet->sheet)->maxallocrow,
           0, GTK_SHEET(worksheet->sheet)->maxalloccol);
}                                   


gint sg_worksheet_update_matrix(SGworksheet *worksheet)
{ SGworksheet *active_sheet_temp;

  active_sheet_temp=active_worksheet;
  if (!worksheet->mode==SG_MODE_MATRIX) return FALSE;
  gtk_sheet_freeze(GTK_SHEET(worksheet->sheet));

  sg_worksheet_update_matrix_exp(worksheet,worksheet->matrix.exp,0,
      gtk_sheet_get_columns_count(GTK_SHEET(worksheet->sheet)) - 1,
        0,gtk_sheet_get_rows_count(GTK_SHEET(worksheet->sheet)) - 1);
  gtk_sheet_thaw(GTK_SHEET(worksheet->sheet));
  
  active_worksheet=active_sheet_temp;
  return TRUE;
}

gint sg_worksheet_update_column(SGworksheet *worksheet, gint col)
{ SGworksheet *active_sheet_temp;

  active_sheet_temp=active_worksheet;

  gtk_sheet_freeze(GTK_SHEET(worksheet->sheet));
  if (worksheet->column[col].exp)
  {  sg_worksheet_update_column_exp(worksheet,worksheet->column[col].exp,col,0,
        gtk_sheet_get_rows_count(GTK_SHEET(worksheet->sheet)) - 1);
  }
  gtk_sheet_thaw(GTK_SHEET(worksheet->sheet));  
  active_worksheet=active_sheet_temp;
  return TRUE;
}

gint sg_worksheet_update_exp_range(SGworksheet *worksheet, 
                                   gint row0, gint rowi,
                                   gint col0, gint coli)
{ 
  SGcolumn *column;
  gint col,row,uneval1=-1,uneval2=0,error;
  gchar *exp, *exp2;
  SGhiddencell *link = NULL;
  gint srow,scol,num_selected=0;
  GtkSheet *sheet;
  SGworksheet *active_sheet_temp;

  active_sheet_temp=active_worksheet;
  active_worksheet=worksheet;
  sheet=GTK_SHEET(worksheet->sheet);
  gtk_sheet_freeze(sheet);

  gtk_sheet_get_active_cell(GTK_SHEET(worksheet->sheet),&srow,&scol);  
  num_selected=((sheet->range.rowi-sheet->range.row0)+1)*
  ((sheet->range.coli-GTK_SHEET(worksheet->sheet)->range.col0)+1);

  sg_report_python_error=FALSE;
  while (uneval1!=uneval2)
  {   /* Report problems from the second pass */
      if (uneval1>=0) sg_report_python_error=TRUE;
      uneval1=uneval2;
      for (col=col0;col<=coli;col++)
      { sg_worksheet_update_column(worksheet,col);
          for(row=row0,uneval2=0;row<=rowi;row++)
          {   exp=g_strdup(sg_worksheet_cell_get_formula(worksheet, row, col));
              link = (SGhiddencell *)gtk_sheet_get_link(sheet, row, col);
              if (!link || !exp)
                continue;
              sg_worksheet_cell_set(worksheet, row, col, exp, TRUE, TRUE);
              if (row==srow && col==scol && num_selected==1){
                 gtk_entry_set_text(GTK_ENTRY(sheet->sheet_entry), g_strdup(exp));
              g_free(exp);
              }
              if (!link->updated) uneval2++;
          }
      }
      if (uneval2==0) break;
  }

  gtk_sheet_thaw(GTK_SHEET(worksheet->sheet));
  active_worksheet=active_sheet_temp;
  return uneval2;
}

gint sg_worksheet_update_exp_all(SGworksheet *worksheet)
{ if (worksheet->mode==SG_MODE_MATRIX)
    sg_worksheet_update_matrix(worksheet);
  return sg_worksheet_update_exp_range(worksheet, 
           0, gtk_sheet_get_rows_count(GTK_SHEET(worksheet->sheet))-1,
           0, gtk_sheet_get_columns_count(GTK_SHEET(worksheet->sheet))-1);
}


static void
sheet_changed (GtkSheet *sheet, gpointer data)
{
  sg_project_changed(TRUE);
}

Generated by  Doxygen 1.6.0   Back to index