~vaifrax/inkscape/bugfix170049

« back to all changes in this revision

Viewing changes to src/dialogs/sp-attribute-widget.cpp

  • Committer: mental
  • Date: 2006-01-16 02:36:01 UTC
  • Revision ID: mental@users.sourceforge.net-20060116023601-wkr0h7edl5veyudq
moving trunk for module inkscape

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#define __SP_ATTRIBUTE_WIDGET_C__
 
2
 
 
3
/**
 
4
 * \brief  SPAttributeWidget
 
5
 *
 
6
 * Widget, that listens and modifies repr attributes
 
7
 *
 
8
 * Authors:
 
9
 *  Lauris Kaplinski <lauris@ximian.com>
 
10
 *
 
11
 * Copyright (C) 2001 Ximian, Inc.
 
12
 *
 
13
 * Licensed under GNU GPL
 
14
 */
 
15
#ifdef HAVE_CONFIG_H
 
16
# include "config.h"
 
17
#endif
 
18
 
 
19
#include <gtk/gtktable.h>
 
20
#include <gtk/gtklabel.h>
 
21
#include "xml/repr.h"
 
22
#include "macros.h"
 
23
#include "document.h"
 
24
#include "sp-object.h"
 
25
#include <glibmm/i18n.h>
 
26
 
 
27
#include "sp-attribute-widget.h"
 
28
 
 
29
static void sp_attribute_widget_class_init (SPAttributeWidgetClass *klass);
 
30
static void sp_attribute_widget_init (SPAttributeWidget *widget);
 
31
static void sp_attribute_widget_destroy (GtkObject *object);
 
32
 
 
33
static void sp_attribute_widget_changed (GtkEditable *editable);
 
34
 
 
35
static void sp_attribute_widget_object_modified ( SPObject *object, 
 
36
                                                  guint flags, 
 
37
                                                  SPAttributeWidget *spaw );
 
38
static void sp_attribute_widget_object_release ( SPObject *object, 
 
39
                                                 SPAttributeWidget *spaw );
 
40
 
 
41
static GtkEntryClass *parent_class;
 
42
 
 
43
 
 
44
 
 
45
 
 
46
GtkType
 
47
sp_attribute_widget_get_type (void)
 
48
{
 
49
    static GtkType type = 0;
 
50
    if (!type) {
 
51
        static const GtkTypeInfo info = {
 
52
            "SPAttributeWidget",
 
53
            sizeof (SPAttributeWidget),
 
54
            sizeof (SPAttributeWidgetClass),
 
55
            (GtkClassInitFunc) sp_attribute_widget_class_init,
 
56
            (GtkObjectInitFunc) sp_attribute_widget_init,
 
57
            NULL, NULL, NULL
 
58
        };
 
59
        type = gtk_type_unique (GTK_TYPE_ENTRY, &info);
 
60
    }
 
61
    return type;
 
62
    
 
63
} // end of sp_attribute_widget_get_type()
 
64
 
 
65
 
 
66
 
 
67
static void
 
68
sp_attribute_widget_class_init (SPAttributeWidgetClass *klass)
 
69
{
 
70
    GtkObjectClass *object_class;
 
71
    GtkWidgetClass *widget_class;
 
72
    GtkEditableClass *editable_class;
 
73
 
 
74
    object_class = GTK_OBJECT_CLASS (klass);
 
75
    widget_class = GTK_WIDGET_CLASS (klass);
 
76
    editable_class = GTK_EDITABLE_CLASS (klass);
 
77
 
 
78
    parent_class = (GtkEntryClass*)gtk_type_class (GTK_TYPE_ENTRY);
 
79
 
 
80
    object_class->destroy = sp_attribute_widget_destroy;
 
81
 
 
82
    editable_class->changed = sp_attribute_widget_changed;
 
83
 
 
84
} // end of sp_attribute_widget_class_init()
 
85
 
 
86
 
 
87
 
 
88
static void
 
89
sp_attribute_widget_init (SPAttributeWidget *spaw)
 
