/* This is -*- C -*- */ /* vim: set sw=2: */ /* $Id: guppi-data-table-bundle.c,v 1.4 2001/10/07 19:56:04 trow Exp $ */ /* * guppi-data-table-bundle.c * * Copyright (C) 2001 The Free Software Foundation * * Developed by Jon Trowbridge * * 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 #include #include "guppi-data-table-bundle.h" static GtkObjectClass *parent_class = NULL; static void free_everything (GuppiDataTableBundle *bundle) { gint i; guppi_data_table_bundle_set_row_labels (bundle, NULL); guppi_data_table_bundle_set_col_labels (bundle, NULL); for (i = 0; i < bundle->C; ++i) guppi_data_table_bundle_set_col_data (bundle, i, NULL); guppi_free0 (bundle->col); } static gboolean get_bounds (GuppiDataTable *dt, gint *r, gint *c) { GuppiDataTableBundle *bundle = (GuppiDataTableBundle *) dt; if (r) *r = bundle->R; if (c) *c = bundle->C; return TRUE; } static void set_bounds (GuppiDataTable *dt, gint r, gint c) { GuppiDataTableBundle *bundle = (GuppiDataTableBundle *) dt; free_everything (bundle); bundle->R = r; bundle->C = c; } static double get_entry (GuppiDataTable *dt, gint r, gint c) { GuppiDataTableBundle *bundle = (GuppiDataTableBundle *) dt; GuppiSeqScalar *seq; if (bundle->col == NULL) return 0; if (bundle->col[c] == NULL) return 0; seq = bundle->col[c]->data; return guppi_seq_in_bounds (GUPPI_SEQ (seq), r) ? guppi_seq_scalar_get (seq, r) : 0; } static void set_entry (GuppiDataTable *dt, gint r, gint c, double x) { GuppiDataTableBundle *bundle = (GuppiDataTableBundle *) dt; GuppiSeqScalar *seq; if (bundle->col == NULL) return; if (bundle->col[c]->data == NULL) return; seq = bundle->col[c]->data; if (! guppi_seq_in_bounds (GUPPI_SEQ (seq), r)) return; guppi_seq_scalar_set (seq, r, x); } static const gchar * get_label (GuppiDataTable *dt, GuppiDataTableSpan span, gint i) { GuppiDataTableBundle *bundle = (GuppiDataTableBundle *) dt; GuppiSeqString *str_seq; if (span == GUPPI_TABLE_ROW) str_seq = bundle->row_labels; else if (span == GUPPI_TABLE_COL) str_seq = bundle->col_labels; else return NULL; if (str_seq == NULL) return ""; return guppi_seq_string_get (str_seq, i); } static GuppiData * copy (GuppiData *data) { return NULL; } static gint get_size_in_bytes (GuppiData *data) { GuppiDataTableBundle *bundle = (GuppiDataTableBundle *) data; gint sz = 0; gint i; if (bundle->col) { for (i = 0; i < bundle->C; ++i) { if (bundle->col[i] && bundle->col[i]->data) sz += guppi_data_get_size_in_bytes (GUPPI_DATA (bundle->col[i]->data)); } if (bundle->row_labels) sz += guppi_data_get_size_in_bytes (GUPPI_DATA (bundle->row_labels)); if (bundle->col_labels) sz += guppi_data_get_size_in_bytes (GUPPI_DATA (bundle->col_labels)); } if (GUPPI_DATA_CLASS (parent_class)->get_size_in_bytes) sz += GUPPI_DATA_CLASS (parent_class)->get_size_in_bytes (data); return sz; } static void set_label (GuppiDataTable *dt, GuppiDataTableSpan span, gint i, const gchar *label) { GuppiDataTableBundle *bundle = (GuppiDataTableBundle *) dt; GuppiSeqString *str_seq; if (span == GUPPI_TABLE_ROW) str_seq = bundle->row_labels; else if (span == GUPPI_TABLE_COL) str_seq = bundle->col_labels; else return; guppi_seq_string_set (str_seq, i, label); } static void guppi_data_table_bundle_finalize (GtkObject *obj) { GuppiDataTableBundle *x = GUPPI_DATA_TABLE_BUNDLE(obj); x->block_signals_hack = TRUE; free_everything (x); guppi_finalized (obj); if (parent_class->finalize) parent_class->finalize (obj); } static void guppi_data_table_bundle_class_init (GuppiDataTableBundleClass *klass) { GtkObjectClass *object_class = (GtkObjectClass *)klass; GuppiDataClass *data_class = GUPPI_DATA_CLASS (klass); GuppiDataTableClass *data_table_class = GUPPI_DATA_TABLE_CLASS (klass); parent_class = gtk_type_class (GUPPI_TYPE_DATA_TABLE); object_class->finalize = guppi_data_table_bundle_finalize; data_class->copy = copy; data_class->get_size_in_bytes = get_size_in_bytes; data_class->is_leaf_type = TRUE; data_table_class->get_bounds = get_bounds; data_table_class->set_bounds = set_bounds; data_table_class->get_entry = get_entry; data_table_class->set_entry = set_entry; data_table_class->get_label = get_label; data_table_class->set_label = set_label; } static void guppi_data_table_bundle_init (GuppiDataTableBundle *obj) { } GtkType guppi_data_table_bundle_get_type (void) { static GtkType guppi_data_table_bundle_type = 0; if (!guppi_data_table_bundle_type) { static const GtkTypeInfo guppi_data_table_bundle_info = { "GuppiDataTableBundle", sizeof (GuppiDataTableBundle), sizeof (GuppiDataTableBundleClass), (GtkClassInitFunc)guppi_data_table_bundle_class_init, (GtkObjectInitFunc)guppi_data_table_bundle_init, NULL, NULL, (GtkClassInitFunc)NULL }; guppi_data_table_bundle_type = gtk_type_unique (GUPPI_TYPE_DATA_TABLE, &guppi_data_table_bundle_info); } return guppi_data_table_bundle_type; } GuppiDataTable * guppi_data_table_bundle_new (void) { guppi_data_table_bundle_get_type (); return (GuppiDataTable *) guppi_data_new ("GuppiDataTableBundle"); } /* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */ static void guppi_data_table_bundle_column_changed (GuppiDataTableBundle *bundle, gint c) { GuppiDataOp noop; if (bundle->block_signals_hack) return; noop.op = NULL; guppi_data_table_changed_table_entries ((GuppiDataTable *) bundle, c, 0, c, bundle->R - 1, &noop); } static void col_changed_cb (GuppiData *data, gpointer closure) { GuppiDataTableBundleColumn *column = closure; guppi_data_table_bundle_column_changed (column->bundle, column->col_num); } static GuppiDataTableBundleColumn * column_new (GuppiDataTableBundle *tb, gint col_num, GuppiSeqScalar *ss) { GuppiDataTableBundleColumn *column; if (col_num < 0 || col_num >= tb->C) return NULL; if (ss == NULL) return NULL; column = g_new (GuppiDataTableBundleColumn, 1); column->bundle = tb; /* no ref -- don't want a circular data structure */ column->col_num = col_num; column->data = ss; guppi_ref (column->data); column->changed_tag = gtk_signal_connect (GTK_OBJECT (column->data), "changed", GTK_SIGNAL_FUNC (col_changed_cb), column); return column; } static void column_free (GuppiDataTableBundleColumn *column) { if (column == NULL) return; if (column->changed_tag != 0) { gtk_signal_disconnect (GTK_OBJECT (column->data), column->changed_tag); } guppi_unref (column->data); guppi_free (column); } void guppi_data_table_bundle_set_col_data (GuppiDataTableBundle *tb, gint c, GuppiSeqScalar *seq) { GuppiDataTableBundleColumn *old_col; g_return_if_fail (GUPPI_IS_DATA_TABLE_BUNDLE (tb)); g_return_if_fail (0 <= c && c < tb->C); g_return_if_fail (GUPPI_IS_SEQ_SCALAR0 (seq)); if (tb->col == NULL) { if (seq == NULL) return; tb->col = guppi_new0 (GuppiDataTableBundleColumn *, tb->C); } old_col = tb->col[c]; if (old_col && old_col->data == seq) return; if (old_col == NULL && seq == NULL) return; tb->col[c] = column_new (tb, c, seq); column_free (old_col); guppi_data_table_bundle_column_changed (tb, c); } /* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */ static void guppi_data_table_bundle_labels_changed (GuppiDataTableBundle *bundle, GuppiDataTableSpan span) { GuppiDataOp noop; gint N; /* Emit a bunch of crazy stuff */ if (bundle->block_signals_hack) return; if (span == GUPPI_TABLE_ROW) N = bundle->R; else N = bundle->C; noop.op = NULL; guppi_data_table_changed_table_labels ((GuppiDataTable *) bundle, span, 0, N-1, &noop); } static void labels_changed_cb (GuppiData *data, gpointer closure) { GuppiDataTableSpan span; GuppiDataTableBundle *bundle; if (GPOINTER_TO_INT (closure) & 1) span = GUPPI_TABLE_ROW; else span = GUPPI_TABLE_COL; bundle = GUPPI_DATA_TABLE_BUNDLE (GINT_TO_POINTER (GPOINTER_TO_INT (closure) & ~1)); guppi_data_table_bundle_labels_changed (bundle, span); } static void guppi_data_table_bundle_set_labels (GuppiDataTableBundle *tb, GuppiDataTableSpan span, GuppiSeqString *seq) { GuppiSeqString *old; gpointer closure_hack; guint *changed_tag; g_return_if_fail (GUPPI_IS_DATA_TABLE_BUNDLE (tb)); g_return_if_fail (GUPPI_IS_SEQ_STRING0 (seq)); closure_hack = tb; if (span == GUPPI_TABLE_ROW) { old = tb->row_labels; changed_tag = &tb->row_labels_changed_tag; closure_hack = GINT_TO_POINTER (GPOINTER_TO_INT (closure_hack) | 1); } else if (span == GUPPI_TABLE_COL) { old = tb->col_labels; changed_tag = &tb->col_labels_changed_tag; } else return; if (old == seq) return; if (*changed_tag != 0) { gtk_signal_disconnect (GTK_OBJECT (old), *changed_tag); *changed_tag = 0; } if (seq) { *changed_tag = gtk_signal_connect (GTK_OBJECT (seq), "changed", GTK_SIGNAL_FUNC (labels_changed_cb), closure_hack); } if (span == GUPPI_TABLE_ROW) tb->row_labels = seq; else if (span == GUPPI_TABLE_COL) tb->col_labels = seq; guppi_ref (seq); guppi_unref (old); guppi_data_table_bundle_labels_changed (tb, span); } void guppi_data_table_bundle_set_row_labels (GuppiDataTableBundle *tb, GuppiSeqString *seq) { guppi_data_table_bundle_set_labels (tb, GUPPI_TABLE_ROW, seq); } void guppi_data_table_bundle_set_col_labels (GuppiDataTableBundle *tb, GuppiSeqString *seq) { guppi_data_table_bundle_set_labels (tb, GUPPI_TABLE_COL, seq); }