diff options
Diffstat (limited to 'src/dialogs/sp-attribute-widget.cpp')
| -rw-r--r-- | src/dialogs/sp-attribute-widget.cpp | 802 |
1 files changed, 802 insertions, 0 deletions
diff --git a/src/dialogs/sp-attribute-widget.cpp b/src/dialogs/sp-attribute-widget.cpp new file mode 100644 index 000000000..d7c4316e1 --- /dev/null +++ b/src/dialogs/sp-attribute-widget.cpp @@ -0,0 +1,802 @@ +#define __SP_ATTRIBUTE_WIDGET_C__ + +/** + * \brief SPAttributeWidget + * + * Widget, that listens and modifies repr attributes + * + * Authors: + * Lauris Kaplinski <lauris@ximian.com> + * + * Copyright (C) 2001 Ximian, Inc. + * + * Licensed under GNU GPL + */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <gtk/gtktable.h> +#include <gtk/gtklabel.h> +#include "xml/repr.h" +#include "macros.h" +#include "document.h" +#include "sp-object.h" +#include <glibmm/i18n.h> + +#include "sp-attribute-widget.h" + +static void sp_attribute_widget_class_init (SPAttributeWidgetClass *klass); +static void sp_attribute_widget_init (SPAttributeWidget *widget); +static void sp_attribute_widget_destroy (GtkObject *object); + +static void sp_attribute_widget_changed (GtkEditable *editable); + +static void sp_attribute_widget_object_modified ( SPObject *object, + guint flags, + SPAttributeWidget *spaw ); +static void sp_attribute_widget_object_release ( SPObject *object, + SPAttributeWidget *spaw ); + +static GtkEntryClass *parent_class; + + + + +GtkType +sp_attribute_widget_get_type (void) +{ + static GtkType type = 0; + if (!type) { + static const GtkTypeInfo info = { + "SPAttributeWidget", + sizeof (SPAttributeWidget), + sizeof (SPAttributeWidgetClass), + (GtkClassInitFunc) sp_attribute_widget_class_init, + (GtkObjectInitFunc) sp_attribute_widget_init, + NULL, NULL, NULL + }; + type = gtk_type_unique (GTK_TYPE_ENTRY, &info); + } + return type; + +} // end of sp_attribute_widget_get_type() + + + +static void +sp_attribute_widget_class_init (SPAttributeWidgetClass *klass) +{ + GtkObjectClass *object_class; + GtkWidgetClass *widget_class; + GtkEditableClass *editable_class; + + object_class = GTK_OBJECT_CLASS (klass); + widget_class = GTK_WIDGET_CLASS (klass); + editable_class = GTK_EDITABLE_CLASS (klass); + + parent_class = (GtkEntryClass*)gtk_type_class (GTK_TYPE_ENTRY); + + object_class->destroy = sp_attribute_widget_destroy; + + editable_class->changed = sp_attribute_widget_changed; + +} // end of sp_attribute_widget_class_init() + + + +static void +sp_attribute_widget_init (SPAttributeWidget *spaw) +{ + spaw->blocked = FALSE; + spaw->hasobj = FALSE; + + spaw->src.object = NULL; + + spaw->attribute = NULL; +} + + + +static void +sp_attribute_widget_destroy (GtkObject *object) +{ + + SPAttributeWidget *spaw; + + spaw = SP_ATTRIBUTE_WIDGET (object); + + if (spaw->attribute) { + g_free (spaw->attribute); + spaw->attribute = NULL; + } + + + if (spaw->hasobj) { + + if (spaw->src.object) { + sp_signal_disconnect_by_data (spaw->src.object, spaw); + spaw->src.object = NULL; + } + } else { + + if (spaw->src.repr) { + spaw->src.repr = Inkscape::GC::release(spaw->src.repr); + } + } // end of if() + + ((GtkObjectClass *) parent_class)->destroy (object); + +} + + + +static void +sp_attribute_widget_changed (GtkEditable *editable) +{ + + SPAttributeWidget *spaw; + + spaw = SP_ATTRIBUTE_WIDGET (editable); + + if (!spaw->blocked) { + + const gchar *text; + spaw->blocked = TRUE; + text = gtk_entry_get_text (GTK_ENTRY (spaw)); + if (!*text) + text = NULL; + + if (spaw->hasobj && spaw->src.object) { + + if (!sp_repr_set_attr ( SP_OBJECT_REPR (spaw->src.object), + spaw->attribute, text) ) + { + /* Cannot set attribute */ + text = SP_OBJECT_REPR (spaw->src.object)->attribute(spaw->attribute); + gtk_entry_set_text (GTK_ENTRY (spaw), text ? text : ""); + } + sp_document_done (SP_OBJECT_DOCUMENT (spaw->src.object)); + + } else if (spaw->src.repr) { + + if (!sp_repr_set_attr (spaw->src.repr, spaw->attribute, text)) + { + /* Cannot set attribute */ + text = spaw->src.repr->attribute(spaw->attribute); + gtk_entry_set_text (GTK_ENTRY (spaw), text ? text : ""); + } + /* TODO: Warning! Undo will not be flushed in given case */ + } + spaw->blocked = FALSE; + } + +} // end of sp_attribute_widget_changed() + + + +GtkWidget * +sp_attribute_widget_new ( SPObject *object, const gchar *attribute ) +{ + SPAttributeWidget *spaw; + + g_return_val_if_fail (!object || SP_IS_OBJECT (object), NULL); + g_return_val_if_fail (!object || attribute, NULL); + + spaw = (SPAttributeWidget*)gtk_type_new (SP_TYPE_ATTRIBUTE_WIDGET); + + sp_attribute_widget_set_object (spaw, object, attribute); + + return GTK_WIDGET (spaw); + +} // end of sp_attribute_widget_new() + + + +GtkWidget * +sp_attribute_widget_new_repr ( Inkscape::XML::Node *repr, const gchar *attribute ) +{ + SPAttributeWidget *spaw; + + spaw = (SPAttributeWidget*)gtk_type_new (SP_TYPE_ATTRIBUTE_WIDGET); + + sp_attribute_widget_set_repr (spaw, repr, attribute); + + return GTK_WIDGET (spaw); +} + + + +void +sp_attribute_widget_set_object ( SPAttributeWidget *spaw, + SPObject *object, + const gchar *attribute ) +{ + + g_return_if_fail (spaw != NULL); + g_return_if_fail (SP_IS_ATTRIBUTE_WIDGET (spaw)); + g_return_if_fail (!object || SP_IS_OBJECT (object)); + g_return_if_fail (!object || attribute); + g_return_if_fail (attribute != NULL); + + if (spaw->attribute) { + g_free (spaw->attribute); + spaw->attribute = NULL; + } + + if (spaw->hasobj) { + + if (spaw->src.object) { + sp_signal_disconnect_by_data (spaw->src.object, spaw); + spaw->src.object = NULL; + } + } else { + + if (spaw->src.repr) { + spaw->src.repr = Inkscape::GC::release(spaw->src.repr); + } + } + + spaw->hasobj = TRUE; + + if (object) { + const gchar *val; + + spaw->blocked = TRUE; + spaw->src.object = object; + g_signal_connect ( G_OBJECT (object), "modified", + G_CALLBACK (sp_attribute_widget_object_modified), + spaw ); + g_signal_connect ( G_OBJECT (object), "release", + G_CALLBACK (sp_attribute_widget_object_release), + spaw ); + + spaw->attribute = g_strdup (attribute); + + val = SP_OBJECT_REPR (object)->attribute(attribute); + gtk_entry_set_text (GTK_ENTRY (spaw), val ? val : (const gchar *) ""); + spaw->blocked = FALSE; + } + + gtk_widget_set_sensitive (GTK_WIDGET (spaw), (spaw->src.object != NULL)); + +} // end of sp_attribute_widget_set_object() + + + +void +sp_attribute_widget_set_repr ( SPAttributeWidget *spaw, + Inkscape::XML::Node *repr, + const gchar *attribute ) +{ + + g_return_if_fail (spaw != NULL); + g_return_if_fail (SP_IS_ATTRIBUTE_WIDGET (spaw)); + g_return_if_fail (attribute != NULL); + + if (spaw->attribute) { + g_free (spaw->attribute); + spaw->attribute = NULL; + } + + if (spaw->hasobj) { + + if (spaw->src.object) { + sp_signal_disconnect_by_data (spaw->src.object, spaw); + spaw->src.object = NULL; + } + } else { + + if (spaw->src.repr) { + spaw->src.repr = Inkscape::GC::release(spaw->src.repr); + } + } + + spaw->hasobj = FALSE; + + if (repr) { + const gchar *val; + + spaw->blocked = TRUE; + spaw->src.repr = Inkscape::GC::anchor(repr); + spaw->attribute = g_strdup (attribute); + + val = repr->attribute(attribute); + gtk_entry_set_text (GTK_ENTRY (spaw), val ? val : (const gchar *) ""); + spaw->blocked = FALSE; + } + + gtk_widget_set_sensitive (GTK_WIDGET (spaw), (spaw->src.repr != NULL)); + +} // end of sp_attribute_widget_set_repr() + + + +static void +sp_attribute_widget_object_modified ( SPObject *object, + guint flags, + SPAttributeWidget *spaw ) +{ + + if (flags && SP_OBJECT_MODIFIED_FLAG) { + + const gchar *val, *text; + val = SP_OBJECT_REPR (spaw->src.object)->attribute(spaw->attribute); + text = gtk_entry_get_text (GTK_ENTRY (spaw)); + + if (val || text) { + + if (!val || !text || strcmp (val, text)) { + /* We are different */ + spaw->blocked = TRUE; + gtk_entry_set_text ( GTK_ENTRY (spaw), + val ? val : (const gchar *) ""); + spaw->blocked = FALSE; + } // end of if() + + } // end of if() + + } //end of if() + +} // end of sp_attribute_widget_object_modified() + + + +static void +sp_attribute_widget_object_release ( SPObject *object, + SPAttributeWidget *spaw ) +{ + sp_attribute_widget_set_object (spaw, NULL, NULL); +} + + + +/* SPAttributeTable */ + +static void sp_attribute_table_class_init (SPAttributeTableClass *klass); +static void sp_attribute_table_init (SPAttributeTable *widget); +static void sp_attribute_table_destroy (GtkObject *object); + +static void sp_attribute_table_object_modified (SPObject *object, guint flags, SPAttributeTable *spaw); +static void sp_attribute_table_object_release (SPObject *object, SPAttributeTable *spaw); +static void sp_attribute_table_entry_changed (GtkEditable *editable, SPAttributeTable *spat); + +static GtkVBoxClass *table_parent_class; + + + + +GtkType +sp_attribute_table_get_type (void) +{ + static GtkType type = 0; + if (!type) { + static const GtkTypeInfo info = { + "SPAttributeTable", + sizeof (SPAttributeTable), + sizeof (SPAttributeTableClass), + (GtkClassInitFunc) sp_attribute_table_class_init, + (GtkObjectInitFunc) sp_attribute_table_init, + NULL, NULL, NULL + }; + type = gtk_type_unique (GTK_TYPE_VBOX, &info); + } + return type; + +} // end of sp_attribute_table_get_type() + + + +static void +sp_attribute_table_class_init (SPAttributeTableClass *klass) +{ + GtkObjectClass *object_class; + GtkWidgetClass *widget_class; + + object_class = GTK_OBJECT_CLASS (klass); + widget_class = GTK_WIDGET_CLASS (klass); + + table_parent_class = (GtkVBoxClass*)gtk_type_class (GTK_TYPE_VBOX); + + object_class->destroy = sp_attribute_table_destroy; + +} // end of sp_attribute_table_class_init() + + + +static void +sp_attribute_table_init ( SPAttributeTable *spat ) +{ + spat->blocked = FALSE; + spat->hasobj = FALSE; + spat->table = NULL; + spat->src.object = NULL; + spat->num_attr = 0; + spat->attributes = NULL; + spat->entries = NULL; +} + +static void +sp_attribute_table_destroy ( GtkObject *object ) +{ + SPAttributeTable *spat; + + spat = SP_ATTRIBUTE_TABLE (object); + + if (spat->attributes) { + gint i; + for (i = 0; i < spat->num_attr; i++) { + g_free (spat->attributes[i]); + } + g_free (spat->attributes); + spat->attributes = NULL; + } + + if (spat->hasobj) { + + if (spat->src.object) { + sp_signal_disconnect_by_data (spat->src.object, spat); + spat->src.object = NULL; + } + } else { + if (spat->src.repr) { + spat->src.repr = Inkscape::GC::release(spat->src.repr); + } + } // end of if() + + + if (spat->entries) { + g_free (spat->entries); + spat->entries = NULL; + } + + spat->table = NULL; + + if (((GtkObjectClass *) table_parent_class)->destroy) { + (* ((GtkObjectClass *) table_parent_class)->destroy) (object); + } + +} // end of sp_attribute_table_destroy() + + +GtkWidget * +sp_attribute_table_new ( SPObject *object, + gint num_attr, + const gchar **labels, + const gchar **attributes ) +{ + SPAttributeTable *spat; + + g_return_val_if_fail (!object || SP_IS_OBJECT (object), NULL); + g_return_val_if_fail (!object || (num_attr > 0), NULL); + g_return_val_if_fail (!num_attr || (labels && attributes), NULL); + + spat = (SPAttributeTable*)gtk_type_new (SP_TYPE_ATTRIBUTE_TABLE); + + sp_attribute_table_set_object (spat, object, num_attr, labels, attributes); + + return GTK_WIDGET (spat); + +} // end of sp_attribute_table_new() + + + +GtkWidget * +sp_attribute_table_new_repr ( Inkscape::XML::Node *repr, + gint num_attr, + const gchar **labels, + const gchar **attributes ) +{ + SPAttributeTable *spat; + + g_return_val_if_fail (!num_attr || (labels && attributes), NULL); + + spat = (SPAttributeTable*)gtk_type_new (SP_TYPE_ATTRIBUTE_TABLE); + + sp_attribute_table_set_repr (spat, repr, num_attr, labels, attributes); + + return GTK_WIDGET (spat); + +} // end of sp_attribute_table_new_repr() + + + +#define XPAD 4 +#define YPAD 0 + +void +sp_attribute_table_set_object ( SPAttributeTable *spat, + SPObject *object, + gint num_attr, + const gchar **labels, + const gchar **attributes ) +{ + + g_return_if_fail (spat != NULL); + g_return_if_fail (SP_IS_ATTRIBUTE_TABLE (spat)); + g_return_if_fail (!object || SP_IS_OBJECT (object)); + g_return_if_fail (!object || (num_attr > 0)); + g_return_if_fail (!num_attr || (labels && attributes)); + + if (spat->table) { + gtk_widget_destroy (spat->table); + spat->table = NULL; + } + + if (spat->attributes) { + gint i; + for (i = 0; i < spat->num_attr; i++) { + g_free (spat->attributes[i]); + } + g_free (spat->attributes); + spat->attributes = NULL; + } + + if (spat->entries) { + g_free (spat->entries); + spat->entries = NULL; + } + + if (spat->hasobj) { + if (spat->src.object) { + sp_signal_disconnect_by_data (spat->src.object, spat); + spat->src.object = NULL; + } + } else { + if (spat->src.repr) { + spat->src.repr = Inkscape::GC::release(spat->src.repr); + } + } + + spat->hasobj = TRUE; + + if (object) { + gint i; + + spat->blocked = TRUE; + + /* Set up object */ + spat->src.object = object; + spat->num_attr = num_attr; + g_signal_connect ( G_OBJECT (object), "modified", + G_CALLBACK (sp_attribute_table_object_modified), + spat ); + g_signal_connect ( G_OBJECT (object), "release", + G_CALLBACK (sp_attribute_table_object_release), + spat ); + /* Create table */ + spat->table = gtk_table_new (num_attr, 2, FALSE); + gtk_container_add (GTK_CONTAINER (spat), spat->table); + /* Arrays */ + spat->attributes = g_new0 (gchar *, num_attr); + spat->entries = g_new0 (GtkWidget *, num_attr); + /* Fill rows */ + for (i = 0; i < num_attr; i++) { + GtkWidget *w; + const gchar *val; + + spat->attributes[i] = g_strdup (attributes[i]); + w = gtk_label_new (_(labels[i])); + gtk_widget_show (w); + gtk_misc_set_alignment (GTK_MISC (w), 1.0, 0.5); + gtk_table_attach ( GTK_TABLE (spat->table), w, 0, 1, i, i + 1, + GTK_FILL, + (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), + XPAD, YPAD ); + w = gtk_entry_new (); + gtk_widget_show (w); + val = SP_OBJECT_REPR (object)->attribute(attributes[i]); + gtk_entry_set_text (GTK_ENTRY (w), val ? val : (const gchar *) ""); + gtk_table_attach ( GTK_TABLE (spat->table), w, 1, 2, i, i + 1, + (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), + (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), + XPAD, YPAD ); + spat->entries[i] = w; + g_signal_connect ( G_OBJECT (w), "changed", + G_CALLBACK (sp_attribute_table_entry_changed), + spat ); + } + /* Show table */ + gtk_widget_show (spat->table); + + spat->blocked = FALSE; + } + + gtk_widget_set_sensitive ( GTK_WIDGET (spat), + (spat->src.object != NULL) ); + +} // end of sp_attribute_table_set_object() + + + +void +sp_attribute_table_set_repr ( SPAttributeTable *spat, + Inkscape::XML::Node *repr, + gint num_attr, + const gchar **labels, + const gchar **attributes ) +{ + g_return_if_fail (spat != NULL); + g_return_if_fail (SP_IS_ATTRIBUTE_TABLE (spat)); + g_return_if_fail (!num_attr || (labels && attributes)); + + if (spat->table) { + gtk_widget_destroy (spat->table); + spat->table = NULL; + } + + if (spat->attributes) { + gint i; + for (i = 0; i < spat->num_attr; i++) { + g_free (spat->attributes[i]); + } + g_free (spat->attributes); + spat->attributes = NULL; + } + + if (spat->entries) { + g_free (spat->entries); + spat->entries = NULL; + } + + if (spat->hasobj) { + if (spat->src.object) { + sp_signal_disconnect_by_data (spat->src.object, spat); + spat->src.object = NULL; + } + } else { + if (spat->src.repr) { + spat->src.repr = Inkscape::GC::release(spat->src.repr); + } + } + + spat->hasobj = FALSE; + + if (repr) { + gint i; + + spat->blocked = TRUE; + + /* Set up repr */ + spat->src.repr = Inkscape::GC::anchor(repr); + spat->num_attr = num_attr; + /* Create table */ + spat->table = gtk_table_new (num_attr, 2, FALSE); + gtk_container_add (GTK_CONTAINER (spat), spat->table); + /* Arrays */ + spat->attributes = g_new0 (gchar *, num_attr); + spat->entries = g_new0 (GtkWidget *, num_attr); + + /* Fill rows */ + for (i = 0; i < num_attr; i++) { + GtkWidget *w; + const gchar *val; + + spat->attributes[i] = g_strdup (attributes[i]); + w = gtk_label_new (labels[i]); + gtk_widget_show (w); + gtk_misc_set_alignment (GTK_MISC (w), 1.0, 0.5); + gtk_table_attach ( GTK_TABLE (spat->table), w, 0, 1, i, i + 1, + GTK_FILL, + (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), + XPAD, YPAD ); + w = gtk_entry_new (); + gtk_widget_show (w); + val = repr->attribute(attributes[i]); + gtk_entry_set_text (GTK_ENTRY (w), val ? val : (const gchar *) ""); + gtk_table_attach ( GTK_TABLE (spat->table), w, 1, 2, i, i + 1, + (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), + (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), + XPAD, YPAD ); + spat->entries[i] = w; + g_signal_connect ( G_OBJECT (w), "changed", + G_CALLBACK (sp_attribute_table_entry_changed), + spat ); + } + /* Show table */ + gtk_widget_show (spat->table); + + spat->blocked = FALSE; + } + + gtk_widget_set_sensitive (GTK_WIDGET (spat), (spat->src.repr != NULL)); + +} // end of sp_attribute_table_set_repr() + + + +static void +sp_attribute_table_object_modified ( SPObject *object, + guint flags, + SPAttributeTable *spat ) +{ + if (flags && SP_OBJECT_MODIFIED_FLAG) + { + gint i; + for (i = 0; i < spat->num_attr; i++) { + const gchar *val, *text; + val = SP_OBJECT_REPR (spat->src.object)->attribute(spat->attributes[i]); + text = gtk_entry_get_text (GTK_ENTRY (spat->entries[i])); + if (val || text) { + if (!val || !text || strcmp (val, text)) { + /* We are different */ + spat->blocked = TRUE; + gtk_entry_set_text ( GTK_ENTRY (spat->entries[i]), + val ? val : (const gchar *) ""); + spat->blocked = FALSE; + } + } + } + } // end of if() + +} // end of sp_attribute_table_object_modified() + + + +static void +sp_attribute_table_object_release (SPObject *object, SPAttributeTable *spat) +{ + sp_attribute_table_set_object (spat, NULL, 0, NULL, NULL); +} + + + +static void +sp_attribute_table_entry_changed ( GtkEditable *editable, + SPAttributeTable *spat ) +{ + if (!spat->blocked) + { + gint i; + for (i = 0; i < spat->num_attr; i++) { + + if (GTK_WIDGET (editable) == spat->entries[i]) { + const gchar *text; + spat->blocked = TRUE; + text = gtk_entry_get_text (GTK_ENTRY (spat->entries[i])); + + if (!*text) + text = NULL; + + if (spat->hasobj && spat->src.object) { + if (!sp_repr_set_attr ( SP_OBJECT_REPR (spat->src.object), + spat->attributes[i], text)) + { + /* Cannot set attribute */ + text = SP_OBJECT_REPR (spat->src.object)->attribute(spat->attributes[i]); + gtk_entry_set_text ( GTK_ENTRY (spat->entries[i]), + text ? text : (const gchar *) ""); + } + sp_document_done (SP_OBJECT_DOCUMENT (spat->src.object)); + + } else if (spat->src.repr) { + + if (!sp_repr_set_attr (spat->src.repr, + spat->attributes[i], text)) + { + /* Cannot set attribute */ + text = spat->src.repr->attribute(spat->attributes[i]); + gtk_entry_set_text ( GTK_ENTRY (spat->entries[i]), + text ? text : (const gchar *) "" ); + } + /* TODO: Warning! Undo will not be flushed in given case */ + } + spat->blocked = FALSE; + return; + } + } + g_warning ("file %s: line %d: Entry signalled change, but there is no such entry", __FILE__, __LINE__); + } // end of if() + +} // end of sp_attribute_table_entry_changed() + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : |
