graph-vector.c 15.5 KB
Newer Older
1 2 3
/* vim: set sw=8: */

/*
4
 * graph-vector.c: Support routines for graph vector.
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * Copyright (C) 2000 Jody Goldberg (jgoldberg@home.com)
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
 */

#include "config.h"
25
#include "graph-vector.h"
26 27 28
#include "idl/gnumeric-graphs.h"
#include <bonobo.h>
#include <gtk/gtkobject.h>
Jody Goldberg's avatar
Jody Goldberg committed
29
#include "eval.h"
30 31
#include "expr.h"
#include "value.h"
32
#include "cell.h"
Jody Goldberg's avatar
Jody Goldberg committed
33
#include "sheet.h"
34 35
#include "gnumeric-type-util.h"

36 37
typedef enum { VECTOR_SCALAR, VECTOR_DATE, VECTOR_STRING } GraphVectorType;
struct _GraphVector {
38 39
	GtkObject 	obj;
	Dependent 	dep;
40

41
	GraphVectorType  type;
42 43 44
	gboolean	 is_column;
	Range		 range;	/* TODO : add support for discontinuous */
	char		*name;
45

46
	CORBA_Object    vector_ref;	/* local CORBA object */
47
	union {
48 49 50 51 52
		POA_GNOME_Gnumeric_VectorScalar		scalar;
		POA_GNOME_Gnumeric_VectorDate		date;
		POA_GNOME_Gnumeric_VectorString		string;
	} servant;

53
	/* The remote server monitoring this vector */
54 55 56 57 58 59 60 61 62
	union {
		GNOME_Gnumeric_VectorScalarNotify	scalar;
		GNOME_Gnumeric_VectorDateNotify		date;
		GNOME_Gnumeric_VectorStringNotify	string;
	} subscriber;
};

typedef struct {
	GtkObjectClass parent_class;
63
} GraphVectorClass;
64

65 66 67 68 69
#define GRAPH_VECTOR_TYPE        (graph_vector_get_type ())
#define GRAPH_VECTOR(o)          (GTK_CHECK_CAST ((o), GRAPH_VECTOR_TYPE, GraphVector))
#define GRAPH_VECTOR_CLASS(k)    (GTK_CHECK_CLASS_CAST((k), GRAPH_VECTOR_TYPE, GraphVectorClass))
#define IS_GRAPH_VECTOR(o)       (GTK_CHECK_TYPE ((o), GRAPH_VECTOR_TYPE))
#define IS_GRAPH_VECTOR_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), GRAPH_VECTOR_TYPE))
70 71
#define DEP_TO_GRAPH_VECTOR(ptr) (GraphVector *)(((char *)ptr) - GTK_STRUCT_OFFSET(GraphVector, dep))
#define SERVANT_TO_GRAPH_VECTOR(ptr) (GraphVector *)(((char *)ptr) - GTK_STRUCT_OFFSET(GraphVector, servant))
72

73
static GtkType graph_vector_get_type (void);
74 75 76 77

/***************************************************************************/

