From: John Darrington <john@darrington.wattle.id.au>
Date: Mon, 24 Nov 2008 13:16:02 +0000 (+0900)
Subject: Merge branch 'rewrite-sheet' of ssh://jmd@git.sv.gnu.org/srv/git/pspp into rewrite... 
X-Git-Tag: sav-api~938
X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ddd7c113f3e50c8d87f6a677856799d05a1f40c7;p=pspp

Merge branch 'rewrite-sheet' of ssh://jmd@git.sv.gnu.org/srv/git/pspp into rewrite-sheet

Conflicts:

	lib/gtksheet/gtksheet.c
---

ddd7c113f3e50c8d87f6a677856799d05a1f40c7
diff --cc lib/gtksheet/gtksheet.c
index 31f242d28f,e38b389553..8b25902c3b
--- a/lib/gtksheet/gtksheet.c
+++ b/lib/gtksheet/gtksheet.c
@@@ -2338,16 -2271,16 +2257,11 @@@ gtk_sheet_range_draw_selection (GtkShee
    gtk_sheet_draw_border (sheet, sheet->range);
  }
  
--static void gtk_sheet_set_cell (GtkSheet *sheet, gint row, gint col,
--				GtkJustification justification,
--				const gchar *text);
--
--
  static inline gint
  safe_strcmp (const gchar *s1, const gchar *s2)
  {
    if ( !s1 && !s2) return 0;
--  if ( !s1) return - 1;
++  if ( !s1) return -1;
    if ( !s2) return +1;
    return strcmp (s1, s2);
  }
@@@ -2373,6 -2306,6 +2287,9 @@@ gtk_sheet_set_cell (GtkSheet *sheet, gi
  
    old_text = g_sheet_model_get_string (model, row, col);
  
++  if (0 != safe_strcmp (old_text, text))
++    g_sheet_model_set_string (model, text, row, col);
++
    if ( g_sheet_model_free_strings (model))
      g_free (old_text);
  }
