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