/* 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 <trow@gnu.org>
*
* 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>
#include <guppi-memory.h>
#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);
}
syntax highlighted by Code2HTML, v. 0.9.1