90
{
 
91
    spaw->blocked = FALSE;
 
92
    spaw->hasobj = FALSE;
 
93
 
 
94
    spaw->src.object = NULL;
 
95
 
 
96
    spaw->attribute = NULL;
 
97
}
 
98
 
 
99
 
 
100
 
 
101
static void
 
102
sp_attribute_widget_destroy (GtkObject *object)
 
103
{
 
104
    
 
105
    SPAttributeWidget *spaw;
 
106
 
 
107
    spaw = SP_ATTRIBUTE_WIDGET (object);
 
108
 
 
109
    if (spaw->attribute) {
 
110
        g_free (spaw->attribute);
 
111
        spaw->attribute = NULL;
 
112
    }
 
113
 
 
114
    
 
115
    if (spaw->hasobj) {
 
116
        
 
117
        if (spaw->src.object) {
 
118
            sp_signal_disconnect_by_data (spaw->src.object, spaw);
 
119
            spaw->src.object = NULL;
 
120
        }
 
121
    } else {
 
122
    
 
123
        if (spaw->src.repr) {
 
124
            spaw->src.repr = Inkscape::GC::release(spaw->src.repr);
 
125
        }
 
126
    } // end of if()
 
127
    
 
128
    ((GtkObjectClass *) parent_class)->destroy (object);
 
129
 
 
130
}
 
131
 
 
132
 
 
133
 
 
134
static void
 
135
sp_attribute_widget_changed (GtkEditable *editable)
 
136
{
 
137
 
 
138
    SPAttributeWidget *spaw;
 
139
 
 
140
    spaw = SP_ATTRIBUTE_WIDGET (editable);
 
141
 
 
142
    if (!spaw->blocked) {
 
143
    
 
144
        const gchar *text;
 
145
        spaw->blocked = TRUE;
 
146
        text = gtk_entry_get_text (GTK_ENTRY (spaw));
 
147
        if (!*text) 
 
148
            text = NULL;
 
149
        
 
150
        if (spaw->hasobj && spaw->src.object) {
 
151
            
 
152
            if (!sp_repr_set_attr ( SP_OBJECT_REPR (spaw->src.object), 
 
153
                                    spaw->attribute, text) )
 
154
            {
 
155
                /* Cannot set attribute */
 
156
                text = SP_OBJECT_REPR (spaw->src.object)->attribute(spaw->attribute);
 
157
                gtk_entry_set_text (GTK_ENTRY (spaw), text ? text : "");
 
158
            }
 
159
            sp_document_done (SP_OBJECT_DOCUMENT (spaw->src.object));
 
160
            
 
161
        } else if (spaw->src.repr) {
 
162
        
 
163
            if (!sp_repr_set_attr (spaw->src.repr, spaw->attribute, text))
 
164
            {
 
165
                /* Cannot set attribute */
 
166
                text = spaw->src.repr->attribute(spaw->attribute);
 
167
                gtk_entry_set_text (GTK_ENTRY (spaw), text ? text : "");
 
168
            }
 
169
            /* TODO: Warning! Undo will not be flushed in given case */
 
170
        }
 
171
        spaw->blocked = FALSE;
 
172
    }
 
173
    
 
174
} // end of sp_attribute_widget_changed()
 
175
 
 
176
 
 
177
 
 
178
GtkWidget *
 
179
sp_attribute_widget_new ( SPObject *object, const gchar *attribute )
 
180
{
 
181
    SPAttributeWidget *spaw;
 
182
 
 
183
    g_return_val_if_fail (!object || SP_IS_OBJECT (object), NULL);
 
184
    g_return_val_if_fail (!object || attribute, NULL);
 
185
 
 
186
    spaw = (SPAttributeWidget*)gtk_type_new (SP_TYPE_ATTRIBUTE_WIDGET);
 
187
 
 
188
    sp_attribute_widget_set_object (spaw, object, attribute);
 
189
 
 
190
    return GTK_WIDGET (spaw);
 
191
    
 
192
} // end of sp_attribute_widget_new()
 
193
 
 
194
 
 
195
 
 
196
GtkWidget *
 
197
sp_attribute_widget_new_repr ( Inkscape::XML::Node *repr, const gchar *attribute )
 
