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