]> git.sur5r.net Git - glabels/blob - glabels2/src/object-editor.c
79515377895d5f592fbc546a341fe0d7e23e28b9
[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         if (editor->priv->gui) {
164                 g_object_unref (G_OBJECT (editor->priv->gui));
165         }
166         g_free (editor->priv);
167
168         g_signal_handlers_disconnect_by_func (G_OBJECT(gl_prefs),
169                                               prefs_changed_cb, editor);
170
171         G_OBJECT_CLASS (gl_object_editor_parent_class)->finalize (object);
172
173         gl_debug (DEBUG_EDITOR, "END");
174 }
175
176 /*****************************************************************************/
177 /* NEW object editor.                                                      */
178 /*****************************************************************************/
179 GtkWidget*
180 gl_object_editor_new (gchar                *image,
181                       gchar                *label,
182                       glObjectEditorOption  first_option, ...)
183 {
184         glObjectEditor *editor;
185         va_list         args;
186
187         gl_debug (DEBUG_EDITOR, "START");
188
189         editor = GL_OBJECT_EDITOR (g_object_new (GL_TYPE_OBJECT_EDITOR, NULL));
190
191         if (image) {
192                 gtk_image_set_from_stock (GTK_IMAGE(editor->priv->title_image),
193                                           image,
194                                           GTK_ICON_SIZE_LARGE_TOOLBAR);
195         }
196
197         if (label) {
198                 gchar *s;
199
200                 s = g_strdup_printf ("<span weight=\"bold\">%s</span>",
201                                      label);
202                 gtk_label_set_text (GTK_LABEL(editor->priv->title_label), s);
203                 g_free (s);
204
205                 gtk_label_set_use_markup (GTK_LABEL(editor->priv->title_label), TRUE);
206                                           
207         }
208
209         gtk_notebook_set_homogeneous_tabs (GTK_NOTEBOOK(editor->priv->notebook), TRUE);
210
211         va_start (args, first_option);
212         gl_object_notebook_construct_valist (editor, first_option, args);
213         va_end (args);
214
215         gl_debug (DEBUG_EDITOR, "END");
216
217         return GTK_WIDGET(editor);
218 }
219
220 /*--------------------------------------------------------------------------*/
221 /* PRIVATE.  Construct notebook.                                            */
222 /*--------------------------------------------------------------------------*/
223 static void
224 gl_object_notebook_construct_valist (glObjectEditor       *editor,
225                                      glObjectEditorOption  first_option,
226                                      va_list               args)
227 {
228         glObjectEditorOption option;
229         gint pages = 0;
230
231         gl_debug (DEBUG_EDITOR, "START");
232
233         option = first_option;
234
235         for ( option=first_option; option; option=va_arg (args, glObjectEditorOption) ) {
236
237                 switch (option) {
238
239                 case GL_OBJECT_EDITOR_EMPTY:
240                         gtk_widget_set_sensitive (editor->priv->title_image, FALSE);
241                         gtk_widget_set_sensitive (editor->priv->title_label, FALSE);
242                         break;
243
244                 case GL_OBJECT_EDITOR_POSITION_PAGE:
245                         gl_object_editor_prepare_position_page (editor);
246                         pages++;
247                         break;
248
249                 case GL_OBJECT_EDITOR_SIZE_PAGE:
250                 case GL_OBJECT_EDITOR_SIZE_IMAGE_PAGE:
251                         gl_object_editor_prepare_size_page (editor, option);
252                         pages++;
253                         break;
254
255                 case GL_OBJECT_EDITOR_SIZE_LINE_PAGE:
256                         gl_object_editor_prepare_lsize_page (editor);
257                         pages++;
258                         break;
259
260                 case GL_OBJECT_EDITOR_FILL_PAGE:
261                         gl_object_editor_prepare_fill_page (editor);
262                         pages++;
263                         break;
264
265                 case GL_OBJECT_EDITOR_LINE_PAGE:
266                         gl_object_editor_prepare_line_page (editor);
267                         pages++;
268                         break;
269
270                 case GL_OBJECT_EDITOR_IMAGE_PAGE:
271                         gl_object_editor_prepare_image_page (editor);
272                         pages++;
273                         break;
274
275                 case GL_OBJECT_EDITOR_TEXT_PAGE:
276                         gl_object_editor_prepare_text_page (editor);
277                         pages++;
278                         break;
279
280                 case GL_OBJECT_EDITOR_EDIT_PAGE:
281                         gl_object_editor_prepare_edit_page (editor);
282                         pages++;
283                         break;
284
285                 case GL_OBJECT_EDITOR_BC_PAGE:
286                         gl_object_editor_prepare_bc_page (editor);
287                         pages++;
288                         break;
289
290                 case GL_OBJECT_EDITOR_DATA_PAGE:
291                         gl_object_editor_prepare_data_page (editor);
292                         pages++;
293                         break;
294
295                 case GL_OBJECT_EDITOR_SHADOW_PAGE:
296                         gl_object_editor_prepare_shadow_page (editor);
297                         pages++;
298                         break;
299
300                 default:
301                         g_message ("option = %d", option);
302                         g_assert_not_reached ();
303                 }
304                 
305         }
306         if (pages) {
307                 gtk_widget_show (editor->priv->notebook);
308         }
309
310         g_signal_connect_swapped (G_OBJECT (gl_prefs), "changed",
311                                   G_CALLBACK (prefs_changed_cb),
312                                   editor);
313
314         gl_debug (DEBUG_EDITOR, "END");
315 }
316
317 /*--------------------------------------------------------------------------*/
318 /* PRIVATE. Widget changed callback.  Emit our "changed" signal.            */
319 /*--------------------------------------------------------------------------*/
320 void
321 gl_object_editor_changed_cb (glObjectEditor *editor)
322 {
323         gl_debug (DEBUG_EDITOR, "START");
324
325         /* Emit our "changed" signal */
326         g_signal_emit (G_OBJECT (editor), gl_object_editor_signals[CHANGED], 0);
327
328         gl_debug (DEBUG_EDITOR, "END");
329 }
330
331 /*--------------------------------------------------------------------------*/
332 /* PRIVATE. Widget size changed callback.  Emit our "size-changed" signal.  */
333 /*--------------------------------------------------------------------------*/
334 void
335 gl_object_editor_size_changed_cb (glObjectEditor *editor)
336 {
337         gl_debug (DEBUG_EDITOR, "START");
338
339         /* Emit our "size_changed" signal */
340         g_signal_emit (G_OBJECT (editor), gl_object_editor_signals[SIZE_CHANGED], 0);
341
342         gl_debug (DEBUG_EDITOR, "END");
343 }
344
345 /*****************************************************************************/
346 /* Set possible key names from merge object.                                 */
347 /*****************************************************************************/
348 void
349 gl_object_editor_set_key_names (glObjectEditor      *editor,
350                                 glMerge             *merge)
351 {
352         GList     *keys;
353         GtkWidget *combo;
354         gboolean   fixed_flag;
355         gboolean   state;
356  
357         gl_debug (DEBUG_EDITOR, "START");
358
359         if (editor->priv->edit_key_label) {
360                 gtk_widget_set_sensitive (editor->priv->edit_key_label, merge != NULL);
361         }
362  
363         if (editor->priv->edit_key_combo) {
364                 gtk_widget_set_sensitive (editor->priv->edit_key_combo, merge != NULL);
365         }
366  
367         if (editor->priv->text_auto_shrink_check) {
368                 gtk_widget_set_sensitive (editor->priv->text_auto_shrink_check,
369                                           merge != NULL);
370         }
371  
372         if (editor->priv->text_page_vbox) {
373                 gtk_widget_set_sensitive (editor->priv->text_color_key_radio, merge != NULL);
374                 if (merge == NULL) {
375                         gtk_toggle_button_set_active (
376                                 GTK_TOGGLE_BUTTON(editor->priv->text_color_radio), TRUE);
377                         gtk_widget_set_sensitive (editor->priv->text_color_combo, TRUE);
378                         gtk_widget_set_sensitive (editor->priv->text_color_key_combo, FALSE);
379                 } else {
380                         state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(editor->priv->text_color_key_radio));
381                         gtk_widget_set_sensitive (editor->priv->text_color_combo, !state);
382                         gtk_widget_set_sensitive (editor->priv->text_color_key_combo, state);
383                                                   
384                 }
385         }
386
387         if (editor->priv->edit_insert_field_button) {
388                 gtk_widget_set_sensitive (editor->priv->edit_insert_field_button,
389                                           merge != NULL);
390         }
391
392         if (editor->priv->img_key_combo) {
393                 gtk_widget_set_sensitive (editor->priv->img_key_combo, merge != NULL);
394         }
395  
396         if (editor->priv->img_key_radio) {
397                 gtk_widget_set_sensitive (editor->priv->img_key_radio, merge != NULL);
398                 if (merge == NULL) {
399                         gtk_toggle_button_set_active (
400                                 GTK_TOGGLE_BUTTON(editor->priv->img_file_radio), TRUE);
401                 }
402         }
403
404         if (editor->priv->data_key_combo) {
405                 gtk_widget_set_sensitive (editor->priv->data_key_combo, merge != NULL);
406         }
407  
408         if (editor->priv->data_key_radio) {
409                 gtk_widget_set_sensitive (editor->priv->data_key_radio, merge != NULL);
410                 if (merge == NULL) {
411                         gtk_toggle_button_set_active (
412                                 GTK_TOGGLE_BUTTON(editor->priv->data_literal_radio), TRUE);
413                 }
414         }
415         
416         fixed_flag = editor->priv->data_format_fixed_flag;
417         if (editor->priv->data_format_label) {
418                 gtk_widget_set_sensitive (editor->priv->data_format_label,
419                                           (merge != NULL));
420         }
421         if (editor->priv->data_ex_label) {
422                 gtk_widget_set_sensitive (editor->priv->data_ex_label,
423                                           (merge != NULL));
424         }
425         if (editor->priv->data_digits_label) {
426                 gtk_widget_set_sensitive (editor->priv->data_digits_label,
427                                           (merge != NULL) && !fixed_flag);
428         }
429         if (editor->priv->data_digits_spin) {
430                 gtk_widget_set_sensitive (editor->priv->data_digits_spin,
431                                           (merge != NULL) && !fixed_flag);
432         }
433
434         if (editor->priv->fill_page_vbox) {
435                 gtk_widget_set_sensitive (editor->priv->fill_key_radio, merge != NULL);
436                 if (merge == NULL) {
437                         gtk_toggle_button_set_active (
438                                 GTK_TOGGLE_BUTTON(editor->priv->fill_color_radio), TRUE);
439                         gtk_widget_set_sensitive (editor->priv->fill_color_combo, TRUE);
440                         gtk_widget_set_sensitive (editor->priv->fill_key_combo, FALSE);
441                 } else {
442                         state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(editor->priv->fill_key_radio));
443                         gtk_widget_set_sensitive (editor->priv->fill_color_combo, !state);
444                         gtk_widget_set_sensitive (editor->priv->fill_key_combo, state);
445                                                   
446                 }
447         }
448
449         if (editor->priv->line_page_vbox) {
450                 gtk_widget_set_sensitive (editor->priv->line_key_radio, merge != NULL);
451                 if (merge == NULL) {
452                         gtk_toggle_button_set_active (
453                                 GTK_TOGGLE_BUTTON(editor->priv->line_color_radio), TRUE);
454                         gtk_widget_set_sensitive (editor->priv->line_color_combo, TRUE);
455                         gtk_widget_set_sensitive (editor->priv->line_key_combo, FALSE);
456                 } else {
457                         state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(editor->priv->line_key_radio));
458                         gtk_widget_set_sensitive (editor->priv->line_color_combo, !state);
459                         gtk_widget_set_sensitive (editor->priv->line_key_combo, state);
460                                                   
461                 }
462         }
463
464         if (editor->priv->bc_page_vbox) {
465                 gtk_widget_set_sensitive (editor->priv->bc_key_radio, merge != NULL);
466                 if (merge == NULL) {
467                         gtk_toggle_button_set_active (
468                                 GTK_TOGGLE_BUTTON(editor->priv->bc_color_radio), TRUE);
469                         gtk_widget_set_sensitive (editor->priv->bc_color_combo, TRUE);
470                         gtk_widget_set_sensitive (editor->priv->bc_key_combo, FALSE);
471                 } else {
472                         state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(editor->priv->bc_key_radio));
473                         gtk_widget_set_sensitive (editor->priv->bc_color_combo, !state);
474                         gtk_widget_set_sensitive (editor->priv->bc_key_combo, state);
475                                                   
476                 }
477         }
478
479         if (editor->priv->shadow_page_vbox) {
480                 gtk_widget_set_sensitive (editor->priv->shadow_key_radio, merge != NULL);
481                 if (merge == NULL) {
482                         gtk_toggle_button_set_active (
483                                 GTK_TOGGLE_BUTTON(editor->priv->shadow_color_radio), TRUE);
484                         gtk_widget_set_sensitive (editor->priv->shadow_color_combo, TRUE);
485                         gtk_widget_set_sensitive (editor->priv->shadow_key_combo, FALSE);
486                 } else {
487                         state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(editor->priv->shadow_key_radio));
488                         gtk_widget_set_sensitive (editor->priv->shadow_color_combo, !state);
489                         gtk_widget_set_sensitive (editor->priv->shadow_key_combo, state);
490                                                   
491                 }
492         }
493
494         keys = gl_merge_get_key_list (merge);
495         if ( keys == NULL ) {
496                 keys = g_list_append (keys, g_strdup (""));
497         }
498
499         combo = editor->priv->img_key_combo;
500         if (combo) {
501                 gl_util_combo_box_set_strings (GTK_COMBO_BOX (combo), keys);
502         }
503
504         combo = editor->priv->edit_key_combo;
505         if (combo) {
506                 gl_util_combo_box_set_strings (GTK_COMBO_BOX (combo), keys);
507         }
508
509         combo = editor->priv->data_key_combo;
510         if (combo) {
511                 gl_util_combo_box_set_strings (GTK_COMBO_BOX (combo), keys);
512         }
513                 
514         combo = editor->priv->fill_key_combo;
515         if (combo) {
516                 gl_util_combo_box_set_strings (GTK_COMBO_BOX (combo), keys);
517         }
518
519         combo = editor->priv->text_color_key_combo;
520         if (combo) {
521                 gl_util_combo_box_set_strings (GTK_COMBO_BOX (combo), keys);
522         }
523
524         combo = editor->priv->line_key_combo;
525         if (combo) {
526                 gl_util_combo_box_set_strings (GTK_COMBO_BOX (combo), keys);
527         }
528                 
529         combo = editor->priv->bc_key_combo;
530         if (combo) {
531                 gl_util_combo_box_set_strings (GTK_COMBO_BOX (combo), keys);
532         }
533                 
534         combo = editor->priv->shadow_key_combo;
535         if (combo) {
536                 gl_util_combo_box_set_strings (GTK_COMBO_BOX (combo), keys);
537         }
538
539         gl_merge_free_key_list (&keys);
540  
541         gl_debug (DEBUG_EDITOR, "END");
542 }
543
544 /*****************************************************************************/
545 /* Construct color combo "Custom widget".                                    */
546 /*****************************************************************************/
547 GtkWidget *
548 gl_object_editor_construct_color_combo (gchar *name,
549                                         gchar *string1,
550                                         gchar *string2,
551                                         gint   int1,
552                                         gint   int2)
553 {
554         GtkWidget  *color_combo;
555         ColorGroup *cg;
556         gchar      *cg_name;
557         guint       color;
558         GdkColor   *gdk_color;
559         gchar      *no_color;
560
561         switch (int1) {
562
563         case 3:
564                 cg_name  = "shadow_color_group";
565                 color    = GL_COLOR_SHADOW_DEFAULT;
566                 no_color = _("Default");
567                 break;
568
569         case 2:
570                 cg_name  = "text_color_group";
571                 color    = gl_prefs->default_text_color;
572                 no_color = _("Default");
573                 break;
574
575         case 1:
576                 cg_name  = "line_color_group";
577                 color    = gl_prefs->default_line_color;
578                 no_color = _("No line");
579                 break;
580
581         case 0:
582         default:
583                 cg_name  = "fill_color_group";
584                 color    = gl_prefs->default_fill_color;
585                 no_color = _("No fill");
586                 break;
587
588         }
589
590         cg = color_group_fetch (cg_name, NULL);
591         gdk_color = gl_color_to_gdk_color (color);
592         color_combo = color_combo_new (NULL, no_color, gdk_color, cg);
593         g_free (gdk_color);
594
595         color_combo_box_set_preview_relief (COLOR_COMBO(color_combo), GTK_RELIEF_NORMAL);
596
597         return color_combo;
598 }
599
600 /*****************************************************************************/
601 /* Construct chain button "Custom widget".                                   */
602 /*****************************************************************************/
603 GtkWidget *
604 gl_object_editor_construct_chain_button (gchar *name,
605                                          gchar *string1,
606                                          gchar *string2,
607                                          gint   int1,
608                                          gint   int2)
609 {
610         GtkWidget  *chain_button;
611
612         chain_button = gl_wdgt_chain_button_new (GL_WDGT_CHAIN_RIGHT);
613         gl_wdgt_chain_button_set_active (GL_WDGT_CHAIN_BUTTON(chain_button), TRUE);
614
615         return chain_button;
616 }
617
618 /*--------------------------------------------------------------------------*/
619 /* PRIVATE. Prefs changed callback.  Update units related items.            */
620 /*--------------------------------------------------------------------------*/
621 static void
622 prefs_changed_cb (glObjectEditor *editor)
623 {
624
625         gl_debug (DEBUG_EDITOR, "START");
626
627         if (editor->priv->lsize_r_spin) {
628                 lsize_prefs_changed_cb (editor);
629         }
630                 
631         if (editor->priv->size_w_spin) {
632                 size_prefs_changed_cb (editor);
633         }
634                 
635         if (editor->priv->pos_x_spin) {
636                 position_prefs_changed_cb (editor);
637         }
638
639         if (editor->priv->shadow_x_spin) {
640                 shadow_prefs_changed_cb (editor);
641         }
642
643         gl_debug (DEBUG_EDITOR, "END");
644 }