1 /*-- ggobi-API.c --*/
2 /*
3 * ggobi
4 * Copyright (C) AT&T, Duncan Temple Lang, Dianne Cook 1999-2005
5 *
6 * ggobi is free software; you may use, redistribute, and/or modify it
7 * under the terms of the Eclipse Public License, which is distributed
8 * with the source code and displayed on the ggobi web site,
9 * www.ggobi.org. For more information, contact the authors:
10 *
11 * Deborah F. Swayne dfs@research.att.com
12 * Di Cook dicook@iastate.edu
13 * Duncan Temple Lang duncan@wald.ucdavis.edu
14 * Andreas Buja andreas.buja@wharton.upenn.edu
15 */
16
17 #include <math.h>
18 #include <string.h>
19 #include <stdlib.h>
20 #include <gtk/gtk.h>
21
22 #include "GGobiAPI.h"
23
24 #include "ggobi.h"
25 #include "ggobi-data.h"
26 #include "types.h"
27 #include "vars.h"
28 #include "externs.h"
29 #include "display.h"
30 #include "plugin.h"
31
32 extern const gchar *const GlyphNames[];
33
34 void warning (const char *msg);
35
36 #ifdef __cplusplus
37 extern "C"
38 {
39 #endif
40 void GGOBI (displays_release) (ggobid * gg);
41 void GGOBI (display_release) (displayd * display, ggobid * gg);
42 void GGOBI (splot_release) (splotd * sp, displayd * display, ggobid * gg);
43 void GGOBI (data_release) (GGobiData *, ggobid * gg);
44 void GGOBI (vartable_free) (GGobiData *, ggobid * gg);
45 void GGOBI (vardatum_free) (vartabled * var, ggobid * gg);
46 #ifdef __cplusplus
47 }
48 #endif
49
GGOBI(getFileName)50 const gchar *GGOBI (getFileName) (ggobid * gg)
51 {
52 return (gg->input->fileName);
53 }
54
GGOBI(setFileName)55 const gchar *GGOBI (setFileName) (const gchar * fileName, DataMode data_mode,
56 ggobid * gg)
57 {
58 const gchar *old = g_strdup (GGOBI (getFileName) (gg));
59 fileset_read_init (fileName, NULL, NULL, gg);
60 display_menu_build (gg);
61 return (old);
62 }
63
64
GGOBI(getDataMode)65 DataMode GGOBI (getDataMode) (ggobid * gg)
66 {
67 return (gg->input->mode);
68 }
69
GGOBI(setDataMode)70 DataMode GGOBI (setDataMode) (DataMode newMode, ggobid * gg)
71 {
72 DataMode old = gg->input->mode;
73 sessionOptions->data_mode = newMode;
74 gg->input->mode = newMode;
75 return (old);
76 }
77
78 /**
79 Caller should now free the return value, but not the elements of the
80 array.
81 This is computed dynamically by querying each of the input plugins
82 for its collection of mode names.
83 */
GGOBI(getDataModeNames)84 const gchar **GGOBI (getDataModeNames) (int *n)
85 {
86 int ctr = 0, num, k, i;
87 GList *plugins;
88 const gchar **ans;
89 GGobiPluginInfo *plugin;
90
91 plugins = sessionOptions->info->inputPlugins;
92 num = g_list_length (plugins);
93 for (i = 0; i < num; i++) {
94 plugin = g_list_nth_data (plugins, i);
95 ctr += plugin->info.i->numModeNames;
96 }
97
98 ans = (const gchar **) g_malloc (sizeof (gchar *) * ctr);
99 ctr = 0;
100 for (i = 0; i < num; i++) {
101 plugin = g_list_nth_data (plugins, i);
102 for (k = 0; k < plugin->info.i->numModeNames; k++) {
103 ans[ctr++] = plugin->info.i->modeNames[k];
104 }
105 }
106
107 if (n)
108 *n = ctr;
109
110 return (ans);
111 }
112
113
GGOBI(getVariableNames)114 gchar **GGOBI (getVariableNames) (gint transformed, GGobiData * d,
115 ggobid * gg)
116 {
117 gchar **names;
118 gint nc = d->ncols, j;
119
120 names = (gchar **) g_malloc (sizeof (gchar *) * nc);
121
122 for (j = 0; j < nc; j++) {
123 names[j] = transformed ? ggobi_data_get_transformed_col_name(d, j) : ggobi_data_get_col_name(d, j);
124 }
125
126 return (names);
127 }
128
129
130 void
GGOBI(setVariableName)131 GGOBI (setVariableName) (gint j, gchar * name, gboolean transformed,
132 GGobiData * d, ggobid * gg)
133 {
134
135 if (transformed)
136 ggobi_data_set_transformed_col_name(d, j, name);
137 else
138 ggobi_data_set_col_name(d, j, name);
139
140 }
141
142
143 /*
144 Closes the specified display
145 */
GGOBI(destroyCurrentDisplay)146 void GGOBI (destroyCurrentDisplay) (ggobid * gg)
147 {
148 display_free (gg->current_display, false, gg);
149 }
150
151
152 MissingValue_p GGobiMissingValue;
153
154 MissingValue_p
GGobi_setMissingValueIdentifier(MissingValue_p f)155 GGobi_setMissingValueIdentifier (MissingValue_p f)
156 {
157 MissingValue_p old = GGobiMissingValue;
158 GGobiMissingValue = f;
159 return (old);
160 }
161
162
163 static const gchar *const DefaultRowNames = NULL;
164
165 const gchar *const *
getDefaultRowNamesPtr()166 getDefaultRowNamesPtr ()
167 {
168 return ((const gchar * const *) &DefaultRowNames);
169 }
170
171 void
setRowNames(GGobiData * d,gchar ** rownames)172 setRowNames (GGobiData * d, gchar ** rownames)
173 {
174 int i;
175 gchar *lbl;
176 for (i = 0; i < d->nrows; i++) {
177 lbl = (rownames != (gchar **) & DefaultRowNames
178 && rownames != (gchar **) NULL
179 && rownames[i] !=
180 (gchar *) NULL) ? g_strdup (rownames[i]) : g_strdup_printf ("%d",
181 i + 1);
182 g_array_append_val (d->rowlab, lbl);
183 }
184 }
185
186 /*
187 An initial attempt to allow new data to be introduced
188 to the Ggobi session, replacing the existing contents.
189
190 There are still a few details remaining regarding the scaling
191 on the axes, etc. (See ruler_ranges_set in scatterplot.c)
192 The reverse pipeline data has not been established correctly
193 and the computation is incorrect.
194 Specifically, the routine splot_screen_to_tform() is not
195
196
197 When this works, we will take the calls for the different stages
198 and put them in separate routines.
199 */
200 /*-- need two of these now, one to replace and one to append --*/
201 void
GGOBI(setData)202 GGOBI (setData) (gdouble * values, gchar ** rownames, gchar ** colnames,
203 gint nr, gint nc, GGobiData * d, gboolean cleanup,
204 ggobid * gg, gchar ** ids, gboolean duplicate,
205 InputDescription * desc)
206 {
207 gint i, j;
208 gchar *lbl;
209 gchar *varname;
210
211 if (cleanup) {
212 /* Release all the displays associated with this datad
213 and then release all the GUI components and memory
214 for this datad.
215
216 This may need some reworking in order to release
217 exactly the right things, no more and no less.
218 */
219 GGOBI (displays_release) (gg);
220 varpanel_clear (d, gg);
221 GGOBI (data_release) (d, gg);
222 /* ?? */
223 gtk_ui_manager_remove_ui (gg->main_menu_manager, gg->mode_merge_id);
224 /*submenu_destroy (gg->pmode_item);
225 submenu_destroy (gg->imode_item); */
226 }
227
228 d->input = desc;
229 if (d->name == NULL)
230 d->name = g_strdup (desc->fileName);
231 if (gg->input == NULL)
232 gg->input = desc;
233
234 d->ncols = nc;
235 d->nrows = nr;
236
237 vectori_init_null (&d->rows_in_plot);
238 d->nrows_in_plot = d->nrows; /*-- for now --*/
239
240 arrayf_alloc (&d->raw, nr, nc);
241
242 if (ids) {
243 datad_record_ids_set (d, ids, duplicate);
244 }
245
246 rowlabels_alloc (d);
247
248 vartable_alloc (d);
249 vartable_init (d);
250
251 br_glyph_ids_alloc (d);
252 br_glyph_ids_init (d);
253
254 br_color_ids_alloc (d);
255 br_color_ids_init (d);
256
257 br_hidden_alloc (d);
258 br_hidden_init (d);
259
260 if (values && d->vartable) {
261 /* the person who created the datad is taking care of populating it. */
262 for (j = 0; j < nc; j++) {
263 varname = (colnames != NULL && colnames[j] != NULL) ? colnames[j] : NULL;
264 ggobi_data_set_col_name(d, j, varname);
265
266 for (i = 0; i < nr; i++) {
267 if (j == 0) {
268 lbl = (rownames != NULL && rownames[i] != NULL) ?
269 g_strdup (rownames[i]) : g_strdup_printf ("%d", i + 1);
270 g_array_append_val (d->rowlab, lbl);
271 /* g_free (lbl); */
272 }
273
274 if (values)
275 ggobi_data_set_raw_value(d, i, j, values[i + j * nr]);
276 }
277 }
278 }
279
280 if (rownames && d->rowlab->len == 0)
281 setRowNames (d, rownames);
282
283
284 /* Now recompute and display the top plot. */
285 if (nc > 0 && datad_init (d, gg, cleanup) != NULL) {
286 /* Have to patch up the displays list since we removed
287 every entry and that makes for meaningless entries.
288
289 IS THIS TRUE? Only if cleanup was specified!
290 This looks very dangerous. Should use g_list_remove();
291 */
292 gg->displays->next = NULL;
293 }
294 display_menu_build (gg);
295 }
296
297
298 /* These are all for freeing the currently held data. */
GGOBI(displays_release)299 void GGOBI (displays_release) (ggobid * gg)
300 {
301 GList *dlist;
302 displayd *display;
303
304 /* We have to be careful here as we are removing all the elements
305 of the singly-linked list. When we remove the last one,
306 the ->next value of the dlist becomes non-NULL. Hence
307 we are getting garbage. Accordingly, we count down from the total
308 number to remove using num and when this is 0, we exit.
309 This should leave the slist allocated, but empty.
310
311 We have to patch the list up afterwards.
312 */
313 gint num = g_list_length (gg->displays);
314
315 for (dlist = gg->displays; dlist != NULL; dlist = dlist->next, num--) {
316 if (num == 0)
317 break;
318 display = (displayd *) dlist->data;
319 /* display_release(display, gg); */
320 display_free (display, true, gg);
321 }
322 }
323
GGOBI(display_release)324 void GGOBI (display_release) (displayd * display, ggobid * gg)
325 {
326 display_free (display, true, gg);
327 }
328
329
GGOBI(splot_release)330 void GGOBI (splot_release) (splotd * sp, displayd * display, ggobid * gg)
331 {
332 splot_free (sp, display, gg);
333 }
334
335 /* Not in the API for the moment. A "protected" routine. */
GGOBI(data_release)336 void GGOBI (data_release) (GGobiData * d, ggobid * gg)
337 {
338 void vartable_free (GGobiData * d);
339
340 if (d == NULL)
341 return;
342 if (d->rowlab) {
343 rowlabels_free (d);
344 d->rowlab = NULL;
345 }
346
347 vartable_free (d);
348 }
349
350
351 /**XX*/
GGOBI(getViewTypes)352 const gchar *const *GGOBI (getViewTypes) (int *n)
353 {
354 *n = NDISPLAYTYPES;
355 return (ViewTypes);
356 }
357
GGOBI(getViewTypeIndices)358 const gint *GGOBI (getViewTypeIndices) (gint * n)
359 {
360 extern const gint ViewTypeIndices[];
361 *n = NDISPLAYTYPES;
362 return (ViewTypeIndices);
363 }
364
365
GGOBI(newScatterplot)366 displayd *GGOBI (newScatterplot) (gint ix, gint iy, gboolean use_window,
367 GGobiData * d, ggobid * gg)
368 {
369 displayd *display = NULL;
370 gint vars[2];
371
372 vars[0] = ix;
373 vars[1] = iy;
374 display = scatterplot_new_with_vars (use_window, false, 2, vars, d, gg);
375 #ifdef FORCE_ADD_DISPLAY
376 display_add (display, gg);
377 #endif
378
379
380 return (display);
381 }
382
GGOBI(newScatmat)383 displayd *GGOBI (newScatmat) (gint * rows, gint * columns, gint nr, gint nc,
384 gboolean use_window, GGobiData * d, ggobid * gg)
385 {
386 displayd *display;
387
388 display = scatmat_new (NULL, use_window, false, nr, rows, nc, columns, d, gg);
389 #ifdef FORCE_ADD_DISPLAY
390 display_add (display, gg); /*XX the caller should add this display. */
391 #endif
392
393 return (display);
394 }
395
GGOBI(newParCoords)396 displayd *GGOBI (newParCoords) (gint * vars, gint numVars, gboolean use_window,
397 GGobiData * d, ggobid * gg)
398 {
399 displayd *display = NULL;
400
401 display = parcoords_new (display, use_window, false, numVars, vars, d, gg);
402 #ifdef FORCE_ADD_DISPLAY
403 display_add (display, gg); /*XX the caller should add this display. */
404 #endif
405
406
407 return (display);
408 }
409
GGOBI(newTimeSeries)410 displayd *GGOBI (newTimeSeries) (gint * yvars, gint numVars, gboolean use_window,
411 GGobiData * d, ggobid * gg)
412 {
413 displayd *display = NULL;
414
415 display = tsplot_new (display, use_window, false, numVars, yvars, d, gg);
416 #ifdef FORCE_ADD_DISPLAY
417 display_add (display, gg); /*XX the caller should add this display. */
418 #endif
419
420 return (display);
421 }
422
GGOBI(createPlot)423 displayd *GGOBI (createPlot) (int type, char **varnames)
424 {
425 displayd *display = NULL;
426 /*
427 display_new(type);
428 */
429 return (display);
430 }
431
432
GGOBI(getCurrentDisplayType)433 const gchar *GGOBI (getCurrentDisplayType) (ggobid * gg)
434 {
435 /*XX */
436 return (GGOBI (getViewTypeName) (gg->current_display));
437 }
438
GGOBI(getViewTypeName)439 const gchar *GGOBI (getViewTypeName) (displayd * dpy)
440 {
441 gchar *val;
442
443 if (!GGOBI_IS_EXTENDED_DISPLAY (dpy))
444 return (NULL);
445
446 /*
447 or use gtk_type_name(GTK_OBJECT_TYPE(dpy))
448 */
449 val = GGOBI_EXTENDED_DISPLAY_GET_CLASS (dpy)->treeLabel;
450
451 return (val);
452 }
453
454
455 /*
456 Pointer to the raw data managed by GGobi.
457 Don't touch this.
458 */
GGOBI(getRawData)459 const gfloat **GGOBI (getRawData) (GGobiData * d, ggobid * gg)
460 {
461 return ((const gfloat **) d->raw.vals);
462 }
463
464 /*
465 Pointer to the second transformation of the data managed by GGobi.
466 Don't touch this.
467 */
GGOBI(getTFormData)468 const gfloat **GGOBI (getTFormData) (GGobiData * d, ggobid * gg)
469 {
470 return ((const gfloat **) d->tform.vals);
471 }
472
473
474 /*
475 Returns a reference to the labels used to identify
476 the observations.
477 Do not change this as it is not a copy.
478 */
GGOBI(getCaseNames)479 const gchar **GGOBI (getCaseNames) (GGobiData * d, ggobid * gg)
480 {
481 gchar **rowlab = (gchar **) g_malloc (sizeof (gchar *) * d->nrows);
482 gint i;
483 for (i = 0; i < d->nrows; i++)
484 rowlab[i] = (gchar *) g_array_index (d->rowlab, gchar *, i);
485
486 return ((const gchar **) rowlab);
487 }
488
489 /*
490 This does not copy the label, so it is assumed
491 that the caller has already allocated the space
492 using the appropriate GTK memory model.
493 If it is apparent that this is being called from
494 contexts that use a very different memory model (e.g. S/R),
495 we can change the behaviour to copy this.
496
497 Similarly, this can be modified to return the previous
498 value, but the caller will have to free that pointer.
499 */
500 void
GGOBI(setCaseName)501 GGOBI (setCaseName) (gint index, const gchar * label, GGobiData * d,
502 ggobid * gg)
503 {
504 gchar *old;
505 if (index < 0 || index >= d->nrows) {
506 warning ("Index is out of range of observations in setCaseName");
507 return;
508 }
509
510 old = g_array_index (d->rowlab, gchar *, index);
511 g_free (old);
512
513 g_array_insert_val (d->rowlab, index, label);
514 }
515
516
517 void
warning(const gchar * msg)518 warning (const gchar * msg)
519 {
520 fprintf (stderr, "%s\n", msg);
521 fflush (stderr);
522 }
523
524
525 /*-------------------------------------------------------------------------*/
526 /* setting and getting point glyph types and sizes */
527 /*-------------------------------------------------------------------------*/
528
GGOBI(getGlyphTypes)529 gint *GGOBI (getGlyphTypes) (int *n)
530 {
531 static gint *glyphIds = NULL;
532 *n = UNKNOWN_GLYPH - 1; /* -1 since we start at 1 */
533
534 if (glyphIds == NULL) {
535 gint i;
536 glyphIds = (gint *) g_malloc (*n * sizeof (gint));
537 for (i = 0; i < *n; i++) {
538 glyphIds[i] = mapGlyphName (GlyphNames[i]);
539 }
540 }
541
542 return (glyphIds);
543 }
544
GGOBI(getGlyphTypeNames)545 const gchar *const *GGOBI (getGlyphTypeNames) (gint * n)
546 {
547 *n = UNKNOWN_GLYPH - 1; /* -1 since we start at 1; starting at 0 now */
548 return ((const gchar * const *) GlyphNames);
549 }
550
551
GGOBI(getGlyphTypeName)552 gchar const *GGOBI (getGlyphTypeName) (gint type)
553 {
554 gchar const *ans;
555 ans = GlyphNames[type];
556
557 return (ans);
558 }
559
560
GGOBI(getCaseGlyphTypes)561 gint *GGOBI (getCaseGlyphTypes) (gint * ids, gint n, GGobiData * d,
562 ggobid * gg)
563 {
564 gint i;
565 gint *ans = (gint *) g_malloc (n * sizeof (gint));
566
567 for (i = 0; i < n; i++)
568 ans[i] = GGOBI (getCaseGlyphType) (ids[i], d, gg);
569
570 return (ids);
571 }
572
GGOBI(getCaseGlyphType)573 gint GGOBI (getCaseGlyphType) (gint id, GGobiData * d, ggobid * gg)
574 {
575 gint index = d->rows_in_plot.els[id];
576 return (d->glyph_now.els[index].type);
577 }
578
GGOBI(getCaseGlyphSizes)579 gint *GGOBI (getCaseGlyphSizes) (gint * ids, gint n, GGobiData * d,
580 ggobid * gg)
581 {
582 gint i;
583 gint *ans = (gint *) g_malloc (n * sizeof (gint));
584
585 for (i = 0; i < n; i++)
586 ans[i] = GGOBI (getCaseGlyphSize) (ids[i], d, gg);
587
588 return (ids);
589 }
590
GGOBI(getCaseGlyphSize)591 gint GGOBI (getCaseGlyphSize) (gint id, GGobiData * d, ggobid * gg)
592 {
593 gint index = d->rows_in_plot.els[id];
594
595 return (d->glyph_now.els[index].size);
596 }
597
598 void
GGOBI(setCaseGlyph)599 GGOBI (setCaseGlyph) (gint index, gint type, gint size, GGobiData * d,
600 ggobid * gg)
601 {
602 if (type > -1) {
603 if (type >= NGLYPHTYPES)
604 g_printerr ("Illegal glyph type: %d\n", type);
605 else
606 d->glyph.els[index].type = d->glyph_now.els[index].type = type;
607 }
608
609 if (size > -1) {
610 if (size >= NGLYPHSIZES)
611 g_printerr ("Illegal glyph size: %d\n", size);
612 else
613 d->glyph.els[index].size = d->glyph_now.els[index].size = size;
614 }
615 }
616
617 void
GGOBI(setCaseGlyphs)618 GGOBI (setCaseGlyphs) (gint * ids, gint n, gint type, gint size,
619 GGobiData * d, ggobid * gg)
620 {
621 gint i, doit = 1;
622 /*
623 * Make sure glyphs are legal before assigning. (It's safe to
624 * ignore values of -1, because those are likely to be deliberately
625 * set by the calling routine as an indication to do nothing.)
626 * Do the check here to avoid generating large numbers of
627 * error messages.
628 */
629 if (type >= NGLYPHTYPES) {
630 g_printerr ("Illegal glyph type: %d\n", type);
631 doit = 0;
632 }
633 if (size >= NGLYPHSIZES) {
634 g_printerr ("Illegal glyph size: %d\n", size);
635 doit = 0;
636 }
637
638 if (doit)
639 for (i = 0; i < n; i++)
640 GGOBI (setCaseGlyph) (ids[i], type, size, d, gg);
641 }
642
643 /*-------------------------------------------------------------------------*/
644 /* setting and getting point colors */
645 /*-------------------------------------------------------------------------*/
646
647 void
GGOBI(setCaseColor)648 GGOBI (setCaseColor) (gint pt, gint colorIndex, GGobiData * d, ggobid * gg)
649 {
650 colorschemed *scheme = gg->activeColorScheme;
651
652 /*-- temporary fix --*/
653 if (colorIndex < 0 || colorIndex > scheme->n - 1)
654 colorIndex = 0;
655 d->color.els[pt] = d->color_now.els[pt] = colorIndex;
656 }
657
658 void
GGOBI(setCaseColors)659 GGOBI (setCaseColors) (gint * pts, gint howMany, gint colorIndex,
660 GGobiData * d, ggobid * gg)
661 {
662 gint i;
663 for (i = 0; i < howMany; i++)
664 d->color.els[pts[i]] = d->color_now.els[pts[i]] = colorIndex;
665 }
666
667
GGOBI(getCaseColor)668 gint GGOBI (getCaseColor) (gint pt, GGobiData * d, ggobid * gg)
669 {
670 return (d->color_now.els[pt]);
671 }
672
GGOBI(getCaseColors)673 gint *GGOBI (getCaseColors) (gint * pts, gint howMany, GGobiData * d,
674 ggobid * gg)
675 {
676 gint i;
677 gint *ans = (gint *) g_malloc (howMany * sizeof (gint));
678
679 for (i = 0; i < howMany; i++)
680 ans[i] = GGOBI (getCaseColor) (pts[i], d, gg);
681
682 return (ans);
683 }
684
685 /*-------------------------------------------------------------------------*/
686 /* setting and getting the point hidden state */
687 /*-------------------------------------------------------------------------*/
688
689 void
GGOBI(setCaseHidden)690 GGOBI (setCaseHidden) (gint pt, gboolean hidden_p, GGobiData * d, ggobid * gg)
691 {
692 d->hidden.els[pt] = d->hidden_now.els[pt] = hidden_p;
693 /*-- don't replot --*/
694 }
695
696 void
GGOBI(setCaseHiddens)697 GGOBI (setCaseHiddens) (gint * pts, gint howMany, gboolean hidden_p,
698 GGobiData * d, ggobid * gg)
699 {
700 gint i;
701 for (i = 0; i < howMany; i++)
702 GGOBI (setCaseHidden) (pts[i], hidden_p, d, gg);
703 displays_plot (NULL, FULL, gg);
704 }
705
GGOBI(getCaseHidden)706 gboolean GGOBI (getCaseHidden) (gint pt, GGobiData * d, ggobid * gg)
707 {
708 return (d->hidden_now.els[pt]);
709 }
710
GGOBI(getCaseHiddens)711 gboolean *GGOBI (getCaseHiddens) (gint * pts, gint howMany, GGobiData * d,
712 ggobid * gg)
713 {
714 gint i;
715 gboolean *ans = (gboolean *) g_malloc (howMany * sizeof (gboolean));
716
717 for (i = 0; i < howMany; i++)
718 ans[i] = GGOBI (getCaseHidden) (pts[i], d, gg);
719
720 return (ans);
721 }
722
723 /*-------------------------------------------------------------------------*/
724 /* setting and getting edges */
725 /*-------------------------------------------------------------------------*/
726
GGOBI(getShowLines)727 gboolean GGOBI (getShowLines) ()
728 {
729 return (GGOBI (getDefaultDisplayOptions) ()->edges_undirected_show_p);
730 }
731
732 /* uh.. this takes a boolean value but always shows lines... what's up */
GGOBI(setShowLines)733 gboolean GGOBI (setShowLines) (displayd * dsp, gboolean val)
734 {
735 GtkAction *action;
736 gboolean old = GGOBI (getShowLines) ();
737 /*GGOBI(getDefaultDisplayOptions)()->edges_undirected_show_p = val; */
738 dsp->options.edges_undirected_show_p = true;
739
740 action = gtk_ui_manager_get_action (dsp->menu_manager,
741 "/menubar/Edges/ShowUndirectedEdges");
742 if (action)
743 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), true);
744
745 return (old);
746 }
747
748 /* setShowAxes will require this code:
749
750 {
751 GtkWidget *topmenu, *menu, *item;
752 topmenu = widget_find_by_name (dspnew->menubar, "DISPLAY:options_topmenu");
753 if (topmenu) {
754 menu = GTK_MENU_ITEM(topmenu)->submenu;
755 if (menu) {
756 item = widget_find_by_name (menu, "DISPLAY:show_axes");
757 if (item) {
758 gtk_check_menu_item_set_active ((GtkCheckMenuItem *) item, false);
759 }
760 }
761 }
762 }
763
764
765 */
766
GGOBI(getDefaultDisplayOptions)767 DisplayOptions *GGOBI (getDefaultDisplayOptions) ()
768 {
769 return (&DefaultDisplayOptions);
770 }
771
772
GGOBI(getDisplay)773 displayd *GGOBI (getDisplay) (gint which, ggobid * gg)
774 {
775 displayd *display = NULL;
776
777 if (which < g_list_length (gg->displays))
778 display = (displayd *) g_list_nth_data (gg->displays, which);
779
780 return (display);
781 }
782
GGOBI(getDisplayOptions)783 DisplayOptions *GGOBI (getDisplayOptions) (int displayNum, ggobid * gg)
784 {
785 DisplayOptions *options = NULL;
786 if (displayNum < 0)
787 options = GGOBI (getDefaultDisplayOptions) ();
788 else {
789 displayd *display;
790 display = GGOBI (getDisplay) (displayNum, gg);
791 if (display)
792 options = &(display->options);
793 }
794
795 return (options);
796 }
797
798
GGOBI(getCurrentDisplay)799 displayd *GGOBI (getCurrentDisplay) (ggobid * gg)
800 {
801 return (gg->current_display);
802 }
803
GGOBI(getCurrentDisplayIndex)804 gint GGOBI (getCurrentDisplayIndex) (ggobid * gg)
805 {
806 return (g_list_index (gg->displays, gg->current_display));
807 }
808
GGOBI(getCurrentPlotIndex)809 gint GGOBI (getCurrentPlotIndex) (ggobid * gg)
810 {
811 int val = -1;
812 displayd *d;
813 if (gg->current_splot) {
814 d = GGOBI (getCurrentDisplay) (gg);
815 val = g_list_index (d->splots, gg->current_splot);
816 }
817
818 return (val);
819 }
820
GGOBI(setCurrentDisplay)821 displayd *GGOBI (setCurrentDisplay) (int which, ggobid * gg)
822 {
823 displayd *d;
824
825 d = GGOBI (getDisplay) (which, gg);
826
827 if (d != NULL)
828 display_set_current (d, gg);
829
830 return (d);
831 }
832
833
GGOBI(getPlot)834 splotd *GGOBI (getPlot) (displayd * display, int which)
835 {
836 splotd *sp = (splotd *) g_list_nth_data (display->splots, which);
837 return (sp);
838 }
839
840
GGOBI(getNumGGobis)841 gint GGOBI (getNumGGobis) ()
842 {
843 extern gint num_ggobis;
844 return (num_ggobis);
845 }
846
847 /*
848 Whether to destory the window or not. If this is being called from an
849 event handler in response to the window being destroyed, we would get
850 a circularity. However, when called programmatically from within the
851 process (or from e.g. R) we need to force it to be closed.
852 */
GGOBI(close)853 gboolean GGOBI (close) (ggobid * gg, gboolean closeWindow)
854 {
855 gboolean val = true;
856
857 if (gg->close_pending)
858 return (false);
859
860 gg->close_pending = true;
861
862 /* close plugin instances */
863 closePlugins (gg);
864
865 procs_activate (off, gg->pmode, gg->current_display, gg);
866
867 display_free_all (gg);
868
869 if (closeWindow && gg->main_window)
870 gtk_widget_destroy (gg->main_window);
871
872 if (gg->display_tree.window)
873 gtk_widget_destroy (gg->display_tree.window);
874 if (gg->vartable_ui.window)
875 gtk_widget_destroy (gg->vartable_ui.window);
876
877 if (gg->color_ui.symbol_window)
878 gtk_widget_destroy (gg->color_ui.symbol_window);
879
880 if (gg->wvis.window)
881 gtk_widget_destroy (gg->wvis.window);
882 if (gg->svis.window)
883 gtk_widget_destroy (gg->svis.window);
884
885 gg->close_pending = false;
886 /* Now fix up the list of ggobi's */
887 val = ggobi_remove (gg) != -1;
888
889 if (GGobi_getNumGGobis () == 0 && sessionOptions->info->quitWithNoGGobi &&
890 gtk_main_level () > 0) {
891 gtk_main_quit ();
892 }
893
894 return (val);
895 }
896
897 #ifdef EXPLICIT_IDENTIFY_HANDLER
GGOBI(setIdentifyHandler)898 void GGOBI (setIdentifyHandler) (IdentifyProc proc, void *data, ggobid * gg)
899 {
900 gg->identify_handler.handler = proc;
901 gg->identify_handler.user_data = data;
902 }
903 #endif
904
GGOBI(getBrushSize)905 void GGOBI (getBrushSize) (gint * w, gint * h, ggobid * gg)
906 {
907 splotd *sp = gg->current_splot;
908
909 *w = ABS (sp->brush_pos.x1 - sp->brush_pos.x2);
910 *h = ABS (sp->brush_pos.y1 - sp->brush_pos.y2);
911 }
912
GGOBI(getBrushLocation)913 void GGOBI (getBrushLocation) (gint * x, gint * y, ggobid * gg)
914 {
915 splotd *sp = gg->current_splot;
916
917 *x = MIN (sp->brush_pos.x1, sp->brush_pos.x2);
918 *y = MIN (sp->brush_pos.y1, sp->brush_pos.y2);
919 }
920
921 void
redraw(splotd * sp,ggobid * gg)922 redraw (splotd * sp, ggobid * gg)
923 {
924 brush_once (true, sp, gg);
925 display_plot (sp->displayptr, FULL, gg);
926 }
927
928
GGOBI(setBrushSize)929 void GGOBI (setBrushSize) (int w, int h, ggobid * gg)
930 {
931 splotd *sp = gg->current_splot;
932 displayd *display = sp->displayptr;
933
934 sp->brush_pos.x1 = MIN (sp->brush_pos.x1, sp->brush_pos.x2);
935 sp->brush_pos.y1 = MIN (sp->brush_pos.y1, sp->brush_pos.y2);
936
937 sp->brush_pos.x2 = sp->brush_pos.x1 + w;
938 sp->brush_pos.y2 = sp->brush_pos.y1 + h;
939
940 brush_once (true, sp, gg);
941 redraw (sp, gg);
942 display_plot (display, FULL, gg);
943 }
944
945
GGOBI(setBrushLocation)946 void GGOBI (setBrushLocation) (gint x, gint y, ggobid * gg)
947 {
948 gint wd, ht;
949 splotd *sp = gg->current_splot;
950
951 GGOBI (getBrushSize) (&wd, &ht, gg);
952
953 sp->brush_pos.x1 = x;
954 sp->brush_pos.y1 = y;
955 sp->brush_pos.x2 = x + wd;
956 sp->brush_pos.y2 = y + ht;
957
958 brush_once (true, sp, gg);
959
960 redraw (sp, gg);
961 }
962
GGOBI(setBrushGlyph)963 gboolean GGOBI (setBrushGlyph) (gint type, gint size, ggobid * gg)
964 {
965 if (type > -1)
966 gg->glyph_id.type = type;
967 if (size > -1)
968 gg->glyph_id.size = size;
969
970 return (true); /* Should be true iff there is a change. */
971 }
972
GGOBI(getBrushGlyph)973 void GGOBI (getBrushGlyph) (gint * type, gint * size, ggobid * gg)
974 {
975 *type = gg->glyph_id.type;
976 *size = gg->glyph_id.size;
977 }
978
979
980 /*
981 Returns the dimensions of the specified
982 splot in pixels which can then be used for
983 specifying.
984 */
GGOBI(getPlotPixelSize)985 void GGOBI (getPlotPixelSize) (gint * w, gint * h, splotd * sp)
986 {
987 /* Temp */
988 *w = -1;
989 *h = -1;
990 }
991
992
GGOBI(getSPlot)993 splotd *GGOBI (getSPlot) (gint which, displayd * display)
994 {
995 splotd *sp = (splotd *) g_list_nth_data (display->splots, which);
996 return (sp);
997 }
998
GGOBI(setPMode)999 gint GGOBI (setPMode) (const gchar * name, ggobid * gg)
1000 {
1001 ProjectionMode old = pmode_get (gg->current_display, gg);
1002 ProjectionMode newMode = (ProjectionMode) GGOBI (getPModeId) (name);
1003 if (newMode != NULL_PMODE)
1004 GGOBI (full_viewmode_set) (newMode, DEFAULT_IMODE, gg);
1005 return (old);
1006 }
1007
GGOBI(getPModeId)1008 gint GGOBI (getPModeId) (const gchar * name)
1009 {
1010 gint n, i;
1011 const gchar *const *names = GGOBI (getPModeNames) (&n);
1012
1013 for (i = 0; i < n; i++) {
1014 if (strcmp (names[i], name) == 0)
1015 return (i);
1016 }
1017
1018 return (-1);
1019 }
1020
GGOBI(getPModeName)1021 const gchar *GGOBI (getPModeName) (int which)
1022 {
1023 int n;
1024 const gchar *const *names;
1025
1026 names = GGOBI (getPModeNames) (&n);
1027 return (names[which]);
1028 }
1029
GGOBI(getPModeScreenName)1030 const gchar *GGOBI (getPModeScreenName) (int which, displayd * display)
1031 {
1032 if (which == EXTENDED_DISPLAY_PMODE) {
1033 gchar *name;
1034 GGOBI_EXTENDED_DISPLAY_GET_CLASS (display)->imode_control_box (display,
1035 &name,
1036 display->
1037 ggobi);
1038 return name;
1039 }
1040 return (GGOBI (getPModeName) (which));
1041 }
1042
GGOBI(setIMode)1043 gint GGOBI (setIMode) (const gchar * name, ggobid * gg)
1044 {
1045 InteractionMode old = imode_get (gg);
1046 InteractionMode newMode = (InteractionMode) GGOBI (getIModeId) (name);
1047 if (newMode != NULL_PMODE)
1048 GGOBI (full_viewmode_set) (NULL_PMODE, newMode, gg);
1049 return (old);
1050 }
1051
GGOBI(getIModeId)1052 gint GGOBI (getIModeId) (const gchar * name)
1053 {
1054 gint n, i;
1055 const gchar *const *names = GGOBI (getIModeNames) (&n);
1056
1057 for (i = 0; i < n; i++) {
1058 if (strcmp (names[i], name) == 0)
1059 return (i);
1060 }
1061
1062 return (-1);
1063 }
1064
GGOBI(getIModeName)1065 const gchar *GGOBI (getIModeName) (int which)
1066 {
1067 int n;
1068 const gchar *const *names;
1069
1070 names = GGOBI (getIModeNames) (&n);
1071 return (names[which]);
1072 }
1073
GGOBI(getIModeScreenName)1074 const gchar *GGOBI (getIModeScreenName) (int which, displayd * display)
1075 {
1076 if (which == DEFAULT_IMODE)
1077 return (GGOBI (getPModeScreenName) (display->cpanel.pmode, display));
1078 return (GGOBI (getIModeName) (which));
1079 }
1080
GGOBI(getPModeKey)1081 const gchar *GGOBI (getPModeKey) (int which)
1082 {
1083 int n;
1084 const gchar *const *keys = GGOBI (getPModeKeys) (&n);
1085 return (keys[which]);
1086 }
1087
1088 /*
1089 gint
1090 GGOBI(getModeId)(const gchar *name)
1091 {
1092 gint n, i;
1093 const gchar *const *names = GGOBI(getOpModeNames)(&n);
1094
1095 for(i = 0; i < n; i++) {
1096 if(strcmp(names[i],name) == 0)
1097 return(i);
1098 }
1099
1100 return(-1);
1101 }
1102
1103 const gchar *
1104 GGOBI(getModeName)(int which)
1105 {
1106 int n;
1107 const gchar *const *names = GGOBI(getOpModeNames)(&n);
1108 return(names[which]);
1109 }
1110 */
1111
GGOBI(setBrushColor)1112 gint GGOBI (setBrushColor) (gint cid, ggobid * gg)
1113 {
1114 gint old = gg->color_id;
1115 if (cid > -1 && cid < gg->activeColorScheme->n)
1116 gg->color_id = cid;
1117
1118 return (old);
1119 }
1120
GGOBI(getBrushColor)1121 gint GGOBI (getBrushColor) (ggobid * gg)
1122 {
1123 return (gg->color_id);
1124 }
1125
GGOBI(getColorName)1126 const gchar *GGOBI (getColorName) (gint cid, ggobid * gg, gboolean inDefault)
1127 {
1128 if (cid >= 0 && cid < gg->activeColorScheme->n) {
1129 return ((gchar *) g_array_index (gg->activeColorScheme->colorNames,
1130 gchar *, cid));
1131 }
1132
1133 return (NULL);
1134 }
1135
1136
1137 static gint
addVariableInternal(gdouble * vals,gint num,gchar * name,gchar ** levels,gint * values,gint * counts,gint numLevels,gboolean update,GGobiData * d,ggobid * gg)1138 addVariableInternal (gdouble * vals, gint num, gchar * name,
1139 gchar ** levels, gint * values, gint * counts,
1140 gint numLevels, gboolean update, GGobiData * d,
1141 ggobid * gg)
1142 {
1143 /*if (d->ncols < 1) {
1144 gchar ** rnames = (gchar **) &DefaultRowNames;
1145 GGOBI(setData)(NULL, rnames, &name, num, d->ncols, d, false, gg, NULL, false, d->input);
1146 datad_init(d, gg, false);
1147 } */
1148
1149 if (num > d->nrows && d->ncols > 0) {
1150 num = d->nrows;
1151 g_warning ("Variable length (%d) exceeds the number of dataset rows (%d)",
1152 num, d->nrows);
1153 }
1154 newvar_add_with_values (vals, num, name,
1155 numLevels > 0 ? categorical : real,
1156 numLevels, levels, values, counts, d);
1157
1158 if (update)
1159 gdk_flush ();
1160
1161 return (d->ncols - 1);
1162 }
1163
1164 /*-- this is really addRealVariable --*/
1165 gint
GGOBI(addVariable)1166 GGOBI (addVariable) (gdouble * vals, gint num, gchar * name,
1167 gboolean update, GGobiData * d, ggobid * gg)
1168 {
1169 return (addVariableInternal
1170 (vals, num, name, NULL, NULL, NULL, 0, update, d, gg));
1171 }
1172
1173 /*
1174 It's hard to get the sequence right of adding a variable, updating its
1175 data, updating the variable table structure, setting the variable's type,
1176 emitting an event saying that a variable has been added, and updating the
1177 GUI. .... This works for now, but the code is not pretty. We're making
1178 only very limted use of the event we emit. dfs 2/7
1179 */
1180 gint
GGOBI(addCategoricalVariable)1181 GGOBI (addCategoricalVariable) (gdouble * vals, gint num, gchar * name,
1182 gchar ** levels, gint * values, gint * counts,
1183 gint numLevels, gboolean update,
1184 GGobiData * d, ggobid * gg)
1185 {
1186
1187 return (addVariableInternal
1188 (vals, num, name, levels, values, counts, numLevels, update, d,
1189 gg));
1190 }
1191
1192
1193 /*
1194 The idea of the update argument is that we can defer recomputing
1195 the statistics for all the variables and then the transformations.
1196 This is useful when we know we will be adding more variables before
1197 redisplaying.
1198 For example,
1199 for(i = 0; i < n; i++)
1200 GGOBI(setVariableValues)(i, values[i], gg->nrows, i == n-1, gg);
1201 causes the update to be done only for the last variable.
1202 */
1203 gboolean
GGOBI(setVariableValues)1204 GGOBI (setVariableValues) (gint whichVar, gdouble * vals, gint num,
1205 gboolean update, GGobiData * d, ggobid * gg)
1206 {
1207 gint i;
1208 for (i = 0; i < num; i++) {
1209 d->raw.vals[i][whichVar] = d->tform.vals[i][whichVar] = vals[i];
1210 }
1211
1212 if (update) {
1213 GGOBI (update_data) (d, gg);
1214 }
1215
1216 return (true);
1217 }
1218
GGOBI(update_data)1219 void GGOBI (update_data) (GGobiData * d, ggobid * gg)
1220 {
1221 limits_set (d, true, true, gg->lims_use_visible);
1222 vartable_limits_set (d);
1223 vartable_stats_set (d);
1224
1225 tform_to_world (d, gg);
1226 }
1227
GGOBI(removeVariable)1228 gint GGOBI (removeVariable) (gchar * name, GGobiData * d, ggobid * gg)
1229 {
1230 gint which = GGOBI (getVariableIndex) (name, d, gg);
1231 if (which > -1 && which < d->ncols)
1232 return (GGOBI (removeVariableByIndex) (which, d, gg));
1233
1234 return (-1);
1235 }
1236
GGOBI(removeVariableByIndex)1237 gint GGOBI (removeVariableByIndex) (gint which, GGobiData * d, ggobid * gg)
1238 {
1239 gint i, j;
1240 for (i = 0; i < d->nrows; i++) {
1241 for (j = which + 1; j < d->ncols; j++) {
1242 /*XXX Fill in */
1243 }
1244 }
1245
1246 d->ncols--;
1247
1248 return (-1);
1249 }
1250
1251
GGOBI(getVariableIndex)1252 gint GGOBI (getVariableIndex) (const gchar * name, GGobiData * d, ggobid * gg)
1253 {
1254 gint j;
1255
1256 for (j = 0; j < d->ncols; j++) {
1257 if (strcmp (ggobi_data_get_col_name(d, j), name) == 0)
1258 return (j);
1259 }
1260
1261 return (-1);
1262 }
1263
1264 void
GGOBI(setPlotRange)1265 GGOBI (setPlotRange) (double *x, double *y, int plotNum, displayd * display,
1266 gboolean pixels, ggobid * gg)
1267 {
1268 splotd *sp;
1269
1270 sp = GGOBI (getPlot) (display, plotNum);
1271
1272 if (pixels) {
1273
1274 }
1275 else {
1276
1277 splot_zoom (sp, *x, *y);
1278 }
1279
1280 /*
1281 fcoords tfmin, tfmax;
1282 tfmin.x = x[0];
1283 tfmin.y = y[0];
1284 tfmax.x = x[1];
1285 tfmax.y = y[1];
1286
1287 if (GTK_WIDGET_VISIBLE (display->hrule)) {
1288 if (((gfloat) GTK_RULER (display->hrule)->lower != tfmin.x) ||
1289 ((gfloat) GTK_RULER (display->hrule)->upper != tfmax.x))
1290 {
1291 GTK_RULER_set_range (GTK_RULER (display->hrule),
1292 (gdouble) tfmin.x, (gdouble) tfmax.x);
1293 }
1294 }
1295
1296 if (GTK_WIDGET_VISIBLE (display->vrule)) {
1297 if (((gfloat) GTK_RULER (display->vrule)->upper != tfmin.y) ||
1298 ((gfloat) GTK_RULER (display->vrule)->lower != tfmax.y))
1299 {
1300 GTK_RULER_set_range (GTK_RULER (display->vrule),
1301 (gdouble) tfmax.y, (gdouble) tfmin.y);
1302 }
1303 }
1304 */
1305 }
1306
1307
1308 /*
1309 This handles the raising and lowering or the iconifying or
1310 de-iconifying of one or more windows. If which is negative,
1311 the operation applies to all the displays with the ggobid
1312 instance. Otherwise, the operation applies just to the
1313 display indexed by which.
1314
1315 The two logical arguments indicate whether to raise/lower
1316 or iconify/deiconify. Within these two operation types, the
1317 up argument indicates whether to raise or lower, an iconify
1318 or deiconify.
1319 */
1320 gboolean
GGOBI(raiseWindow)1321 GGOBI (raiseWindow) (int which, gboolean raiseOrIcon, gboolean up,
1322 ggobid * gg)
1323 {
1324 windowDisplayd *display;
1325 gboolean ok = false;
1326 int start, end, i;
1327
1328 if (which < 0) {
1329 start = 0;
1330 end = g_list_length (gg->displays);
1331 }
1332 else {
1333 end = which + 1;
1334 start = which;
1335 }
1336
1337 for (i = start; i < end; i++) {
1338 display = (windowDisplayd *) g_list_nth_data (gg->displays, i);
1339 if (GGOBI_IS_WINDOW_DISPLAY (display) == false)
1340 continue;
1341 if (raiseOrIcon) {
1342 if (up)
1343 gdk_window_raise (display->window->window);
1344 else
1345 gdk_window_lower (display->window->window);
1346 }
1347 else {
1348 if (up)
1349 gtk_widget_hide_all (display->window);
1350 else
1351 gtk_widget_show_all (display->window);
1352
1353 }
1354 }
1355
1356 ok = true;
1357
1358
1359 gdk_flush ();
1360 return (ok);
1361 }
1362
GGOBI(getDescription)1363 gchar *GGOBI (getDescription) (ggobid * gg)
1364 {
1365 if (!gg->input)
1366 return (NULL);
1367
1368 return (g_strdup (gg->input->fileName));
1369 }
1370
1371 /*
1372 Finds the index of the dataset named `name'
1373 in the specified ggobid object.
1374 */
GGOBI(datasetIndex)1375 int GGOBI (datasetIndex) (const char *name, const ggobid * const gg)
1376 {
1377 GGobiData *d;
1378 int ctr = 0;
1379 GSList *tmp = gg->d;
1380
1381 while (tmp) {
1382 d = (GGobiData *) tmp->data;
1383 if (strcmp (name, d->name) == 0)
1384 return (ctr);
1385 ctr++;
1386 tmp = tmp->next;
1387 }
1388
1389 return (-1);
1390 }
1391
1392 /*
1393 Returns the names of the different datasets
1394 maintained in the specified ggobid object.
1395 */
GGOBI(getDatasetNames)1396 gchar **GGOBI (getDatasetNames) (gint * n, ggobid * gg)
1397 {
1398 gint i;
1399 GGobiData *d;
1400 gchar **names;
1401 GSList *tmp = gg->d;
1402 *n = g_slist_length (gg->d);
1403 names = (gchar **) g_malloc (sizeof (gchar *) * (*n));
1404 for (i = 0; i < *n; i++) {
1405 d = (GGobiData *) tmp->data;
1406 names[i] = g_strdup (d->name);
1407 tmp = tmp->next;
1408 }
1409
1410 return (names);
1411 }
1412
1413 /*
1414 Added to the API and to avoid breaking code (e.g. in RSggobi)
1415 we add it here with a new name GGOBI(ggobi_get).
1416 */
GGOBI(ggobi_get)1417 ggobid *GGOBI (ggobi_get) (gint which)
1418 {
1419 return (ggobi_get (which));
1420 }
1421
GGOBI(ncols)1422 gint GGOBI (ncols) (GGobiData * data)
1423 {
1424 return (data->ncols);
1425 }
1426
GGOBI(nrecords)1427 gint GGOBI (nrecords) (GGobiData * data)
1428 {
1429 return (data->nrows);
1430 }
1431
1432
1433 /*
1434 This is the routine one uses to register a handler for key press events
1435 for the numbered keys, i.e. 0, 1, ..., 9
1436 One can specify null values for each of these to remove the handler and have
1437 these events discarded.
1438
1439 See notes/NumberedKeys.*, splot.c and ggobi.h also for more details
1440 */
GGOBI(registerNumberedKeyEventHandler)1441 KeyEventHandler *GGOBI (registerNumberedKeyEventHandler) (KeyEventHandlerFunc
1442 routine,
1443 void *userData,
1444 char *description,
1445 ReleaseData *
1446 releaseData,
1447 ggobid * gg,
1448 ProgrammingLanguage
1449 lang)
1450 {
1451 KeyEventHandler *old = gg->NumberedKeyEventHandler;
1452 KeyEventHandler *newValue;
1453 if (routine == NULL)
1454 newValue = NULL;
1455 else {
1456 newValue = g_malloc (1 * sizeof (KeyEventHandler));
1457 newValue->handlerRoutine = routine;
1458 newValue->userData = userData;
1459 newValue->description = g_strdup (description);
1460 newValue->language = lang;
1461 newValue->releaseData = releaseData;
1462 }
1463
1464 gg->NumberedKeyEventHandler = newValue;
1465
1466 return (old);
1467 }
1468
GGOBI(removeNumberedKeyEventHandler)1469 KeyEventHandler *GGOBI (removeNumberedKeyEventHandler) (ggobid * gg)
1470 {
1471 return (GGOBI
1472 (registerNumberedKeyEventHandler (NULL, NULL, NULL, NULL, gg, C)));
1473 }
1474
1475
1476 #include "config.h"
1477 static const gchar *version_date = GGOBI_RELEASE_DATE;
1478 static const int GgobiVersionNumbers[] =
1479 { MAJOR_VERSION, MINOR_VERSION, MICRO_VERSION };
1480 static const gchar *version_string = PACKAGE_VERSION;
1481
GGOBI(getVersionDate)1482 const char *GGOBI (getVersionDate) ()
1483 {
1484 return (version_date);
1485 }
1486
GGOBI(getVersionString)1487 const char *GGOBI (getVersionString) ()
1488 {
1489 return (version_string);
1490 }
1491
GGOBI(getVersionNumbers)1492 const int *GGOBI (getVersionNumbers) ()
1493 {
1494 return (GgobiVersionNumbers);
1495 }
1496
1497
GGOBI(data_get)1498 GGobiData *GGOBI (data_get) (gint which, const ggobid * const gg)
1499 {
1500 GGobiData *data = NULL;
1501
1502 if (gg->d != NULL)
1503 data = g_slist_nth_data (gg->d, which);
1504
1505 return (data);
1506 }
1507
GGOBI(data_get_by_name)1508 GGobiData *GGOBI (data_get_by_name) (const gchar * const name,
1509 const ggobid * const gg)
1510 {
1511 gint which;
1512 GGobiData *data = NULL;
1513
1514 which = GGOBI (datasetIndex) (name, gg);
1515 if (which > -1) {
1516 data = GGOBI (data_get) (which, gg);
1517 }
1518
1519 return (NULL);
1520 }
1521
1522 void
GGobi_setSessionOptions(GGobiOptions * opts)1523 GGobi_setSessionOptions (GGobiOptions * opts)
1524 {
1525 sessionOptions = opts;
1526 }
1527
1528 const gchar *
GGobi_getLevelName(vartabled * vt,double value)1529 GGobi_getLevelName (vartabled * vt, double value)
1530 {
1531 int which = 0;
1532 for (which = 0; which < vt->nlevels; which++) {
1533 if (vt->level_values[which] == (int) value)
1534 return (vt->level_names[which]);
1535 }
1536
1537 return (NULL);
1538 }
1539
1540
1541 void
GGobi_setDataName(const char * const name,GGobiData * d)1542 GGobi_setDataName (const char *const name, GGobiData * d)
1543 {
1544 if (d->name)
1545 g_free ((gchar *) d->name);
1546
1547 d->name = g_strdup (name);
1548 /* Update the different labels. */
1549 }
1550
1551
1552 /* sets the tour projection matrix, F */
1553 gboolean
GGOBI(setTour2DProjectionMatrix)1554 GGOBI (setTour2DProjectionMatrix) (gdouble * Fvalues, gint ncols, gint ndim,
1555 gboolean vals_scaled, ggobid * gg)
1556 {
1557 ProjectionMode vm = pmode_get (gg->current_display, gg);
1558 displayd *dsp = gg->current_display;
1559 cpaneld *cpanel = &dsp->cpanel;
1560 GGobiData *d = dsp->d;
1561 gboolean candoit = true;
1562 gint i, j;
1563
1564 if ((ncols != d->ncols) || ndim != 2)
1565 candoit = false;
1566
1567 if (candoit) {
1568 /* Set the scatterplot display mode to be tour2d */
1569 if (vm != TOUR2D) {
1570 /* Needs to be filled in */
1571 }
1572
1573 /* Pause the tour */
1574 if (!cpanel->t2d.paused)
1575 tour2d_pause (cpanel, true, dsp, gg);
1576
1577 /* Set the projection vector F */
1578 for (i = 0; i < ndim; i++)
1579 for (j = 0; j < ncols; j++)
1580 dsp->t2d.F.vals[i][j] = Fvalues[i + j * 2];
1581
1582 /* If the values are scaled, then we need to multiply
1583 them by the tform data, else we multiply them by the
1584 world data */
1585 if (vals_scaled) {
1586 /* Needs to be filled in */
1587 }
1588 else {
1589 display_tailpipe (dsp, FULL, gg);
1590 varcircles_refresh (d, gg);
1591 }
1592 }
1593
1594 return (candoit);
1595 }
1596
GGOBI(getTour2DProjectionMatrix)1597 const gdouble **GGOBI (getTour2DProjectionMatrix) (gint ncols, gint ndim,
1598 gboolean vals_scaled,
1599 ggobid * gg)
1600 {
1601 displayd *dsp = gg->current_display;
1602 GGobiData *d = dsp->d;
1603 gdouble **Fvals;
1604 gint i, j;
1605
1606 ncols = d->ncols;
1607 ndim = 2;
1608
1609 Fvals = (gdouble **) g_malloc (sizeof (gdouble *) * ncols);
1610
1611 if (vals_scaled) {
1612 /* run the F values through the reverse pipeline */
1613 }
1614 else {
1615 for (i = 0; i < ndim; i++)
1616 for (j = 0; j < ncols; j++)
1617 Fvals[i][j] = dsp->t2d.F.vals[i][j];
1618 }
1619
1620 return ((const gdouble **) Fvals);
1621 }
1622
1623
1624 guint
getGGobiSignal(GGobiSignalType which)1625 getGGobiSignal (GGobiSignalType which)
1626 {
1627 /*
1628 XXX assert(which > -1 && which < MAX_GGOBI_SIGNALS);
1629 */
1630 return (GGobiSignals[which]);
1631 }
1632
1633
GGOBI(getExtendedDisplayTypes)1634 GSList *GGOBI (getExtendedDisplayTypes) ()
1635 {
1636 return (ExtendedDisplayTypes);
1637 }
1638