2
* @brief Widget that listens and modifies repr attributes
5
* Lauris Kaplinski <lauris@ximian.com>
7
* Copyright (C) 2001 Ximian, Inc.
8
* Released under GNU GPL, read the file 'COPYING' for more information
11
#include <gtk/gtktable.h>
12
#include <gtk/gtklabel.h>
16
#include "sp-object.h"
17
#include <glibmm/i18n.h>
19
#include <sigc++/functors/ptr_fun.h>
20
#include <sigc++/adaptors/bind.h>
22
#include "sp-attribute-widget.h"
24
static void sp_attribute_widget_class_init (SPAttributeWidgetClass *klass);
25
static void sp_attribute_widget_init (SPAttributeWidget *widget);
26
static void sp_attribute_widget_destroy (GtkObject *object);
28
static void sp_attribute_widget_changed (GtkEditable *editable);
30
static void sp_attribute_widget_object_modified ( SPObject *object,
32
SPAttributeWidget *spaw );
33
static void sp_attribute_widget_object_release ( SPObject *object,
34
SPAttributeWidget *spaw );
36
static GtkEntryClass *parent_class;
41
GType sp_attribute_widget_get_type(void)
43
static GtkType type = 0;
46
sizeof(SPAttributeWidgetClass),
49
(GClassInitFunc)sp_attribute_widget_class_init,
52
sizeof(SPAttributeWidget),
54
(GInstanceInitFunc)sp_attribute_widget_init,
57
type = g_type_register_static(GTK_TYPE_ENTRY, "SPAttributeWidget", &info, static_cast<GTypeFlags>(0));
60
} // end of sp_attribute_widget_get_type()
65
sp_attribute_widget_class_init (SPAttributeWidgetClass *klass)
67
GtkObjectClass *object_class;
68
GtkWidgetClass *widget_class;
69
GtkEditableClass *editable_class;
71
object_class = GTK_OBJECT_CLASS (klass);
72
widget_class = GTK_WIDGET_CLASS (klass);
73
editable_class = GTK_EDITABLE_CLASS (klass);
75
parent_class = (GtkEntryClass*)gtk_type_class (GTK_TYPE_ENTRY);
77
object_class->destroy = sp_attribute_widget_destroy;
79
editable_class->changed = sp_attribute_widget_changed;
81
} // end of sp_attribute_widget_class_init()
86
sp_attribute_widget_init (SPAttributeWidget *spaw)
88
spaw->blocked = FALSE;
91
spaw->src.object = NULL;
93
spaw->attribute = NULL;
95
new (&spaw->modified_connection) sigc::connection();
96
new (&spaw->release_connection) sigc::connection();
102
sp_attribute_widget_destroy (GtkObject *object)
105
SPAttributeWidget *spaw;
107
spaw = SP_ATTRIBUTE_WIDGET (object);
109
if (spaw->attribute) {
110
g_free (spaw->attribute);
111
spaw->attribute = NULL;
117
if (spaw->src.object) {
118
spaw->modified_connection.disconnect();
119
spaw->release_connection.disconnect();
120
spaw->src.object = NULL;
124
if (spaw->src.repr) {
125
spaw->src.repr = Inkscape::GC::release(spaw->src.repr);
129
spaw->modified_connection.~connection();
130
spaw->release_connection.~connection();
132
((GtkObjectClass *) parent_class)->destroy (object);
139
sp_attribute_widget_changed (GtkEditable *editable)
142
SPAttributeWidget *spaw;
144
spaw = SP_ATTRIBUTE_WIDGET (editable);
146
if (!spaw->blocked) {
149
spaw->blocked = TRUE;
150
text = gtk_entry_get_text (GTK_ENTRY (spaw));
154
if (spaw->hasobj && spaw->src.object) {
156
SP_OBJECT_REPR (spaw->src.object)->setAttribute(spaw->attribute, text, false);
157
sp_document_done (SP_OBJECT_DOCUMENT (spaw->src.object), SP_VERB_NONE,
160
} else if (spaw->src.repr) {
162
spaw->src.repr->setAttribute(spaw->attribute, text, false);
163
/* TODO: Warning! Undo will not be flushed in given case */
165
spaw->blocked = FALSE;
168
} // end of sp_attribute_widget_changed()
173
sp_attribute_widget_new ( SPObject *object, const gchar *attribute )
175
SPAttributeWidget *spaw;
177
g_return_val_if_fail (!object || SP_IS_OBJECT (object), NULL);
178
g_return_val_if_fail (!object || attribute, NULL);
180
spaw = (SPAttributeWidget*)gtk_type_new (SP_TYPE_ATTRIBUTE_WIDGET);
182
sp_attribute_widget_set_object (spaw, object, attribute);
184
return GTK_WIDGET (spaw);
186
} // end of sp_attribute_widget_new()
191
sp_attribute_widget_new_repr ( Inkscape::XML::Node *repr, const gchar *attribute )
193
SPAttributeWidget *spaw;
195
spaw = (SPAttributeWidget*)gtk_type_new (SP_TYPE_ATTRIBUTE_WIDGET);
197
sp_attribute_widget_set_repr (spaw, repr, attribute);
199
return GTK_WIDGET (spaw);
205
sp_attribute_widget_set_object ( SPAttributeWidget *spaw,
207
const gchar *attribute )
210
g_return_if_fail (spaw != NULL);
211
g_return_if_fail (SP_IS_ATTRIBUTE_WIDGET (spaw));
212
g_return_if_fail (!object || SP_IS_OBJECT (object));
213
g_return_if_fail (!object || attribute);
214
g_return_if_fail (attribute != NULL);
216
if (spaw->attribute) {
217
g_free (spaw->attribute);
218
spaw->attribute = NULL;
223
if (spaw->src.object) {
224
spaw->modified_connection.disconnect();
225
spaw->release_connection.disconnect();
226
spaw->src.object = NULL;
230
if (spaw->src.repr) {
231
spaw->src.repr = Inkscape::GC::release(spaw->src.repr);
240
spaw->blocked = TRUE;
241
spaw->src.object = object;
243
spaw->modified_connection = object->connectModified(sigc::bind<2>(sigc::ptr_fun(&sp_attribute_widget_object_modified), spaw));
244
spaw->release_connection = object->connectRelease(sigc::bind<1>(sigc::ptr_fun(&sp_attribute_widget_object_release), spaw));
246
spaw->attribute = g_strdup (attribute);
248
val = SP_OBJECT_REPR (object)->attribute(attribute);
249
gtk_entry_set_text (GTK_ENTRY (spaw), val ? val : (const gchar *) "");
250
spaw->blocked = FALSE;
253
gtk_widget_set_sensitive (GTK_WIDGET (spaw), (spaw->src.object != NULL));
255
} // end of sp_attribute_widget_set_object()
260
sp_attribute_widget_set_repr ( SPAttributeWidget *spaw,
261
Inkscape::XML::Node *repr,
262
const gchar *attribute )
265
g_return_if_fail (spaw != NULL);
266
g_return_if_fail (SP_IS_ATTRIBUTE_WIDGET (spaw));
267
g_return_if_fail (attribute != NULL);
269
if (spaw->attribute) {
270
g_free (spaw->attribute);
271
spaw->attribute = NULL;
276
if (spaw->src.object) {
277
spaw->modified_connection.disconnect();
278
spaw->release_connection.disconnect();
279
spaw->src.object = NULL;
283
if (spaw->src.repr) {
284
spaw->src.repr = Inkscape::GC::release(spaw->src.repr);
288
spaw->hasobj = FALSE;
293
spaw->blocked = TRUE;
294
spaw->src.repr = Inkscape::GC::anchor(repr);
295
spaw->attribute = g_strdup (attribute);
297
val = repr->attribute(attribute);
298
gtk_entry_set_text (GTK_ENTRY (spaw), val ? val : (const gchar *) "");
299
spaw->blocked = FALSE;
302
gtk_widget_set_sensitive (GTK_WIDGET (spaw), (spaw->src.repr != NULL));
304
} // end of sp_attribute_widget_set_repr()
309
sp_attribute_widget_object_modified ( SPObject */*object*/,
311
SPAttributeWidget *spaw )
314
if (flags && SP_OBJECT_MODIFIED_FLAG) {
316
const gchar *val, *text;
317
val = SP_OBJECT_REPR (spaw->src.object)->attribute(spaw->attribute);
318
text = gtk_entry_get_text (GTK_ENTRY (spaw));
322
if (!val || !text || strcmp (val, text)) {
323
/* We are different */
324
spaw->blocked = TRUE;
325
gtk_entry_set_text ( GTK_ENTRY (spaw),
326
val ? val : (const gchar *) "");
327
spaw->blocked = FALSE;
334
} // end of sp_attribute_widget_object_modified()
339
sp_attribute_widget_object_release ( SPObject */*object*/,
340
SPAttributeWidget *spaw )
342
sp_attribute_widget_set_object (spaw, NULL, NULL);
347
/* SPAttributeTable */
349
static void sp_attribute_table_class_init (SPAttributeTableClass *klass);
350
static void sp_attribute_table_init (SPAttributeTable *widget);
351
static void sp_attribute_table_destroy (GtkObject *object);
353
static void sp_attribute_table_object_modified (SPObject *object, guint flags, SPAttributeTable *spaw);
354
static void sp_attribute_table_object_release (SPObject *object, SPAttributeTable *spaw);
355
static void sp_attribute_table_entry_changed (GtkEditable *editable, SPAttributeTable *spat);
357
static GtkVBoxClass *table_parent_class;
362
GType sp_attribute_table_get_type(void)
364
static GtkType type = 0;
367
sizeof(SPAttributeTableClass),
370
(GClassInitFunc)sp_attribute_table_class_init,
373
sizeof(SPAttributeTable),
375
(GInstanceInitFunc)sp_attribute_table_init,
378
type = g_type_register_static(GTK_TYPE_VBOX, "SPAttributeTable", &info, static_cast<GTypeFlags>(0));
381
} // end of sp_attribute_table_get_type()
386
sp_attribute_table_class_init (SPAttributeTableClass *klass)
388
GtkObjectClass *object_class;
389
GtkWidgetClass *widget_class;
391
object_class = GTK_OBJECT_CLASS (klass);
392
widget_class = GTK_WIDGET_CLASS (klass);
394
table_parent_class = (GtkVBoxClass*)gtk_type_class (GTK_TYPE_VBOX);
396
object_class->destroy = sp_attribute_table_destroy;
398
} // end of sp_attribute_table_class_init()
403
sp_attribute_table_init ( SPAttributeTable *spat )
405
spat->blocked = FALSE;
406
spat->hasobj = FALSE;
408
spat->src.object = NULL;
410
spat->attributes = NULL;
411
spat->entries = NULL;
413
new (&spat->modified_connection) sigc::connection();
414
new (&spat->release_connection) sigc::connection();
418
sp_attribute_table_destroy ( GtkObject *object )
420
SPAttributeTable *spat;
422
spat = SP_ATTRIBUTE_TABLE (object);
424
if (spat->attributes) {
426
for (i = 0; i < spat->num_attr; i++) {
427
g_free (spat->attributes[i]);
429
g_free (spat->attributes);
430
spat->attributes = NULL;
435
if (spat->src.object) {
436
spat->modified_connection.disconnect();
437
spat->release_connection.disconnect();
438
spat->src.object = NULL;
441
if (spat->src.repr) {
442
spat->src.repr = Inkscape::GC::release(spat->src.repr);
446
spat->modified_connection.~connection();
447
spat->release_connection.~connection();
450
g_free (spat->entries);
451
spat->entries = NULL;
456
if (((GtkObjectClass *) table_parent_class)->destroy) {
457
(* ((GtkObjectClass *) table_parent_class)->destroy) (object);
460
} // end of sp_attribute_table_destroy()
464
sp_attribute_table_new ( SPObject *object,
466
const gchar **labels,
467
const gchar **attributes )
469
SPAttributeTable *spat;
471
g_return_val_if_fail (!object || SP_IS_OBJECT (object), NULL);
472
g_return_val_if_fail (!object || (num_attr > 0), NULL);
473
g_return_val_if_fail (!num_attr || (labels && attributes), NULL);
475
spat = (SPAttributeTable*)gtk_type_new (SP_TYPE_ATTRIBUTE_TABLE);
477
sp_attribute_table_set_object (spat, object, num_attr, labels, attributes);
479
return GTK_WIDGET (spat);
481
} // end of sp_attribute_table_new()
486
sp_attribute_table_new_repr ( Inkscape::XML::Node *repr,
488
const gchar **labels,
489
const gchar **attributes )
491
SPAttributeTable *spat;
493
g_return_val_if_fail (!num_attr || (labels && attributes), NULL);
495
spat = (SPAttributeTable*)gtk_type_new (SP_TYPE_ATTRIBUTE_TABLE);
497
sp_attribute_table_set_repr (spat, repr, num_attr, labels, attributes);
499
return GTK_WIDGET (spat);
501
} // end of sp_attribute_table_new_repr()
509
sp_attribute_table_set_object ( SPAttributeTable *spat,
512
const gchar **labels,
513
const gchar **attributes )
516
g_return_if_fail (spat != NULL);
517
g_return_if_fail (SP_IS_ATTRIBUTE_TABLE (spat));
518
g_return_if_fail (!object || SP_IS_OBJECT (object));
519
g_return_if_fail (!object || (num_attr > 0));
520
g_return_if_fail (!num_attr || (labels && attributes));
523
gtk_widget_destroy (spat->table);
527
if (spat->attributes) {
529
for (i = 0; i < spat->num_attr; i++) {
530
g_free (spat->attributes[i]);
532
g_free (spat->attributes);
533
spat->attributes = NULL;
537
g_free (spat->entries);
538
spat->entries = NULL;
542
if (spat->src.object) {
543
spat->modified_connection.disconnect();
544
spat->release_connection.disconnect();
545
spat->src.object = NULL;
548
if (spat->src.repr) {
549
spat->src.repr = Inkscape::GC::release(spat->src.repr);
558
spat->blocked = TRUE;
561
spat->src.object = object;
562
spat->num_attr = num_attr;
564
spat->modified_connection = object->connectModified(sigc::bind<2>(sigc::ptr_fun(&sp_attribute_table_object_modified), spat));
565
spat->release_connection = object->connectRelease(sigc::bind<1>(sigc::ptr_fun(&sp_attribute_table_object_release), spat));
568
spat->table = gtk_table_new (num_attr, 2, FALSE);
569
gtk_container_add (GTK_CONTAINER (spat), spat->table);
571
spat->attributes = g_new0 (gchar *, num_attr);
572
spat->entries = g_new0 (GtkWidget *, num_attr);
574
for (i = 0; i < num_attr; i++) {
578
spat->attributes[i] = g_strdup (attributes[i]);
579
w = gtk_label_new (_(labels[i]));
581
gtk_misc_set_alignment (GTK_MISC (w), 1.0, 0.5);
582
gtk_table_attach ( GTK_TABLE (spat->table), w, 0, 1, i, i + 1,
584
(GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
586
w = gtk_entry_new ();
588
val = SP_OBJECT_REPR (object)->attribute(attributes[i]);
589
gtk_entry_set_text (GTK_ENTRY (w), val ? val : (const gchar *) "");
590
gtk_table_attach ( GTK_TABLE (spat->table), w, 1, 2, i, i + 1,
591
(GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
592
(GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
594
spat->entries[i] = w;
595
g_signal_connect ( G_OBJECT (w), "changed",
596
G_CALLBACK (sp_attribute_table_entry_changed),
600
gtk_widget_show (spat->table);
602
spat->blocked = FALSE;
605
gtk_widget_set_sensitive ( GTK_WIDGET (spat),
606
(spat->src.object != NULL) );
608
} // end of sp_attribute_table_set_object()
613
sp_attribute_table_set_repr ( SPAttributeTable *spat,
614
Inkscape::XML::Node *repr,
616
const gchar **labels,
617
const gchar **attributes )
619
g_return_if_fail (spat != NULL);
620
g_return_if_fail (SP_IS_ATTRIBUTE_TABLE (spat));
621
g_return_if_fail (!num_attr || (labels && attributes));
624
gtk_widget_destroy (spat->table);
628
if (spat->attributes) {
630
for (i = 0; i < spat->num_attr; i++) {
631
g_free (spat->attributes[i]);
633
g_free (spat->attributes);
634
spat->attributes = NULL;
638
g_free (spat->entries);
639
spat->entries = NULL;
643
if (spat->src.object) {
644
spat->modified_connection.disconnect();
645
spat->release_connection.disconnect();
646
spat->src.object = NULL;
649
if (spat->src.repr) {
650
spat->src.repr = Inkscape::GC::release(spat->src.repr);
654
spat->hasobj = FALSE;
659
spat->blocked = TRUE;
662
spat->src.repr = Inkscape::GC::anchor(repr);
663
spat->num_attr = num_attr;
665
spat->table = gtk_table_new (num_attr, 2, FALSE);
666
gtk_container_add (GTK_CONTAINER (spat), spat->table);
668
spat->attributes = g_new0 (gchar *, num_attr);
669
spat->entries = g_new0 (GtkWidget *, num_attr);
672
for (i = 0; i < num_attr; i++) {
676
spat->attributes[i] = g_strdup (attributes[i]);
677
w = gtk_label_new (labels[i]);
679
gtk_misc_set_alignment (GTK_MISC (w), 1.0, 0.5);
680
gtk_table_attach ( GTK_TABLE (spat->table), w, 0, 1, i, i + 1,
682
(GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
684
w = gtk_entry_new ();
686
val = repr->attribute(attributes[i]);
687
gtk_entry_set_text (GTK_ENTRY (w), val ? val : (const gchar *) "");
688
gtk_table_attach ( GTK_TABLE (spat->table), w, 1, 2, i, i + 1,
689
(GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
690
(GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
692
spat->entries[i] = w;
693
g_signal_connect ( G_OBJECT (w), "changed",
694
G_CALLBACK (sp_attribute_table_entry_changed),
698
gtk_widget_show (spat->table);
700
spat->blocked = FALSE;
703
gtk_widget_set_sensitive (GTK_WIDGET (spat), (spat->src.repr != NULL));
705
} // end of sp_attribute_table_set_repr()
710
sp_attribute_table_object_modified ( SPObject */*object*/,
712
SPAttributeTable *spat )
714
if (flags && SP_OBJECT_MODIFIED_FLAG)
717
for (i = 0; i < spat->num_attr; i++) {
718
const gchar *val, *text;
719
val = SP_OBJECT_REPR (spat->src.object)->attribute(spat->attributes[i]);
720
text = gtk_entry_get_text (GTK_ENTRY (spat->entries[i]));
722
if (!val || !text || strcmp (val, text)) {
723
/* We are different */
724
spat->blocked = TRUE;
725
gtk_entry_set_text ( GTK_ENTRY (spat->entries[i]),
726
val ? val : (const gchar *) "");
727
spat->blocked = FALSE;
733
} // end of sp_attribute_table_object_modified()
738
sp_attribute_table_object_release (SPObject */*object*/, SPAttributeTable *spat)
740
sp_attribute_table_set_object (spat, NULL, 0, NULL, NULL);
746
sp_attribute_table_entry_changed ( GtkEditable *editable,
747
SPAttributeTable *spat )
752
for (i = 0; i < spat->num_attr; i++) {
754
if (GTK_WIDGET (editable) == spat->entries[i]) {
756
spat->blocked = TRUE;
757
text = gtk_entry_get_text (GTK_ENTRY (spat->entries[i]));
762
if (spat->hasobj && spat->src.object) {
763
SP_OBJECT_REPR (spat->src.object)->setAttribute(spat->attributes[i], text, false);
764
sp_document_done (SP_OBJECT_DOCUMENT (spat->src.object), SP_VERB_NONE,
767
} else if (spat->src.repr) {
769
spat->src.repr->setAttribute(spat->attributes[i], text, false);
770
/* TODO: Warning! Undo will not be flushed in given case */
772
spat->blocked = FALSE;
776
g_warning ("file %s: line %d: Entry signalled change, but there is no such entry", __FILE__, __LINE__);
779
} // end of sp_attribute_table_entry_changed()
784
c-file-style:"stroustrup"
785
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
790
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :