/* This is -*- C -*- */ /* vim: set sw=2: */ /* $Id: guppi-attribute-widget.c,v 1.1 2001/11/16 17:12:57 trow Exp $ */ /* * guppi-attribute-widget.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 "guppi-attribute-widget.h" #include #include static GtkObjectClass *parent_class = NULL; enum { BAG_TO_WIDGET, LAST_SIGNAL }; static guint guppi_attribute_widget_signals[LAST_SIGNAL] = { 0 }; struct _GuppiAttributeWidgetPrivate { gchar *key; GuppiAttributeFlavor flavor; gint set_lock; GuppiAttributeBag *bag; guint bag_changed_tag; }; static void guppi_attribute_widget_destroy (GtkObject *obj) { if (parent_class->destroy) parent_class->destroy (obj); } static void guppi_attribute_widget_finalize (GtkObject *obj) { GuppiAttributeWidget *x = GUPPI_ATTRIBUTE_WIDGET(obj); guppi_free (x->priv->key); if (x->priv->bag_changed_tag && x->priv->bag) { gtk_signal_disconnect (GTK_OBJECT (x->priv->bag), x->priv->bag_changed_tag); } guppi_unref (x->priv->bag); g_free (x->priv); x->priv = NULL; guppi_finalized (obj); if (parent_class->finalize) parent_class->finalize (obj); } static void guppi_attribute_widget_class_init (GuppiAttributeWidgetClass *klass) { GtkObjectClass *object_class = (GtkObjectClass *)klass; parent_class = gtk_type_class (GTK_TYPE_TABLE); object_class->destroy = guppi_attribute_widget_destroy; object_class->finalize = guppi_attribute_widget_finalize; guppi_attribute_widget_signals[BAG_TO_WIDGET] = gtk_signal_new ("bag_to_widget", GTK_RUN_FIRST, object_class->type, GTK_SIGNAL_OFFSET (GuppiAttributeWidgetClass, bag_to_widget), gtk_marshal_NONE__NONE, GTK_TYPE_NONE, 0); gtk_object_class_add_signals (object_class, guppi_attribute_widget_signals, LAST_SIGNAL); } static void guppi_attribute_widget_init (GuppiAttributeWidget *obj) { GuppiAttributeWidgetPrivate *p = g_new0 (GuppiAttributeWidgetPrivate, 1); obj->priv = p; } GtkType guppi_attribute_widget_get_type (void) { static GtkType guppi_attribute_widget_type = 0; if (!guppi_attribute_widget_type) { static const GtkTypeInfo guppi_attribute_widget_info = { "GuppiAttributeWidget", sizeof (GuppiAttributeWidget), sizeof (GuppiAttributeWidgetClass), (GtkClassInitFunc)guppi_attribute_widget_class_init, (GtkObjectInitFunc)guppi_attribute_widget_init, NULL, NULL, (GtkClassInitFunc)NULL }; guppi_attribute_widget_type = gtk_type_unique (GTK_TYPE_TABLE, &guppi_attribute_widget_info); } return guppi_attribute_widget_type; } static void emit_bag_to_widget (GuppiAttributeWidget *gaw) { gtk_signal_emit (GTK_OBJECT (gaw), guppi_attribute_widget_signals[BAG_TO_WIDGET]); } GtkWidget * guppi_attribute_widget_new (GuppiAttributeFlavor flavor, const gchar *key) { GtkWidget *w; g_return_val_if_fail (key && *key, NULL); w = GTK_WIDGET (guppi_type_new (guppi_attribute_widget_get_type ())); guppi_attribute_widget_construct (GUPPI_ATTRIBUTE_WIDGET (w), flavor, key); return w; } void guppi_attribute_widget_construct (GuppiAttributeWidget *gaw, GuppiAttributeFlavor flavor, const gchar *key) { g_return_if_fail (GUPPI_IS_ATTRIBUTE_WIDGET (gaw)); g_return_if_fail (key != NULL); g_return_if_fail (gaw->priv->key == NULL); gaw->priv->key = guppi_strdup (key); gaw->priv->flavor = flavor; } static void bag_changed_cb (GuppiAttributeBag *bag, const gchar *key, gpointer closure) { GuppiAttributeWidget *gaw = GUPPI_ATTRIBUTE_WIDGET (closure); g_assert (gaw != NULL); if (gaw->priv->set_lock > 0) return; if (strcmp (key, gaw->priv->key)) return; emit_bag_to_widget (gaw); } void guppi_attribute_widget_attach_bag (GuppiAttributeWidget *gaw, GuppiAttributeBag *bag) { GuppiAttributeFlavor bag_flavor; g_return_if_fail (GUPPI_IS_ATTRIBUTE_WIDGET (gaw)); g_return_if_fail (GUPPI_IS_ATTRIBUTE_BAG (bag)); g_return_if_fail (gaw->priv->bag == NULL); if (! guppi_attribute_bag_contains (bag, gaw->priv->key)) { g_warning ("Bag does not contain key '%s'", gaw->priv->key); return; } bag_flavor = guppi_attribute_bag_get_flavor (bag, gaw->priv->key); if (bag_flavor != gaw->priv->flavor) { g_message ("%d %d", bag_flavor, gaw->priv->flavor); g_warning ("Flavor mismatch on key '%s'", gaw->priv->key); return; } gaw->priv->bag = bag; guppi_ref (bag); gaw->priv->bag_changed_tag = gtk_signal_connect (GTK_OBJECT (bag), "changed", GTK_SIGNAL_FUNC (bag_changed_cb), gaw); emit_bag_to_widget (gaw); } void guppi_attribute_widget_recursively_attach_bag (GtkWidget *w, GuppiAttributeBag *bag) { g_return_if_fail (GTK_IS_WIDGET (w)); g_return_if_fail (GUPPI_IS_ATTRIBUTE_BAG (bag)); if (GUPPI_IS_ATTRIBUTE_WIDGET (w)) { guppi_attribute_widget_attach_bag (GUPPI_ATTRIBUTE_WIDGET (w), bag); } else if (GTK_IS_CONTAINER (w)) { gtk_container_foreach (GTK_CONTAINER (w), (GtkCallback) guppi_attribute_widget_recursively_attach_bag, bag); } } void guppi_attribute_widget_bag_get (GuppiAttributeWidget *gaw, const gchar *subkey, gpointer dest) { gchar *key = NULL; g_return_if_fail (GUPPI_IS_ATTRIBUTE_WIDGET (gaw)); g_return_if_fail (dest != NULL); if (gaw->priv->bag == NULL) { g_warning ("Getting without a bag."); return; } if (subkey && *subkey) { key = guppi_strdup_printf ("%s::%s", gaw->priv->key, subkey); } guppi_attribute_bag_get1 (gaw->priv->bag, key ? key : gaw->priv->key, dest); guppi_free (key); } void guppi_attribute_widget_bag_set (GuppiAttributeWidget *gaw, const gchar *subkey, ...) { gchar *key = NULL; va_list varargs; g_return_if_fail (GUPPI_IS_ATTRIBUTE_WIDGET (gaw)); if (gaw->priv->bag == NULL) { g_warning ("Setting without a bag."); return; } if (subkey && *subkey) { key = guppi_strdup_printf ("%s::%s", gaw->priv->key, subkey); } va_start (varargs, subkey); ++gaw->priv->set_lock; guppi_attribute_bag_vset1 (gaw->priv->bag, key ? key : gaw->priv->key, &varargs); --gaw->priv->set_lock; va_end (varargs); guppi_free (key); }