Commit 425a749a authored by Jody Goldberg's avatar Jody Goldberg Committed by Jody Goldberg

NOTE : The idl change requires an update to guppi.

2002-01-18  Jody Goldberg <jody@gnome.org>

	* dialog-graph-guru.c (graph_guru_plot_name) : fix the stupid name
	  generation.
	(vector_state_series_set_dimension) : create a series if necessary.
	(cb_graph_guru_series_add) : implement.
	(graph_guru_select_plot) : make series reset optional.
	(graph_guru_init) : hook up the add/delete series buttons.
	(cb_graph_guru_series_delete) : new.
	(cb_graph_guru_series_add) : new.

2002-01-18  Jody Goldberg <jody@gnome.org>

	* src/eval.c : Add a new dependency hashing scheme but leave it
	  disabled until 1.1  so thet we can get it tested.

2002-01-18  Jody Goldberg <jody@gnome.org>

	* src/gnumeric-graph.c (gnm_graph_range_to_vectors) : be smarter about
	  handling vectors rather than ranges.  vectors maintain orientation.
parent c50cf243
......@@ -7,6 +7,7 @@ release, and longer term bugs.
Release Critical
----------------
- rangesel for quoted sheet names misses leading quote
Pending Patches
---------------
......
2002-01-18 Jody Goldberg <jody@gnome.org>
* src/eval.c : Add a new dependency hashing scheme but leave it
disabled until 1.1 so thet we can get it tested.
2002-01-18 Jody Goldberg <jody@gnome.org>
* src/gnumeric-graph.c (gnm_graph_range_to_vectors) : be smarter about
handling vectors rather than ranges. vectors maintain orientation.
2002-01-18 Zbigniew Chyla <cyba@gnome.pl>
* src/bonobo-io.c
......
......@@ -4,6 +4,7 @@ Andreas:
* Improve compatibility of COUP_ fuctions
Jody:
* Enable Add/Delete Series for Graph Guru
* More work on XL import for 3d references.
* Import checkbox links from XL.
......
2002-01-18 Jody Goldberg <jody@gnome.org>
* src/eval.c : Add a new dependency hashing scheme but leave it
disabled until 1.1 so thet we can get it tested.
2002-01-18 Jody Goldberg <jody@gnome.org>
* src/gnumeric-graph.c (gnm_graph_range_to_vectors) : be smarter about
handling vectors rather than ranges. vectors maintain orientation.
2002-01-18 Zbigniew Chyla <cyba@gnome.pl>
* src/bonobo-io.c
......
2002-01-18 Jody Goldberg <jody@gnome.org>
* src/eval.c : Add a new dependency hashing scheme but leave it
disabled until 1.1 so thet we can get it tested.
2002-01-18 Jody Goldberg <jody@gnome.org>
* src/gnumeric-graph.c (gnm_graph_range_to_vectors) : be smarter about
handling vectors rather than ranges. vectors maintain orientation.
2002-01-18 Zbigniew Chyla <cyba@gnome.pl>
* src/bonobo-io.c
......
2002-01-18 Jody Goldberg <jody@gnome.org>
* src/eval.c : Add a new dependency hashing scheme but leave it
disabled until 1.1 so thet we can get it tested.
2002-01-18 Jody Goldberg <jody@gnome.org>
* src/gnumeric-graph.c (gnm_graph_range_to_vectors) : be smarter about
handling vectors rather than ranges. vectors maintain orientation.
2002-01-18 Zbigniew Chyla <cyba@gnome.pl>
* src/bonobo-io.c
......
......@@ -46,7 +46,7 @@ module GNOME {
};
};
module Graph_v1 {
module Graph_v2 {
interface ConfigGuru : Bonobo::Control {
oneway void applyChanges ();
};
......@@ -67,12 +67,10 @@ module GNOME {
in VectorID vectorID)
raises (Error);
/**
* seriesDelete :
*
* Remove a series from a plot.
*/
void seriesDelete (in SeriesID series) raises (Error);
PlotID plotAdd () raises (Error);
void plotDelete (in PlotID plot) raises (Error);
SeriesID seriesAdd (in PlotID plot) raises (Error);
void seriesDelete (in SeriesID series) raises (Error);
};
interface Manager : Bonobo::Embeddable {
......
......@@ -49,7 +49,6 @@
/* Note, that ->prev_dep and ->next_dep are still valid. */ \
} while (0)
static GPtrArray *dep_classes = NULL;
void
......@@ -263,6 +262,202 @@ cb_dependent_queue_recalc (Dependent *dep, gpointer ignore)
}
/**************************************************************************/
#undef ENABLE_MICRO_HASH
#ifdef ENABLE_MICRO_HASH
typedef struct {
gint num_buckets;
gint num_elements;
union {
GSList **buckets;
GSList *singleton;
} u;
} MicroHash;
#define MICRO_HASH_MIN_SIZE 11
#define MICRO_HASH_MAX_SIZE 13845163
#define MICRO_HASH_RESIZE(hash_table) \
G_STMT_START { \
if ((hash_table->num_buckets > MICRO_HASH_MIN_SIZE && \
hash_table->num_buckets >= 3 * hash_table->num_elements) || \
(hash_table->num_buckets < MICRO_HASH_MAX_SIZE && \
3 * hash_table->num_buckets <= hash_table->num_elements)) \
micro_hash_resize (hash_table); \
} G_STMT_END
/* The records are aligned so the bottom few bits don't hold much
* entropy
*/
#define MICRO_HASH_hash(key) ((guint)((int) (key) >> 9))
static void
micro_hash_resize (MicroHash *hash_table)
{
GSList **new_buckets, *node, *next;
guint bucket;
gint old_num_buckets = hash_table->num_buckets;
gint new_num_buckets = CLAMP (g_spaced_primes_closest (hash_table->num_elements),
MICRO_HASH_MIN_SIZE, MICRO_HASH_MAX_SIZE);
if (old_num_buckets <= 1) {
if (new_num_buckets == 1)
return;
new_buckets = g_new0 (GSList *, new_num_buckets);
for (node = hash_table->u.singleton; node; node = next) {
next = node->next;
bucket = MICRO_HASH_hash (node->data) % new_num_buckets;
node->next = new_buckets [bucket];
new_buckets [bucket] = node;
}
hash_table->u.buckets = new_buckets;
} else if (new_num_buckets > 1) {
new_buckets = g_new0 (GSList *, new_num_buckets);
for (old_num_buckets = hash_table->num_buckets; old_num_buckets-- > 0 ; )
for (node = hash_table->u.buckets [old_num_buckets]; node; node = next) {
next = node->next;
bucket = MICRO_HASH_hash (node->data) % new_num_buckets;
node->next = new_buckets [bucket];
new_buckets [bucket] = node;
}
g_free (hash_table->u.buckets);
hash_table->u.buckets = new_buckets;
} else {
GSList *singleton = NULL;
while (old_num_buckets-- > 0)
singleton = g_slist_concat (singleton, hash_table->u.buckets [old_num_buckets]);
g_free (hash_table->u.buckets);
hash_table->u.singleton = singleton;
}
hash_table->num_buckets = new_num_buckets;
}
static void
micro_hash_insert (MicroHash *hash_table, gpointer key)
{
GSList **head;
int const hash_size = hash_table->num_buckets;
if (hash_size > 1) {
guint const bucket = MICRO_HASH_hash (key) % hash_size;
head = hash_table->u.buckets + bucket;
} else
head = & (hash_table->u.singleton);
if (g_slist_find (*head, key) == NULL) {
*head = g_slist_prepend (*head, key);
hash_table->num_elements++;
MICRO_HASH_RESIZE (hash_table);
}
}
static void
micro_hash_remove (MicroHash *hash_table, gpointer key)
{
GSList **head;
int const hash_size = hash_table->num_buckets;
if (hash_size > 1) {
guint const bucket = MICRO_HASH_hash (key) % hash_size;
head = hash_table->u.buckets + bucket;
} else
head = & (hash_table->u.singleton);
for (; *head != NULL ; head = &((*head)->next))
if ((*head)->data == key) {
*head = (*head)->next;
hash_table->num_elements--;
MICRO_HASH_RESIZE (hash_table);
return;
}
}
static void
micro_hash_release (MicroHash *hash_table)
{
guint i = hash_table->num_buckets;
if (i > 1) {
while (i-- > 0)
g_slist_free (hash_table->u.buckets[i]);
g_free (hash_table->u.buckets);
hash_table->u.buckets = NULL;
} else {
g_slist_free (hash_table->u.singleton);
hash_table->u.singleton = NULL;
}
hash_table->num_elements = 0;
hash_table->num_buckets = 1;
}
static void
micro_hash_init (MicroHash *hash_table, gpointer key)
{
hash_table->num_elements = 0;
hash_table->num_buckets = 1;
hash_table->u.singleton = g_slist_prepend (NULL, key);
}
/*************************************************************************/
typedef MicroHash DepCollection;
#define dep_collection_init(dc, dep) \
micro_hash_init (&(dc), dep)
#define dep_collection_insert(dc, dep) \
micro_hash_insert (&(dc), dep)
#define dep_collection_remove(dc, dep) \
micro_hash_remove (&(dc), dep)
#define dep_collection_is_empty(dc) \
(dc.num_elements == 0)
#define dep_collection_foreach_dep(dc, dep, code) do { \
GSList *l; \
int i = dc.num_buckets; \
if (i <= 1) { \
for (l = dc.u.singleton; l ; l = l->next) { \
Dependent *dep = l->data; \
code \
} \
} else while (i-- > 0) { \
for (l = dc.u.buckets [i]; l ; l = l->next) { \
Dependent *dep = l->data; \
code \
} \
} \
} while (0)
#define dep_collection_foreach_list(dc, list, code) do { \
GSList *list; \
int i = dc.num_buckets; \
if (i <= 1) { \
list = dc.u.singleton; \
code \
} else while (i-- > 0) { \
list = dc.u.buckets[i]; \
code \
} \
} while (0)
#else
typedef GSList * DepCollection;
#define dep_collection_init(dc, dep) \
dc = g_slist_prepend (NULL, dep)
#define dep_collection_insert(dc, dep) \
if (!g_slist_find (dc, dep)) dc = g_slist_prepend (dc, dep)
#define dep_collection_remove(dc, dep) \
dc = g_slist_remove (dc, dep);
#define dep_collection_is_empty(dc) \
(dc == NULL)
#define dep_collection_foreach_dep(dc, dep, code) do { \
GSList *l; \
for (l = dc; l != NULL ; l = l->next) { \
Dependent *dep = l->data; \
code \
} \
} while (0)
#define dep_collection_foreach_list(dc, list, code) do { \
GSList *list = dc; \
code \
} while (0)
#endif
/**************************************************************************
* Data structures for managing dependencies between objects.
*
......@@ -275,10 +470,10 @@ cb_dependent_queue_recalc (Dependent *dep, gpointer ignore)
* are used by another objects in the spreadsheet.
*
* A change in those cells will trigger a recomputation on the
* cells listed in dependent_list.
* cells listed in deps.
*/
typedef struct {
GSList *dependent_list; /* Must be first */
DepCollection deps; /* Must be first */
Range range;
} DependencyRange;
......@@ -287,16 +482,16 @@ typedef struct {
* on the cell at @pos.
*
* A change in this cell will trigger a recomputation on the
* cells listed in dependent_list.
* cells listed in deps.
*/
typedef struct {
GSList *dependent_list; /* Must be first */
DepCollection deps; /* Must be first */
CellPos pos;
} DependencySingle;
/* A utility type */
typedef struct {
GSList *dependent_list; /* Must be first */
DepCollection deps; /* Must be first */
} DependencyAny;
typedef enum {
......@@ -372,21 +567,18 @@ handle_cell_single_dep (Dependent *dep, CellPos const *pos,
if (operation == ADD_DEPS) {
if (single) {
if (!g_slist_find (single->dependent_list, dep))
single->dependent_list =
g_slist_prepend (single->dependent_list, dep);
else
/* Referenced twice in the same formula */;
/* Inserts if it is not already there */
dep_collection_insert (single->deps, dep);
} else {
single = g_new (DependencySingle, 1);
*single = lookup;
single->dependent_list = g_slist_prepend (NULL, dep);
dep_collection_init (single->deps, dep);
g_hash_table_insert (deps->single_hash, single, single);
}
} else { /* Remove */
if (single) {
single->dependent_list = g_slist_remove (single->dependent_list, dep);
if (single->dependent_list == NULL) {
dep_collection_remove (single->deps, dep);
if (dep_collection_is_empty (single->deps)) {
g_hash_table_remove (deps->single_hash, single);
g_free (single);
}
......@@ -396,7 +588,7 @@ handle_cell_single_dep (Dependent *dep, CellPos const *pos,
}
static void
add_range_dep (DependencyContainer *deps, Dependent *dependent,
add_range_dep (DependencyContainer *deps, Dependent *dep,
DependencyRange const *r)
{
int i = r->range.start.row / BUCKET_SIZE;
......@@ -415,16 +607,8 @@ add_range_dep (DependencyContainer *deps, Dependent *dependent,
result = g_hash_table_lookup (deps->range_hash[i], r);
if (result) {
/* Is the dependent already listed? */
GSList const *cl = g_slist_find (result->dependent_list,
dependent);
if (cl)
continue;
/* It was not: add it */
result->dependent_list = g_slist_prepend (result->dependent_list,
dependent);
/* Inserts if it is not already there */
dep_collection_insert (result->deps, dep);
continue;
}
}
......@@ -432,30 +616,27 @@ add_range_dep (DependencyContainer *deps, Dependent *dependent,
/* Create a new DependencyRange structure */
result = g_new (DependencyRange, 1);
*result = *r;
result->dependent_list = g_slist_prepend (NULL, dependent);
dep_collection_init (result->deps, dep);
g_hash_table_insert (deps->range_hash[i], result, result);
}
}
static void
drop_range_dep (DependencyContainer *deps, Dependent *dependent,
drop_range_dep (DependencyContainer *deps, Dependent *dep,
DependencyRange const *r)
{
int i = r->range.start.row / BUCKET_SIZE;
int const end = r->range.end.row / BUCKET_SIZE;
DependencyRange *result;
if (!deps)
return;
for ( ; i <= end; i++) {
DependencyRange *result;
result = g_hash_table_lookup (deps->range_hash[i], r);
if (result) {
result->dependent_list =
g_slist_remove (result->dependent_list, dependent);
if (result->dependent_list == NULL) {
dep_collection_remove (result->deps, dep);
if (dep_collection_is_empty (result->deps)) {
g_hash_table_remove (deps->range_hash[i], result);
g_free (result);
}
......@@ -463,19 +644,6 @@ drop_range_dep (DependencyContainer *deps, Dependent *dependent,
}
}
static void
deprange_init (DependencyRange *range, CellPos const *pos,
CellRef const *a, CellRef const *b)
{
cellref_get_abs_pos (a, pos, &range->range.start);
cellref_get_abs_pos (b, pos, &range->range.end);
range_normalize (&range->range);
range->dependent_list = NULL;
if (b->sheet && a->sheet != b->sheet)
g_warning ("FIXME: 3D references need work");
}
/*
* Add the dependency of Dependent dep on the range
* enclose by CellRef a and CellRef b
......@@ -489,7 +657,9 @@ handle_cell_range_deps (Dependent *dep, CellPos const *pos,
DependencyRange range;
DependencyContainer *depsa, *depsb;
deprange_init (&range, pos, a, b);
cellref_get_abs_pos (a, pos, &range.range.start);
cellref_get_abs_pos (b, pos, &range.range.end);
range_normalize (&range.range);
depsa = eval_sheet (a->sheet, dep->sheet)->deps;
if (operation)
......@@ -848,11 +1018,9 @@ cb_search_rangedeps (gpointer key, gpointer value, gpointer closure)
/* No intersection is the common case */
if (range_contains (range, c->col, c->row)) {
GSList *l;
for (l = deprange->dependent_list; l; l = l->next) {
Dependent *dep = l->data;
(*c->func) (dep, c->user);
}
DepFunc func = c->func;
dep_collection_foreach_dep (deprange->deps, dep,
(func) (dep, c->user););
}
}
......@@ -887,19 +1055,14 @@ cell_foreach_single_dep (Sheet const *sheet, int col, int row,
{
DependencySingle lookup, *single;
DependencyContainer *deps = sheet->deps;
GSList *ptr;
lookup.pos.col = col;
lookup.pos.row = row;
single = g_hash_table_lookup (deps->single_hash, &lookup);
if (single == NULL)
return;
for (ptr = single->dependent_list ; ptr != NULL ; ptr = ptr->next) {
Dependent *dep = ptr->data;
(*func) (dep, user);
}
if (single != NULL)
dep_collection_foreach_dep (single->deps, dep,
(*func) (dep, user););
}
void
......@@ -920,7 +1083,8 @@ static void
cb_recalc_all_depends (gpointer key, gpointer value, gpointer ignore)
{
DependencyAny const *depany = key;
dependent_queue_recalc_list (depany->dependent_list);
dep_collection_foreach_list (depany->deps, list,
dependent_queue_recalc_list (list););
}
static void
......@@ -931,7 +1095,8 @@ cb_range_contained_depend (gpointer key, gpointer value, gpointer user)
Range const *target = user;
if (range_overlap (target, range))
dependent_queue_recalc_list (deprange->dependent_list);
dep_collection_foreach_list (deprange->deps, list,
dependent_queue_recalc_list (list););
}
static void
......@@ -941,7 +1106,8 @@ cb_single_contained_depend (gpointer key, gpointer value, gpointer user)
Range const *target = user;
if (range_contains (target, depsingle->pos.col, depsingle->pos.row))
dependent_queue_recalc_list (depsingle->dependent_list);
dep_collection_foreach_list (depsingle->deps, list,
dependent_queue_recalc_list (list););
}
/**
......@@ -1026,11 +1192,12 @@ cb_dep_hash_invalidate (gpointer key, gpointer value, gpointer closure)
{
ExprRewriteInfo const *rwinfo = closure;
DependencyAny *depany = value;
GSList *deps = depany->dependent_list;
#ifndef ENABLE_MICRO_HASH
GSList *deps = depany->deps;
GSList *ptr = deps;
Dependent *dependent;
depany->dependent_list = NULL; /* poison it */
depany->deps = NULL; /* poison it */
if (rwinfo->type == EXPR_REWRITE_SHEET) {
Sheet const *target = rwinfo->u.sheet;
for (; ptr != NULL; ptr = ptr->next) {
......@@ -1050,6 +1217,23 @@ cb_dep_hash_invalidate (gpointer key, gpointer value, gpointer closure)
}
g_slist_free (deps);
#else
if (rwinfo->type == EXPR_REWRITE_SHEET) {
Sheet const *target = rwinfo->u.sheet;
dep_collection_foreach_dep (depany->deps, dep,
if (dep->sheet != target)
invalidate_refs (dep, rwinfo););
} else if (rwinfo->type == EXPR_REWRITE_WORKBOOK) {
Workbook const *target = rwinfo->u.workbook;
dep_collection_foreach_dep(depany->deps, dep,
if (dep->sheet->workbook != target)
invalidate_refs (dep, rwinfo););
} else {
g_assert_not_reached ();
}
micro_hash_release (&depany->deps);
#endif
g_free (depany);
}
......@@ -1262,17 +1446,19 @@ dump_range_dep (gpointer key, gpointer value, gpointer closure)
printf ("\t%s:", cell_pos_name (&range->start));
printf ("%s -> ", cell_pos_name (&range->end));
dump_dependent_list (deprange->dependent_list);
dep_collection_foreach_list (deprange->deps, list,
dump_dependent_list (list););
}
static void
dump_single_dep (gpointer key, gpointer value, gpointer closure)
{
DependencySingle *dep = key;
DependencySingle *depsingle = key;
printf ("\t%s -> ", cell_pos_name (&dep->pos));
printf ("\t%s -> ", cell_pos_name (&depsingle->pos));
dump_dependent_list (dep->dependent_list);
dep_collection_foreach_list (depsingle->deps, list,
dump_dependent_list (list););
}
/**
......
2002-01-18 Jody Goldberg <jody@gnome.org>
* dialog-graph-guru.c (graph_guru_plot_name) : fix the stupid name
generation.
(vector_state_series_set_dimension) : create a series if necessary.
(cb_graph_guru_series_add) : implement.
(graph_guru_select_plot) : make series reset optional.
(graph_guru_init) : hook up the add/delete series buttons.
(cb_graph_guru_series_delete) : new.
(cb_graph_guru_series_add) : new.
2002-01-18 Morten Welinder <terra@diku.dk>
* dialog-formula-guru.c (formula_guru_init): Always show table.
......
......@@ -41,10 +41,10 @@
#include <gal/util/e-xml-utils.h>
#include <libxml/parser.h>
#define CONFIG_GURU GNOME_Gnumeric_Graph_v1_ConfigGuru
#define CONFIG_GURU1(suffix) GNOME_Gnumeric_Graph_v1_ConfigGuru_ ## suffix
#define DATA_GURU GNOME_Gnumeric_Graph_v1_DataGuru
#define DATA_GURU1(suffix) GNOME_Gnumeric_Graph_v1_DataGuru_ ## suffix
#define CONFIG_GURU GNOME_Gnumeric_Graph_v2_ConfigGuru
#define CONFIG_GURU1(suffix) GNOME_Gnumeric_Graph_v2_ConfigGuru_ ## suffix
#define DATA_GURU GNOME_Gnumeric_Graph_v2_DataGuru
#define DATA_GURU1(suffix) GNOME_Gnumeric_Graph_v2_DataGuru_ ## suffix
typedef struct _GraphGuruState GraphGuruState;
typedef struct
......@@ -78,7 +78,7 @@ struct _GraphGuruState
GtkWidget *plot_remove;
GtkWidget *series_selector;
GtkWidget *series_add;
GtkWidget *series_remove;
GtkWidget *series_delete;
GtkWidget *series_details;
GtkWidget *shared_series_details;
GtkWidget *sample_frame;
......@@ -99,8 +99,6 @@ struct _GraphGuruState
gboolean updating;
xmlDoc *xml_doc;
gboolean is_columns;
/* external state */
WorkbookControlGUI *wbcg;
SheetControlGUI *scg;
......@@ -108,7 +106,7 @@ struct _GraphGuruState
Sheet *sheet;
};
static void graph_guru_select_plot (GraphGuruState *s, xmlNode *plot);
static void graph_guru_select_plot (GraphGuruState *s, xmlNode *plot, int seriesID);
static void
graph_guru_clear_xml (GraphGuruState *state)
......@@ -156,16 +154,20 @@ graph_guru_get_series (GraphGuruState *s, int indx)
static char *
graph_guru_plot_name (GraphGuruState *s, xmlNode *plot)
{
xmlChar const *t = (xmlChar *)"Plot";
char *name;
xmlChar *t;
int i = e_xml_get_integer_prop_by_name_with_default (plot, (xmlChar *)"index", -1);
xmlNode *type = e_xml_get_child_by_name (plot, (xmlChar *)"Type");
g_return_val_if_fail (i >= 0, g_strdup ("ERROR Missing Index"));
if (type != NULL && type->xmlChildrenNode)
t = type->xmlChildrenNode->name;
t = xml_node_get_cstr (type, "name");
if (t == NULL)
t = xmlMemStrdup ("Plot");
return g_strdup_printf ("%s%d", t, i+1);
name = g_strdup_printf ("%s%d", t, i+1);
xmlFree (t);
return name;
}
static void
......@@ -231,7 +233,7 @@ graph_guru_get_spec (GraphGuruState *s)
GINT_TO_POINTER (indx));
if (s->current_plot < 0 || s->current_plot == indx)
graph_guru_select_plot (s, plot);
graph_guru_select_plot (s, plot, s->current_series);
}
}
......@@ -270,10 +272,23 @@ vector_state_series_set_dimension (VectorState *vs, ExprTree *expr)
vector_id = gnm_graph_add_vector (vs->state->graph,
expr, GNM_VECTOR_AUTO, vs->state->sheet);
CORBA_exception_init (&ev);
/* We need to create the series */
if (vs->series_index < 0) {
vs->series_index = DATA_GURU1 (seriesAdd) (vs->state->data_guru,
vs->state->current_plot, &ev);
if (ev._major != CORBA_NO_EXCEPTION) {
g_warning ("'%s' : adding a series to graph data_guru %p",
gnm_graph_exception (&ev), vs->state->data_guru);
CORBA_exception_free (&ev);
return;
}
}
/* Future simplification. If we are changing an unshared dimension we
* can do the substitution in place. and just tweak the expression.
*/
CORBA_exception_init (&ev);
DATA_GURU1 (seriesSetDimension) (vs->state->data_guru,
vs->series_index, (CORBA_char *)vs->dim_name, vector_id, &ev);
if (ev._major == CORBA_NO_EXCEPTION)
......@@ -458,7 +473,7 @@ graph_guru_state_destroy (GraphGuruState *state)
{
g_return_if_fail (state != NULL);
graph_guru_select_plot (state, NULL);
graph_guru_select_plot (state, NULL, -1);
if (state->plot_selector) {
gtk_signal_disconnect_by_data (
......@@ -575,13 +590,13 @@ graph_guru_select_series (GraphGuruState *s, xmlNode *series)
}
static void
graph_guru_select_plot (GraphGuruState *s, xmlNode *plot)
graph_guru_select_plot (GraphGuruState *s, xmlNode *plot, int seriesID)
{
xmlNode *layout, *series;
char *name;
GtkWidget *item;
int shared, unshared;
int indx;
int indx, count = 0;
if (s->updating)
return;
......@@ -591,10 +606,12 @@ graph_guru_select_plot (GraphGuruState *s, xmlNode *plot)
gnm_combo_text_clear (GNM_COMBO_TEXT (s->series_selector));
s->current_plot = -1;
}
s->current_series = -1;
if (plot == NULL)
if (plot == NULL) {
s->current_series = -1;
return;
}
s->current_series = seriesID;
s->current_plot =
e_xml_get_integer_prop_by_name_with_default (plot, (xmlChar *)"index", -1);
......@@ -656,6 +673,7 @@ graph_guru_select_plot (GraphGuruState *s, xmlNode *plot)
GINT_TO_POINTER (indx));
if (s->current_series < 0)
graph_guru_select_series (s, series);
count++;
}