static GNOME_Gnumeric_SeqScalar *
78
graph_vector_seq_scalar (GraphVector *vector)
79
{
Jody Goldberg's avatar
Jody Goldberg committed
80
	int i, len;
81 82 83 84
	Value *v;
	EvalPos pos;
	GNOME_Gnumeric_SeqScalar *values;

85
	pos.sheet = vector->dep.sheet;
86
	pos.eval.row = pos.eval.col = 0;
87
	v = eval_expr (&pos, vector->dep.expression, EVAL_PERMIT_NON_SCALAR);
88

Jody Goldberg's avatar
Jody Goldberg committed
89
	len = value_area_get_height  (&pos, v);
90
	values = GNOME_Gnumeric_SeqScalar__alloc ();
Jody Goldberg's avatar
Jody Goldberg committed
91 92
	values->_length = values->_maximum = len;
	values->_buffer = CORBA_sequence_CORBA_double_allocbuf (len);
Jody Goldberg's avatar
Jody Goldberg committed
93
	values->_release = CORBA_TRUE;
94 95

	/* FIXME : This is dog slow */
96
	for (i = 0; i < len ; ++i) {
97
		Value const *elem = vector->is_column
98 99 100 101 102 103
			? value_area_get_x_y (&pos, v, 0, i)
			: value_area_get_x_y (&pos, v, i, 0);
		values->_buffer [i] = value_get_as_float (elem);
	}

	value_release (v);
104 105 106 107

	return values;
}
static GNOME_Gnumeric_SeqDate *
108
graph_vector_seq_date (GraphVector *vector)
109
{
Jody Goldberg's avatar
Jody Goldberg committed
110
	int i, len;
111 112 113 114
	Value *v;
	EvalPos pos;
	GNOME_Gnumeric_SeqDate *values;

115
	pos.sheet = vector->dep.sheet;
116
	pos.eval.row = pos.eval.col = 0;
117
	v = eval_expr (&pos, vector->dep.expression, EVAL_PERMIT_NON_SCALAR);
118

Jody Goldberg's avatar
Jody Goldberg committed
119
	len = value_area_get_height  (&pos, v);
120
	values = GNOME_Gnumeric_SeqDate__alloc ();
Jody Goldberg's avatar
Jody Goldberg committed
121 122
	values->_length = values->_maximum = len;
	values->_buffer = CORBA_sequence_CORBA_long_allocbuf (len);
Jody Goldberg's avatar
Jody Goldberg committed
123
	values->_release = CORBA_TRUE;
124 125

	/* FIXME : This is dog slow */
126
	for (i = 0; i < len ; ++i) {
127
		Value const *elem = vector->is_column
128 129 130 131
			? value_area_get_x_y (&pos, v, 0, i)
			: value_area_get_x_y (&pos, v, i, 0);
		values->_buffer [i] = value_get_as_int (elem);
	}
132 133 134 135

	return values;
}
static GNOME_Gnumeric_SeqString *
136
graph_vector_seq_string (GraphVector *vector)
137
{
Jody Goldberg's avatar
Jody Goldberg committed
138
	int i, len;
139 140 141 142
	Value *v;
	EvalPos pos;
	GNOME_Gnumeric_SeqString *values;

143
	pos.sheet = vector->dep.sheet;
144
	pos.eval.row = pos.eval.col = 0;
145
	v = eval_expr (&pos, vector->dep.expression, EVAL_PERMIT_NON_SCALAR);
146

Jody Goldberg's avatar
Jody Goldberg committed
147
	len = value_area_get_height  (&pos, v);
148
	values = GNOME_Gnumeric_SeqString__alloc ();
Jody Goldberg's avatar
Jody Goldberg committed
149 150
	values->_length = values->_maximum = len;
	values->_buffer = CORBA_sequence_CORBA_string_allocbuf (len);
Jody Goldberg's avatar
Jody Goldberg committed
151
	values->_release = CORBA_TRUE;
152 153

	/* FIXME : This is dog slow */
154
	for (i = 0; i < len ; ++i) {
155
		Value const *elem = vector->is_column
156 157
			? value_area_get_x_y (&pos, v, 0, i)
			: value_area_get_x_y (&pos, v, i, 0);
Morten Welinder's avatar
Morten Welinder committed
158 159
		const char *tmp = value_peek_string (elem);
		values->_buffer[i] = CORBA_string_dup (tmp);
160 161 162 163 164 165
	}

	return values;
}