198
{
 
199
    SPAttributeWidget *spaw;
 
200
 
 
201
    spaw = (SPAttributeWidget*)gtk_type_new (SP_TYPE_ATTRIBUTE_WIDGET);
 
202
 
 
203
    sp_attribute_widget_set_repr (spaw, repr, attribute);
 
204
 
 
205
    return GTK_WIDGET (spaw);
 
206
}
 
207
 
 
208
 
 
209
 
 
210
void
 
211
sp_attribute_widget_set_object ( SPAttributeWidget *spaw, 
 
212
                                 SPObject *object, 
 
213
                                 const gchar *attribute )
 
214
{
 
215
 
 
216
    g_return_if_fail (spaw != NULL);
 
217
    g_return_if_fail (SP_IS_ATTRIBUTE_WIDGET (spaw));
 
218
    g_return_if_fail (!object || SP_IS_OBJECT (object));
 
219
    g_return_if_fail (!object || attribute);
 
220
    g_return_if_fail (attribute != NULL);
 
221
 
 
222
    if (spaw->attribute) {
 
223
        g_free (spaw->attribute);
 
224
        spaw->attribute = NULL;
 
225
    }
 
226
 
 
227
    if (spaw->hasobj) {
 
228
    
 
229
        if (spaw->src.object) {
 
230
            sp_signal_disconnect_by_data (spaw->src.object, spaw);
 
231
            spaw->src.object = NULL;
 
232
        }
 
233
    } else {
 
234
        
 
235
        if (spaw->src.repr) {
 
236
            spaw->src.repr = Inkscape::GC::release(spaw->src.repr);
 
237
        }
 
238
    }
 
239
 
 
240
    spaw->hasobj = TRUE;
 
241
 
 
242
    if (object) {
 
243
        const gchar *val;
 
244
 
 
245
        spaw->blocked = TRUE;
 
246
        spaw->src.object = object;
 
247
        g_signal_connect ( G_OBJECT (object), "modified", 
 
248
                           G_CALLBACK (sp_attribute_widget_object_modified), 
 
249
                           spaw );
 
250
        g_signal_connect ( G_OBJECT (object), "release", 
 
251
                           G_CALLBACK (sp_attribute_widget_object_release), 
 
252
                           spaw );
 
253
 
 
254
        spaw->attribute = g_strdup (attribute);
 
255
 
 
256
        val = SP_OBJECT_REPR (object)->attribute(attribute);
 
257
        gtk_entry_set_text (GTK_ENTRY (spaw), val ? val : (const gchar *) "");
 
258
        spaw->blocked = FALSE;
 
259
    }
 
260
 
 
261
    gtk_widget_set_sensitive (GTK_WIDGET (spaw), (spaw->src.object != NULL));
 
262
 
 
263
} // end of sp_attribute_widget_set_object()
 
264
 
 
265
 
 
266
 
 
267
void
 
268
sp_attribute_widget_set_repr ( SPAttributeWidget *spaw, 
 
269
                               Inkscape::XML::Node *repr, 
 
270
                               const gchar *attribute )
 
271
{
 
272
 
 
273
    g_return_if_fail (spaw != NULL);
 
274
    g_return_if_fail (SP_IS_ATTRIBUTE_WIDGET (spaw));
 
275
    g_return_if_fail (attribute != NULL);
 
276
 
 
277
    if (spaw->attribute) {
 
278
        g_free (spaw->attribute);
 
279
        spaw->attribute = NULL;
 
280
    }
 
281
 
 
282
    if (spaw->hasobj) {
 
283
    
 
284
        if (spaw->src.object) {
 
285
            sp_signal_disconnect_by_data (spaw->src.object, spaw);
 
286
            spaw->src.object = NULL;
 
287
        }
 
288
    } else {
 
289
        
 
290
        if (spaw->src.repr) {
 
291
            spaw->src.repr = Inkscape::GC::release(spaw->src.repr);
 
292
        }
 
293
    }
 
294
 
 
295
    spaw->hasobj = FALSE;
 
296
 
 
297
    if (repr) {
 
298
        const gchar *val;
 
299
 
 
300
        spaw->blocked = TRUE;
 
301
        spaw->src.repr = Inkscape::GC::anchor(repr);
 
302
        spaw->attribute = g_strdup (attribute);
 
303
 
 
304
        val = repr->attribute(attribute);
 
305
        gtk_entry_set_text (GTK_ENTRY (spaw), val ? val : (const gchar *) "");
 
306
        spaw->blocked = FALSE;
 
307
    }
 
308
 
 
309
    gtk_widget_set_sensitive (GTK_WIDGET (spaw), (spaw->src.repr != NULL));
 
310
 
 
311
} // end of sp_attribute_widget_set_repr()
 
