Some documenting thingies.
[irreco.git] / irreco / trunk / src / core / irreco_background_dlg.c
blobc62a949d800a2de37165208dda9e29aafcd5870d
1 /*
2 * irreco - Ir Remote Control
3 * Copyright (C) 2007 Arto Karppinen (arto.karppinen@iki.fi)
4 * 2008 Joni Kokko (t5kojo01@students.oamk.fi)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "irreco_background_dlg.h"
22 #include <hildon/hildon-color-button.h>
23 #include <hildon/hildon-file-chooser-dialog.h>
26 /**
27 * @typedef IrrecoBackgroundDlg
29 * Allow user to setup layout background.
32 #define IRRECO_BACKGROUND_PREVIEW_WIDHT (IRRECO_SCREEN_WIDTH / 6)
33 #define IRRECO_BACKGROUND_PREVIEW_HEIGHT (IRRECO_SCREEN_HEIGHT / 6)
37 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
38 /* Prototypes */
39 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
41 void irreco_background_dlg_sync_radio(IrrecoBackgroundDlg * self);
42 gboolean irreco_background_dlg_draw_preview(IrrecoBackgroundDlg * self);
43 gboolean irreco_background_dlg_draw_preview_custom(IrrecoBackgroundDlg * self,
44 const gchar * image,
45 const GdkColor * bg_color);
46 void irreco_background_dlg_color_clicked(GtkColorButton *widget,
47 IrrecoBackgroundDlg * self);
48 void irreco_background_dlg_type_toggled(GtkToggleButton * togglebutton,
49 IrrecoBackgroundDlg * self);
50 void irreco_background_dlg_image_clicked(gpointer * ignore,
51 IrrecoBackgroundDlg * self);
52 void irreco_background_dlg_preview_clicked(gpointer * ignore1,
53 gpointer * ignore2,
54 IrrecoBackgroundDlg * self);
55 void irreco_background_dlg_theme_image_selection_changed(
56 GtkTreeSelection * selection,
57 IrrecoBackgroundDlg * self);
60 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
61 /* Public functions */
62 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
64 IrrecoBackgroundDlg *irreco_background_dlg_create(IrrecoData *irreco_data,
65 GtkWindow *parent_window)
67 IrrecoBackgroundDlg *self;
68 GtkWidget *vbox;
69 GtkWidget *hbox;
70 GtkWidget *vbox_left;
71 GtkWidget *vbox_right;
72 GtkTable *table_right;
74 GtkWidget *label_left;
75 GtkWidget *label_right;
76 GtkWidget *label_color;
77 GtkWidget *label_image;
79 GtkWidget *radio_default_a;
80 GtkWidget *radio_color_a;
81 GtkWidget *radio_image_a;
83 GtkWidget *button_image;
84 GtkWidget *preview_frame;
85 GtkWidget *preview_event_box;
86 IRRECO_ENTER
88 self = g_slice_new0(IrrecoBackgroundDlg);
89 self->filename = g_string_new(NULL);
90 self->dialog = gtk_dialog_new_with_buttons(
91 _("Background"), parent_window,
92 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT |
93 GTK_DIALOG_NO_SEPARATOR,
94 GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
95 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
96 NULL);
98 /* Create widgets. */
100 vbox = gtk_vbox_new(0, 0);
103 hbox = gtk_hbox_new(0, 12);
104 vbox_left = gtk_vbox_new(0, 0);
105 vbox_right = gtk_vbox_new(0, 0);
107 self->notebook = gtk_notebook_new();
109 gtk_notebook_append_page(GTK_NOTEBOOK(self->notebook),
110 vbox, gtk_label_new("Default"));
112 self->theme_bg_browser = irreco_bg_browser_widget_new(irreco_data);
113 gtk_notebook_append_page(GTK_NOTEBOOK(self->notebook),
114 GTK_WIDGET(self->theme_bg_browser),
115 gtk_label_new("Theme"));
117 gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(self->dialog)->vbox),
118 self->notebook);
120 label_left = irreco_gtk_label_bold(_("Background"), 0, 0, 0, 6, 0, 0);
121 label_right = irreco_gtk_label_bold(_("Select"), 0, 0, 0, 6, 0, 0);
122 label_color = irreco_gtk_label(_("Color"), 0, 0.5, 0, 0, 12, 0);
123 label_image = irreco_gtk_label(_("Image"), 0, 0.5, 0, 0, 12, 0);
125 self->radio_default =
126 gtk_radio_button_new_with_label(
127 NULL, _("Default image"));
128 self->radio_color =
129 gtk_radio_button_new_with_label_from_widget(
130 GTK_RADIO_BUTTON(self->radio_default),
131 _("Color only"));
132 self->radio_image =
133 gtk_radio_button_new_with_label_from_widget(
134 GTK_RADIO_BUTTON(self->radio_color),
135 _("Color and Image"));
136 radio_default_a = irreco_gtk_pad(self->radio_default,
137 0, 0, 12, 0);
138 radio_color_a = irreco_gtk_pad(self->radio_color,
139 0, 0, 12, 0);
140 radio_image_a = irreco_gtk_pad(self->radio_image,
141 0, 0, 12, 0);
143 self->color_button = hildon_color_button_new();
144 button_image = gtk_button_new_with_label(_("Select"));
146 preview_frame = gtk_frame_new(NULL);
147 preview_event_box = gtk_event_box_new();
148 self->preview = gtk_drawing_area_new();
149 gtk_drawing_area_size(GTK_DRAWING_AREA(self->preview),
150 IRRECO_BACKGROUND_PREVIEW_WIDHT,
151 IRRECO_BACKGROUND_PREVIEW_HEIGHT);
153 /* Build dialog. */
154 table_right = GTK_TABLE(gtk_table_new(2, 2, FALSE));
155 gtk_table_set_row_spacings(table_right, 6);
156 gtk_table_set_col_spacings(table_right, 12);
157 gtk_table_attach_defaults(table_right, label_color, 0, 1, 0, 1);
158 gtk_table_attach_defaults(table_right, label_image, 0, 1, 1, 2);
159 gtk_table_attach_defaults(table_right, self->color_button,
160 1, 2, 0, 1);
161 gtk_table_attach_defaults(table_right, button_image, 1, 2, 1, 2);
163 gtk_box_pack_start_defaults(GTK_BOX(vbox),
164 irreco_gtk_pad(hbox, 12, 0, 12, 12));
165 gtk_box_pack_start_defaults(GTK_BOX(hbox), vbox_left);
166 gtk_box_pack_start_defaults(GTK_BOX(hbox), vbox_right);
167 gtk_box_pack_start(GTK_BOX(vbox_left), label_left, 0, 0, 0);
168 gtk_box_pack_start(GTK_BOX(vbox_left), radio_default_a, 0, 0, 0);
169 gtk_box_pack_start(GTK_BOX(vbox_left), radio_color_a, 0, 0, 0);
170 gtk_box_pack_start(GTK_BOX(vbox_left), radio_image_a, 0, 0, 0);
171 gtk_box_pack_start(GTK_BOX(vbox_right), label_right, 0, 0, 0);
172 gtk_box_pack_start(GTK_BOX(vbox_right), GTK_WIDGET(table_right),
173 0, 0, 0);
175 gtk_container_add(GTK_CONTAINER(preview_event_box), preview_frame);
176 gtk_container_add(GTK_CONTAINER(preview_frame),self->preview);
177 gtk_box_pack_start_defaults(GTK_BOX(vbox), irreco_gtk_align(
178 preview_event_box,
179 0.5, 0.5, 0, 0, 12, 0, 0, 0));
180 /* Radio button signals. */
181 g_signal_connect(G_OBJECT(self->radio_default), "toggled",
182 G_CALLBACK(irreco_background_dlg_type_toggled),
183 self);
184 g_object_set_data(G_OBJECT(self->radio_default),
185 "IrrecoButtonLayoutBgType",
186 (gpointer) IRRECO_BACKGROUND_DEFAULT);
187 g_signal_connect(G_OBJECT(self->radio_color), "toggled",
188 G_CALLBACK(irreco_background_dlg_type_toggled),
189 self);
190 g_object_set_data(G_OBJECT(self->radio_color),
191 "IrrecoButtonLayoutBgType",
192 (gpointer) IRRECO_BACKGROUND_COLOR);
193 g_signal_connect(G_OBJECT(self->radio_image), "toggled",
194 G_CALLBACK(irreco_background_dlg_type_toggled),
195 self);
196 g_object_set_data(G_OBJECT(self->radio_image),
197 "IrrecoButtonLayoutBgType",
198 (gpointer) IRRECO_BACKGROUND_IMAGE);
200 /* Button signals. */
201 g_signal_connect(G_OBJECT(button_image), "clicked",
202 G_CALLBACK(irreco_background_dlg_image_clicked),
203 self);
204 g_signal_connect(G_OBJECT(self->color_button), "clicked",
205 G_CALLBACK(irreco_background_dlg_color_clicked),
206 self);
207 g_signal_connect(G_OBJECT(preview_event_box), "button-release-event",
208 G_CALLBACK(irreco_background_dlg_preview_clicked),
209 self);
211 /* Signal handler for theme_bg_browser*/
212 g_signal_connect(G_OBJECT(IRRECO_LISTBOX(
213 self->theme_bg_browser->images)->tree_selection),
214 "changed",
215 G_CALLBACK(irreco_background_dlg_theme_image_selection_changed),
216 self);
218 gtk_widget_show_all(self->dialog);
219 IRRECO_RETURN_PTR(self);
223 * Destroys and hides dialog.
225 void irreco_background_dlg_destroy(IrrecoBackgroundDlg * self)
227 IRRECO_ENTER
228 gtk_widget_destroy(self->dialog);
229 g_string_free(self->filename, TRUE);
230 g_slice_free(IrrecoBackgroundDlg, self);
231 IRRECO_RETURN
235 * Show dialog, and ask user for input.
237 gboolean irreco_background_dlg_run(IrrecoBackgroundDlg * self,
238 IrrecoButtonLayout * irreco_layout)
240 IRRECO_ENTER
242 /* Setup dialog. */
243 self->type = irreco_button_layout_get_bg_type(irreco_layout);
244 irreco_gstring_set(self->filename,
245 irreco_button_layout_get_bg_image(irreco_layout));
246 hildon_color_button_set_color(
247 HILDON_COLOR_BUTTON(self->color_button),
248 irreco_button_layout_get_bg_color(irreco_layout));
250 /* Prepare ui. */
251 irreco_background_dlg_sync_radio(self);
252 irreco_background_dlg_draw_preview(self);
254 if (gtk_dialog_run(GTK_DIALOG(self->dialog))
255 == GTK_RESPONSE_ACCEPT) {
256 GdkColor *color;
257 g_object_get(G_OBJECT(self->color_button),
258 "color", &color, NULL);
259 irreco_button_layout_set_bg_type(irreco_layout,
260 self->type);
261 irreco_button_layout_set_bg_color(irreco_layout, color);
262 irreco_button_layout_set_bg_image(
263 irreco_layout, self->filename->str);
265 IRRECO_PRINTF("%i\n",
266 irreco_button_layout_get_bg_type(irreco_layout));
268 IRRECO_RETURN_BOOL(TRUE);
270 IRRECO_RETURN_BOOL(FALSE);
275 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
276 /* Private functions */
277 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
279 void irreco_background_dlg_sync_radio(IrrecoBackgroundDlg * self)
281 IRRECO_ENTER
282 switch (self->type) {
283 case IRRECO_BACKGROUND_DEFAULT:
284 gtk_widget_grab_focus(self->radio_default);
285 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
286 self->radio_default),
287 TRUE);
288 break;
290 case IRRECO_BACKGROUND_COLOR:
291 gtk_widget_grab_focus(self->radio_color);
292 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
293 self->radio_color),
294 TRUE);
295 break;
297 case IRRECO_BACKGROUND_IMAGE:
298 gtk_widget_grab_focus(self->radio_image);
299 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
300 self->radio_image),
301 TRUE);
302 break;
304 IRRECO_RETURN
308 * Draw preview with current image.
310 gboolean
311 irreco_background_dlg_draw_preview(IrrecoBackgroundDlg * self)
313 const gchar *image = NULL;
314 const GdkColor *color = NULL;
315 IRRECO_ENTER
317 switch (self->type) {
318 case IRRECO_BACKGROUND_DEFAULT:
319 image = irreco_button_layout_default_image;
320 color = &irreco_button_layout_default_color;
321 break;
323 case IRRECO_BACKGROUND_IMAGE:
324 image = self->filename->str;
325 if (irreco_str_isempty(image)) image = NULL;
327 case IRRECO_BACKGROUND_COLOR:
328 g_object_get(G_OBJECT(self->color_button),
329 "color", &color, NULL);
330 break;
333 IRRECO_RETURN_BOOL(irreco_background_dlg_draw_preview_custom(
334 self, image, color));
338 * Draw preview with custom image.
340 gboolean
341 irreco_background_dlg_draw_preview_custom(IrrecoBackgroundDlg * self,
342 const gchar * image,
343 const GdkColor * bg_color)
345 GError *error = NULL;
346 GdkPixbuf *pixbuf = NULL;
347 GdkPixmap *pixmap = NULL;
348 GdkGC *bg_gc = NULL;
349 IRRECO_ENTER
351 g_assert(self != NULL);
353 /* Attempt to load the image. */
354 if (image != NULL) {
355 pixbuf = gdk_pixbuf_new_from_file_at_scale(image,
356 IRRECO_BACKGROUND_PREVIEW_WIDHT,
357 IRRECO_BACKGROUND_PREVIEW_HEIGHT,
358 FALSE, &error);
359 if (irreco_gerror_check_print(&error)) {
360 IRRECO_RETURN_BOOL(FALSE);
364 pixmap = gdk_pixmap_new(GDK_DRAWABLE(
365 self->preview->window),
366 IRRECO_BACKGROUND_PREVIEW_WIDHT,
367 IRRECO_BACKGROUND_PREVIEW_HEIGHT,
368 -1);
370 /* Fill background with solid color. */
371 bg_gc = gdk_gc_new(GDK_DRAWABLE(self->preview->window));
372 gdk_gc_set_rgb_fg_color(bg_gc, bg_color);
373 gdk_gc_set_rgb_bg_color(bg_gc, bg_color);
374 gdk_draw_rectangle(GDK_DRAWABLE(pixmap), bg_gc, TRUE, 0, 0,
375 IRRECO_BACKGROUND_PREVIEW_WIDHT,
376 IRRECO_BACKGROUND_PREVIEW_HEIGHT);
377 g_object_unref(G_OBJECT(bg_gc));
379 /* Draw images to pixmap. */
380 if (pixbuf != NULL) {
381 gdk_draw_pixbuf(GDK_DRAWABLE(pixmap), NULL, pixbuf, 0, 0, 0, 0,
382 IRRECO_BACKGROUND_PREVIEW_WIDHT,
383 IRRECO_BACKGROUND_PREVIEW_HEIGHT,
384 GDK_RGB_DITHER_NORMAL, 0, 0);
387 /* Set background image, and queque redraw, so the image is shown.*/
388 gdk_window_set_back_pixmap(self->preview->window,
389 pixmap, FALSE);
390 gtk_widget_queue_draw_area(self->preview, 0, 0,
391 self->preview->allocation.width,
392 self->preview->allocation.height);
394 if (pixbuf != NULL) g_object_unref(G_OBJECT(pixbuf));
395 if (pixmap != NULL) g_object_unref(G_OBJECT(pixmap));
396 IRRECO_RETURN_BOOL(TRUE);
399 void irreco_background_dlg_select_image(IrrecoBackgroundDlg * self)
401 GdkColor *color = NULL;
402 GtkWidget *file_dlg = NULL;
403 gchar *image_dir = NULL;
404 IRRECO_ENTER
406 /* Create image select dialog. */
407 file_dlg = hildon_file_chooser_dialog_new(GTK_WINDOW(
408 self->dialog),
409 GTK_FILE_CHOOSER_ACTION_OPEN);
410 gtk_window_set_title(GTK_WINDOW(file_dlg),_("Select background image"));
411 gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(file_dlg), TRUE);
412 image_dir = g_build_path("/", getenv("HOME"), "MyDocs/.images/", NULL);
413 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_dlg),
414 image_dir);
415 g_free(image_dir);
417 /* Loop until user cancels or we get a valid image. */
418 gtk_widget_show_all(GTK_WIDGET(file_dlg));
419 while (gtk_dialog_run(GTK_DIALOG(file_dlg)) == GTK_RESPONSE_OK) {
420 gchar *filename = gtk_file_chooser_get_filename(
421 GTK_FILE_CHOOSER(file_dlg));
422 IRRECO_PRINTF("Attempting to display background "
423 "image: \"%s\".\n", filename);
425 /* Attempt to display the image. */
426 g_object_get(G_OBJECT(self->color_button),
427 "color", &color, NULL);
428 if (irreco_background_dlg_draw_preview_custom(
429 self, filename, color)) {
430 IRRECO_PRINTF("Image OK.\n");
431 irreco_gstring_set_and_free(
432 self->filename, filename);
433 filename = NULL;
434 self->theme_bg_browser->current_image = NULL;
436 /* Set type as image. */
437 if (self->type != IRRECO_BACKGROUND_IMAGE) {
438 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
439 self->radio_image), TRUE);
441 break;
443 /* Cleanup */
444 } else {
445 gchar *basename = g_path_get_basename(filename);
446 irreco_error_dlg_printf(GTK_WINDOW(file_dlg),
447 _("Cannot open image \"%s\""),
448 basename);
449 IRRECO_PRINTF("Image invalid.\n");
450 g_free(basename);
451 g_free(filename);
455 gtk_widget_grab_focus(self->radio_image);
456 gtk_widget_destroy(file_dlg);
457 IRRECO_RETURN
462 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
463 /* Signal handlers. */
464 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
466 void irreco_background_dlg_color_clicked(GtkColorButton *widget,
467 IrrecoBackgroundDlg * self)
469 IRRECO_ENTER
471 /* Make sure the background type is color or image. */
472 if (self->type == IRRECO_BACKGROUND_DEFAULT) {
473 /* This should trigger a redraw ... */
474 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
475 self->radio_color),
476 TRUE);
477 } else {
478 irreco_background_dlg_draw_preview(self);
480 IRRECO_RETURN
483 void irreco_background_dlg_type_toggled(GtkToggleButton * togglebutton,
484 IrrecoBackgroundDlg * self)
486 IrrecoButtonLayoutBgType type;
487 IRRECO_ENTER
489 if (gtk_toggle_button_get_active(togglebutton) == TRUE) {
490 type = (IrrecoButtonLayoutBgType) g_object_get_data(
491 G_OBJECT(togglebutton), "IrrecoButtonLayoutBgType");
492 self->type = type;
493 IRRECO_PRINTF("Type: %i\n", self->type);
496 irreco_background_dlg_draw_preview(self);
497 IRRECO_RETURN
500 void irreco_background_dlg_image_clicked(gpointer * ignore,
501 IrrecoBackgroundDlg * self)
503 IRRECO_ENTER
504 irreco_background_dlg_select_image(self);
505 IRRECO_RETURN
508 void irreco_background_dlg_preview_clicked(gpointer * ignore1,
509 gpointer * ignore2,
510 IrrecoBackgroundDlg * self)
512 IRRECO_ENTER
513 irreco_background_dlg_select_image(self);
514 IRRECO_RETURN
517 void irreco_background_dlg_theme_image_selection_changed(
518 GtkTreeSelection * selection,
519 IrrecoBackgroundDlg * self)
521 IrrecoThemeBg *bg = self->theme_bg_browser->current_image;
522 IRRECO_ENTER
524 if (bg != NULL) {
525 g_string_printf (self->filename, "%s", bg->image_path->str);
527 /* Set type as image. */
528 if (self->type != IRRECO_BACKGROUND_IMAGE) {
529 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
530 self->radio_image), TRUE);
532 } else {
533 g_string_printf (self->filename, "%s", "");
536 irreco_background_dlg_draw_preview(self);
538 IRRECO_RETURN