static void
166
graph_vector_eval (Dependent *dep)
167 168
{
	CORBA_Environment ev;
169
	GraphVector *vector;
170

171 172
	vector = DEP_TO_GRAPH_VECTOR (dep);
	vector = GRAPH_VECTOR (vector);
173

174
	g_return_if_fail (vector != NULL);
175 176

	CORBA_exception_init (&ev);
177 178
	switch (vector->type) {
	case VECTOR_SCALAR :
179
		GNOME_Gnumeric_VectorScalarNotify_valueChanged (
180 181
			vector->subscriber.scalar,
			0, graph_vector_seq_scalar (vector), &ev);
182 183
		break;

184
	case VECTOR_DATE :
185
		GNOME_Gnumeric_VectorDateNotify_valueChanged (
186 187
			vector->subscriber.date,
			0, graph_vector_seq_date (vector), &ev);
188 189
		break;

190
	case VECTOR_STRING :
191
		GNOME_Gnumeric_VectorStringNotify_valueChanged (
192 193
			vector->subscriber.string,
			0, graph_vector_seq_string (vector), &ev);
194 195 196 197 198 199
		break;

	default :
		g_assert_not_reached ();
	}
	if (ev._major != CORBA_NO_EXCEPTION)
200
		g_warning ("Problems notifying graph of change %p", vector);
201 202 203 204 205 206 207 208 209 210 211
	CORBA_exception_free (&ev);
}

/******************************************************************************/

static void
impl_vector_scalar_value (PortableServer_Servant servant,
			  GNOME_Gnumeric_SeqScalar **values,
			  CORBA_char **name,
			  CORBA_Environment *ev)
{
212
	GraphVector *vector = SERVANT_TO_GRAPH_VECTOR (servant);
213

214 215
	g_return_if_fail (GRAPH_VECTOR (vector) != NULL);
	g_return_if_fail (vector->type == VECTOR_SCALAR);
216

217 218
	*name = CORBA_string_dup (vector->name);
	*values = graph_vector_seq_scalar (vector);
219 220 221 222 223 224 225 226
}

static void
impl_vector_date_value (PortableServer_Servant servant,
			GNOME_Gnumeric_SeqDate **values,
			CORBA_char **name,
			CORBA_Environment *ev)
{
227
	GraphVector *vector = SERVANT_TO_GRAPH_VECTOR (servant);
228

229 230
	g_return_if_fail (GRAPH_VECTOR (vector) != NULL);
	g_return_if_fail (vector->type == VECTOR_DATE);
231

232 233
	*name = CORBA_string_dup (vector->name);
	*values = graph_vector_seq_date (vector);
234 235 236 237 238 239 240 241
}

static void
impl_vector_string_value (PortableServer_Servant servant,
			  GNOME_Gnumeric_SeqString **values,
			  CORBA_char **name,
			  CORBA_Environment *ev)
{
242
	GraphVector *vector = SERVANT_TO_GRAPH_VECTOR (servant);
243

244 245
	g_return_if_fail (GRAPH_VECTOR (vector) != NULL);
	g_return_if_fail (vector->type == VECTOR_STRING);
246

247 248
	*name = CORBA_string_dup (vector->name);
	*values = graph_vector_seq_string (vector);
249 250 251 252 253 254 255 256 257 258
}

/******************************************************************************/

static void
impl_vector_scalar_changed (PortableServer_Servant servant,
			    const CORBA_short start,
			    const GNOME_Gnumeric_SeqScalar *vals,
			    CORBA_Environment *ev)
{
259
	GraphVector *vector = SERVANT_TO_GRAPH_VECTOR (servant);
260

261 262
	g_return_if_fail (GRAPH_VECTOR (vector) != NULL);
	g_return_if_fail (vector->type == VECTOR_STRING);
263

264
	g_warning ("Gnumeric : scalar vector changed remotely (%p)", vector);
265 266 267 268 269 270 271 272
}

