]> git.sur5r.net Git - glabels/blob - glabels2/src/object-editor.c
2005-01-22 Jim Evins <evins@snaught.com>
[glabels] / glabels2 / src / object-editor.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  object-editor.c:  object properties editor module
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 #include <config.h>
23
24 #include <gnome.h>
25 #include <glade/glade-xml.h>
26 #include <math.h>
27
28 #include "object-editor.h"
29 #include "prefs.h"
30 #include "mygal/widget-color-combo.h"
31 #include "color.h"
32 #include "wdgt-chain-button.h"
33 #include "marshal.h"
34
35 #include "object-editor-private.h"
36
37 #include "debug.h"
38
39 /*===========================================*/
40 /* Private macros                            */
41 /*===========================================*/
42
43 /*===========================================*/
44 /* Private data types                        */
45 /*===========================================*/
46
47 typedef void (*ChangedSignal) (GObject * object, gpointer data);
48
49 /*===========================================*/
50 /* Private globals                           */
51 /*===========================================*/
52
53 gint gl_object_editor_signals[LAST_SIGNAL] = { 0 };
54
55 static GtkVBoxClass *parent_class = NULL;
56
57 /*===========================================*/
58 /* Local function prototypes                 */
59 /*===========================================*/
60
61 static void gl_object_editor_class_init         (glObjectEditorClass  *klass);
62 static void gl_object_editor_init               (glObjectEditor       *editor);
63 static void gl_object_editor_finalize           (GObject              *object);
64
65 static void gl_object_notebook_construct_valist (glObjectEditor       *editor,
66                                                  glObjectEditorOption  first_option,
67                                                  va_list               args);
68
69 static void prefs_changed_cb                    (glObjectEditor       *editor);
70
71 \f
72 /*****************************************************************************/
73 /* Boilerplate object stuff.                                                 */
74 /*****************************************************************************/
75 GType
76 gl_object_editor_get_type (void)
77 {
78         static GType type = 0;
79
80         if (!type)
81         {
82                 static const GTypeInfo info =
83                 {
84                         sizeof (glObjectEditorClass),
85                         NULL,           /* base_init */
86                         NULL,           /* base_finalize */
87                         (GClassInitFunc) gl_object_editor_class_init,
88                         NULL,           /* class_finalize */
89                         NULL,           /* class_data */
90                         sizeof (glObjectEditor),
91                         0,              /* n_preallocs */
92                         (GInstanceInitFunc) gl_object_editor_init,
93                         NULL
94                 };
95
96                 type = g_type_register_static (GTK_TYPE_VBOX,
97                                                "glObjectEditor", &info, 0);
98         }
99
100         return type;
101 }
102
103 static void
104 gl_object_editor_class_init (glObjectEditorClass *klass)
105 {
106         GObjectClass *object_class = G_OBJECT_CLASS (klass);
107
108         gl_debug (DEBUG_EDITOR, "START");
109         
110         parent_class = g_type_class_peek_parent (klass);
111
112         object_class->finalize = gl_object_editor_finalize;     
113
114         gl_object_editor_signals[CHANGED] =
115             g_signal_new ("changed",
116                           G_OBJECT_CLASS_TYPE(object_class),
117                           G_SIGNAL_RUN_LAST,
118                           G_STRUCT_OFFSET (glObjectEditorClass, changed),
119                           NULL, NULL,
120                           gl_marshal_VOID__VOID,
121                           G_TYPE_NONE, 0);
122
123         gl_object_editor_signals[SIZE_CHANGED] =
124             g_signal_new ("size_changed",
125                           G_OBJECT_CLASS_TYPE(object_class),
126                           G_SIGNAL_RUN_LAST,
127                           G_STRUCT_OFFSET (glObjectEditorClass, size_changed),
128                           NULL, NULL,
129                           gl_marshal_VOID__VOID,
130                           G_TYPE_NONE, 0);
131
132         gl_debug (DEBUG_EDITOR, "END");
133 }
134
135 static void
136 gl_object_editor_init (glObjectEditor *editor)
137 {
138         gl_debug (DEBUG_EDITOR, "START");
139         
140         editor->priv = g_new0 (glObjectEditorPrivate, 1);
141
142         editor->priv->gui = glade_xml_new (GLABELS_GLADE_DIR "object-editor.glade",
143                                            "editor_vbox",
144                                            NULL);
145
146         if (!editor->priv->gui) {
147                 g_warning ("Could not open object-editor.glade, reinstall glabels!");
148                 return;
149         }
150
151         editor->priv->editor_vbox = glade_xml_get_widget (editor->priv->gui,
152                                                           "editor_vbox");
153         gtk_box_pack_start (GTK_BOX(editor),
154                             editor->priv->editor_vbox,
155                             FALSE, FALSE, 0);
156
157         editor->priv->title_image = glade_xml_get_widget (editor->priv->gui,
158                                                           "title_image");
159         editor->priv->title_label = glade_xml_get_widget (editor->priv->gui,
160                                                           "title_label");
161         editor->priv->notebook    = glade_xml_get_widget (editor->priv->gui,
162                                                           "notebook");
163
164         gtk_widget_show_all (GTK_WIDGET(editor));
165
166         /* Hide all notebook pages to start with. */
167         gtk_widget_hide_all (editor->priv->notebook);
168
169         gl_debug (DEBUG_EDITOR, "END");
170 }
171
172 static void 
173 gl_object_editor_finalize (GObject *object)
174 {
175         glObjectEditor* editor;
176         
177         gl_debug (DEBUG_EDITOR, "START");
178         
179         g_return_if_fail (object != NULL);
180         
181         editor = GL_OBJECT_EDITOR (object);
182
183         g_return_if_fail (GL_IS_OBJECT_EDITOR (editor));
184         g_return_if_fail (editor->priv != NULL);
185
186         g_free (editor->priv);
187
188         g_signal_handlers_disconnect_by_func (G_OBJECT(gl_prefs),
189                                               prefs_changed_cb, editor);
190
191         G_OBJECT_CLASS (parent_class)->finalize (object);
192
193         gl_debug (DEBUG_EDITOR, "END");
194 }
195
196 /*****************************************************************************/
197 /* NEW object editor.                                                      */
198 /*****************************************************************************/
199 GtkWidget*
200 gl_object_editor_new (gchar                *image,
201                       gchar                *label,
202                       glObjectEditorOption  first_option, ...)
203 {
204         glObjectEditor *editor;
205         va_list         args;
206
207         gl_debug (DEBUG_EDITOR, "START");
208
209         editor = GL_OBJECT_EDITOR (g_object_new (GL_TYPE_OBJECT_EDITOR, NULL));
210
211         if (image) {
212                 gtk_image_set_from_stock (GTK_IMAGE(editor->priv->title_image),
213                                           image,
214                                           GTK_ICON_SIZE_LARGE_TOOLBAR);
215         }
216
217         if (label) {
218                 gchar *s;
219
220                 s = g_strdup_printf ("<span weight=\"bold\">%s</span>",
221                                      label);
222                 gtk_label_set_text (GTK_LABEL(editor->priv->title_label), s);
223                 g_free (s);
224
225                 gtk_label_set_use_markup (GTK_LABEL(editor->priv->title_label), TRUE);
226                                           
227         }
228
229         gtk_notebook_set_homogeneous_tabs (GTK_NOTEBOOK(editor->priv->notebook), TRUE);
230
231         va_start (args, first_option);
232         gl_object_notebook_construct_valist (editor, first_option, args);
233         va_end (args);
234
235         gl_debug (DEBUG_EDITOR, "END");
236
237         return GTK_WIDGET(editor);
238 }
239
240 /*--------------------------------------------------------------------------*/
241 /* PRIVATE.  Construct notebook.                                            */
242 /*--------------------------------------------------------------------------*/
243 static void
244 gl_object_notebook_construct_valist (glObjectEditor       *editor,
245                                      glObjectEditorOption  first_option,
246                                      va_list               args)
247 {
248         glObjectEditorOption option;
249         gint pages = 0;
250
251         gl_debug (DEBUG_EDITOR, "START");
252
253         option = first_option;
254
255         for ( option=first_option; option; option=va_arg (args, glObjectEditorOption) ) {
256
257                 switch (option) {
258
259                 case GL_OBJECT_EDITOR_EMPTY:
260                         gtk_widget_set_sensitive (editor->priv->title_image, FALSE);
261                         gtk_widget_set_sensitive (editor->priv->title_label, FALSE);
262                         break;
263
264                 case GL_OBJECT_EDITOR_POSITION_PAGE:
265                         gl_object_editor_prepare_position_page (editor);
266                         pages++;
267                         break;
268
269                 case GL_OBJECT_EDITOR_SIZE_PAGE:
270                 case GL_OBJECT_EDITOR_SIZE_IMAGE_PAGE:
271                         gl_object_editor_prepare_size_page (editor, option);
272                         pages++;
273                         break;
274
275                 case GL_OBJECT_EDITOR_SIZE_LINE_PAGE:
276                         gl_object_editor_prepare_lsize_page (editor);
277                         pages++;
278                         break;
279
280                 case GL_OBJECT_EDITOR_FILL_PAGE:
281                         gl_object_editor_prepare_fill_page (editor);
282                         pages++;
283                         break;
284
285                 case GL_OBJECT_EDITOR_LINE_PAGE:
286                         gl_object_editor_prepare_line_page (editor);
287                         pages++;
288                         break;
289
290                 case GL_OBJECT_EDITOR_IMAGE_PAGE:
291                         gl_object_editor_prepare_image_page (editor);
292                         pages++;
293                         break;
294
295                 case GL_OBJECT_EDITOR_TEXT_PAGE:
296                         gl_object_editor_prepare_text_page (editor);
297                         pages++;
298                         break;
299
300                 case GL_OBJECT_EDITOR_EDIT_PAGE:
301                         gl_object_editor_prepare_edit_page (editor);
302                         pages++;
303                         break;
304
305                 case GL_OBJECT_EDITOR_BC_PAGE:
306                         gl_object_editor_prepare_bc_page (editor);
307                         pages++;
308                         break;
309
310                 case GL_OBJECT_EDITOR_DATA_PAGE:
311                         gl_object_editor_prepare_data_page (editor);
312                         pages++;
313                         break;
314
315                 default:
316                         g_warning ("option = %d", option);
317                         g_assert_not_reached ();
318                 }
319                 
320         }
321         if (pages) {
322                 gtk_widget_show (editor->priv->notebook);
323         }
324
325         g_signal_connect_swapped (G_OBJECT (gl_prefs), "changed",
326                                   G_CALLBACK (prefs_changed_cb),
327                                   editor);
328
329         gl_debug (DEBUG_EDITOR, "END");
330 }
331
332 /*--------------------------------------------------------------------------*/
333 /* PRIVATE. Widget changed callback.  Emit our "changed" signal.            */
334 /*--------------------------------------------------------------------------*/
335 void
336 gl_object_editor_changed_cb (glObjectEditor *editor)
337 {
338         gl_debug (DEBUG_EDITOR, "START");
339
340         /* Emit our "changed" signal */
341         g_signal_emit (G_OBJECT (editor), gl_object_editor_signals[CHANGED], 0);
342
343         gl_debug (DEBUG_EDITOR, "END");
344 }
345
346 /*--------------------------------------------------------------------------*/
347 /* PRIVATE. Widget size changed callback.  Emit our "size-changed" signal.  */
348 /*--------------------------------------------------------------------------*/
349 void
350 gl_object_editor_size_changed_cb (glObjectEditor *editor)
351 {
352         gl_debug (DEBUG_EDITOR, "START");
353
354         /* Emit our "size_changed" signal */
355         g_signal_emit (G_OBJECT (editor), gl_object_editor_signals[SIZE_CHANGED], 0);
356
357         gl_debug (DEBUG_EDITOR, "END");
358 }
359
360 /*****************************************************************************/
361 /* Set possible key names from merge object.                                 */
362 /*****************************************************************************/
363 void
364 gl_object_editor_set_key_names (glObjectEditor      *editor,
365                                 glMerge             *merge)
366 {
367         GList     *keys;
368         GtkWidget *combo;
369         gboolean   fixed_flag;
370  
371         gl_debug (DEBUG_EDITOR, "START");
372
373         if (editor->priv->edit_key_label) {
374                 gtk_widget_set_sensitive (editor->priv->edit_key_label, merge != NULL);
375         }
376  
377         if (editor->priv->edit_key_combo) {
378                 gtk_widget_set_sensitive (editor->priv->edit_key_combo, merge != NULL);
379         }
380  
381         if (editor->priv->text_auto_shrink_check) {
382                 gtk_widget_set_sensitive (editor->priv->text_auto_shrink_check,
383                                           merge != NULL);
384         }
385  
386         if (editor->priv->text_color_key_combo) {
387                 gtk_widget_set_sensitive (editor->priv->text_color_key_combo, merge != NULL);
388         }
389  
390         if (editor->priv->text_color_key_radio) {
391                 gtk_widget_set_sensitive (editor->priv->text_color_key_radio, merge != NULL);
392                 if (merge == NULL) {
393                         gtk_toggle_button_set_active (
394                                 GTK_TOGGLE_BUTTON(editor->priv->text_color_radio), TRUE);
395                 }
396         }       
397         
398         if (editor->priv->edit_insert_field_button) {
399                 gtk_widget_set_sensitive (editor->priv->edit_insert_field_button,
400                                           merge != NULL);
401         }
402
403         if (editor->priv->img_key_combo) {
404                 gtk_widget_set_sensitive (editor->priv->img_key_combo, merge != NULL);
405         }
406  
407         if (editor->priv->img_key_radio) {
408                 gtk_widget_set_sensitive (editor->priv->img_key_radio, merge != NULL);
409                 if (merge == NULL) {
410                         gtk_toggle_button_set_active (
411                                 GTK_TOGGLE_BUTTON(editor->priv->img_file_radio), TRUE);
412                 }
413         }
414
415         if (editor->priv->data_key_combo) {
416                 gtk_widget_set_sensitive (editor->priv->data_key_combo, merge != NULL);
417         }
418  
419         if (editor->priv->data_key_radio) {
420                 gtk_widget_set_sensitive (editor->priv->data_key_radio, merge != NULL);
421                 if (merge == NULL) {
422                         gtk_toggle_button_set_active (
423                                 GTK_TOGGLE_BUTTON(editor->priv->data_literal_radio), TRUE);
424                 }
425         }
426         
427         fixed_flag = editor->priv->data_format_fixed_flag;
428         if (editor->priv->data_format_label) {
429                 gtk_widget_set_sensitive (editor->priv->data_format_label,
430                                           (merge != NULL));
431         }
432         if (editor->priv->data_ex_label) {
433                 gtk_widget_set_sensitive (editor->priv->data_ex_label,
434                                           (merge != NULL));
435         }
436         if (editor->priv->data_digits_label) {
437                 gtk_widget_set_sensitive (editor->priv->data_digits_label,
438                                           (merge != NULL) && !fixed_flag);
439         }
440         if (editor->priv->data_digits_spin) {
441                 gtk_widget_set_sensitive (editor->priv->data_digits_spin,
442                                           (merge != NULL) && !fixed_flag);
443         }
444
445         if (editor->priv->fill_key_combo) {
446                 gtk_widget_set_sensitive (editor->priv->fill_key_combo, merge != NULL);
447         }
448  
449         if (editor->priv->fill_key_radio) {
450                 gtk_widget_set_sensitive (editor->priv->fill_key_radio, merge != NULL);
451                 if (merge == NULL) {
452                         gtk_toggle_button_set_active (
453                                 GTK_TOGGLE_BUTTON(editor->priv->fill_color_radio), TRUE);
454                 }
455         }
456         
457         if (editor->priv->line_key_combo) {
458                 gtk_widget_set_sensitive (editor->priv->line_key_combo, merge != NULL);
459         }
460  
461         if (editor->priv->line_key_radio) {
462                 gtk_widget_set_sensitive (editor->priv->line_key_radio, merge != NULL);
463                 if (merge == NULL) {
464                         gtk_toggle_button_set_active (
465                                 GTK_TOGGLE_BUTTON(editor->priv->line_color_radio), TRUE);
466                 }
467         }
468         
469         if (editor->priv->bc_key_combo) {
470                 gtk_widget_set_sensitive (editor->priv->bc_key_combo, merge != NULL);
471         }
472  
473         if (editor->priv->bc_key_radio) {
474                 gtk_widget_set_sensitive (editor->priv->bc_key_radio, merge != NULL);
475                 if (merge == NULL) {
476                         gtk_toggle_button_set_active (
477                                 GTK_TOGGLE_BUTTON(editor->priv->bc_color_radio), TRUE);
478                 }
479         }       
480         
481         keys = gl_merge_get_key_list (merge);
482         if ( keys != NULL ) {
483
484                 combo = editor->priv->img_key_combo;
485                 if (combo) {
486                         gtk_combo_set_popdown_strings (GTK_COMBO (combo), keys);
487                 }
488
489                 combo = editor->priv->edit_key_combo;
490                 if (combo) {
491                         gtk_combo_set_popdown_strings (GTK_COMBO (combo), keys);
492                 }
493
494                 combo = editor->priv->data_key_combo;
495                 if (combo) {
496                         gtk_combo_set_popdown_strings (GTK_COMBO (combo), keys);
497                 }
498                 
499                 combo = editor->priv->fill_key_combo;
500                 if (combo) {
501                         gtk_combo_set_popdown_strings (GTK_COMBO (combo), keys);
502                 }
503
504                 combo = editor->priv->text_color_key_combo;
505                 if (combo) {
506                         gtk_combo_set_popdown_strings (GTK_COMBO (combo), keys);
507                 }
508
509                 combo = editor->priv->line_key_combo;
510                 if (combo) {
511                         gtk_combo_set_popdown_strings (GTK_COMBO (combo), keys);
512                 }
513                 
514                 combo = editor->priv->bc_key_combo;
515                 if (combo) {
516                         gtk_combo_set_popdown_strings (GTK_COMBO (combo), keys);
517                 }
518                 
519                 gl_merge_free_key_list (&keys);
520         } else {
521
522                 keys = g_list_append (keys, "");
523
524                 combo = editor->priv->img_key_combo;
525                 if (combo) {
526                         gtk_combo_set_popdown_strings (GTK_COMBO (combo), keys);
527                 }
528
529                 combo = editor->priv->edit_key_combo;
530                 if (combo) {
531                         gtk_combo_set_popdown_strings (GTK_COMBO (combo), keys);
532                 }
533                 
534                 combo = editor->priv->data_key_combo;
535                 if (combo) {
536                         gtk_combo_set_popdown_strings (GTK_COMBO (combo), keys);
537                 }
538                 
539                 combo = editor->priv->fill_key_combo;
540                 if (combo) {
541                         gtk_combo_set_popdown_strings (GTK_COMBO (combo), keys);
542                 }
543                 
544                 combo = editor->priv->text_color_key_combo;
545                 if (combo) {
546                         gtk_combo_set_popdown_strings (GTK_COMBO (combo), keys);
547                 }
548
549                 combo = editor->priv->line_key_combo;
550                 if (combo) {
551                         gtk_combo_set_popdown_strings (GTK_COMBO (combo), keys);
552                 }
553                 
554                 combo = editor->priv->bc_key_combo;
555                 if (combo) {
556                         gtk_combo_set_popdown_strings (GTK_COMBO (combo), keys);
557                 }
558                 
559                 g_list_free (keys);
560         }
561  
562         gl_debug (DEBUG_EDITOR, "END");
563 }
564
565 /*****************************************************************************/
566 /* Construct color combo "Custom widget".                                    */
567 /*****************************************************************************/
568 GtkWidget *
569 gl_object_editor_construct_color_combo (gchar *name,
570                                         gchar *string1,
571                                         gchar *string2,
572                                         gint   int1,
573                                         gint   int2)
574 {
575         GtkWidget  *color_combo;
576         ColorGroup *cg;
577         gchar      *cg_name;
578         guint       color;
579         GdkColor   *gdk_color;
580         gchar      *no_color;
581
582         switch (int1) {
583
584         case 2:
585                 cg_name  = "text_color_group";
586                 color    = gl_prefs->default_text_color;
587                 no_color = _("Default");
588                 break;
589
590         case 1:
591                 cg_name  = "line_color_group";
592                 color    = gl_prefs->default_line_color;
593                 no_color = _("No line");
594                 break;
595
596         case 0:
597         default:
598                 cg_name  = "fill_color_group";
599                 color    = gl_prefs->default_fill_color;
600                 no_color = _("No fill");
601                 break;
602
603         }
604
605         cg = color_group_fetch (cg_name, NULL);
606         gdk_color = gl_color_to_gdk_color (color);
607         color_combo = color_combo_new (NULL, no_color, gdk_color, cg);
608         g_free (gdk_color);
609
610         color_combo_box_set_preview_relief (COLOR_COMBO(color_combo), GTK_RELIEF_NORMAL);
611
612         return color_combo;
613 }
614
615 /*****************************************************************************/
616 /* Construct chain button "Custom widget".                                   */
617 /*****************************************************************************/
618 GtkWidget *
619 gl_object_editor_construct_chain_button (gchar *name,
620                                          gchar *string1,
621                                          gchar *string2,
622                                          gint   int1,
623                                          gint   int2)
624 {
625         GtkWidget  *chain_button;
626
627         chain_button = gl_wdgt_chain_button_new (GL_WDGT_CHAIN_RIGHT);
628         gl_wdgt_chain_button_set_active (GL_WDGT_CHAIN_BUTTON(chain_button), TRUE);
629
630         return chain_button;
631 }
632
633 /*--------------------------------------------------------------------------*/
634 /* PRIVATE. Prefs changed callback.  Update units related items.            */
635 /*--------------------------------------------------------------------------*/
636 static void
637 prefs_changed_cb (glObjectEditor *editor)
638 {
639
640         gl_debug (DEBUG_EDITOR, "START");
641
642         if (editor->priv->lsize_r_spin) {
643                 lsize_prefs_changed_cb (editor);
644         }
645                 
646         if (editor->priv->size_w_spin) {
647                 size_prefs_changed_cb (editor);
648         }
649                 
650         if (editor->priv->pos_x_spin) {
651                 position_prefs_changed_cb (editor);
652         }
653
654         gl_debug (DEBUG_EDITOR, "END");
655 }