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 <gtk/gtkbuilder.h>
30 #include <gtk/gtklabel.h>
31 #include <gtk/gtknotebook.h>
32 #include <gtk/gtkcombobox.h>
33 #include <gtk/gtktogglebutton.h>
38 #include "color-combo.h"
40 #include "wdgt-chain-button.h"
41 #include "wdgt-merge-menu.h"
45 #include "object-editor-private.h"
49 /*===========================================*/
51 /*===========================================*/
53 /*===========================================*/
54 /* Private data types */
55 /*===========================================*/
57 typedef void (*ChangedSignal) (GObject * object, gpointer data);
59 /*===========================================*/
61 /*===========================================*/
63 gint gl_object_editor_signals[LAST_SIGNAL] = { 0 };
65 /*===========================================*/
66 /* Local function prototypes */
67 /*===========================================*/
69 static void gl_object_editor_finalize (GObject *object);
71 static void gl_object_notebook_construct_valist (glObjectEditor *editor,
73 glObjectEditorOption first_option,
76 static void prefs_changed_cb (glObjectEditor *editor);
78 static void label_changed_cb (glLabel *label,
79 glObjectEditor *editor);
82 /*****************************************************************************/
83 /* Boilerplate object stuff. */
84 /*****************************************************************************/
85 G_DEFINE_TYPE (glObjectEditor, gl_object_editor, GTK_TYPE_VBOX);
88 gl_object_editor_class_init (glObjectEditorClass *class)
90 GObjectClass *object_class = G_OBJECT_CLASS (class);
92 gl_debug (DEBUG_EDITOR, "START");
94 gl_object_editor_parent_class = g_type_class_peek_parent (class);
96 object_class->finalize = gl_object_editor_finalize;
98 gl_object_editor_signals[CHANGED] =
99 g_signal_new ("changed",
100 G_OBJECT_CLASS_TYPE(object_class),
102 G_STRUCT_OFFSET (glObjectEditorClass, changed),
104 gl_marshal_VOID__VOID,
107 gl_object_editor_signals[SIZE_CHANGED] =
108 g_signal_new ("size_changed",
109 G_OBJECT_CLASS_TYPE(object_class),
111 G_STRUCT_OFFSET (glObjectEditorClass, size_changed),
113 gl_marshal_VOID__VOID,
116 gl_debug (DEBUG_EDITOR, "END");
120 gl_object_editor_init (glObjectEditor *editor)
122 GError *error = NULL;
124 gl_debug (DEBUG_EDITOR, "START");
126 editor->priv = g_new0 (glObjectEditorPrivate, 1);
128 editor->priv->gui = gtk_builder_new ();
130 gtk_builder_add_from_file (editor->priv->gui,
131 GLABELS_BUILDER_DIR "object-editor.builder",
134 g_critical ("%s\n\ngLabels may not be installed correctly!", error->message);
135 g_error_free (error);
139 gl_util_get_builder_widgets (editor->priv->gui,
140 "editor_vbox", &editor->priv->editor_vbox,
141 "title_image", &editor->priv->title_image,
142 "title_label", &editor->priv->title_label,
143 "notebook", &editor->priv->notebook,
146 gtk_box_pack_start (GTK_BOX(editor),
147 editor->priv->editor_vbox,
150 gtk_widget_show_all (GTK_WIDGET(editor));
152 /* Hide all notebook pages to start with. */
153 gtk_widget_hide_all (editor->priv->notebook);
154 gtk_widget_set_no_show_all (editor->priv->notebook, TRUE);
156 gl_debug (DEBUG_EDITOR, "END");
160 gl_object_editor_finalize (GObject *object)
162 glObjectEditor* editor = GL_OBJECT_EDITOR (object);;
164 gl_debug (DEBUG_EDITOR, "START");
166 g_return_if_fail (object != NULL);
167 g_return_if_fail (GL_IS_OBJECT_EDITOR (editor));
168 g_return_if_fail (editor->priv != NULL);
170 g_signal_handlers_disconnect_by_func (G_OBJECT(gl_prefs),
171 prefs_changed_cb, editor);
172 g_signal_handlers_disconnect_by_func (G_OBJECT(editor->priv->label),
173 label_changed_cb, editor);
175 g_object_unref (editor->priv->gui);
176 g_free (editor->priv);
178 G_OBJECT_CLASS (gl_object_editor_parent_class)->finalize (object);
180 gl_debug (DEBUG_EDITOR, "END");
183 /*****************************************************************************/
184 /* NEW object editor. */
185 /*****************************************************************************/
187 gl_object_editor_new (gchar *image,
190 glObjectEditorOption first_option, ...)
192 glObjectEditor *editor;
195 gl_debug (DEBUG_EDITOR, "START");
197 editor = GL_OBJECT_EDITOR (g_object_new (GL_TYPE_OBJECT_EDITOR, NULL));
200 gtk_image_set_from_stock (GTK_IMAGE(editor->priv->title_image),
202 GTK_ICON_SIZE_LARGE_TOOLBAR);
208 s = g_strdup_printf ("<span weight=\"bold\">%s</span>",
210 gtk_label_set_text (GTK_LABEL(editor->priv->title_label), s);
213 gtk_label_set_use_markup (GTK_LABEL(editor->priv->title_label), TRUE);
217 gtk_notebook_set_homogeneous_tabs (GTK_NOTEBOOK(editor->priv->notebook), TRUE);
219 va_start (args, first_option);
220 gl_object_notebook_construct_valist (editor, label, first_option, args);
223 gl_debug (DEBUG_EDITOR, "END");
225 return GTK_WIDGET(editor);
228 /*--------------------------------------------------------------------------*/
229 /* PRIVATE. Construct notebook. */
230 /*--------------------------------------------------------------------------*/
232 gl_object_notebook_construct_valist (glObjectEditor *editor,
234 glObjectEditorOption first_option,
237 glObjectEditorOption option;
240 gl_debug (DEBUG_EDITOR, "START");
242 editor->priv->label = label;
244 option = first_option;
246 for ( option=first_option; option; option=va_arg (args, glObjectEditorOption) ) {
250 case GL_OBJECT_EDITOR_EMPTY:
251 gtk_widget_set_sensitive (editor->priv->title_image, FALSE);
252 gtk_widget_set_sensitive (editor->priv->title_label, FALSE);
255 case GL_OBJECT_EDITOR_POSITION_PAGE:
256 gl_object_editor_prepare_position_page (editor);
260 case GL_OBJECT_EDITOR_SIZE_PAGE:
261 case GL_OBJECT_EDITOR_SIZE_IMAGE_PAGE:
262 gl_object_editor_prepare_size_page (editor, option);
266 case GL_OBJECT_EDITOR_SIZE_LINE_PAGE:
267 gl_object_editor_prepare_lsize_page (editor);
271 case GL_OBJECT_EDITOR_FILL_PAGE:
272 gl_object_editor_prepare_fill_page (editor);
276 case GL_OBJECT_EDITOR_LINE_PAGE:
277 gl_object_editor_prepare_line_page (editor);
281 case GL_OBJECT_EDITOR_IMAGE_PAGE:
282 gl_object_editor_prepare_image_page (editor);
286 case GL_OBJECT_EDITOR_TEXT_PAGE:
287 gl_object_editor_prepare_text_page (editor);
291 case GL_OBJECT_EDITOR_EDIT_PAGE:
292 gl_object_editor_prepare_edit_page (editor);
296 case GL_OBJECT_EDITOR_BC_PAGE:
297 gl_object_editor_prepare_bc_page (editor);
301 case GL_OBJECT_EDITOR_DATA_PAGE:
302 gl_object_editor_prepare_data_page (editor);
306 case GL_OBJECT_EDITOR_SHADOW_PAGE:
307 gl_object_editor_prepare_shadow_page (editor);
312 g_message ("option = %d", option);
313 g_assert_not_reached ();
318 gtk_widget_show (editor->priv->notebook);
321 g_signal_connect_swapped (G_OBJECT (gl_prefs), "changed",
322 G_CALLBACK (prefs_changed_cb),
326 label_changed_cb (label, editor);
327 g_signal_connect (G_OBJECT (label), "size_changed",
328 G_CALLBACK (label_changed_cb),
330 g_signal_connect (G_OBJECT (label), "merge_changed",
331 G_CALLBACK (label_changed_cb),
335 gl_debug (DEBUG_EDITOR, "END");
338 /*--------------------------------------------------------------------------*/
339 /* PRIVATE. Widget changed callback. Emit our "changed" signal. */
340 /*--------------------------------------------------------------------------*/
342 gl_object_editor_changed_cb (glObjectEditor *editor)
344 if (editor->priv->stop_signals) return;
346 gl_debug (DEBUG_EDITOR, "START");
348 /* Emit our "changed" signal */
349 g_signal_emit (G_OBJECT (editor), gl_object_editor_signals[CHANGED], 0);
351 gl_debug (DEBUG_EDITOR, "END");
354 /*--------------------------------------------------------------------------*/
355 /* PRIVATE. Widget size changed callback. Emit our "size-changed" signal. */
356 /*--------------------------------------------------------------------------*/
358 gl_object_editor_size_changed_cb (glObjectEditor *editor)
360 if (editor->priv->stop_signals) return;
362 gl_debug (DEBUG_EDITOR, "START");
364 /* Emit our "size_changed" signal */
365 g_signal_emit (G_OBJECT (editor), gl_object_editor_signals[SIZE_CHANGED], 0);
367 gl_debug (DEBUG_EDITOR, "END");
370 /*****************************************************************************/
371 /* Set possible key names from merge object. */
372 /*****************************************************************************/
374 gl_object_editor_set_key_names (glObjectEditor *editor,
383 gl_debug (DEBUG_EDITOR, "START");
385 if (editor->priv->text_auto_shrink_check) {
386 gtk_widget_set_sensitive (editor->priv->text_auto_shrink_check,
390 if (editor->priv->text_page_vbox) {
391 gtk_widget_set_sensitive (editor->priv->text_color_key_radio, merge != NULL);
393 gtk_toggle_button_set_active (
394 GTK_TOGGLE_BUTTON(editor->priv->text_color_radio), TRUE);
395 gtk_widget_set_sensitive (editor->priv->text_color_combo, TRUE);
396 gtk_widget_set_sensitive (editor->priv->text_color_key_combo, FALSE);
398 state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(editor->priv->text_color_key_radio));
399 gtk_widget_set_sensitive (editor->priv->text_color_combo, !state);
400 gtk_widget_set_sensitive (editor->priv->text_color_key_combo, state);
405 if (editor->priv->edit_insert_field_button) {
406 gtk_widget_set_sensitive (editor->priv->edit_insert_field_button,
410 if (editor->priv->img_key_combo) {
411 gtk_widget_set_sensitive (editor->priv->img_key_combo, merge != NULL);
414 if (editor->priv->img_key_radio) {
415 gtk_widget_set_sensitive (editor->priv->img_key_radio, merge != NULL);
417 gtk_toggle_button_set_active (
418 GTK_TOGGLE_BUTTON(editor->priv->img_file_radio), TRUE);
422 if (editor->priv->data_key_combo) {
423 gtk_widget_set_sensitive (editor->priv->data_key_combo, merge != NULL);
426 if (editor->priv->data_key_radio) {
427 gtk_widget_set_sensitive (editor->priv->data_key_radio, merge != NULL);
429 gtk_toggle_button_set_active (
430 GTK_TOGGLE_BUTTON(editor->priv->data_literal_radio), TRUE);
434 fixed_flag = editor->priv->data_format_fixed_flag;
435 if (editor->priv->data_format_label) {
436 gtk_widget_set_sensitive (editor->priv->data_format_label,
439 if (editor->priv->data_ex_label) {
440 gtk_widget_set_sensitive (editor->priv->data_ex_label,
443 if (editor->priv->data_digits_label) {
444 gtk_widget_set_sensitive (editor->priv->data_digits_label,
445 (merge != NULL) && !fixed_flag);
447 if (editor->priv->data_digits_spin) {
448 gtk_widget_set_sensitive (editor->priv->data_digits_spin,
449 (merge != NULL) && !fixed_flag);
452 if (editor->priv->fill_page_vbox) {
453 gtk_widget_set_sensitive (editor->priv->fill_key_radio, merge != NULL);
455 gtk_toggle_button_set_active (
456 GTK_TOGGLE_BUTTON(editor->priv->fill_color_radio), TRUE);
457 gtk_widget_set_sensitive (editor->priv->fill_color_combo, TRUE);
458 gtk_widget_set_sensitive (editor->priv->fill_key_combo, FALSE);
460 state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(editor->priv->fill_key_radio));
461 gtk_widget_set_sensitive (editor->priv->fill_color_combo, !state);
462 gtk_widget_set_sensitive (editor->priv->fill_key_combo, state);
467 if (editor->priv->line_page_vbox) {
468 gtk_widget_set_sensitive (editor->priv->line_key_radio, merge != NULL);
470 gtk_toggle_button_set_active (
471 GTK_TOGGLE_BUTTON(editor->priv->line_color_radio), TRUE);
472 gtk_widget_set_sensitive (editor->priv->line_color_combo, TRUE);
473 gtk_widget_set_sensitive (editor->priv->line_key_combo, FALSE);
475 state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(editor->priv->line_key_radio));
476 gtk_widget_set_sensitive (editor->priv->line_color_combo, !state);
477 gtk_widget_set_sensitive (editor->priv->line_key_combo, state);
482 if (editor->priv->bc_page_vbox) {
483 gtk_widget_set_sensitive (editor->priv->bc_key_radio, merge != NULL);
485 gtk_toggle_button_set_active (
486 GTK_TOGGLE_BUTTON(editor->priv->bc_color_radio), TRUE);
487 gtk_widget_set_sensitive (editor->priv->bc_color_combo, TRUE);
488 gtk_widget_set_sensitive (editor->priv->bc_key_combo, FALSE);
490 state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(editor->priv->bc_key_radio));
491 gtk_widget_set_sensitive (editor->priv->bc_color_combo, !state);
492 gtk_widget_set_sensitive (editor->priv->bc_key_combo, state);
497 if (editor->priv->shadow_page_vbox) {
498 gtk_widget_set_sensitive (editor->priv->shadow_key_radio, merge != NULL);
500 gtk_toggle_button_set_active (
501 GTK_TOGGLE_BUTTON(editor->priv->shadow_color_radio), TRUE);
502 gtk_widget_set_sensitive (editor->priv->shadow_color_combo, TRUE);
503 gtk_widget_set_sensitive (editor->priv->shadow_key_combo, FALSE);
505 state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(editor->priv->shadow_key_radio));
506 gtk_widget_set_sensitive (editor->priv->shadow_color_combo, !state);
507 gtk_widget_set_sensitive (editor->priv->shadow_key_combo, state);
512 keys = gl_merge_get_key_list (merge);
513 if ( keys == NULL ) {
514 keys = g_list_append (keys, g_strdup (""));
517 combo = editor->priv->img_key_combo;
519 gl_util_combo_box_set_strings (GTK_COMBO_BOX (combo), keys);
522 menu = editor->priv->edit_insert_field_menu;
524 gl_wdgt_merge_menu_set_fields (GL_WDGT_MERGE_MENU(menu), keys);
527 combo = editor->priv->data_key_combo;
529 gl_util_combo_box_set_strings (GTK_COMBO_BOX (combo), keys);
532 combo = editor->priv->fill_key_combo;
534 gl_util_combo_box_set_strings (GTK_COMBO_BOX (combo), keys);
537 combo = editor->priv->text_color_key_combo;
539 gl_util_combo_box_set_strings (GTK_COMBO_BOX (combo), keys);
542 combo = editor->priv->line_key_combo;
544 gl_util_combo_box_set_strings (GTK_COMBO_BOX (combo), keys);
547 combo = editor->priv->bc_key_combo;
549 gl_util_combo_box_set_strings (GTK_COMBO_BOX (combo), keys);
552 combo = editor->priv->shadow_key_combo;
554 gl_util_combo_box_set_strings (GTK_COMBO_BOX (combo), keys);
557 gl_merge_free_key_list (&keys);
559 gl_debug (DEBUG_EDITOR, "END");
563 /*--------------------------------------------------------------------------*/
564 /* PRIVATE. Prefs changed callback. Update units related items. */
565 /*--------------------------------------------------------------------------*/
567 prefs_changed_cb (glObjectEditor *editor)
570 gl_debug (DEBUG_EDITOR, "START");
572 if (editor->priv->lsize_r_spin) {
573 lsize_prefs_changed_cb (editor);
576 if (editor->priv->size_w_spin) {
577 size_prefs_changed_cb (editor);
580 if (editor->priv->pos_x_spin) {
581 position_prefs_changed_cb (editor);
584 if (editor->priv->shadow_x_spin) {
585 shadow_prefs_changed_cb (editor);
588 gl_debug (DEBUG_EDITOR, "END");
591 /*---------------------------------------------------------------------------*/
592 /* PRIVATE. label "changed" callback. */
593 /*---------------------------------------------------------------------------*/
595 label_changed_cb (glLabel *label,
596 glObjectEditor *editor)
598 gdouble label_width, label_height;
601 gl_debug (DEBUG_EDITOR, "START");
603 gl_label_get_size (label, &label_width, &label_height);
604 gl_object_editor_set_max_position (GL_OBJECT_EDITOR (editor),
605 label_width, label_height);
606 gl_object_editor_set_max_size (GL_OBJECT_EDITOR (editor),
607 label_width, label_height);
608 gl_object_editor_set_max_lsize (GL_OBJECT_EDITOR (editor),
609 label_width, label_height);
610 gl_object_editor_set_max_shadow_offset (GL_OBJECT_EDITOR (editor),
611 label_width, label_height);
613 merge = gl_label_get_merge (label);
614 gl_object_editor_set_key_names (editor, merge);
616 gl_debug (DEBUG_EDITOR, "END");