static void
impl_vector_date_changed (PortableServer_Servant servant,
			  const CORBA_short start,
			  const GNOME_Gnumeric_SeqDate *vals,
			  CORBA_Environment *ev)
{
273
	GraphVector *vector = SERVANT_TO_GRAPH_VECTOR (servant);
274

275 276
	g_return_if_fail (GRAPH_VECTOR (vector) != NULL);
	g_return_if_fail (vector->type == VECTOR_DATE);
277

278
	g_warning ("Gnumeric : date vector changed remotely (%p)", vector);
279 280 281 282 283 284 285 286
}

static void
impl_vector_string_changed (PortableServer_Servant servant,
			    const CORBA_short start,
			    const GNOME_Gnumeric_SeqString *vals,
			    CORBA_Environment *ev)
{
287
	GraphVector *vector = SERVANT_TO_GRAPH_VECTOR (servant);
288

289 290
	g_return_if_fail (GRAPH_VECTOR (vector) != NULL);
	g_return_if_fail (vector->type == VECTOR_STRING);
291

292
	g_warning ("Gnumeric : string vector changed remotely (%p)", vector);
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
}

/******************************************************************************/

static POA_GNOME_Gnumeric_VectorScalar__vepv vector_scalar_vepv;
static POA_GNOME_Gnumeric_VectorDate__vepv vector_date_vepv;
static POA_GNOME_Gnumeric_VectorString__vepv vector_string_vepv;

static void
corba_implementation_classes_init (void)
{
	static POA_GNOME_Gnumeric_VectorScalarNotify__epv
		vector_scalar_notify_epv;
	static POA_GNOME_Gnumeric_VectorScalar__epv
		vector_scalar_epv;
	static POA_GNOME_Gnumeric_VectorDateNotify__epv
		vector_date_notify_epv;
	static POA_GNOME_Gnumeric_VectorDate__epv
		vector_date_epv;
	static POA_GNOME_Gnumeric_VectorStringNotify__epv
		vector_string_notify_epv;
	static POA_GNOME_Gnumeric_VectorString__epv
		vector_string_epv;

317
	vector_scalar_notify_epv.valueChanged = &impl_vector_scalar_changed;
318 319 320 321 322 323
	vector_scalar_epv.value = & impl_vector_scalar_value;
	vector_scalar_vepv.GNOME_Gnumeric_VectorScalarNotify_epv =
		&vector_scalar_notify_epv;
	vector_scalar_vepv.GNOME_Gnumeric_VectorScalar_epv =
		&vector_scalar_epv;

324
	vector_date_notify_epv.valueChanged = & impl_vector_date_changed;
325 326 327 328 329 330
	vector_date_epv.value = & impl_vector_date_value;
	vector_date_vepv.GNOME_Gnumeric_VectorDateNotify_epv =
		&vector_date_notify_epv;
	vector_date_vepv.GNOME_Gnumeric_VectorDate_epv =
		&vector_date_epv;

331
	vector_string_notify_epv.valueChanged = & impl_vector_string_changed;
332 333 334 335 336 337 338 339
	vector_string_epv.value = & impl_vector_string_value;
	vector_string_vepv.GNOME_Gnumeric_VectorStringNotify_epv =
		&vector_string_notify_epv;
	vector_string_vepv.GNOME_Gnumeric_VectorString_epv =
		&vector_string_epv;
}

static void
340
graph_vector_destroy (GtkObject *object)
341
{
342
	GraphVector *vector = GRAPH_VECTOR(object);
Jody Goldberg's avatar
Jody Goldberg committed
343

344 345 346 347 348
	printf ("Destroying vector %p\n", object);
	dependent_unlink (&vector->dep, NULL);
	if (vector->dep.expression != NULL) {
		expr_tree_unref (vector->dep.expression);
		vector->dep.expression = NULL;
Jody Goldberg's avatar
Jody Goldberg committed
349
	}
350 351 352
	if (vector->name != NULL) {
		g_free (vector->name);
		vector->name = NULL;
353
	}
354 355 356
}