@@@ -2625,6 -2558,6 +2542,8 @@@ gtk_sheet_entry_changed (GtkWidget *wid
  
    text = gtk_entry_get_text (GTK_ENTRY (gtk_sheet_get_entry (sheet)));
  
++
++
    if (text && strlen (text) > 0)
      {
        gtk_sheet_get_attributes (sheet, row, col, &attributes);
@@@ -4921,20 -4812,38 +4794,35 @@@ draw_column_title_buttons_range (GtkShe
  
    if (!sheet->column_titles_visible) return;
  
-   if (column < min_visible_column (sheet)) return;
-   if (column > max_visible_column (sheet)) return;
+   g_return_if_fail (first >= min_visible_column (sheet));
+   g_return_if_fail (last <= max_visible_column (sheet));
  
-   button = g_sheet_model_get_column_button (sheet->model, column);
-   allocation.y = 0;
-   allocation.x = psppire_axis_pixel_start (sheet->haxis, column) + CELL_SPACING;
-   allocation.x -= sheet->hadjustment->value;
+   region =
+     gdk_drawable_get_visible_region (GDK_DRAWABLE (sheet->column_title_window));
  
-   allocation.height = sheet->column_title_area.height;
-   allocation.width = psppire_axis_unit_size (sheet->haxis, column);
-   is_sensitive = g_sheet_model_get_column_sensitivity (sheet->model, column);
+   gdk_window_begin_paint_region (sheet->column_title_window, region);
  
-   gtk_sheet_button_draw (sheet, sheet->column_title_window,
- 			 button, is_sensitive, allocation);
+   for (col = first ; col <= last ; ++col)
+     {
+       GdkRectangle allocation;
+       gboolean is_sensitive = FALSE;
+ 
+       GtkSheetButton *
 -	button = g_sheet_column_get_button (sheet->column_geometry, col);
++	button = g_sheet_model_get_column_button (sheet->model, col);
+       allocation.y = 0;
 -      allocation.x =
 -	g_sheet_column_start_pixel (sheet->column_geometry, col)
++      allocation.x = psppire_axis_pixel_start (sheet->haxis, col)
+ 	+ CELL_SPACING;
+       allocation.x -= sheet->hadjustment->value;
+ 
+       allocation.height = sheet->column_title_area.height;
 -      allocation.width =
 -	g_sheet_column_get_width (sheet->column_geometry, col);
 -      is_sensitive =
 -	g_sheet_column_get_sensitivity (sheet->column_geometry, col);
++      allocation.width = psppire_axis_unit_size (sheet->haxis, col);
++      is_sensitive = g_sheet_model_get_column_sensitivity (sheet->model, col);
+ 
+       draw_button (sheet, sheet->column_title_window,
+ 		   button, is_sensitive, allocation);
+     }
+ 
+   gdk_window_end_paint (sheet->column_title_window);
  }
  
  
diff --cc lib/gtksheet/psppire-axis.c
index 2a69fbef07,0000000000..a3609afae6
mode 100644,000000..100644
--- a/lib/gtksheet/psppire-axis.c
+++ b/lib/gtksheet/psppire-axis.c
@@@ -1,181 -1,0 +1,204 @@@
 +/* PSPPIRE - a graphical user interface for PSPP.
 +   Copyright (C) 2008  Free Software Foundation
 +
 +   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 3 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, see <http://www.gnu.org/licenses/>. */
 +
 +#include <config.h>
 +#include <string.h>
 +#include <stdlib.h>
 +
 +#include <libpspp/tower.h>
++#include <libpspp/pool.h>
 +#include "psppire-axis.h"
 +#include <gtk/gtk.h>
 +
 +
 +/* --- prototypes --- */
 +static void psppire_axis_class_init (PsppireAxisClass	*class);
 +static void psppire_axis_init	(PsppireAxis		*axis);
 +static void psppire_axis_finalize   (GObject		*object);
 +
 +
 +/* --- variables --- */
 +static GObjectClass     *parent_class = NULL;
 +
 +/* --- functions --- */
 +/**
 + * psppire_axis_get_type:
 + * @returns: the type ID for accelerator groups.
 + */
 +GType
 +psppire_axis_get_type (void)
 +{
 +  static GType object_type = 0;
 +
 +  if (!object_type)
 +    {
 +      static const GTypeInfo object_info = {
 +	sizeof (PsppireAxisClass),
 +	(GBaseInitFunc) NULL,
 +	(GBaseFinalizeFunc) NULL,
 +	(GClassInitFunc) psppire_axis_class_init,
 +	NULL,   /* class_finalize */
 +	NULL,   /* class_data */
 +	sizeof (PsppireAxis),
 +	0,      /* n_preallocs */
 +	(GInstanceInitFunc) psppire_axis_init,
 +      };
 +
 +      object_type = g_type_register_static (G_TYPE_OBJECT,
 +					    "PsppireAxis",
 +					    &object_info, 0);
 +    }
 +
 +  return object_type;
 +}
 +
 +
 +static void
 +psppire_axis_class_init (PsppireAxisClass *class)
 +{
 +  GObjectClass *object_class = G_OBJECT_CLASS (class);
 +
 +  parent_class = g_type_class_peek_parent (class);
 +
 +  object_class->finalize = psppire_axis_finalize;
 +}
 +
 +static void
 +psppire_axis_init (PsppireAxis *axis)
 +{
-   tower_init (&axis->tower);
++  axis->pool = NULL;
++  psppire_axis_clear (axis);
 +}
 +
 +
 +static void
 +psppire_axis_finalize (GObject *object)
 +{
++  PsppireAxis *a = PSPPIRE_AXIS (object);
++  pool_destroy (a->pool);
 +  G_OBJECT_CLASS (parent_class)->finalize (object);
 +}
 +
 +/**
 + * psppire_axis_new:
 + * @returns: a new #PsppireAxis object
 + *
 + * Creates a new #PsppireAxis.
 + */
 +PsppireAxis*
- psppire_axis_new (gint w)
++psppire_axis_new (void)
 +{
-   PsppireAxis *new_axis = g_object_new (G_TYPE_PSPPIRE_AXIS, NULL);
- 
-   new_axis->width = w;
- 
-   return new_axis;
++  return g_object_new (G_TYPE_PSPPIRE_AXIS, NULL);
 +}
 +
 +
 +gint
 +psppire_axis_unit_size (PsppireAxis *a, gint unit)
 +{
-   if ( a->width == -1)
-     {
-       const struct tower_node *node;
-       if  (unit >= tower_count (&a->tower))
- 	return 0;
++  const struct tower_node *node;
++  if  (unit >= tower_count (&a->tower))
++    return 0;
 +
-       node = tower_get (&a->tower, unit);
- 
-       return tower_node_get_size (node);
-     }
++  node = tower_get (&a->tower, unit);
 +
-   return a->width;
++  return tower_node_get_size (node);
 +}
 +
 +gint
 +psppire_axis_unit_count (PsppireAxis *a)
 +{
-   if (a->width == -1)
-     return tower_count (&a->tower);
- 
-   return 600;
++  return tower_count (&a->tower);
 +}
 +
 +glong
 +psppire_axis_pixel_start (PsppireAxis *a, gint unit)
 +{
-   if ( a->width == -1 )
-     {
-       const struct tower_node *node;
++  const struct tower_node *node;
 +
-       if ( unit >= tower_count (&a->tower))
- 	return tower_height (&a->tower);
++  if ( unit >= tower_count (&a->tower))
++    return tower_height (&a->tower);
 +
-       node = tower_get (&a->tower, unit);
- 
-       return  tower_node_get_level (node);
-     }
++  node = tower_get (&a->tower, unit);
 +
-   return a->width * unit;
++  return  tower_node_get_level (node);
 +}
 +
 +gint
 +psppire_axis_get_unit_at_pixel (PsppireAxis *a, glong pixel)
 +{
-   if (a->width == -1)
-     {
-       const struct tower_node *node;
-       unsigned long int node_start;
++  const struct tower_node *node;
++  unsigned long int node_start;
 +
-       if (pixel >= tower_height (&a->tower))
- 	return tower_count (&a->tower);
++  if (pixel >= tower_height (&a->tower))
++    return tower_count (&a->tower);
 +
-       node = tower_lookup (&a->tower, pixel, &node_start);
++  node = tower_lookup (&a->tower, pixel, &node_start);
 +
-       return tower_node_get_index (node);
-     }
++  return tower_node_get_index (node);
++}
 +
-   return pixel / a->width;
++void
++psppire_axis_append (PsppireAxis *a, gint size)
++{
++  struct tower_node *new = pool_malloc (a->pool, sizeof *new);
++
++  tower_insert (&a->tower, size, new, NULL);
 +}
 +
++
++
++/* Insert a new unit of size SIZE before position POSN */
 +void
- psppire_axis_append (PsppireAxis *a, gint width)
++psppire_axis_insert (PsppireAxis *a, gint size, gint posn)
 +{
-   struct tower_node *new = g_slice_alloc0 (sizeof *new);
-   tower_insert (&a->tower, width, new, NULL);
++  struct tower_node *new = pool_malloc (a->pool, sizeof *new);
++
++  struct tower_node *before = tower_get (&a->tower, posn);
++
++  tower_insert (&a->tower, size, new, before);
++}
++
++
++void
++psppire_axis_remove (PsppireAxis *a, gint posn)
++{
++  struct tower_node *node = tower_get (&a->tower, posn);
++
++  tower_delete (&a->tower, node);
++
++  pool_free (a->pool, node);
 +}
 +
 +
++void
++psppire_axis_resize_unit (PsppireAxis *a, gint size, gint posn)
++{
++  struct tower_node *node = tower_get (&a->tower, posn);
++
++  tower_resize (&a->tower, node, size);
++}
++
 +
 +
++void
++psppire_axis_clear (PsppireAxis *a)
++{
++  pool_destroy (a->pool);
++  a->pool = pool_create ();
++  tower_init (&a->tower);
++}
++
 +
diff --cc lib/gtksheet/psppire-axis.h
index 8c362d6e11,0000000000..72484773e8
mode 100644,000000..100644
--- a/lib/gtksheet/psppire-axis.h
+++ b/lib/gtksheet/psppire-axis.h
@@@ -1,82 -1,0 +1,92 @@@
 +/* PSPPIRE - a graphical user interface for PSPP.
 +   Copyright (C) 2008  Free Software Foundation
 +
 +   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 3 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, see <http://www.gnu.org/licenses/>. */
 +
 +
 +#ifndef PSPPIRE_AXIS_H__
 +#define PSPPIRE_AXIS_H__
 +
 +
 +#include <glib-object.h>
 +#include <glib.h>
 +
 +#include <libpspp/tower.h>
 +
 +G_BEGIN_DECLS
 +
 +
 +/* --- type macros --- */
 +#define G_TYPE_PSPPIRE_AXIS              (psppire_axis_get_type ())
 +#define PSPPIRE_AXIS(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), G_TYPE_PSPPIRE_AXIS, PsppireAxis))
 +#define PSPPIRE_AXIS_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), G_TYPE_PSPPIRE_AXIS, PsppireAxisClass))
 +#define PSPPIRE_IS_AXIS(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), G_TYPE_PSPPIRE_AXIS))
 +#define PSPPIRE_IS_AXIS_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), G_TYPE_PSPPIRE_AXIS))
 +#define PSPPIRE_AXIS_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_PSPPIRE_AXIS, PsppireAxisClass))
 +
 +
 +
 +/* --- typedefs & structures --- */
 +typedef struct _PsppireAxis	   PsppireAxis;
 +typedef struct _PsppireAxisClass PsppireAxisClass;
 +
++struct pool;
 +
 +struct _PsppireAxis
 +{
 +  GObject             parent;
-   gint width ;
 +
 +  struct tower tower;
++  struct pool *pool;
 +};
 +
 +struct _PsppireAxisClass
 +{
 +  GObjectClass parent_class;
 +
 +};
 +
 +GType          psppire_axis_get_type (void);
 +
- PsppireAxis*   psppire_axis_new (gint w);
++PsppireAxis*   psppire_axis_new (void);
 +
 +
 +/* Interface between sheet and axis */
 +
 +gint psppire_axis_unit_size (PsppireAxis *a, gint unit);
 +
 +gint psppire_axis_unit_count (PsppireAxis *a);
 +
 +glong psppire_axis_pixel_start (PsppireAxis *a, gint unit);
 +
 +gint psppire_axis_get_unit_at_pixel (PsppireAxis *a, glong pixel);
 +
 +
 +
 +/* Interface between axis and model */
 +
- void psppire_axis_append (PsppireAxis *a, gint width);
++void psppire_axis_clear (PsppireAxis *a);
++
++void psppire_axis_append (PsppireAxis *a, gint size);
++
++void psppire_axis_insert (PsppireAxis *a, gint size, gint posn);
++
++void psppire_axis_remove (PsppireAxis *a, gint posn);
++
++void psppire_axis_resize_unit (PsppireAxis *a, gint size, gint posn);
++
 +
 +G_END_DECLS
 +
 +#endif /* PSPPIRE_AXIS_H__ */
diff --cc src/data/dictionary.c
index caf8e2fc34,caf8e2fc34..02c6aa76bc
--- a/src/data/dictionary.c
+++ b/src/data/dictionary.c
@@@ -1352,3 -1352,3 +1352,21 @@@ dict_var_resized (const struct variabl
  	d->callbacks->var_resized (d, var_get_dict_index (v), delta, d->cb_data);
      }
  }
++
++/* Called from variable.c to notify the dictionary that the variable's display width
++   has changed */
++void
++dict_var_display_width_changed (const struct variable *v)
++{
++  if ( var_has_vardict (v))
++    {
++      const struct vardict_info *vdi = var_get_vardict (v);
++      struct dictionary *d;
++
++      d = vdi->dict;
++
++      if ( d->callbacks && d->callbacks->var_display_width_changed )
++	d->callbacks->var_display_width_changed (d, var_get_dict_index (v), d->cb_data);
++    }
++}
++
diff --cc src/data/dictionary.h
index bb14f52ebe,bb14f52ebe..682409e242
--- a/src/data/dictionary.h
+++ b/src/data/dictionary.h
@@@ -157,6 -157,6 +157,7 @@@ struct dict_callback
    void (*weight_changed) (struct dictionary *, int, void *);
    void (*filter_changed) (struct dictionary *, int, void *);
    void (*split_changed) (struct dictionary *, void *);
++  void (*var_display_width_changed) (struct dictionary *, int, void *);
   };
  
  void dict_set_callbacks (struct dictionary *, const struct dict_callbacks *,
diff --cc src/data/vardict.h
index 35440a0de6,35440a0de6..dfde1bffc0
--- a/src/data/vardict.h
+++ b/src/data/vardict.h
@@@ -41,5 -41,5 +41,6 @@@ void var_clear_vardict (struct variabl
  /* Called by variable.c, defined in dictionary.c. */
  void dict_var_changed (const struct variable *v);
  void dict_var_resized (const struct variable *v, int delta);
++void dict_var_display_width_changed (const struct variable *v);
  
  #endif /* data/vardict.h */
diff --cc src/data/variable.c
index d14237d925,d14237d925..ccbe65dc0e
--- a/src/data/variable.c
+++ b/src/data/variable.c
@@@ -778,9 -778,9 +778,15 @@@ var_get_display_width (const struct var
  
  /* Sets V's display width to DISPLAY_WIDTH. */
  void
--var_set_display_width (struct variable *v, int display_width)
++var_set_display_width (struct variable *v, int new_width)
  {
--  v->display_width = display_width;
++  int old_width = v->display_width;
++
++  v->display_width = new_width;
++
++  if ( old_width != new_width)
++    dict_var_display_width_changed (v);
++
    dict_var_changed (v);
  }
  
diff --cc src/ui/gui/psppire-data-editor.c
index fe4fcb62a5,072e55bad3..2e1dee8954
--- a/src/ui/gui/psppire-data-editor.c
+++ b/src/ui/gui/psppire-data-editor.c
@@@ -198,6 -199,6 +198,81 @@@ enu
      PROP_SPLIT_WINDOW
    };
  
++
++#define WIDTH_OF_M 10
++
++static void
++new_variables_callback (PsppireDict *dict, gpointer data)
++{
++  gint v, i;
++  PsppireDataEditor *de = PSPPIRE_DATA_EDITOR (data);
++
++  for (i = 0 ; i < 4 ; ++i)
++    {
++      PsppireAxis *haxis;
++      g_object_get (de->data_sheet[i], "horizontal-axis", &haxis, NULL);
++
++      psppire_axis_clear (haxis);
++
++      for (v = 0 ; v < psppire_dict_get_var_cnt (dict); ++v)
++	{
++	  const struct variable *var = psppire_dict_get_variable (dict, v);
++
++	  psppire_axis_append (haxis, 10 * var_get_display_width (var));
++	}
++    }
++}
++
++static void
++insert_variable_callback (PsppireDict *dict, gint x, gpointer data)
++{
++  gint i;
++  PsppireDataEditor *de = PSPPIRE_DATA_EDITOR (data);
++
++  for (i = 0 ; i < 4 ; ++i)
++    {
++      const struct variable *var = psppire_dict_get_variable (dict, x);
++      PsppireAxis *haxis;
++      g_object_get (de->data_sheet[i], "horizontal-axis", &haxis, NULL);
++
++      psppire_axis_insert (haxis, WIDTH_OF_M * var_get_display_width (var), x);
++    }
++}
++
++
++static void
++delete_variable_callback (PsppireDict *dict, gint posn, gint x UNUSED, gint y UNUSED, gpointer data)
++{
++  gint i;
++  PsppireDataEditor *de = PSPPIRE_DATA_EDITOR (data);
++
++  for (i = 0 ; i < 4 ; ++i)
++    {
++      PsppireAxis *haxis;
++      g_object_get (de->data_sheet[i], "horizontal-axis", &haxis, NULL);
++
++      psppire_axis_remove (haxis, posn);
++    }
++}
++
++
++static void
++rewidth_variable_callback (PsppireDict *dict, gint posn, gpointer data)
++{
++  gint i;
++  PsppireDataEditor *de = PSPPIRE_DATA_EDITOR (data);
++
++  for (i = 0 ; i < 4 ; ++i)
++    {
++      const struct variable *var = psppire_dict_get_variable (dict, posn);
++      PsppireAxis *haxis;
++      g_object_get (de->data_sheet[i], "horizontal-axis", &haxis, NULL);
++
++      psppire_axis_resize_unit (haxis, WIDTH_OF_M * var_get_display_width (var), posn);
++    }
++}
++
++
  static void
  psppire_data_editor_set_property (GObject         *object,
  				  guint            prop_id,
@@@ -220,8 -221,9 +295,14 @@@
        for (i = 0 ; i < 4 ; ++i )
  	g_object_set (de->data_sheet[i],
  		      "row-geometry", de->data_store,
 -		      "column-geometry", de->data_store,
  		      "model", de->data_store,
  		      NULL);
++
++      g_signal_connect (de->data_store->dict, "backend-changed",   G_CALLBACK (new_variables_callback), de);
++      g_signal_connect (de->data_store->dict, "variable-inserted", G_CALLBACK (insert_variable_callback), de);
++      g_signal_connect (de->data_store->dict, "variable-deleted",  G_CALLBACK (delete_variable_callback), de);
++      //      g_signal_connect (de->data_store->dict, "variable-changed",  G_CALLBACK (alter_variable_callback), de);
++      g_signal_connect (de->data_store->dict, "variable-display-width-changed",  G_CALLBACK (rewidth_variable_callback), de);
        break;
      case PROP_VAR_STORE:
        if ( de->var_store) g_object_unref (de->var_store);
@@@ -611,7 -613,6 +692,7 @@@ static voi
  init_sheet (PsppireDataEditor *de, int i,
  	    GtkAdjustment *hadj, GtkAdjustment *vadj)
  {
-   PsppireAxis *haxis = psppire_axis_new (100);
++  PsppireAxis *haxis = psppire_axis_new ();
    de->sheet_bin[i] = gtk_scrolled_window_new (hadj, vadj);
  
    de->data_sheet[i] = gtk_sheet_new (NULL, NULL, NULL);
@@@ -789,16 -786,16 +870,10 @@@ GtkWidget
  psppire_data_editor_new (PsppireVarStore *var_store,
  			 PsppireDataStore *data_store)
  {
--  GtkWidget *widget;
--
--  widget =  g_object_new (PSPPIRE_DATA_EDITOR_TYPE,
--			  "var-store",  var_store,
--			  "data-store",  data_store,
--			  NULL);
--
--
--
--  return widget;
++  return  g_object_new (PSPPIRE_DATA_EDITOR_TYPE,
++				     "var-store",  var_store,
++				     "data-store",  data_store,
++				     NULL);
  }
  
  
diff --cc src/ui/gui/psppire-dict.c
index e6f1373a54,e6f1373a54..8f7fed618f
--- a/src/ui/gui/psppire-dict.c
+++ b/src/ui/gui/psppire-dict.c
@@@ -30,16 -30,16 +30,6 @@@
  #include "helper.h"
  #include "message-dialog.h"
  
--/* --- prototypes --- */
--static void psppire_dict_class_init	(PsppireDictClass	*class);
--static void psppire_dict_init	(PsppireDict		*dict);
--static void psppire_dict_finalize	(GObject		*object);
--
--static void dictionary_tree_model_init (GtkTreeModelIface *iface);
--
--
--/* --- variables --- */
--static GObjectClass     *parent_class = NULL;
  
  enum  {
    BACKEND_CHANGED,
@@@ -48,6 -48,6 +38,7 @@@
    VARIABLE_RESIZED,
    VARIABLE_INSERTED,
    VARIABLE_DELETED,
++  VARIABLE_DISPLAY_WIDTH_CHANGED,
  
    WEIGHT_CHANGED,
    FILTER_CHANGED,
@@@ -55,6 -55,6 +46,18 @@@
    n_SIGNALS
  };
  
++
++/* --- prototypes --- */
++static void psppire_dict_class_init	(PsppireDictClass	*class);
++static void psppire_dict_init	(PsppireDict		*dict);
++static void psppire_dict_finalize	(GObject		*object);
++
++static void dictionary_tree_model_init (GtkTreeModelIface *iface);
++
++
++/* --- variables --- */
++static GObjectClass     *parent_class = NULL;
++
  static guint signals [n_SIGNALS];
  
  /* --- functions --- */
@@@ -93,8 -93,8 +96,6 @@@ psppire_dict_get_type (void
  
        g_type_add_interface_static (object_type, GTK_TYPE_TREE_MODEL,
  				   &tree_model_info);
--
--
      }
  
    return object_type;
@@@ -172,6 -172,6 +173,17 @@@ psppire_dict_class_init (PsppireDictCla
  		  G_TYPE_INT,
  		  G_TYPE_INT);
  
++  signals [VARIABLE_DISPLAY_WIDTH_CHANGED] =
++    g_signal_new ("variable-display-width-changed",
++		  G_TYPE_FROM_CLASS (class),
++		  G_SIGNAL_RUN_FIRST,
++		  0,
++		  NULL, NULL,
++		  g_cclosure_marshal_VOID__INT,
++		  G_TYPE_NONE,
++		  1,
++		  G_TYPE_INT);
++
  
    signals [WEIGHT_CHANGED] =
      g_signal_new ("weight-changed",
@@@ -223,7 -223,7 +235,10 @@@ psppire_dict_finalize (GObject *object
  static void
  addcb (struct dictionary *d, int idx, void *pd)
  {
--  g_signal_emit (pd, signals [VARIABLE_INSERTED], 0, idx);
++  PsppireDict *dict = PSPPIRE_DICT (pd);
++
++  if ( ! dict->disable_insert_signal)
++    g_signal_emit (dict, signals [VARIABLE_INSERTED], 0, idx);
  }
  
  static void
@@@ -264,6 -264,6 +279,13 @@@ split_changed_callback (struct dictiona
    g_signal_emit (pd, signals [SPLIT_CHANGED], 0);
  }
  
++static void
++variable_display_width_callback (struct dictionary *d, int idx, void *pd)
++{
++  g_signal_emit (pd, signals [VARIABLE_DISPLAY_WIDTH_CHANGED], 0, idx);
++}
++
++
  
  static const struct dict_callbacks gui_callbacks =
    {
@@@ -273,13 -273,13 +295,15 @@@
      resize_cb,
      weight_changed_callback,
      filter_changed_callback,
--    split_changed_callback
++    split_changed_callback,
++    variable_display_width_callback
    };
  
  static void
  psppire_dict_init (PsppireDict *psppire_dict)
  {
    psppire_dict->stamp = g_random_int ();
++  psppire_dict->disable_insert_signal = FALSE;
  }
  
  /**
@@@ -349,9 -349,9 +373,15 @@@ psppire_dict_insert_variable (PsppireDi
    if ( ! name )
      name = auto_generate_var_name (d);
  
++  d->disable_insert_signal = TRUE;
++
    var = dict_create_var (d->dict, name, 0);
  
    dict_reorder_var (d->dict, var, idx);
++
++  d->disable_insert_signal = FALSE;
++
++  g_signal_emit (d, signals[VARIABLE_INSERTED], 0, idx);
  }
  
  /* Delete N variables beginning at FIRST */
diff --cc src/ui/gui/psppire-dict.h
index 1bf8bd3523,1bf8bd3523..534f0707ea
--- a/src/ui/gui/psppire-dict.h
+++ b/src/ui/gui/psppire-dict.h
@@@ -38,7 -38,7 +38,6 @@@ G_BEGIN_DECL
  #define PSPPIRE_DICT_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_PSPPIRE_DICT, PsppireDictClass))
  
  
--
  /* --- typedefs & structures --- */
  typedef struct _PsppireDict	   PsppireDict;
  typedef struct _PsppireDictClass PsppireDictClass;
@@@ -50,6 -50,6 +49,7 @@@ struct _PsppireDic
    GObject             parent;
    struct dictionary *dict;
  
++  gboolean disable_insert_signal;
    /* For GtkTreeModelIface */
    gint stamp;
  };
diff --cc src/ui/gui/psppire-var-sheet.c
index 5406949108,0708bf3e04..033652025a
--- a/src/ui/gui/psppire-var-sheet.c
+++ b/src/ui/gui/psppire-var-sheet.c
@@@ -533,16 -538,5 +533,16 @@@ static const struct column_parameters c
  GtkWidget*
  psppire_var_sheet_new (void)
  {
 -  return GTK_WIDGET (g_object_new (psppire_var_sheet_get_type (), NULL));
 +  gint i;
-   PsppireAxis *a = psppire_axis_new (-1);
++  PsppireAxis *a = psppire_axis_new ();
 +  GtkWidget *w = g_object_new (psppire_var_sheet_get_type (), NULL);
 +
 +  for (i = 0 ; i < 10 ; ++i)
 +    psppire_axis_append (a, column_def[i].width);
 +
 +  g_object_set (w,
 +		"horizontal-axis", a,
 +		NULL);
 +
 +  return w;
  }