312
 
 
313
 
 
314
 
 
315
static void
 
316
sp_attribute_widget_object_modified ( SPObject *object, 
 
317
                                      guint flags, 
 
318
                                      SPAttributeWidget *spaw )
 
319
{
 
320
 
 
321
    if (flags && SP_OBJECT_MODIFIED_FLAG) {
 
322
        
 
323
        const gchar *val, *text;
 
324
        val = SP_OBJECT_REPR (spaw->src.object)->attribute(spaw->attribute);
 
325
        text = gtk_entry_get_text (GTK_ENTRY (spaw));
 
326
        
 
327
        if (val || text) {
 
328
            
 
329
            if (!val || !text || strcmp (val, text)) {
 
330
                /* We are different */
 
331
                spaw->blocked = TRUE;
 
332
                gtk_entry_set_text ( GTK_ENTRY (spaw), 
 
333
                                     val ? val : (const gchar *) "");
 
334
                spaw->blocked = FALSE;
 
335
            } // end of if()
 
336
        
 
337
        } // end of if()
 
338
        
 
339
    } //end of if()
 
340
 
 
341
} // end of sp_attribute_widget_object_modified()
 
342
 
 
343
 
 
344
 
 
345
static void
 
346
sp_attribute_widget_object_release ( SPObject *object, 
 
347
                                     SPAttributeWidget *spaw )
 
348
{
 
349
    sp_attribute_widget_set_object (spaw, NULL, NULL);
 
350
}
 
351
 
 
352
 
 
353
 
 
354
/* SPAttributeTable */
 
355
 
 
356
static void sp_attribute_table_class_init (SPAttributeTableClass *klass);
 
357
static void sp_attribute_table_init (SPAttributeTable *widget);
 
358
static void sp_attribute_table_destroy (GtkObject *object);
 
359
 
 
360
static void sp_attribute_table_object_modified (SPObject *object, guint flags, SPAttributeTable *spaw);
 
361
static void sp_attribute_table_object_release (SPObject *object, SPAttributeTable *spaw);
 
362
static void sp_attribute_table_entry_changed (GtkEditable *editable, SPAttributeTable *spat);
 
363
 
 
364
static GtkVBoxClass *table_parent_class;
 
365
 
 
366
 
 
367
 
 
368
 
 
369
GtkType
 
370
sp_attribute_table_get_type (void)
 
371
{
 
372
    static GtkType type = 0;
 
373
    if (!type) {
 
374
        static const GtkTypeInfo info = {
 
375
            "SPAttributeTable",
 
376
            sizeof (SPAttributeTable),
 
377
            sizeof (SPAttributeTableClass),
 
378
            (GtkClassInitFunc) sp_attribute_table_class_init,
 
379
            (GtkObjectInitFunc) sp_attribute_table_init,
 
380
            NULL, NULL, NULL
 
381
        };
 
382
        type = gtk_type_unique (GTK_TYPE_VBOX, &info);
 
383
    }
 
384
    return type;
 
385
 
 
386
} // end of sp_attribute_table_get_type()
 
387
 
 
388
 
 
389
 
 
390
static void
 
391
sp_attribute_table_class_init (SPAttributeTableClass *klass)
 
