1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
4 * (GLABELS) Label and Business Card Creation program for GNOME
6 * object-editor.c: object properties editor module
8 * Copyright (C) 2003 Jim Evins <evins@snaught.com>.
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.
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.
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
26 #include "object-editor.h"
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>
38 #include "mygal/widget-color-combo.h"
40 #include "wdgt-chain-button.h"
44 #include "object-editor-private.h"
48 /*===========================================*/
50 /*===========================================*/
52 /*===========================================*/
53 /* Private data types */
54 /*===========================================*/
56 typedef void (*ChangedSignal) (GObject * object, gpointer data);
58 /*===========================================*/
60 /*===========================================*/
62 gint gl_object_editor_signals[LAST_SIGNAL] = { 0 };
64 /*===========================================*/
65 /* Local function prototypes */
66 /*===========================================*/
68 static void gl_object_editor_finalize (GObject *object);
70 static void gl_object_notebook_construct_valist (glObjectEditor *editor,
72 glObjectEditorOption first_option,
75 static void prefs_changed_cb (glObjectEditor *editor);
77 static void label_changed_cb (glLabel *label,
78 glObjectEditor *editor);
81 /*****************************************************************************/
82 /* Boilerplate object stuff. */
83 /*****************************************************************************/
84 G_DEFINE_TYPE (glObjectEditor, gl_object_editor, GTK_TYPE_VBOX);
87 gl_object_editor_class_init (glObjectEditorClass *class)
89 GObjectClass *object_class = G_OBJECT_CLASS (class);
91 gl_debug (DEBUG_EDITOR, "START");
93 gl_object_editor_parent_class = g_type_class_peek_parent (class);
95 object_class->finalize = gl_object_editor_finalize;
97 gl_object_editor_signals[CHANGED] =
98 g_signal_new ("changed",
99 G_OBJECT_CLASS_TYPE(object_class),
101 G_STRUCT_OFFSET (glObjectEditorClass, changed),
103 gl_marshal_VOID__VOID,
106 gl_object_editor_signals[SIZE_CHANGED] =
107 g_signal_new ("size_changed",
108 G_OBJECT_CLASS_TYPE(object_class),
110 G_STRUCT_OFFSET (glObjectEditorClass, size_changed),
112 gl_marshal_VOID__VOID,
115 gl_debug (DEBUG_EDITOR, "END");
119 gl_object_editor_init (glObjectEditor *editor)
121 gl_debug (DEBUG_EDITOR, "START");
123 editor->priv = g_new0 (glObjectEditorPrivate, 1);
125 editor->priv->gui = glade_xml_new (GLABELS_GLADE_DIR "object-editor.glade",
129 if (!editor->priv->gui) {
130 g_critical ("Could not open object-editor.glade. gLabels may not be installed correctly!");
134 editor->priv->editor_vbox = glade_xml_get_widget (editor->priv->gui,
136 gtk_box_pack_start (GTK_BOX(editor),
137 editor->priv->editor_vbox,
140 editor->priv->title_image = glade_xml_get_widget (editor->priv->gui,
142 editor->priv->title_label = glade_xml_get_widget (editor->priv->gui,
144 editor->priv->notebook = glade_xml_get_widget (editor->priv->gui,
147 gtk_widget_show_all (GTK_WIDGET(editor));
149 /* Hide all notebook pages to start with. */
150 gtk_widget_hide_all (editor->priv->notebook);
151 gtk_widget_set_no_show_all (editor->priv->notebook, TRUE);
153 gl_debug (DEBUG_EDITOR, "END");
157 gl_object_editor_finalize (GObject *object)
159 glObjectEditor* editor = GL_OBJECT_EDITOR (object);;
161 gl_debug (DEBUG_EDITOR, "START");
163 g_return_if_fail (object != NULL);
164 g_return_if_fail (GL_IS_OBJECT_EDITOR (editor));
165 g_return_if_fail (editor->priv != NULL);
167 g_signal_handlers_disconnect_by_func (G_OBJECT(gl_prefs),
168 prefs_changed_cb, editor);
169 g_signal_handlers_disconnect_by_func (G_OBJECT(editor->priv->label),
170 label_changed_cb, editor);
172 g_object_unref (editor->priv->gui);
173 g_free (editor->priv);
175 G_OBJECT_CLASS (gl_object_editor_parent_class)->finalize (object);
177 gl_debug (DEBUG_EDITOR, "END");
180 /*****************************************************************************/
181 /* NEW object editor. */
182 /*****************************************************************************/
184 gl_object_editor_new (gchar *image,
187 glObjectEditorOption first_option, ...)
189 glObjectEditor *editor;
192 gl_debug (DEBUG_EDITOR, "START");
194 editor = GL_OBJECT_EDITOR (g_object_new (GL_TYPE_OBJECT_EDITOR, NULL));
197 gtk_image_set_from_stock (GTK_IMAGE(editor->priv->title_image),
199 GTK_ICON_SIZE_LARGE_TOOLBAR);
205 s = g_strdup_printf ("<span weight=\"bold\">%s</span>",
207 gtk_label_set_text (GTK_LABEL(editor->priv->title_label), s);
210 gtk_label_set_use_markup (GTK_LABEL(editor->priv->title_label), TRUE);
214 gtk_notebook_set_homogeneous_tabs (GTK_NOTEBOOK(editor->priv->notebook), TRUE);
216 va_start (args, first_option);
217 gl_object_notebook_construct_valist (editor, label, first_option, args);
220 gl_debug (DEBUG_EDITOR, "END");
222 return GTK_WIDGET(editor);
225 /*--------------------------------------------------------------------------*/
226 /* PRIVATE. Construct notebook. */
227 /*--------------------------------------------------------------------------*/
229 gl_object_notebook_construct_valist (glObjectEditor *editor,
231 glObjectEditorOption first_option,
234 glObjectEditorOption option;
237 gl_debug (DEBUG_EDITOR, "START");
239 editor->priv->label = label;
241 option = first_option;
243 for ( option=first_option; option; option=va_arg (args, glObjectEditorOption) ) {
247 case GL_OBJECT_EDITOR_EMPTY:
248 gtk_widget_set_sensitive (editor->priv->title_image, FALSE);
249 gtk_widget_set_sensitive (editor->priv->title_label, FALSE);
252 case GL_OBJECT_EDITOR_POSITION_PAGE:
253 gl_object_editor_prepare_position_page (editor);
257 case GL_OBJECT_EDITOR_SIZE_PAGE:
258 case GL_OBJECT_EDITOR_SIZE_IMAGE_PAGE:
259 gl_object_editor_prepare_size_page (editor, option);
263 case GL_OBJECT_EDITOR_SIZE_LINE_PAGE:
264 gl_object_editor_prepare_lsize_page (editor);
268 case GL_OBJECT_EDITOR_FILL_PAGE:
269 gl_object_editor_prepare_fill_page (editor);
273 case GL_OBJECT_EDITOR_LINE_PAGE:
274 gl_object_editor_prepare_line_page (editor);
278 case GL_OBJECT_EDITOR_IMAGE_PAGE:
279 gl_object_editor_prepare_image_page (editor);
283 case GL_OBJECT_EDITOR_TEXT_PAGE:
284 gl_object_editor_prepare_text_page (editor);
288 case GL_OBJECT_EDITOR_EDIT_PAGE:
289 gl_object_editor_prepare_edit_page (editor);
293 case GL_OBJECT_EDITOR_BC_PAGE:
294 gl_object_editor_prepare_bc_page (editor);
298 case GL_OBJECT_EDITOR_DATA_PAGE:
299 gl_object_editor_prepare_data_page (editor);
303 case GL_OBJECT_EDITOR_SHADOW_PAGE:
304 gl_object_editor_prepare_shadow_page (editor);
309 g_message ("option = %d", option);
310 g_assert_not_reached ();
315 gtk_widget_show (editor->priv->notebook);
318 g_signal_connect_swapped (G_OBJECT (gl_prefs), "changed",
319 G_CALLBACK (prefs_changed_cb),
323 label_changed_cb (label, editor);
324 g_signal_connect (G_OBJECT (label), "size_changed",
325 G_CALLBACK (label_changed_cb),
327 g_signal_connect (G_OBJECT (label), "merge_changed",
328 G_CALLBACK (label_changed_cb),
332 gl_debug (DEBUG_EDITOR, "END");
335 /*--------------------------------------------------------------------------*/
336 /* PRIVATE. Widget changed callback. Emit our "changed" signal. */
337 /*--------------------------------------------------------------------------*/
339 gl_object_editor_changed_cb (glObjectEditor *editor)
341 if (editor->priv->stop_signals) return;
343 gl_debug (DEBUG_EDITOR, "START");
345 /* Emit our "changed" signal */
346 g_signal_emit (G_OBJECT (editor), gl_object_editor_signals[CHANGED], 0);
348 gl_debug (DEBUG_EDITOR, "END");
351 /*--------------------------------------------------------------------------*/
352 /* PRIVATE. Widget size changed callback. Emit our "size-changed" signal. */
353 /*--------------------------------------------------------------------------*/
355 gl_object_editor_size_changed_cb (glObjectEditor *editor)
357 if (editor->priv->stop_signals) return;
359 gl_debug (DEBUG_EDITOR, "START");
361 /* Emit our "size_changed" signal */
362 g_signal_emit (G_OBJECT (editor), gl_object_editor_signals[SIZE_CHANGED], 0);
364 gl_debug (DEBUG_EDITOR, "END");
367 /*****************************************************************************/
368 /* Set possible key names from merge object. */
369 /*****************************************************************************/
371 gl_object_editor_set_key_names (glObjectEditor *editor,
379 gl_debug (DEBUG_EDITOR, "START");
381 if (editor->priv->edit_key_label) {
382 gtk_widget_set_sensitive (editor->priv->edit_key_label, merge != NULL);
385 if (editor->priv->edit_key_combo) {
386 gtk_widget_set_sensitive (editor->priv->edit_key_combo, merge != NULL);
389 if (editor->priv->text_auto_shrink_check) {
390 gtk_widget_set_sensitive (editor->priv->text_auto_shrink_check,
394 if (editor->priv->text_page_vbox) {
395 gtk_widget_set_sensitive (editor->priv->text_color_key_radio, merge != NULL);
397 gtk_toggle_button_set_active (
398 GTK_TOGGLE_BUTTON(editor->priv->text_color_radio), TRUE);
399 gtk_widget_set_sensitive (editor->priv->text_color_combo, TRUE);
400 gtk_widget_set_sensitive (editor->priv->text_color_key_combo, FALSE);
402 state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(editor->priv->text_color_key_radio));
403 gtk_widget_set_sensitive (editor->priv->text_color_combo, !state);
404 gtk_widget_set_sensitive (editor->priv->text_color_key_combo, state);
409 if (editor->priv->edit_insert_field_button) {
410 gtk_widget_set_sensitive (editor->priv->edit_insert_field_button,
414 if (editor->priv->img_key_combo) {
415 gtk_widget_set_sensitive (editor->priv->img_key_combo, merge != NULL);
418 if (editor->priv->img_key_radio) {
419 gtk_widget_set_sensitive (editor->priv->img_key_radio, merge != NULL);
421 gtk_toggle_button_set_active (
422 GTK_TOGGLE_BUTTON(editor->priv->img_file_radio), TRUE);
426 if (editor->priv->data_key_combo) {
427 gtk_widget_set_sensitive (editor->priv->data_key_combo, merge != NULL);
430 if (editor->priv->data_key_radio) {
431 gtk_widget_set_sensitive (editor->priv->data_key_radio, merge != NULL);
433 gtk_toggle_button_set_active (
434 GTK_TOGGLE_BUTTON(editor->priv->data_literal_radio), TRUE);
438 fixed_flag = editor->priv->data_format_fixed_flag;
439 if (editor->priv->data_format_label) {
440 gtk_widget_set_sensitive (editor->priv->data_format_label,
443 if (editor->priv->data_ex_label) {
444 gtk_widget_set_sensitive (editor->priv->data_ex_label,
447 if (editor->priv->data_digits_label) {
448 gtk_widget_set_sensitive (editor->priv->data_digits_label,
449 (merge != NULL) && !fixed_flag);
451 if (editor->priv->data_digits_spin) {
452 gtk_widget_set_sensitive (editor->priv->data_digits_spin,
453 (merge != NULL) && !fixed_flag);
456 if (editor->priv->fill_page_vbox) {
457 gtk_widget_set_sensitive (editor->priv->fill_key_radio, merge != NULL);
459 gtk_toggle_button_set_active (
460 GTK_TOGGLE_BUTTON(editor->priv->fill_color_radio), TRUE);
461 gtk_widget_set_sensitive (editor->priv->fill_color_combo, TRUE);
462 gtk_widget_set_sensitive (editor->priv->fill_key_combo, FALSE);
464 state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(editor->priv->fill_key_radio));
465 gtk_widget_set_sensitive (editor->priv->fill_color_combo, !state);
466 gtk_widget_set_sensitive (editor->priv->fill_key_combo, state);
471 if (editor->priv->line_page_vbox) {
472 gtk_widget_set_sensitive (editor->priv->line_key_radio, merge != NULL);
474 gtk_toggle_button_set_active (
475 GTK_TOGGLE_BUTTON(editor->priv->line_color_radio), TRUE);
476 gtk_widget_set_sensitive (editor->priv->line_color_combo, TRUE);
477 gtk_widget_set_sensitive (editor->priv->line_key_combo, FALSE);
479 state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(editor->priv->line_key_radio));
480 gtk_widget_set_sensitive (editor->priv->line_color_combo, !state);
481 gtk_widget_set_sensitive (editor->priv->line_key_combo, state);
486 if (editor->priv->bc_page_vbox) {
487 gtk_widget_set_sensitive (editor->priv->bc_key_radio, merge != NULL);
489 gtk_toggle_button_set_active (
490 GTK_TOGGLE_BUTTON(editor->priv->bc_color_radio), TRUE);
491 gtk_widget_set_sensitive (editor->priv->bc_color_combo, TRUE);
492 gtk_widget_set_sensitive (editor->priv->bc_key_combo, FALSE);
494 state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(editor->priv->bc_key_radio));
495 gtk_widget_set_sensitive (editor->priv->bc_color_combo, !state);
496 gtk_widget_set_sensitive (editor->priv->bc_key_combo, state);
501 if (editor->priv->shadow_page_vbox) {
502 gtk_widget_set_sensitive (editor->priv->shadow_key_radio, merge != NULL);
504 gtk_toggle_button_set_active (
505 GTK_TOGGLE_BUTTON(editor->priv->shadow_color_radio), TRUE);
506 gtk_widget_set_sensitive (editor->priv->shadow_color_combo, TRUE);
507 gtk_widget_set_sensitive (editor->priv->shadow_key_combo, FALSE);
509 state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(editor->priv->shadow_key_radio));
510 gtk_widget_set_sensitive (editor->priv->shadow_color_combo, !state);
511 gtk_widget_set_sensitive (editor->priv->shadow_key_combo, state);
516 keys = gl_merge_get_key_list (merge);
517 if ( keys == NULL ) {
518 keys = g_list_append (keys, g_strdup (""));
521 combo = editor->priv->img_key_combo;
523 gl_util_combo_box_set_strings (GTK_COMBO_BOX (combo), keys);
526 combo = editor->priv->edit_key_combo;
528 gl_util_combo_box_set_strings (GTK_COMBO_BOX (combo), keys);
531 combo = editor->priv->data_key_combo;
533 gl_util_combo_box_set_strings (GTK_COMBO_BOX (combo), keys);
536 combo = editor->priv->fill_key_combo;
538 gl_util_combo_box_set_strings (GTK_COMBO_BOX (combo), keys);
541 combo = editor->priv->text_color_key_combo;
543 gl_util_combo_box_set_strings (GTK_COMBO_BOX (combo), keys);
546 combo = editor->priv->line_key_combo;
548 gl_util_combo_box_set_strings (GTK_COMBO_BOX (combo), keys);
551 combo = editor->priv->bc_key_combo;
553 gl_util_combo_box_set_strings (GTK_COMBO_BOX (combo), keys);
556 combo = editor->priv->shadow_key_combo;
558 gl_util_combo_box_set_strings (GTK_COMBO_BOX (combo), keys);
561 gl_merge_free_key_list (&keys);
563 gl_debug (DEBUG_EDITOR, "END");
566 /*****************************************************************************/
567 /* Construct color combo "Custom widget". */
568 /*****************************************************************************/
570 gl_object_editor_construct_color_combo (gchar *name,
576 GtkWidget *color_combo;
585 cg_name = "shadow_color_group";
586 gdk_color = gl_color_to_gdk_color (GL_COLOR_SHADOW_DEFAULT);
587 no_color = _("Default");
591 cg_name = "text_color_group";
592 gdk_color = gl_color_to_gdk_color (gl_prefs->default_text_color);
593 no_color = _("Default");
597 cg_name = "line_color_group";
599 no_color = _("No line");
604 cg_name = "fill_color_group";
606 no_color = _("No fill");
611 cg = color_group_fetch (cg_name, NULL);
612 color_combo = color_combo_new (NULL, no_color, gdk_color, cg);
615 color_combo_box_set_preview_relief (COLOR_COMBO(color_combo), GTK_RELIEF_NORMAL);
620 /*****************************************************************************/
621 /* Construct chain button "Custom widget". */
622 /*****************************************************************************/
624 gl_object_editor_construct_chain_button (gchar *name,
630 GtkWidget *chain_button;
632 chain_button = gl_wdgt_chain_button_new (GL_WDGT_CHAIN_RIGHT);
633 gl_wdgt_chain_button_set_active (GL_WDGT_CHAIN_BUTTON(chain_button), TRUE);
638 /*--------------------------------------------------------------------------*/
639 /* PRIVATE. Prefs changed callback. Update units related items. */
640 /*--------------------------------------------------------------------------*/
642 prefs_changed_cb (glObjectEditor *editor)
645 gl_debug (DEBUG_EDITOR, "START");
647 if (editor->priv->lsize_r_spin) {
648 lsize_prefs_changed_cb (editor);
651 if (editor->priv->size_w_spin) {
652 size_prefs_changed_cb (editor);
655 if (editor->priv->pos_x_spin) {
656 position_prefs_changed_cb (editor);
659 if (editor->priv->shadow_x_spin) {
660 shadow_prefs_changed_cb (editor);
663 gl_debug (DEBUG_EDITOR, "END");
666 /*---------------------------------------------------------------------------*/
667 /* PRIVATE. label "changed" callback. */
668 /*---------------------------------------------------------------------------*/
670 label_changed_cb (glLabel *label,
671 glObjectEditor *editor)
673 gdouble label_width, label_height;
676 gl_debug (DEBUG_EDITOR, "START");
678 gl_label_get_size (label, &label_width, &label_height);
679 gl_object_editor_set_max_position (GL_OBJECT_EDITOR (editor),
680 label_width, label_height);
681 gl_object_editor_set_max_size (GL_OBJECT_EDITOR (editor),
682 label_width, label_height);
683 gl_object_editor_set_max_lsize (GL_OBJECT_EDITOR (editor),
684 label_width, label_height);
685 gl_object_editor_set_max_shadow_offset (GL_OBJECT_EDITOR (editor),
686 label_width, label_height);
688 merge = gl_label_get_merge (label);
689 gl_object_editor_set_key_names (editor, merge);
691 gl_debug (DEBUG_EDITOR, "END");