static void
357
graph_vector_class_init (GtkObjectClass *object_class)
358
{
359
	static GtkObjectClass *graph_vector_parent_class = NULL;
360

361
	graph_vector_parent_class = gtk_type_class (gtk_object_get_type ());
362

363
	object_class->destroy = & graph_vector_destroy;
364 365 366 367
	corba_implementation_classes_init ();
}

static void
368
graph_vector_init (GtkObject *object)
369
{
370
	GraphVector *vector = GRAPH_VECTOR (object);
371

372 373 374 375 376
	/* vector->type; */
	vector->vector_ref = CORBA_OBJECT_NIL;
	vector->subscriber.scalar = CORBA_OBJECT_NIL;
	vector->subscriber.date = CORBA_OBJECT_NIL;
	vector->subscriber.string = CORBA_OBJECT_NIL;
377 378
}

379 380
static GNUMERIC_MAKE_TYPE (graph_vector,"GraphVector",GraphVector,
			   &graph_vector_class_init, &graph_vector_init,
381 382 383 384
			   gtk_object_get_type ())


static void
385
graph_vector_set_expr (Dependent *dep, ExprTree *expr)
386
{
387 388 389 390 391 392 393 394 395 396 397 398
	ParsePos pos;
	char * new_str;

	pos.sheet = dep->sheet;
	pos.eval.col = pos.eval.row = 0;
	new_str = expr_tree_as_string (expr, &pos);
	printf("new = %s\n", new_str);
	g_free (new_str);
	new_str = expr_tree_as_string (dep->expression, &pos);
	printf("old = %s\n", new_str);
	g_free (new_str);

399
	expr_tree_ref (expr);
400
	dependent_unlink (dep, NULL);
401 402
	expr_tree_unref (dep->expression);
	dep->expression = expr;
403
	dependent_changed (dep, NULL, TRUE);
404 405 406
}

static void
407
graph_vector_debug_name (Dependent const *dep, FILE *out)
408
{
409
	fprintf (out, "GraphVector%p", dep);
410 411 412
}

static guint
Morten Welinder's avatar
Morten Welinder committed
413
graph_vector_get_dep_type (void)
414 415 416 417
{
	static guint32 type = 0;
	if (type == 0) {
		static DependentClass klass;
418 419 420
		klass.eval = &graph_vector_eval;
		klass.set_expr = &graph_vector_set_expr;
		klass.debug_name = &graph_vector_debug_name;
421 422 423 424 425
		type = dependent_type_register (&klass);
	}
	return type;
}

426 427 428 429 430 431 432 433 434 435 436 437 438

/* TODO:
 * Do we need to evaluate this as an expression ?
 */
static Value *
cb_check_range_for_pure_string (Sheet *sheet, int col, int row,
				Cell *cell, void *user_data)
{
	if (cell == NULL || cell->value->type != VALUE_STRING)
		return value_terminate ();
	return NULL;
}