392
{
 
393
    GtkObjectClass *object_class;
 
394
    GtkWidgetClass *widget_class;
 
395
 
 
396
    object_class = GTK_OBJECT_CLASS (klass);
 
397
    widget_class = GTK_WIDGET_CLASS (klass);
 
398
 
 
399
    table_parent_class = (GtkVBoxClass*)gtk_type_class (GTK_TYPE_VBOX);
 
400
 
 
401
    object_class->destroy = sp_attribute_table_destroy;
 
402
 
 
403
} // end of sp_attribute_table_class_init()
 
404
 
 
405
 
 
406
 
 
407
static void
 
408
sp_attribute_table_init ( SPAttributeTable *spat )
 
409
{
 
410
    spat->blocked = FALSE;
 
411
    spat->hasobj = FALSE;
 
412
    spat->table = NULL;
 
413
    spat->src.object = NULL;
 
414
    spat->num_attr = 0;
 
415
    spat->attributes = NULL;
 
416
    spat->entries = NULL;
 
417
}
 
418
 
 
419
static void
 
420
sp_attribute_table_destroy ( GtkObject *object )
 
421
{
 
422
    SPAttributeTable *spat;
 
423
 
 
424
    spat = SP_ATTRIBUTE_TABLE (object);
 
425
 
 
426
    if (spat->attributes) {
 
427
        gint i;
 
428
        for (i = 0; i < spat->num_attr; i++) {
 
429
            g_free (spat->attributes[i]);
 
430
        }
 
431
        g_free (spat->attributes);
 
432
        spat->attributes = NULL;
 
433
    }
 
434
 
 
435
    if (spat->hasobj) {
 
436
        
 
437
        if (spat->src.object) {
 
438
            sp_signal_disconnect_by_data (spat->src.object, spat);
 
439
            spat->src.object = NULL;
 
440
        }
 
441
    } else {
 
442
        if (spat->src.repr) {
 
443
            spat->src.repr = Inkscape::GC::release(spat->src.repr);
 
444
        }
 
445
    } // end of if()
 
446
 
 
447
    
 
448
    if (spat->entries) {
 
449
        g_free (spat->entries);
 
450
        spat->entries = NULL;
 
451
    }
 
452
 
 
453
    spat->table = NULL;
 
454
 
 
455
    if (((GtkObjectClass *) table_parent_class)->destroy) {
 
456
        (* ((GtkObjectClass *) table_parent_class)->destroy) (object);
 
457
    }
 
458
        
 
459
} // end of sp_attribute_table_destroy()
 
460
 
 
461
 
 
462
GtkWidget *
 
463
sp_attribute_table_new ( SPObject *object, 
 
464
                         gint num_attr, 
 
465
                         const gchar **labels, 
 
466
                         const gchar **attributes )
 
467
{
 
468
    SPAttributeTable *spat;
 
469
 
 
470
    g_return_val_if_fail (!object || SP_IS_OBJECT (object), NULL);
 
471
    g_return_val_if_fail (!object || (num_attr > 0), NULL);
 
472
    g_return_val_if_fail (!num_attr || (labels && attributes), NULL);
 
473
 
 
474
    spat = (SPAttributeTable*)gtk_type_new (SP_TYPE_ATTRIBUTE_TABLE);
 
475
 
 
476
    sp_attribute_table_set_object (spat, object, num_attr, labels, attributes);
 
477
 
 
478
    return GTK_WIDGET (spat);
 
479
 
 
480
} // end of sp_attribute_table_new()
 
481
 
 
482
 
 
483
 
 
484
GtkWidget *
 
485
sp_attribute_table_new_repr ( Inkscape::XML::Node *repr, 
 
486
                              gint num_attr, 
 
487
                              const gchar **labels, 
 
488
                              const gchar **attributes )
 
489
{
 
490
    SPAttributeTable *spat;
 
491
 
 
492
    g_return_val_if_fail (!num_attr || (labels && attributes), NULL);
 
493
 
 
494
    spat = (SPAttributeTable*)gtk_type_new (SP_TYPE_ATTRIBUTE_TABLE);
 
495
 
 
496
    sp_attribute_table_set_repr (spat, repr, num_attr, labels, attributes);
 
497
 
 
498
    return GTK_WIDGET (spat);
 
499
 
 
500
} // end of sp_attribute_table_new_repr()
 
