~ubuntu-branches/ubuntu/utopic/inkscape/utopic-proposed

« back to all changes in this revision

Viewing changes to inkscape-0.47pre1/src/widgets/sp-attribute-widget.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Bryce Harrington
  • Date: 2009-07-02 17:09:45 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20090702170945-nn6d6zswovbwju1t
Tags: 0.47~pre1-0ubuntu1
* New upstream release.
  - Don't constrain maximization on small resolution devices (pre0)
    (LP: #348842)
  - Fixes segfault on startup (pre0)
    (LP: #391149)

Show diffs side-by-side

added added

removed removed

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