439 440
GraphVector *
graph_vector_new (Sheet *sheet, Range const *r, char *name)
441 442 443
{
	CORBA_Environment ev;
	PortableServer_Servant serv = CORBA_OBJECT_NIL;
444 445
	GraphVector *vector;
	GraphVectorType type;
446

447
	vector = gtk_type_new (graph_vector_get_type ());
448

449
	if (sheet_foreach_cell_in_range (sheet, FALSE,
450 451 452 453
				      r->start.col, r->start.row,
				      r->end.col, r->end.row,
				      &cb_check_range_for_pure_string,
				      NULL))
454
		type = VECTOR_SCALAR;
455
	else
456
		type = VECTOR_STRING;
457

458 459 460 461 462
	printf ("vector::new (%d) = 0x%p\n", type, vector);
	vector->type = type;
	vector->is_column = (r->start.col == r->end.col);
	vector->range = *r;
	vector->name = name;
463

464 465 466
	vector->dep.sheet = sheet;
	vector->dep.flags = graph_vector_get_dep_type ();
	vector->dep.expression = expr_tree_new_constant (
467
		value_new_cellrange_r (sheet, r));
468
	dependent_link (&vector->dep, NULL, FALSE);
469 470 471

	CORBA_exception_init (&ev);
	switch (type) {
472 473 474
	case VECTOR_SCALAR :
		serv = &vector->servant.scalar;
		vector->servant.scalar.vepv = &vector_scalar_vepv;
475 476 477
		POA_GNOME_Gnumeric_VectorScalar__init (serv, &ev);
		break;

478 479 480
	case VECTOR_DATE :
		serv = &vector->servant.date;
		vector->servant.date.vepv = &vector_date_vepv;
481 482 483
		POA_GNOME_Gnumeric_VectorDate__init (serv, &ev);
		break;

484 485 486
	case VECTOR_STRING :
		serv = &vector->servant.string;
		vector->servant.string.vepv = &vector_string_vepv;
487 488 489 490 491 492 493 494 495 496 497 498 499
		POA_GNOME_Gnumeric_VectorString__init (serv, &ev);
		break;

	default :
		g_assert_not_reached ();
	};

	if (ev._major == CORBA_NO_EXCEPTION) {
		PortableServer_POA poa = bonobo_poa ();
		PortableServer_ObjectId *oid;

		oid = PortableServer_POA_activate_object (poa, serv, &ev);
		CORBA_free (oid);
500
		vector->vector_ref = PortableServer_POA_servant_to_reference (poa, serv, &ev);
501 502 503
	}
	CORBA_exception_free (&ev);

504
	return vector;
505 506 507
}

void
508
graph_vector_set_subscriber (GraphVector *vector, CORBA_Object graph_manager)
509
{
510 511 512
	CORBA_Environment ev;
	GNOME_Gnumeric_Graph_Manager manager = graph_manager;

513
	g_return_if_fail (vector->subscriber.scalar == CORBA_OBJECT_NIL);
514 515 516

	CORBA_exception_init (&ev);

517 518 519
	switch (vector->type) {
	case VECTOR_SCALAR :
		vector->subscriber.scalar =
520
			GNOME_Gnumeric_Graph_Manager_addVectorScalar (manager,
521
				vector->vector_ref, &ev);
522 523
		break;

524 525
	case VECTOR_DATE :
		vector->subscriber.date =
526
			GNOME_Gnumeric_Graph_Manager_addVectorDate (manager,
527
				vector->vector_ref, &ev);
528 529
		break;

530 531
	case VECTOR_STRING :
		vector->subscriber.string =
532
			GNOME_Gnumeric_Graph_Manager_addVectorString (manager,
533
				vector->vector_ref, &ev);
534 535 536 537
		break;
	default :
		g_assert_not_reached();
	}
Jody Goldberg's avatar
Jody Goldberg committed
538

539
	if (ev._major != CORBA_NO_EXCEPTION)
540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571
		g_warning ("Problems registering vector %p", vector);

	CORBA_exception_free (&ev);
}

void
graph_vector_unsubscribe (GraphVector *vector)
{
	CORBA_Environment ev;

	g_return_if_fail (vector->subscriber.scalar != CORBA_OBJECT_NIL);

	CORBA_exception_init (&ev);

	switch (vector->type) {
	case VECTOR_SCALAR :
		GNOME_Gnumeric_VectorScalar_remove (vector->subscriber.scalar, &ev);
		break;

	case VECTOR_DATE :
		GNOME_Gnumeric_VectorDate_remove (vector->subscriber.date, &ev);
		break;

	case VECTOR_STRING :
		GNOME_Gnumeric_VectorString_remove (vector->subscriber.string, &ev);
		break;
	default :
		g_assert_not_reached();
	}

	if (ev._major != CORBA_NO_EXCEPTION)
		g_warning ("Problems unregistering vector %p", vector);
Jody Goldberg's avatar
Jody Goldberg committed
572

573
	CORBA_exception_free (&ev);
574
}