501
 
 
502
 
 
503
 
 
504
#define XPAD 4
 
505
#define YPAD 0
 
506
 
 
507
void
 
508
sp_attribute_table_set_object ( SPAttributeTable *spat, 
 
509
                                SPObject *object, 
 
510
                                gint num_attr, 
 
511
                                const gchar **labels, 
 
512
                                const gchar **attributes )
 
513
{
 
514
 
 
515
    g_return_if_fail (spat != NULL);
 
516
    g_return_if_fail (SP_IS_ATTRIBUTE_TABLE (spat));
 
517
    g_return_if_fail (!object || SP_IS_OBJECT (object));
 
518
    g_return_if_fail (!object || (num_attr > 0));
 
519
    g_return_if_fail (!num_attr || (labels && attributes));
 
520
 
 
521
    if (spat->table) {
 
522
        gtk_widget_destroy (spat->table);
 
523
        spat->table = NULL;
 
524
    }
 
525
 
 
526
    if (spat->attributes) {
 
527
        gint i;
 
528
        for (i = 0; i < spat->num_attr; i++) {
 
529
            g_free (spat->attributes[i]);
 
530
        }
 
531
        g_free (spat->attributes);
 
532
        spat->attributes = NULL;
 
533
    }
 
534
 
 
535
    if (spat->entries) {
 
536
        g_free (spat->entries);
 
537
        spat->entries = NULL;
 
538
    }
 
539
 
 
540
    if (spat->hasobj) {
 
541
        if (spat->src.object) {
 
542
            sp_signal_disconnect_by_data (spat->src.object, spat);
 
543
            spat->src.object = NULL;
 
544
        }
 
545
    } else {
 
546
        if (spat->src.repr) {
 
547
            spat->src.repr = Inkscape::GC::release(spat->src.repr);
 
548
        }
 
549
    }
 
550
 
 
551
    spat->hasobj = TRUE;
 
552
 
 
553
    if (object) {
 
554
        gint i;
 
555
 
 
556
        spat->blocked = TRUE;
 
557
 
 
558
        /* Set up object */
 
559
        spat->src.object = object;
 
560
        spat->num_attr = num_attr;
 
561
        g_signal_connect ( G_OBJECT (object), "modified", 
 
562
                           G_CALLBACK (sp_attribute_table_object_modified), 
 
563
                           spat );
 
564
        g_signal_connect ( G_OBJECT (object), "release", 
 
565
                           G_CALLBACK (sp_attribute_table_object_release), 
 
566
                           spat );
 
567
        /* Create table */
 
568
        spat->table = gtk_table_new (num_attr, 2, FALSE);
 
569
        gtk_container_add (GTK_CONTAINER (spat), spat->table);
 
570
        /* Arrays */
 
571
        spat->attributes = g_new0 (gchar *, num_attr);
 
572
        spat->entries = g_new0 (GtkWidget *, num_attr);
 
573
        /* Fill rows */
 
574
        for (i = 0; i < num_attr; i++) {
 
575
            GtkWidget *w;
 
576
            const gchar *val;
 
577
 
 
578
            spat->attributes[i] = g_strdup (attributes[i]);
 
579
            w = gtk_label_new (_(labels[i]));
 
580
            gtk_widget_show (w);
 
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, 
 
583
                               GTK_FILL, 
 
584
                               (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), 
 
585
                               XPAD, YPAD );
 
586
            w = gtk_entry_new ();
 
587
            gtk_widget_show (w);
 
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), 
 
593
                               XPAD, YPAD );
 
594
            spat->entries[i] = w;
 
595
            g_signal_connect ( G_OBJECT (w), "changed", 
 
596
                               G_CALLBACK (sp_attribute_table_entry_changed), 
 
597
                               spat );
 
598
        }
 
599
        /* Show table */
 
600
        gtk_widget_show (spat->table);
 
601
 
 
602
        spat->blocked = FALSE;
 
603
    }
 
