]> git.sur5r.net Git - glabels/blob - glabels2/src/ui-property-bar.c
2005-04-08 Jim Evins <evins@snaught.com>
[glabels] / glabels2 / src / ui-property-bar.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  property-bar.c:  gLabels property bar
5  *
6  *  Copyright (C) 2003  Jim Evins <evins@snaught.com>.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21  */
22
23 #include <config.h>
24
25 #include <glib/gi18n.h>
26 #include <libgnomeprint/gnome-font.h>
27
28 #include "ui-property-bar.h"
29 #include "ui-util.h"
30 #include "mygal/widget-color-combo.h"
31 #include "stock-pixmaps/stockpixbufs.h"
32 #include "prefs.h"
33 #include "color.h"
34
35 #include "debug.h"
36
37 /*============================================================================*/
38 /* Private macros and constants.                                              */
39 /*============================================================================*/
40
41 /*============================================================================*/
42 /* Private globals                                                            */
43 /*============================================================================*/
44
45 static GObjectClass *parent_class;
46
47 static gchar* doc_verbs [] = {
48         "/commands/PropFontName",
49         "/commands/PropFontSize",
50         "/commands/PropFontBold",
51         "/commands/PropFontItalic",
52         "/commands/PropTextAlignLeft",
53         "/commands/PropTextAlignCenter",
54         "/commands/PropTextAlignRight",
55         "/commands/PropFillColor",
56         "/commands/PropLineColor",
57         "/commands/PropTextColor",
58         "/commands/PropLineWidth",
59
60         NULL
61 };
62
63 static gchar* text_verbs [] = {
64         "/commands/PropFontName",
65         "/commands/PropFontSize",
66         "/commands/PropFontBold",
67         "/commands/PropFontItalic",
68         "/commands/PropTextAlignLeft",
69         "/commands/PropTextAlignCenter",
70         "/commands/PropTextAlignRight",
71         "/commands/PropTextColor",
72
73         NULL
74 };
75
76 static gchar* fill_verbs [] = {
77         "/commands/PropFillColor",
78
79         NULL
80 };
81
82 static gchar* line_color_verbs [] = {
83         "/commands/PropLineColor",
84
85         NULL
86 };
87
88 static gchar* line_width_verbs [] = {
89         "/commands/PropLineWidth",
90
91         NULL
92 };
93
94
95 /*============================================================================*/
96 /* Local function prototypes                                                  */
97 /*============================================================================*/
98
99 static void     gl_ui_property_bar_class_init    (glUIPropertyBarClass *class);
100 static void     gl_ui_property_bar_instance_init (glUIPropertyBar      *property_bar);
101 static void     gl_ui_property_bar_finalize      (GObject              *object);
102
103 static void     gl_ui_property_bar_construct     (glUIPropertyBar      *property_bar,
104                                                   BonoboUIComponent    *ui_component);
105
106 static void     selection_changed_cb             (glUIPropertyBar      *property_bar);
107
108 static void     font_family_changed_cb           (GtkComboBox          *combo,
109                                                   glUIPropertyBar      *property_bar);
110
111 static void     font_size_changed_cb             (GtkSpinButton        *spin,
112                                                   glUIPropertyBar      *property_bar);
113
114 static void     text_color_changed_cb            (ColorCombo           *cc,
115                                                   GdkColor             *gdk_color,
116                                                   gboolean              custom,
117                                                   gboolean              by_user,
118                                                   gboolean              is_default,
119                                                   glUIPropertyBar      *property_bar);
120
121 static void     fill_color_changed_cb            (ColorCombo           *cc,
122                                                   GdkColor             *gdk_color,
123                                                   gboolean              custom,
124                                                   gboolean              by_user,
125                                                   gboolean              is_default,
126                                                   glUIPropertyBar      *property_bar);
127
128 static void     line_color_changed_cb            (ColorCombo           *cc,
129                                                   GdkColor             *gdk_color,
130                                                   gboolean              custom,
131                                                   gboolean              by_user,
132                                                   gboolean              is_default,
133                                                   glUIPropertyBar      *property_bar);
134
135 static void     line_width_changed_cb            (GtkSpinButton        *spin,
136                                                   glUIPropertyBar      *property_bar);
137
138 static void prop_item_toggled_cb (BonoboUIComponent           *ui_component,
139                                   const char                  *path,
140                                   Bonobo_UIComponent_EventType type,
141                                   const char                  *state,
142                                   glUIPropertyBar             *property_bar);
143
144 static void null_cmd             (BonoboUIComponent           *ui_component,
145                                   gpointer                     user_data,
146                                   const gchar                 *verbname);
147
148
149
150 \f
151 /****************************************************************************/
152 /* Boilerplate Object stuff.                                                */
153 /****************************************************************************/
154 GType
155 gl_ui_property_bar_get_type (void)
156 {
157         static GType type = 0;
158
159         if (!type) {
160                 static const GTypeInfo info = {
161                         sizeof (glUIPropertyBarClass),
162                         NULL,
163                         NULL,
164                         (GClassInitFunc) gl_ui_property_bar_class_init,
165                         NULL,
166                         NULL,
167                         sizeof (glUIPropertyBar),
168                         0,
169                         (GInstanceInitFunc) gl_ui_property_bar_instance_init,
170                         NULL
171                 };
172
173                 type = g_type_register_static (G_TYPE_OBJECT,
174                                                "glUIPropertyBar", &info, 0);
175         }
176
177         return type;
178 }
179
180 static void
181 gl_ui_property_bar_class_init (glUIPropertyBarClass *class)
182 {
183         GObjectClass   *object_class     = (GObjectClass *) class;
184
185         gl_debug (DEBUG_PROPERTY_BAR, "START");
186
187         parent_class = g_type_class_peek_parent (class);
188
189         object_class->finalize = gl_ui_property_bar_finalize;
190
191         gl_debug (DEBUG_PROPERTY_BAR, "END");
192 }
193
194 static void
195 gl_ui_property_bar_instance_init (glUIPropertyBar *property_bar)
196 {
197         gl_debug (DEBUG_PROPERTY_BAR, "START");
198
199         property_bar->view = NULL;
200
201         gl_debug (DEBUG_PROPERTY_BAR, "END");
202 }
203
204 static void
205 gl_ui_property_bar_finalize (GObject *object)
206 {
207         glUIPropertyBar *property_bar;
208
209         gl_debug (DEBUG_PROPERTY_BAR, "START");
210
211         g_return_if_fail (object != NULL);
212         g_return_if_fail (GL_IS_UI_PROPERTY_BAR (object));
213
214         property_bar = GL_UI_PROPERTY_BAR (object);
215
216         if (property_bar->view) {
217                 g_object_unref (G_OBJECT(property_bar->view));
218                 property_bar = NULL;
219         }
220
221         G_OBJECT_CLASS (parent_class)->finalize (object);
222
223         gl_debug (DEBUG_PROPERTY_BAR, "END");
224 }
225
226 /****************************************************************************/
227 /* Create a NEW property_bar.                                               */
228 /****************************************************************************/
229 GObject *
230 gl_ui_property_bar_new (BonoboUIComponent *ui_component)
231 {
232         glUIPropertyBar *property_bar;
233
234         gl_debug (DEBUG_PROPERTY_BAR, "START");
235
236         property_bar = g_object_new (gl_ui_property_bar_get_type (), NULL);
237
238         gl_ui_property_bar_construct (property_bar, ui_component);
239
240         gl_debug (DEBUG_PROPERTY_BAR, "END");
241
242         return G_OBJECT(property_bar);
243 }
244
245 /******************************************************************************/
246 /* Initialize property toolbar.                                               */
247 /******************************************************************************/
248 static void
249 gl_ui_property_bar_construct (glUIPropertyBar   *property_bar,
250                               BonoboUIComponent *ui_component)
251 {
252         GtkWidget  *wcombo;
253         GList      *family_names = NULL;
254         GList      *family_node;
255         GtkObject  *adjust;
256         ColorGroup *cg;
257         GdkPixbuf  *pixbuf;
258         GdkColor   *gdk_color;
259
260         gl_debug (DEBUG_PROPERTY_BAR, "START");
261
262         property_bar->stop_signals = TRUE;
263         property_bar->ui_component = ui_component;
264
265         /* Font family entry widget */
266         wcombo = gtk_combo_box_new_text ();
267         family_names = gnome_font_family_list ();
268         gl_util_combo_box_set_strings (GTK_COMBO_BOX (wcombo), family_names);
269         property_bar->font_family_combo = wcombo;
270         gtk_widget_set_size_request (wcombo, 200, -1);
271
272         /* Make sure we have a valid font.  if not provide a good default. */
273         family_node = g_list_find_custom (family_names,
274                                           gl_prefs->default_font_family,
275                                           (GCompareFunc)g_utf8_collate);
276         if (family_node) {
277                 gtk_combo_box_set_active (wcombo,
278                                           g_list_position (family_names,
279                                                            family_node));
280         } else {
281                 gtk_combo_box_set_active (wcombo, 0);
282         }
283         gnome_font_family_list_free (family_names);
284
285         g_signal_connect (G_OBJECT (property_bar->font_family_combo),
286                           "changed", G_CALLBACK (font_family_changed_cb), property_bar);
287
288         gl_ui_util_insert_widget (ui_component, wcombo, "/PropertyToolbar/PropFontName");
289
290         /* Font size entry widget */
291         adjust = gtk_adjustment_new (1.0, 1.0, 250.0, 1.0, 10.0, 10.0);
292         property_bar->font_size_spin =  gtk_spin_button_new (GTK_ADJUSTMENT (adjust),
293                                                              1.0, 0);
294         gtk_spin_button_set_value (GTK_SPIN_BUTTON(property_bar->font_size_spin),
295                                    gl_prefs->default_font_size);
296
297         g_signal_connect (G_OBJECT (property_bar->font_size_spin),
298                           "changed", G_CALLBACK (font_size_changed_cb), property_bar);
299
300         gl_ui_util_insert_widget (ui_component, property_bar->font_size_spin,
301                                   "/PropertyToolbar/PropFontSize");
302
303         /* Bold and Italic toggles */
304         bonobo_ui_component_add_verb (ui_component, "PropFontBold", null_cmd, NULL);
305         gl_ui_util_set_verb_state (ui_component, "/commands/PropFontBold",
306                                    (gl_prefs->default_font_weight == GNOME_FONT_BOLD));
307         bonobo_ui_component_add_listener (ui_component, "PropFontBold", 
308                         (BonoboUIListenerFn)prop_item_toggled_cb, 
309                         (gpointer)property_bar);
310         bonobo_ui_component_add_verb (ui_component, "PropFontItalic", null_cmd, NULL);
311         gl_ui_util_set_verb_state (ui_component, "/commands/PropFontItalic",
312                                    gl_prefs->default_font_italic_flag);
313         bonobo_ui_component_add_listener (ui_component, "PropFontItalic", 
314                         (BonoboUIListenerFn)prop_item_toggled_cb, 
315                         (gpointer)property_bar);
316
317         /* Text alignment radio group */
318         bonobo_ui_component_add_verb (ui_component, "PropTextAlignLeft", null_cmd, NULL);
319         gl_ui_util_set_verb_state (ui_component, "/commands/PropTextAlignLeft",
320                                    (gl_prefs->default_text_alignment == GTK_JUSTIFY_LEFT));
321         bonobo_ui_component_add_listener (ui_component, "PropTextAlignLeft", 
322                         (BonoboUIListenerFn)prop_item_toggled_cb, 
323                         (gpointer)property_bar);
324         bonobo_ui_component_add_verb (ui_component, "PropTextAlignCenter", null_cmd, NULL);
325         gl_ui_util_set_verb_state (ui_component, "/commands/PropTextAlignCenter",
326                                    (gl_prefs->default_text_alignment == GTK_JUSTIFY_CENTER));
327         bonobo_ui_component_add_listener (ui_component, "PropTextAlignCenter", 
328                         (BonoboUIListenerFn)prop_item_toggled_cb, 
329                         (gpointer)property_bar);
330         bonobo_ui_component_add_verb (ui_component, "PropTextAlignRight", null_cmd, NULL);
331         gl_ui_util_set_verb_state (ui_component, "/commands/PropTextAlignRight",
332                                    (gl_prefs->default_text_alignment == GTK_JUSTIFY_RIGHT));
333         bonobo_ui_component_add_listener (ui_component, "PropTextAlignRight", 
334                         (BonoboUIListenerFn)prop_item_toggled_cb, 
335                         (gpointer)property_bar);
336
337         /* Text color widget */
338         cg = color_group_fetch ("text_color_group", NULL);
339         pixbuf = gdk_pixbuf_new_from_inline (-1, stock_text_24, FALSE, NULL);
340         gdk_color = gl_color_to_gdk_color (gl_prefs->default_text_color);
341         property_bar->text_color_combo = color_combo_new (pixbuf, _("Default"),
342                                                           gdk_color, cg);
343         g_free (gdk_color);
344
345         g_signal_connect (G_OBJECT (property_bar->text_color_combo),
346                           "color_changed",
347                           G_CALLBACK (text_color_changed_cb), property_bar);
348
349         gl_ui_util_insert_widget (ui_component, property_bar->text_color_combo,
350                                   "/PropertyToolbar/PropTextColor");
351
352         /* Fill color widget */
353         cg = color_group_fetch ("fill_color_group", NULL);
354         pixbuf = gdk_pixbuf_new_from_inline (-1, stock_bucket_fill_24, FALSE, NULL);
355         gdk_color = gl_color_to_gdk_color (gl_prefs->default_fill_color);
356         property_bar->fill_color_combo = color_combo_new (pixbuf, _("No fill"),
357                                                           gdk_color, cg);
358         g_free (gdk_color);
359
360         g_signal_connect (G_OBJECT (property_bar->fill_color_combo),
361                           "color_changed",
362                           G_CALLBACK (fill_color_changed_cb), property_bar);
363
364         gl_ui_util_insert_widget (ui_component, property_bar->fill_color_combo,
365                                   "/PropertyToolbar/PropFillColor");
366
367         /* Line color widget */
368         cg = color_group_fetch ("line_color_group", NULL);
369         pixbuf = gdk_pixbuf_new_from_inline (-1, stock_pencil_24, FALSE, NULL);
370         gdk_color = gl_color_to_gdk_color (gl_prefs->default_line_color);
371         property_bar->line_color_combo = color_combo_new (pixbuf, _("No line"),
372                                                           gdk_color, cg);
373         g_free (gdk_color);
374
375         g_signal_connect (G_OBJECT (property_bar->line_color_combo),
376                           "color_changed",
377                           G_CALLBACK (line_color_changed_cb), property_bar);
378
379         gl_ui_util_insert_widget (ui_component, property_bar->line_color_combo,
380                                   "/PropertyToolbar/PropLineColor");
381
382         /* Line width entry widget */
383         adjust = gtk_adjustment_new (1.0, 0.25, 4.0, 0.25, 1.0, 1.0);
384         property_bar->line_width_spin =  gtk_spin_button_new (GTK_ADJUSTMENT (adjust), 0.25, 2);
385
386         g_signal_connect (G_OBJECT (property_bar->line_width_spin),
387                           "changed",
388                           G_CALLBACK (line_width_changed_cb), property_bar);
389
390         gl_ui_util_insert_widget (ui_component, property_bar->line_width_spin,
391                                   "/PropertyToolbar/PropLineWidth");
392
393         gl_ui_util_set_verb_list_sensitive (ui_component, doc_verbs, FALSE);
394
395         property_bar->stop_signals = FALSE;
396
397         gl_debug (DEBUG_PROPERTY_BAR, "END");
398 }
399
400 /****************************************************************************/
401 /* Fill widgets with default values.                                        */
402 /****************************************************************************/
403 static void
404 reset_to_default_properties (glView *view,
405                              glUIPropertyBar *property_bar)
406 {
407         GList     *family_names;
408         gchar     *good_font_family;
409         GdkColor  *gdk_color;
410
411         /* Make sure we have a valid font.  if not provide a good default. */
412         family_names = gnome_font_family_list ();
413         if (g_list_find_custom (family_names,
414                                 view->default_font_family,
415                                 (GCompareFunc)g_utf8_collate)) {
416                 good_font_family = g_strdup (view->default_font_family);
417         } else {
418                 if (family_names != NULL) {
419                         good_font_family = g_strdup (family_names->data); /* 1st entry */
420                 } else {
421                         good_font_family = NULL;
422                 }
423         }
424         gl_util_combo_box_set_active_text (GTK_COMBO_BOX (property_bar->font_family_combo),
425                                            good_font_family);
426         g_free (good_font_family);
427
428         gtk_spin_button_set_value (GTK_SPIN_BUTTON(property_bar->font_size_spin),
429                                    view->default_font_size);
430
431         gl_ui_util_set_verb_state (property_bar->ui_component,
432                                    "/commands/PropFontBold",
433                                    (view->default_font_weight == GNOME_FONT_BOLD));
434         gl_ui_util_set_verb_state (property_bar->ui_component,
435                                    "/commands/PropFontItalic",
436                                    view->default_font_italic_flag);
437
438         gl_ui_util_set_verb_state (property_bar->ui_component,
439                                    "/commands/PropTextAlignLeft",
440                                    (view->default_text_alignment == GTK_JUSTIFY_LEFT));
441         gl_ui_util_set_verb_state (property_bar->ui_component,
442                                    "/commands/PropTextAlignCenter",
443                                    (view->default_text_alignment == GTK_JUSTIFY_CENTER));
444         gl_ui_util_set_verb_state (property_bar->ui_component,
445                                    "/commands/PropTextAlignRight",
446                                    (view->default_text_alignment == GTK_JUSTIFY_RIGHT));
447
448         gdk_color = gl_color_to_gdk_color (view->default_text_color);
449         color_combo_set_color (COLOR_COMBO(property_bar->text_color_combo), gdk_color);
450         g_free (gdk_color);
451
452         gdk_color = gl_color_to_gdk_color (view->default_fill_color);
453         color_combo_set_color (COLOR_COMBO(property_bar->fill_color_combo), gdk_color);
454         g_free (gdk_color);
455
456         gdk_color = gl_color_to_gdk_color (view->default_line_color);
457         color_combo_set_color (COLOR_COMBO(property_bar->line_color_combo), gdk_color);
458         g_free (gdk_color);
459
460         gtk_spin_button_set_value (GTK_SPIN_BUTTON(property_bar->line_width_spin),
461                                    view->default_line_width);
462 }
463
464 /****************************************************************************/
465 /* Set view associated with property_bar.                                   */
466 /****************************************************************************/
467 void
468 gl_ui_property_bar_set_view (glUIPropertyBar *property_bar,
469                              glView          *view)
470 {
471         glLabel   *label;
472
473         gl_debug (DEBUG_PROPERTY_BAR, "START");
474
475         g_return_if_fail (view && GL_IS_VIEW (view));
476         label = view->label;
477         g_return_if_fail (label && GL_IS_LABEL (label));
478
479         gl_ui_util_set_verb_list_sensitive (property_bar->ui_component, doc_verbs, TRUE);
480
481         property_bar->view = GL_VIEW (g_object_ref (G_OBJECT (view)));
482
483         reset_to_default_properties (view, property_bar);
484
485         g_signal_connect_swapped (G_OBJECT(view), "selection_changed",
486                                   G_CALLBACK(selection_changed_cb), property_bar);
487
488         g_signal_connect_swapped (G_OBJECT(view->label), "changed",
489                                   G_CALLBACK(selection_changed_cb), property_bar);
490
491         gl_debug (DEBUG_PROPERTY_BAR, "END");
492 }
493
494 /*---------------------------------------------------------------------------*/
495 /* PRIVATE.  View "selection state changed" callback.                        */
496 /*---------------------------------------------------------------------------*/
497
498 static void
499 update_text_properties (glView *view,
500                         glUIPropertyBar *property_bar)
501 {
502         gboolean can_text, is_first_object;
503         gboolean is_same_font_family, is_same_font_size;
504         gboolean is_same_text_color, is_same_is_italic;
505         gboolean is_same_is_bold, is_same_justification;
506         GList *p;
507         glLabelObject *object;
508         gchar *selection_font_family, *font_family;
509         gdouble selection_font_size, font_size;
510         guint selection_text_color, text_color;
511         glColorNode *text_color_node;
512         gboolean selection_is_italic, is_italic;
513         gboolean selection_is_bold, is_bold;
514         GtkJustification selection_justification, justification;
515         GdkColor *gdk_color;
516
517         can_text = gl_view_can_selection_text (view);
518         gl_ui_util_set_verb_list_sensitive (property_bar->ui_component,
519                                             text_verbs,
520                                             can_text);
521         if (!can_text) 
522                 return;
523
524         is_same_is_italic =
525         is_same_is_bold =
526         is_same_justification =
527         is_same_text_color =
528         is_same_font_size =
529         is_same_font_family = TRUE;
530         selection_font_family = NULL;
531         selection_font_size = -1;
532         is_first_object = TRUE;
533         
534         for (p = view->selected_object_list; p != NULL; p = p->next) {
535
536                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
537                 if (!gl_label_object_can_text (object)) 
538                         continue;
539
540                 font_family = gl_label_object_get_font_family (object);
541                 if (font_family != NULL) {
542                         if (selection_font_family == NULL)
543                                 selection_font_family = g_strdup (font_family);
544                         else 
545                                 if (strcmp (font_family, selection_font_family) != 0) 
546                                         is_same_font_family = FALSE;
547                         g_free (font_family);
548                 }       
549
550                 font_size = gl_label_object_get_font_size (object);
551                 
552                 text_color_node = gl_label_object_get_text_color (object);
553                 if (text_color_node->field_flag) {
554                         /* If a merge field is set we use the default color for merged color*/
555                         text_color = GL_COLOR_MERGE_DEFAULT;
556                         
557                 } else {
558                         text_color = text_color_node->color;
559                 }
560                 gl_color_node_free (&text_color_node);
561                 
562                 is_italic = gl_label_object_get_font_italic_flag (object);
563                 is_bold = gl_label_object_get_font_weight (object) == GNOME_FONT_BOLD;
564                 justification = gl_label_object_get_text_alignment (object);
565
566                 if (is_first_object) {
567                         selection_font_size = font_size;
568                         selection_text_color = text_color;
569                         selection_is_italic = is_italic;
570                         selection_is_bold = is_bold;
571                         selection_justification = justification;
572                 } else {
573                         if (font_size != selection_font_size) 
574                                 is_same_font_size = FALSE;
575                         if (text_color != selection_text_color)
576                                 is_same_text_color = FALSE;
577                         if (is_italic != selection_is_italic)
578                                 is_same_is_italic = FALSE;
579                         if (is_bold != selection_is_bold)
580                                 is_same_is_bold = FALSE;
581                         if (justification != selection_justification)
582                                 is_same_justification = FALSE;
583                 }
584                 is_first_object = FALSE;
585         }
586
587         if (is_same_font_family && (selection_font_family != NULL)) 
588                 gl_debug (DEBUG_PROPERTY_BAR, "same font family = %s", 
589                           selection_font_family);
590         gl_util_combo_box_set_active_text (GTK_COMBO_BOX (property_bar->font_family_combo),
591                                            is_same_font_family?selection_font_family:"");
592         g_free (selection_font_family);
593
594         if (is_same_font_size) {
595                 gl_debug (DEBUG_PROPERTY_BAR, "same font size = %g", 
596                           selection_font_size);
597                 gtk_spin_button_set_value (GTK_SPIN_BUTTON (property_bar->font_size_spin),
598                                            selection_font_size);
599         } else {
600                 gtk_entry_set_text (GTK_ENTRY (property_bar->font_size_spin), "");
601         }
602
603         if (is_same_text_color) {
604                 gl_debug (DEBUG_PROPERTY_BAR, "same text color = %08x", selection_text_color);
605                 gdk_color = gl_color_to_gdk_color (selection_text_color);
606                 color_combo_set_color (COLOR_COMBO (property_bar->text_color_combo),
607                                        gdk_color);
608                 g_free (gdk_color);
609         }
610
611         if (is_same_is_italic)  
612                 gl_debug (DEBUG_PROPERTY_BAR, "same italic flag = %d", 
613                           selection_is_italic);
614         gl_ui_util_set_verb_state (property_bar->ui_component,
615                                    "/commands/PropFontItalic",
616                                    selection_is_italic && is_same_is_italic);
617
618         if (is_same_is_bold)  
619                 gl_debug (DEBUG_PROPERTY_BAR, "same bold flag = %d",
620                           selection_is_bold);
621         gl_ui_util_set_verb_state (property_bar->ui_component,
622                                    "/commands/PropFontBold",
623                                    selection_is_bold && is_same_is_bold);
624
625         if (is_same_justification) 
626                 gl_debug (DEBUG_PROPERTY_BAR, "same justification");
627         gl_ui_util_set_verb_state (property_bar->ui_component,
628                                    "/commands/PropTextAlignRight",
629                                    (selection_justification == GTK_JUSTIFY_RIGHT) &&
630                                    is_same_justification);
631         gl_ui_util_set_verb_state (property_bar->ui_component,
632                                    "/commands/PropTextAlignLeft",
633                                    (selection_justification == GTK_JUSTIFY_LEFT) &&
634                                    is_same_justification);
635         gl_ui_util_set_verb_state (property_bar->ui_component,
636                                    "/commands/PropTextAlignCenter",
637                                    (selection_justification == GTK_JUSTIFY_CENTER) &&
638                                    is_same_justification);
639 }
640
641 static void
642 update_fill_color (glView *view,
643                    glUIPropertyBar *property_bar)
644 {
645         gboolean can, is_first_object;
646         gboolean is_same_fill_color;
647         GList *p;
648         glLabelObject *object;
649         guint selection_fill_color, fill_color;
650         GdkColor *gdk_color;
651         glColorNode *fill_color_node;
652
653         can = gl_view_can_selection_fill (view);
654         gl_ui_util_set_verb_list_sensitive (property_bar->ui_component,
655                                             fill_verbs,
656                                             can);
657         if (!can) 
658                 return;
659
660         is_same_fill_color = TRUE;
661         is_first_object = TRUE;
662         
663         for (p = view->selected_object_list; p != NULL; p = p->next) {
664
665                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
666                 if (!gl_label_object_can_fill (object)) 
667                         continue;
668
669                 fill_color_node = gl_label_object_get_fill_color (object);
670                 if (fill_color_node->field_flag) {
671                         /* If a merge field is set we use the default color for merged color*/
672                         fill_color = GL_COLOR_FILL_MERGE_DEFAULT;
673                         
674                 } else {
675                         fill_color = fill_color_node->color;
676                 }
677                 gl_color_node_free (&fill_color_node);
678
679                 if (is_first_object) {
680                         selection_fill_color = fill_color;
681                 } else {
682                         if (fill_color != selection_fill_color)
683                                 is_same_fill_color = FALSE;
684                 }
685                 is_first_object = FALSE;
686         }
687
688         if (is_same_fill_color) {
689                 gl_debug (DEBUG_PROPERTY_BAR, "same fill color = %08x", selection_fill_color);
690                 gdk_color = gl_color_to_gdk_color (selection_fill_color);
691                 color_combo_set_color (COLOR_COMBO (property_bar->fill_color_combo),
692                                        gdk_color);
693                 g_free (gdk_color);
694         }
695 }
696
697 static void
698 update_line_color (glView *view,
699                    glUIPropertyBar *property_bar)
700 {
701         gboolean can, is_first_object;
702         gboolean is_same_line_color;
703         GList *p;
704         glLabelObject *object;
705         guint selection_line_color, line_color;
706         glColorNode *line_color_node;
707         GdkColor *gdk_color;
708
709         can = gl_view_can_selection_line_color (view);
710         gl_ui_util_set_verb_list_sensitive (property_bar->ui_component,
711                                             line_color_verbs,
712                                             can);
713         if (!can) 
714                 return;
715
716         is_same_line_color = TRUE;
717         is_first_object = TRUE;
718         
719         for (p = view->selected_object_list; p != NULL; p = p->next) {
720
721                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
722                 if (!gl_label_object_can_line_color (object)) 
723                         continue;
724
725                 line_color_node = gl_label_object_get_line_color (object);
726                 if (line_color_node->field_flag) {
727                         /* If a merge field is set we use the default color for merged color*/
728                         line_color = GL_COLOR_MERGE_DEFAULT;
729                         
730                 } else {
731                         line_color = line_color_node->color;
732                 }
733                 gl_color_node_free (&line_color_node);
734
735                 if (is_first_object) {
736                         selection_line_color = line_color;
737                 } else {
738                         if (line_color != selection_line_color)
739                                 is_same_line_color = FALSE;
740                 }
741                 is_first_object = FALSE;
742         }
743
744         if (is_same_line_color) {
745                 gl_debug (DEBUG_PROPERTY_BAR, "same line color = %08x", selection_line_color);
746                 gdk_color = gl_color_to_gdk_color (selection_line_color);
747                 color_combo_set_color (COLOR_COMBO (property_bar->line_color_combo),
748                                        gdk_color);
749                 g_free (gdk_color);
750         }
751 }
752
753 static void
754 update_line_width (glView *view,
755                    glUIPropertyBar *property_bar)
756 {
757         gboolean can, is_first_object;
758         gboolean is_same_line_width;
759         GList *p;
760         glLabelObject *object;
761         gdouble selection_line_width, line_width;
762
763         can = gl_view_can_selection_line_width (view);
764         gl_ui_util_set_verb_list_sensitive (property_bar->ui_component,
765                                             line_width_verbs,
766                                             can);
767         if (!can) 
768                 return;
769
770         is_same_line_width = TRUE;
771         is_first_object = TRUE;
772         
773         for (p = view->selected_object_list; p != NULL; p = p->next) {
774
775                 object = gl_view_object_get_object(GL_VIEW_OBJECT (p->data));
776                 if (!gl_label_object_can_line_width (object)) 
777                         continue;
778
779                 line_width = gl_label_object_get_line_width (object);
780
781                 if (is_first_object) {
782                         selection_line_width = line_width;
783                 } else {
784                         if (line_width != selection_line_width)
785                                 is_same_line_width = FALSE;
786                 }
787                 is_first_object = FALSE;
788         }
789
790         if (is_same_line_width) {
791                 gl_debug (DEBUG_PROPERTY_BAR, "same line width = %g", selection_line_width);
792                 gtk_spin_button_set_value (GTK_SPIN_BUTTON (property_bar->line_width_spin),
793                                            selection_line_width);
794         } else {
795                 gtk_entry_set_text (GTK_ENTRY (property_bar->line_width_spin), "");
796         }
797 }
798
799 static void 
800 selection_changed_cb (glUIPropertyBar *property_bar)
801 {
802         glView *view = property_bar->view;
803         
804         gl_debug (DEBUG_PROPERTY_BAR, "START");
805
806         g_return_if_fail (view && GL_IS_VIEW (view));
807         g_return_if_fail (property_bar && GL_IS_UI_PROPERTY_BAR (property_bar));
808
809         property_bar->stop_signals = TRUE;
810
811         if (gl_view_is_selection_empty (view)) {
812
813                 /* No selection: make all controls active. */
814                 reset_to_default_properties (view, property_bar);
815                 gl_ui_util_set_verb_list_sensitive (property_bar->ui_component,
816                                                     doc_verbs, TRUE);
817
818         } else {
819
820                 update_text_properties (view, property_bar);
821                 update_fill_color (view, property_bar);
822                 update_line_color (view, property_bar);
823                 update_line_width (view, property_bar);
824
825         }
826
827         property_bar->stop_signals = FALSE;
828
829         gl_debug (DEBUG_PROPERTY_BAR, "END");
830 }
831
832 /*--------------------------------------------------------------------------*/
833 /* PRIVATE.  Font family entry changed.                                     */
834 /*--------------------------------------------------------------------------*/
835 static void
836 font_family_changed_cb (GtkComboBox     *combo,
837                         glUIPropertyBar *property_bar)
838 {
839         gchar *font_family;
840
841         if (property_bar->stop_signals)
842                 return;
843
844         gl_debug (DEBUG_PROPERTY_BAR, "START");
845
846         g_signal_handlers_block_by_func (G_OBJECT(property_bar->view->label),
847                                          selection_changed_cb,
848                                          property_bar);
849
850         font_family = gtk_combo_box_get_active_text (GTK_COMBO_BOX (combo));
851         if ( strlen(font_family) ) {
852                 gl_view_set_selection_font_family (property_bar->view,
853                                                    font_family);
854                 gl_view_set_default_font_family   (property_bar->view,
855                                                    font_family);
856         }
857         g_free (font_family);
858
859         g_signal_handlers_unblock_by_func (G_OBJECT(property_bar->view->label),
860                                            selection_changed_cb,
861                                            property_bar);
862
863         gl_debug (DEBUG_PROPERTY_BAR, "END");
864 }
865
866 /*--------------------------------------------------------------------------*/
867 /* PRIVATE.  Font size spin button changed.                                 */
868 /*--------------------------------------------------------------------------*/
869 static void
870 font_size_changed_cb (GtkSpinButton        *spin,
871                       glUIPropertyBar      *property_bar)
872 {
873         gdouble font_size;
874
875         if (property_bar->stop_signals)
876                 return;
877
878         gl_debug (DEBUG_PROPERTY_BAR, "START");
879
880         g_signal_handlers_block_by_func (G_OBJECT(property_bar->view->label),
881                                          selection_changed_cb,
882                                          property_bar);
883
884         font_size = gtk_spin_button_get_value (spin);
885
886         gl_view_set_selection_font_size (property_bar->view,
887                                          font_size);
888         gl_view_set_default_font_size   (property_bar->view,
889                                          font_size);
890
891         g_signal_handlers_unblock_by_func (G_OBJECT(property_bar->view->label),
892                                            selection_changed_cb,
893                                            property_bar);
894
895         gl_debug (DEBUG_PROPERTY_BAR, "END");
896 }
897
898 /*--------------------------------------------------------------------------*/
899 /* PRIVATE.  Text color combo changed.                                      */
900 /*--------------------------------------------------------------------------*/
901 static void
902 text_color_changed_cb (ColorCombo           *cc,
903                        GdkColor             *gdk_color,
904                        gboolean              custom,
905                        gboolean              by_user,
906                        gboolean              is_default,
907                        glUIPropertyBar      *property_bar)
908 {
909         glColorNode *text_color_node;
910
911         if (property_bar->stop_signals)
912                 return;
913
914         g_return_if_fail (property_bar && GL_IS_UI_PROPERTY_BAR (property_bar));
915
916         gl_debug (DEBUG_PROPERTY_BAR, "START");
917
918         g_signal_handlers_block_by_func (G_OBJECT(property_bar->view->label),
919                                          selection_changed_cb,
920                                          property_bar);
921
922         text_color_node = gl_color_node_new_default ();
923         text_color_node->color = gl_color_from_gdk_color (gdk_color);
924         
925         gl_debug (DEBUG_PROPERTY_BAR, "Color=%08x, Custom=%d, By_User=%d, Is_default=%d",
926                   text_color_node->color, custom, by_user, is_default);
927
928         if (is_default) {
929                 text_color_node->color = gl_prefs->default_text_color;
930                 gl_view_set_selection_text_color (property_bar->view,
931                                                   text_color_node);
932                 gl_view_set_default_text_color   (property_bar->view,
933                                                   gl_prefs->default_text_color);
934
935         } else {
936
937                 gl_view_set_selection_text_color (property_bar->view,
938                                                   text_color_node);
939                 gl_view_set_default_text_color   (property_bar->view,
940                                                   text_color_node->color);
941
942         }
943
944         gl_color_node_free (&text_color_node);
945         
946         g_signal_handlers_unblock_by_func (G_OBJECT(property_bar->view->label),
947                                            selection_changed_cb,
948                                            property_bar);
949
950         gl_debug (DEBUG_PROPERTY_BAR, "END");
951 }
952
953 /*--------------------------------------------------------------------------*/
954 /* PRIVATE.  Fill color combo changed.                                      */
955 /*--------------------------------------------------------------------------*/
956 static void
957 fill_color_changed_cb (ColorCombo           *cc,
958                        GdkColor             *gdk_color,
959                        gboolean              custom,
960                        gboolean              by_user,
961                        gboolean              is_default,
962                        glUIPropertyBar      *property_bar)
963 {
964         glColorNode *fill_color_node;
965
966         if (property_bar->stop_signals)
967                 return;
968
969         g_return_if_fail (property_bar && GL_IS_UI_PROPERTY_BAR (property_bar));
970
971         gl_debug (DEBUG_PROPERTY_BAR, "START");
972
973         g_signal_handlers_block_by_func (G_OBJECT(property_bar->view->label),
974                                          selection_changed_cb,
975                                          property_bar);
976
977         fill_color_node = gl_color_node_new_default ();
978
979         fill_color_node->color = gl_color_from_gdk_color (gdk_color);
980
981         gl_debug (DEBUG_PROPERTY_BAR, "Color=%08x, Custom=%d, By_User=%d, Is_default=%d",
982                   fill_color_node->color, custom, by_user, is_default);
983
984         if (is_default) {
985
986                 fill_color_node->color = GL_COLOR_NONE;
987                 gl_view_set_selection_fill_color (property_bar->view,
988                                                   fill_color_node);
989                 gl_view_set_default_fill_color   (property_bar->view,
990                                                   fill_color_node->color);
991
992         } else {
993
994                 gl_view_set_selection_fill_color (property_bar->view,
995                                                   fill_color_node);
996                 gl_view_set_default_fill_color   (property_bar->view,
997                                                   fill_color_node->color);
998
999         }
1000         gl_color_node_free (&fill_color_node);
1001         
1002         g_signal_handlers_unblock_by_func (G_OBJECT(property_bar->view->label),
1003                                            selection_changed_cb,
1004                                            property_bar);
1005
1006         gl_debug (DEBUG_PROPERTY_BAR, "END");
1007 }
1008
1009 /*--------------------------------------------------------------------------*/
1010 /* PRIVATE.  Line color combo changed.                                      */
1011 /*--------------------------------------------------------------------------*/
1012 static void
1013 line_color_changed_cb (ColorCombo           *cc,
1014                        GdkColor             *gdk_color,
1015                        gboolean              custom,
1016                        gboolean              by_user,
1017                        gboolean              is_default,
1018                        glUIPropertyBar      *property_bar)
1019 {
1020         glColorNode *line_color_node;
1021
1022         if (property_bar->stop_signals)
1023                 return;
1024
1025         g_return_if_fail (property_bar && GL_IS_UI_PROPERTY_BAR (property_bar));
1026
1027         gl_debug (DEBUG_PROPERTY_BAR, "START");
1028
1029         g_signal_handlers_block_by_func (G_OBJECT(property_bar->view->label),
1030                                          selection_changed_cb,
1031                                          property_bar);
1032
1033         line_color_node = gl_color_node_new_default ();
1034         line_color_node->color = gl_color_from_gdk_color (gdk_color);
1035
1036         gl_debug (DEBUG_PROPERTY_BAR, "Color=%08x, Custom=%d, By_User=%d, Is_default=%d",
1037                   line_color_node->color, custom, by_user, is_default);
1038
1039         if (is_default) {
1040                 line_color_node->color = GL_COLOR_NONE;
1041                 gl_view_set_selection_line_color (property_bar->view,
1042                                                   line_color_node);
1043                 gl_view_set_default_line_color   (property_bar->view,
1044                                                   line_color_node->color);
1045
1046         } else {
1047
1048                 gl_view_set_selection_line_color (property_bar->view,
1049                                                   line_color_node);
1050                 gl_view_set_default_line_color   (property_bar->view,
1051                                                   line_color_node->color);
1052
1053         }
1054         gl_color_node_free (&line_color_node);
1055
1056         g_signal_handlers_unblock_by_func (G_OBJECT(property_bar->view->label),
1057                                            selection_changed_cb,
1058                                            property_bar);
1059
1060         gl_debug (DEBUG_PROPERTY_BAR, "END");
1061 }
1062
1063 /*--------------------------------------------------------------------------*/
1064 /* PRIVATE.  Line width spin button changed.                                */
1065 /*--------------------------------------------------------------------------*/
1066 static void
1067 line_width_changed_cb (GtkSpinButton        *spin,
1068                        glUIPropertyBar      *property_bar)
1069 {
1070         gdouble line_width;
1071
1072         if (property_bar->stop_signals)
1073                 return;
1074
1075         gl_debug (DEBUG_PROPERTY_BAR, "START");
1076
1077         g_signal_handlers_block_by_func (G_OBJECT(property_bar->view->label),
1078                                          selection_changed_cb,
1079                                          property_bar);
1080
1081         line_width = gtk_spin_button_get_value (spin);
1082
1083         gl_view_set_selection_line_width (property_bar->view,
1084                                           line_width);
1085         gl_view_set_default_line_width   (property_bar->view,
1086                                           line_width);
1087
1088         g_signal_handlers_unblock_by_func (G_OBJECT(property_bar->view->label),
1089                                            selection_changed_cb,
1090                                            property_bar);
1091
1092         gl_debug (DEBUG_PROPERTY_BAR, "END");
1093 }
1094
1095 /*---------------------------------------------------------------------------*/
1096 /* PRIVATE.  Property bar item toggled callback.                             */
1097 /*---------------------------------------------------------------------------*/
1098 static void
1099 prop_item_toggled_cb (BonoboUIComponent           *ui_component,
1100                       const char                  *path,
1101                       Bonobo_UIComponent_EventType type,
1102                       const char                  *state,
1103                       glUIPropertyBar             *property_bar)
1104 {
1105         gboolean s;
1106
1107         if (property_bar->stop_signals)
1108                 return;
1109
1110         gl_debug (DEBUG_PROPERTY_BAR, "");
1111
1112         g_signal_handlers_block_by_func (G_OBJECT(property_bar->view->label),
1113                                          selection_changed_cb,
1114                                          property_bar);
1115
1116         s = (strcmp (state, "1") == 0);
1117
1118         /*
1119          * Font properties: Bold & Italic
1120          */
1121         if (strcmp (path, "PropFontBold") == 0)
1122         {               
1123                 GnomeFontWeight weight = s ? GNOME_FONT_BOLD : GNOME_FONT_BOOK;
1124
1125                 gl_view_set_selection_font_weight (property_bar->view, weight);
1126                 gl_view_set_default_font_weight   (property_bar->view, weight);
1127         }
1128
1129         if (strcmp (path, "PropFontItalic") == 0)
1130         {               
1131                 gl_view_set_selection_font_italic_flag (property_bar->view, s);
1132                 gl_view_set_default_font_italic_flag   (property_bar->view, s);
1133         }
1134
1135
1136         /*
1137          * Text alignment group
1138          */
1139         if (s && (strcmp (path, "PropTextAlignLeft") == 0))
1140         {               
1141                 gl_view_set_selection_text_alignment (property_bar->view,
1142                                                       GTK_JUSTIFY_LEFT);
1143                 gl_view_set_default_text_alignment   (property_bar->view,
1144                                                       GTK_JUSTIFY_LEFT);
1145
1146                 /* Adjust state of siblings */
1147                 gl_ui_util_set_verb_state (ui_component,
1148                                            "/commands/PropTextAlignCenter",
1149                                            FALSE);
1150                 gl_ui_util_set_verb_state (ui_component,
1151                                            "/commands/PropTextAlignRight",
1152                                            FALSE);
1153         }
1154
1155         if (s && (strcmp (path, "PropTextAlignCenter") == 0))
1156         {               
1157                 gl_view_set_selection_text_alignment (property_bar->view,
1158                                                       GTK_JUSTIFY_CENTER);
1159                 gl_view_set_default_text_alignment   (property_bar->view,
1160                                                       GTK_JUSTIFY_CENTER);
1161
1162                 /* Adjust state of siblings */
1163                 gl_ui_util_set_verb_state (ui_component,
1164                                            "/commands/PropTextAlignLeft",
1165                                            FALSE);
1166                 gl_ui_util_set_verb_state (ui_component,
1167                                            "/commands/PropTextAlignRight",
1168                                            FALSE);
1169         }
1170
1171         if (s && (strcmp (path, "PropTextAlignRight") == 0))
1172         {               
1173                 gl_view_set_selection_text_alignment (property_bar->view,
1174                                                       GTK_JUSTIFY_RIGHT);
1175                 gl_view_set_default_text_alignment   (property_bar->view,
1176                                                       GTK_JUSTIFY_RIGHT);
1177
1178                 /* Adjust state of siblings */
1179                 gl_ui_util_set_verb_state (ui_component,
1180                                            "/commands/PropTextAlignLeft",
1181                                            FALSE);
1182                 gl_ui_util_set_verb_state (ui_component,
1183                                            "/commands/PropTextAlignCenter",
1184                                            FALSE);
1185         }
1186
1187         g_signal_handlers_unblock_by_func (G_OBJECT(property_bar->view->label),
1188                                            selection_changed_cb,
1189                                            property_bar);
1190
1191 }
1192
1193 /*---------------------------------------------------------------------------------------*/
1194 /* NULL command handler -- hides bogus "verb not found" errors for toggle toolbar items. */
1195 /*---------------------------------------------------------------------------------------*/
1196 static void
1197 null_cmd (BonoboUIComponent           *ui_component,
1198           gpointer                     user_data,
1199           const gchar                 *verbname)
1200 {
1201 }