604
 
 
605
    gtk_widget_set_sensitive ( GTK_WIDGET (spat), 
 
606
                               (spat->src.object != NULL) );
 
607
 
 
608
} // end of sp_attribute_table_set_object()
 
609
 
 
610
 
 
611
 
 
612
void
 
613
sp_attribute_table_set_repr ( SPAttributeTable *spat, 
 
614
                              Inkscape::XML::Node *repr, 
 
615
                              gint num_attr, 
 
616
                              const gchar **labels, 
 
617
                              const gchar **attributes )
 
618
{
 
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));
 
622
 
 
623
    if (spat->table) {
 
624
        gtk_widget_destroy (spat->table);
 
625
        spat->table = NULL;
 
626
    }
 
627
 
 
628
    if (spat->attributes) {
 
629
        gint i;
 
630
        for (i = 0; i < spat->num_attr; i++) {
 
631
            g_free (spat->attributes[i]);
 
632
        }
 
633
        g_free (spat->attributes);
 
634
        spat->attributes = NULL;
 
635
    }
 
636
 
 
637
    if (spat->entries) {
 
638
        g_free (spat->entries);
 
639
        spat->entries = NULL;
 
640
    }
 
641
 
 
642
    if (spat->hasobj) {
 
643
        if (spat->src.object) {
 
644
            sp_signal_disconnect_by_data (spat->src.object, spat);
 
645
            spat->src.object = NULL;
 
646
        }
 
647
    } else {
 
648
        if (spat->src.repr) {
 
649
            spat->src.repr = Inkscape::GC::release(spat->src.repr);
 
650
        }
 
651
    }
 
652
 
 
653
    spat->hasobj = FALSE;
 
654
 
 
655
    if (repr) {
 
656
        gint i;
 
657
 
 
658
        spat->blocked = TRUE;
 
659
 
 
660
        /* Set up repr */
 
661
        spat->src.repr = Inkscape::GC::anchor(repr);
 
662
        spat->num_attr = num_attr;
 
663
        /* Create table */
 
664
        spat->table = gtk_table_new (num_attr, 2, FALSE);
 
665
        gtk_container_add (GTK_CONTAINER (spat), spat->table);
 
666
        /* Arrays */
 
667
        spat->attributes = g_new0 (gchar *, num_attr);
 
668
        spat->entries = g_new0 (GtkWidget *, num_attr);
 
669
        
 
670
        /* Fill rows */
 
671
        for (i = 0; i < num_attr; i++) {
 
672
            GtkWidget *w;
 
673
            const gchar *val;
 
674
 
 
675
            spat->attributes[i] = g_strdup (attributes[i]);
 
676
            w = gtk_label_new (labels[i]);
 
677
            gtk_widget_show (w);
 
678
            gtk_misc_set_alignment (GTK_MISC (w), 1.0, 0.5);
 
679
            gtk_table_attach ( GTK_TABLE (spat->table), w, 0, 1, i, i + 1, 
 
680
                               GTK_FILL, 
 
681
                               (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), 
 
682
                               XPAD, YPAD );
 
683
            w = gtk_entry_new ();
 
684
            gtk_widget_show (w);
 
685
            val = repr->attribute(attributes[i]);
 
686
            gtk_entry_set_text (GTK_ENTRY (w), val ? val : (const gchar *) "");
 
687
            gtk_table_attach ( GTK_TABLE (spat->table), w, 1, 2, i, i + 1, 
 
688
                               (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), 
 
689
                               (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), 
 
690
                               XPAD, YPAD );
 
691
            spat->entries[i] = w;
 
692
            g_signal_connect ( G_OBJECT (w), "changed", 
 
693
                               G_CALLBACK (sp_attribute_table_entry_changed), 
 
694
                               spat );
 
695
        }
 
696
        /* Show table */
 
697
        gtk_widget_show (spat->table);
 
698
 
 
699
        spat->blocked = FALSE;
 
700
    }
 
701
 
 
702
    gtk_widget_set_sensitive (GTK_WIDGET (spat), (spat->src.repr != NULL));
 
703
 
 
704
} // end of sp_attribute_table_set_repr()
 
705
 
 
706
 
 
707
 
 
708
static void
 
709
sp_attribute_table_object_modified ( SPObject *object, 
 
710
                                     guint flags, 
 
711
                                     SPAttributeTable *spat )
 
712
{
 
713
    if (flags && SP_OBJECT_MODIFIED_FLAG)
 
714
    {
 
715
        gint i;
 
716
        for (i = 0; i < spat->num_attr; i++) {
 
717
            const gchar *val, *text;
 
718
            val = SP_OBJECT_REPR (spat->src.object)->attribute(spat->attributes[i]);
 
719
            text = gtk_entry_get_text (GTK_ENTRY (spat->entries[i]));
 
720
            if (val || text) {
 
721
                if (!val || !text || strcmp (val, text)) {
 
722
                    /* We are different */
 
723
                    spat->blocked = TRUE;
 
724
                    gtk_entry_set_text ( GTK_ENTRY (spat->entries[i]), 
 
725
                                         val ? val : (const gchar *) "");
 
726
                    spat->blocked = FALSE;
 
727
                }
 
728
            }
 
729
        }
 
730
    } // end of if()
 
731
    
 
732
} // end of sp_attribute_table_object_modified()
 
733
 
 
734
 
 
735
 
 
736
static void
 
737
sp_attribute_table_object_release (SPObject *object, SPAttributeTable *spat)
 
738
{
 
739
    sp_attribute_table_set_object (spat, NULL, 0, NULL, NULL);
 
740
}
 
741
 
 
742
 
 
743
 
 
744
static void
 
745
sp_attribute_table_entry_changed ( GtkEditable *editable, 
 
746
                                   SPAttributeTable *spat )
 
747
{
 
748
    if (!spat->blocked)
 
749
    {
 
750
        gint i;
 
751
        for (i = 0; i < spat->num_attr; i++) {
 
752
        
 
753
            if (GTK_WIDGET (editable) == spat->entries[i]) {
 
754
                const gchar *text;
 
755
                spat->blocked = TRUE;
 
756
                text = gtk_entry_get_text (GTK_ENTRY (spat->entries[i]));
 
757
                
 
758
                if (!*text) 
 
759
                    text = NULL;
 
760
                
 
761
                if (spat->hasobj && spat->src.object) {
 
762
                    if (!sp_repr_set_attr ( SP_OBJECT_REPR (spat->src.object), 
 
763
                                            spat->attributes[i], text))
 
764
                    {
 
765
                        /* Cannot set attribute */
 
766
                        text = SP_OBJECT_REPR (spat->src.object)->attribute(spat->attributes[i]);
 
767
                        gtk_entry_set_text ( GTK_ENTRY (spat->entries[i]), 
 
768
                                             text ? text : (const gchar *) "");
 
769
                    }
 
770
                    sp_document_done (SP_OBJECT_DOCUMENT (spat->src.object));
 
771
                    
 
772
                } else if (spat->src.repr) {
 
773
                    
 
774
                    if (!sp_repr_set_attr (spat->src.repr, 
 
775
                                           spat->attributes[i], text)) 
 
776
                    {
 
777
                        /* Cannot set attribute */
 
778
                        text = spat->src.repr->attribute(spat->attributes[i]);
 
779
                        gtk_entry_set_text ( GTK_ENTRY (spat->entries[i]), 
 
780
                                             text ? text : (const gchar *) "" );
 
781
                    }
 
782
                    /* TODO: Warning! Undo will not be flushed in given case */
 
783
                }
 
784
                spat->blocked = FALSE;
 
785
                return;
 
786
            }
 
787
        }
 
788
        g_warning ("file %s: line %d: Entry signalled change, but there is no such entry", __FILE__, __LINE__);
 
789
    } // end of if()
 
790
 
 
791
} // end of sp_attribute_table_entry_changed()
 
792
 
 
793
/*
 
794
  Local Variables:
 
795
  mode:c++
 
796
  c-file-style:"stroustrup"
 
797
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
 
798
  indent-tabs-mode:nil
 
799
  fill-column:99
 
800
  End:
 
801
*/
 
802
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :