Clean code and added a few amendments (if()).
[irreco.git] / irreco / src / core / irreco_window_edit.c
blob89ae4d2fab4af6cf4254fb9aec1c517fbb889a0a
1 /*
2 * irreco - Ir Remote Control
3 * Copyright (C) 2007 Arto Karppinen (arto.karppinen@iki.fi)
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include "irreco_window_edit.h"
21 #include "irreco_window_user.h"
22 #include "irreco_button_dlg.h"
23 #include "irreco_config.h"
24 #include "irreco_input_dlg.h"
25 #include "irreco_backend_dlg.h"
26 #include "irreco_background_dlg.h"
27 #include "irreco_device_dlg.h"
28 #include "irreco_hardkey_dlg.h"
29 #include "irreco_webdb_dlg.h"
30 #include "irreco_theme_manager_dlg.h"
32 /**
33 * @addtogroup IrrecoWindowEdit
34 * @ingroup Irreco
36 * User interface for editing button layouts.
38 * @{
41 /**
42 * @file
43 * Source file of @ref IrrecoWindowEdit.
47 typedef struct _ButtonMenuForeachData ButtonMenuForeachData;
48 struct _ButtonMenuForeachData {
49 GtkWidget *button_menu;
50 gint i;
55 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
56 /* Prototypes. */
57 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
58 void irreco_window_edit_controller_help(IrrecoWindowEdit * edit_window);
59 gboolean irreco_window_edit_expose(GtkWidget * widget, GdkEventExpose * event,
60 IrrecoWindowEdit * edit_window);
61 static void irreco_window_edit_sync_grid(IrrecoWindowEdit * edit_window);
62 static void irreco_window_edit_draw_background(IrrecoWindowEdit * edit_window);
63 static void irreco_window_load_background(IrrecoWindowEdit * edit_window,
64 const gchar * grid_image_filename,
65 GdkPixbuf ** grid_pixbuf_pointer);
67 void irreco_window_edit_button_motion_callback(IrrecoButton * irreco_button,
68 IrrecoWindowEdit * edit_window);
69 gboolean irreco_window_edit_drag_handler(IrrecoWindowEdit * edit_window);
71 void irreco_window_edit_button_press_callback(IrrecoButton * irreco_button,
72 IrrecoWindowEdit * edit_window);
73 void irreco_window_edit_button_release_callback(IrrecoButton * irreco_button,
74 IrrecoWindowEdit * edit_window);
76 void irreco_window_edit_main_menu_create(IrrecoWindowEdit * edit_window);
77 void irreco_window_edit_main_menu_save(GtkMenuItem * menuitem,
78 IrrecoWindowEdit * edit_window);
79 void irreco_window_edit_main_menu_background(GtkMenuItem * menuitem,
80 IrrecoWindowEdit * edit_window);
81 void irreco_window_edit_main_menu_hardkeys(GtkMenuItem * menuitem,
82 IrrecoWindowEdit * edit_window);
83 void irreco_window_edit_main_menu_controllers(GtkMenuItem * menuitem,
84 IrrecoWindowEdit * edit_window);
85 void irreco_window_edit_main_menu_devices(GtkMenuItem * menuitem,
86 IrrecoWindowEdit * edit_window);
87 void irreco_window_edit_main_menu_download_device(GtkMenuItem * menuitem,
88 IrrecoWindowEdit * edit_window);
89 void irreco_window_edit_main_menu_newbutton(GtkMenuItem * menuitem,
90 IrrecoWindowEdit * edit_window);
91 void irreco_window_edit_main_menu_select_button(GtkMenuItem * menuitem,
92 IrrecoButton * irreco_button);
93 void irreco_window_edit_main_menu_theme_manager(GtkMenuItem * menuitem,
94 IrrecoWindowEdit
95 *edit_window);
97 void irreco_window_edit_menu_grid(GtkMenuItem * menuitem,
98 IrrecoWindowEdit * edit_window);
99 void irreco_window_edit_main_menu_grid_1(GtkCheckMenuItem * menuitem,
100 IrrecoWindowEdit * edit_window);
101 void irreco_window_edit_main_menu_grid_2(GtkCheckMenuItem * menuitem,
102 IrrecoWindowEdit * edit_window);
103 void irreco_window_edit_main_menu_grid_4(GtkCheckMenuItem * menuitem,
104 IrrecoWindowEdit * edit_window);
105 void irreco_window_edit_main_menu_grid_8(GtkCheckMenuItem * menuitem,
106 IrrecoWindowEdit * edit_window);
107 void irreco_window_edit_main_menu_grid_16(GtkCheckMenuItem * menuitem,
108 IrrecoWindowEdit * edit_window);
110 void irreco_window_edit_button_menu_create(IrrecoWindowEdit * edit_window);
111 void irreco_window_edit_buttons_menu_update(IrrecoWindowEdit * edit_window);
112 void irreco_window_edit_buttons_menu_update_foreach(IrrecoButton * button,
113 ButtonMenuForeachData * data);
114 void irreco_window_edit_button_menu_show(IrrecoButton * irreco_button,
115 IrrecoWindowEdit * edit_window);
116 void irreco_window_edit_button_menu_show_position(GtkMenu * menu,
117 gint * x, gint * y,
118 gboolean * push_in,
119 IrrecoWindowEdit * edit_window);
120 void irreco_window_edit_button_menu_front(GtkMenuItem * menuitem,
121 IrrecoWindowEdit * edit_window);
122 void irreco_window_edit_button_menu_edit(GtkMenuItem * menuitem,
123 IrrecoWindowEdit * edit_window);
124 void irreco_window_edit_button_menu_delete(GtkMenuItem * menuitem,
125 IrrecoWindowEdit * edit_window);
126 void irreco_window_edit_button_menu_done(GtkMenuItem * menuitem,
127 IrrecoWindowEdit * edit_window);
131 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
132 /* Public functions. */
133 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
136 * @name Public Functions
137 * @{
141 * Crate and display IrrecoWindowEdit.
143 IrrecoWindowEdit *irreco_window_edit_create(IrrecoWindowManager * manager)
145 IrrecoData *irreco_data = manager->irreco_data;
146 IrrecoWindowEdit *edit_window;
147 IRRECO_ENTER
149 g_assert(manager != NULL);
150 edit_window = g_slice_new0(IrrecoWindowEdit);
151 edit_window->window = irreco_window_create();
152 edit_window->irreco_data = irreco_data;
153 edit_window->manager = manager;
154 edit_window->drag_grid = 8;
155 edit_window->drag_handler_set = FALSE;
157 edit_window->expose_handler_id = g_signal_connect(
158 G_OBJECT(irreco_window_get_gtk_window(edit_window->window)),
159 "expose-event", G_CALLBACK(irreco_window_edit_expose),
160 edit_window);
162 irreco_window_edit_set_layout(edit_window, manager->current_layout);
163 irreco_window_edit_main_menu_create(edit_window);
164 irreco_window_edit_button_menu_create(edit_window);
166 irreco_window_edit_sync_grid(edit_window);
167 gtk_window_set_title(irreco_window_get_gtk_window(edit_window->window),
168 _("Edit remote"));
169 IRRECO_RETURN_PTR(edit_window);
172 void irreco_window_edit_destroy(IrrecoWindowEdit *edit_window)
174 IRRECO_ENTER
176 /* Release background images. */
177 if (edit_window->image_background != NULL) {
178 g_object_unref(G_OBJECT(edit_window->image_background));
180 if (edit_window->image_grid_1 != NULL) {
181 g_object_unref(G_OBJECT(edit_window->image_grid_1));
183 if (edit_window->image_grid_2 != NULL) {
184 g_object_unref(G_OBJECT(edit_window->image_grid_2));
186 if (edit_window->image_grid_4 != NULL) {
187 g_object_unref(G_OBJECT(edit_window->image_grid_4));
189 if (edit_window->image_grid_8 != NULL) {
190 g_object_unref(G_OBJECT(edit_window->image_grid_8));
192 if (edit_window->image_grid_16 != NULL) {
193 g_object_unref(G_OBJECT(edit_window->image_grid_16));
196 if (edit_window->irreco_layout != NULL) {
197 irreco_button_layout_reset(edit_window->irreco_layout);
200 gtk_widget_destroy(edit_window->button_menu);
201 irreco_window_destroy(edit_window->window);
202 g_slice_free(IrrecoWindowEdit, edit_window);
203 IRRECO_RETURN
206 void irreco_window_edit_set_layout(IrrecoWindowEdit * edit_window,
207 IrrecoButtonLayout * irreco_layout)
209 IRRECO_ENTER
211 if (edit_window->irreco_layout != NULL) {
212 irreco_button_layout_reset(edit_window->irreco_layout);
215 if (irreco_layout == NULL) {
216 edit_window->irreco_layout = NULL;
217 IRRECO_RETURN
220 irreco_button_layout_reset(irreco_layout);
221 edit_window->irreco_layout = irreco_layout;
222 irreco_button_layout_set_motion_callback(
223 irreco_layout, irreco_window_edit_button_motion_callback);
224 irreco_button_layout_set_press_callback(
225 irreco_layout, irreco_window_edit_button_press_callback);
226 irreco_button_layout_set_release_callback(
227 irreco_layout, irreco_window_edit_button_release_callback);
228 irreco_button_layout_set_callback_data(irreco_layout, edit_window);
230 irreco_button_layout_set_container(irreco_layout,
231 edit_window->window->layout);
232 irreco_button_layout_create_widgets(irreco_layout);
233 irreco_button_layout_set_size(irreco_layout,
234 IRRECO_LAYOUT_WIDTH,
235 IRRECO_LAYOUT_HEIGHT);
237 IRRECO_RETURN
240 /** @} */
244 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
245 /* Help. */
246 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
249 * @name Help
250 * @{
253 void irreco_window_edit_device_help(IrrecoWindowEdit * edit_window)
255 IrrecoBackendManager *manager;
256 IRRECO_ENTER
258 manager = edit_window->irreco_data->irreco_backend_manager;
259 IRRECO_BACKEND_MANAGER_FOREACH_INSTANCE(manager, instace)
260 if (!irreco_string_table_is_empty(instace->device_list)) {
261 IRRECO_RETURN
263 IRRECO_BACKEND_MANAGER_FOREACH_END
265 irreco_info_dlg(irreco_window_get_gtk_window(edit_window->window),
266 _(IRRECO_NO_DEVICE_HELP));
267 IRRECO_RETURN
270 void irreco_window_edit_controller_help(IrrecoWindowEdit * edit_window)
272 IrrecoBackendManager *manager;
273 IRRECO_ENTER
275 manager = edit_window->irreco_data->irreco_backend_manager;
276 if (irreco_string_table_is_empty(manager->instance_table)) {
277 irreco_info_dlg(irreco_window_get_gtk_window(
278 edit_window->window),
279 _(IRRECO_NO_CONTROLLER_HELP));
281 IRRECO_RETURN
284 gboolean irreco_window_edit_expose(GtkWidget * widget, GdkEventExpose * event,
285 IrrecoWindowEdit * edit_window)
287 IRRECO_ENTER
288 g_signal_handler_disconnect(
289 G_OBJECT(irreco_window_get_gtk_window(edit_window->window)),
290 edit_window->expose_handler_id);
291 irreco_window_edit_controller_help(edit_window);
292 IRRECO_RETURN_BOOL(FALSE);
295 /** @} */
299 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
300 /* Private functions. */
301 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
304 * @name Private Functions
305 * @{
309 * Make sure the selected menu item matches the value of edit_window->drag_grid.
311 static void irreco_window_edit_sync_grid(IrrecoWindowEdit * edit_window)
313 IRRECO_ENTER
314 switch (edit_window->drag_grid) {
315 case 1: gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
316 edit_window->menu_grid_1), TRUE); IRRECO_RETURN
317 case 2: gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
318 edit_window->menu_grid_2), TRUE); IRRECO_RETURN
319 case 4: gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
320 edit_window->menu_grid_4), TRUE); IRRECO_RETURN
321 case 8: gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
322 edit_window->menu_grid_8), TRUE); IRRECO_RETURN
323 case 16: gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
324 edit_window->menu_grid_16), TRUE); IRRECO_RETURN
325 default: IRRECO_ERROR("Unknown grid value \"%i\"\n",
326 edit_window->drag_grid); IRRECO_RETURN
328 IRRECO_RETURN
331 static void irreco_window_edit_draw_background(IrrecoWindowEdit * edit_window)
333 gchar *image = NULL;
334 GdkPixbuf **grid_pixbuf = NULL;
335 IRRECO_ENTER
337 switch (edit_window->drag_grid) {
338 case 1:
339 image = NULL;
340 grid_pixbuf = NULL;
342 image = "grid-1x1.png";
343 grid_pixbuf = &edit_window->image_grid_1;
345 break;
347 case 2:
348 image = "grid-2x2.png";
349 grid_pixbuf = &edit_window->image_grid_2;
350 break;
352 case 4:
353 image = "grid-4x4.png";
354 grid_pixbuf = &edit_window->image_grid_4;
355 break;
357 case 8:
358 image = "grid-8x8.png";
359 grid_pixbuf = &edit_window->image_grid_8;
360 break;
362 case 16:
363 image = "grid-16x16.png";
364 grid_pixbuf = &edit_window->image_grid_16;
365 break;
367 default:
368 IRRECO_ERROR("Unknown grid value \"%i\"\n",
369 edit_window->drag_grid);
370 IRRECO_RETURN
373 irreco_window_load_background(edit_window, image, grid_pixbuf);
374 IRRECO_RETURN
378 * Load window background images, and draw them.
380 * If the *grid_pixbuf_pointer is NULL this function will load the image into
381 * a pixbuf and store it into the *grid_pixbuf_pointer.
383 * Or if *grid_pixbuf_pointer is set, then uses the existing pixbuf.
385 * Basically the grid_pixbuf_pointer is used to cache the image data.
387 static void irreco_window_load_background(IrrecoWindowEdit * edit_window,
388 const gchar * grid_image_filename,
389 GdkPixbuf ** grid_pixbuf_pointer)
391 const gchar *image;
392 const GdkColor *color;
393 GError *error = NULL;
394 IRRECO_ENTER
396 /* Load grid image. */
397 if (grid_image_filename != NULL
398 && grid_pixbuf_pointer != NULL
399 && *grid_pixbuf_pointer == NULL) {
400 gchar *image_path = g_build_path("/", IRRECO_IMAGE_DIR,
401 grid_image_filename, NULL);
402 *grid_pixbuf_pointer = gdk_pixbuf_new_from_file_at_scale(
403 image_path, IRRECO_SCREEN_WIDTH,
404 IRRECO_SCREEN_HEIGHT, FALSE, &error);
405 g_free(image_path);
406 irreco_gerror_check_print(&error);
409 /* Load background image. */
410 irreco_button_layout_get_bg(edit_window->irreco_layout, &image, &color);
411 if (edit_window->image_background == NULL && image != NULL) {
412 edit_window->image_background =
413 gdk_pixbuf_new_from_file_at_scale(image,
414 IRRECO_SCREEN_WIDTH, IRRECO_SCREEN_HEIGHT,
415 FALSE, &error);
416 irreco_gerror_check_print(&error);
419 if (grid_pixbuf_pointer == NULL || grid_image_filename == NULL) {
420 irreco_window_set_background_buf(edit_window->window, color,
421 edit_window->image_background,
422 NULL);
423 } else {
424 irreco_window_set_background_buf(edit_window->window, color,
425 edit_window->image_background,
426 *grid_pixbuf_pointer);
428 IRRECO_RETURN
431 /** @} */
435 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
436 /* IrrecoButton callbacks. */
437 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
440 * @name IrrecoButton callbacks
441 * @{
445 * Instead of handling the movement of mouse immediately here, in the
446 * high priority event handler, we set up a low priority callback.
447 * Basically this should make sure that if resoirrecoes are tight, some
448 * movements will be ignored.
450 void irreco_window_edit_button_motion_callback(IrrecoButton * irreco_button,
451 IrrecoWindowEdit * edit_window)
453 GTimeVal now;
454 IRRECO_ENTER
456 if (edit_window->drag_target == NULL) {
457 IRRECO_RETURN
460 /* Save pointer location at the time of the event. */
461 gdk_window_get_pointer(edit_window->window->event_box->window,
462 &edit_window->drag_pointer_x,
463 &edit_window->drag_pointer_y,
464 &edit_window->drag_pointer_mask);
466 /* Dont move button right away, this removes most jitters from fast
467 click button location reset code. */
468 g_get_current_time(&now);
469 if (irreco_time_diff(&edit_window->drag_start_time, &now)
470 <= 0.05 * IRRECO_SECOND_IN_USEC) {
471 IRRECO_RETURN
474 /* Somethimes we get several drag events before we have time to
475 actually move the button. */
476 if (edit_window->drag_handler_set != TRUE) {
477 g_idle_add(G_SOURCEFUNC(irreco_window_edit_drag_handler),
478 edit_window);
479 edit_window->drag_handler_set = TRUE;
481 IRRECO_RETURN
483 gboolean irreco_window_edit_drag_handler(IrrecoWindowEdit * edit_window)
485 gint grid_x, grid_y;
486 gint pointer_x, pointer_y;
487 IrrecoButton *irreco_button = edit_window->drag_target;
488 IRRECO_ENTER
490 if (edit_window->drag_target == NULL) {
491 edit_window->drag_handler_set = FALSE;
492 IRRECO_RETURN_BOOL(FALSE);
495 /* New coordinates. */
496 pointer_x = edit_window->drag_pointer_x
497 - edit_window->drag_pointer_offset_x;
498 pointer_y = edit_window->drag_pointer_y
499 - edit_window->drag_pointer_offset_y;
500 grid_x = pointer_x - (pointer_x % edit_window->drag_grid);
501 grid_y = pointer_y - (pointer_y % edit_window->drag_grid);
503 /* Move the widget only if the widget has moved in relation to the grid
504 and in relation of the old coordinates. */
505 if ((pointer_x != irreco_button->x || pointer_y != irreco_button->y) &&
506 (grid_x != irreco_button->x || grid_y != irreco_button->y)) {
507 edit_window->drag_button_moved = TRUE;
508 irreco_button_move(edit_window->drag_target, &grid_x, &grid_y);
509 IRRECO_DEBUG("Widget moved to: x%i y%i\n",
510 edit_window->drag_target->x,
511 edit_window->drag_target->y);
514 edit_window->drag_handler_set = FALSE;
515 IRRECO_RETURN_BOOL(FALSE);
518 void irreco_window_edit_button_press_callback(IrrecoButton * irreco_button,
519 IrrecoWindowEdit * edit_window)
521 gint x, y;
522 GdkModifierType mask;
523 IRRECO_ENTER
525 /* Save start data. */
526 g_get_current_time(&edit_window->drag_start_time);
527 edit_window->drag_start_x = irreco_button->x;
528 edit_window->drag_start_y = irreco_button->y;
530 /* Set button as drag target. */
531 edit_window->drag_button_moved = FALSE;
532 edit_window->drag_target = irreco_button;
533 gdk_window_get_pointer(edit_window->window->event_box->window,
534 &x, &y, &mask);
535 edit_window->drag_pointer_offset_x = x - irreco_button->x;
536 edit_window->drag_pointer_offset_y = y - irreco_button->y;
537 IRRECO_DEBUG("Drag Offset: x%i y%i\n",
538 edit_window->drag_pointer_offset_x,
539 edit_window->drag_pointer_offset_y);
540 IRRECO_DEBUG("Widget size: w%i h%i\n",
541 irreco_button->width, irreco_button->height);
542 irreco_button_down(irreco_button);
544 IRRECO_RETURN
547 void irreco_window_edit_button_release_callback(IrrecoButton * irreco_button,
548 IrrecoWindowEdit * edit_window)
550 GTimeVal now;
551 IRRECO_ENTER
553 /* Because of the impresision of the touch screen in N8xx tables,
554 a simple click on the screen may end up moving the button when
555 the user simply want's to see the popup menu. We try to fix this by
556 resetting the button location if the click is fast enough.*/
557 g_get_current_time(&now);
558 if (irreco_time_diff(&edit_window->drag_start_time, &now)
559 <= 0.1 * IRRECO_SECOND_IN_USEC) {
560 irreco_button_move(edit_window->drag_target,
561 &edit_window->drag_start_x,
562 &edit_window->drag_start_y);
563 IRRECO_DEBUG("Widget moved to: x%i y%i\n",
564 edit_window->drag_start_x,
565 edit_window->drag_start_y);
566 edit_window->drag_button_moved = FALSE;
569 edit_window->drag_target = NULL;
570 irreco_button_up(irreco_button);
571 if (edit_window->drag_button_moved == FALSE) {
572 irreco_window_edit_button_menu_show(irreco_button, edit_window);
574 IRRECO_RETURN
577 /** @} */
581 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
582 /* Main menu construction. */
583 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
586 * @name Main menu construction
587 * @{
590 void irreco_window_edit_main_menu_create(IrrecoWindowEdit * edit_window)
592 GtkWidget *button_menu;
593 GtkWidget *grid_menu;
594 GSList *group;
595 GtkWidget *menu_grid_1;
596 GtkWidget *menu_grid_2;
597 GtkWidget *menu_grid_4;
598 GtkWidget *menu_grid_8;
599 GtkWidget *menu_grid_16;
600 IRRECO_ENTER
602 /* Build menu. */
603 edit_window->menu = gtk_menu_new();
604 edit_window->menu_save =
605 gtk_menu_item_new_with_label(_("Save remote"));
606 edit_window->menu_background =
607 gtk_menu_item_new_with_label(_("Background"));
608 edit_window->menu_hardkeys =
609 gtk_menu_item_new_with_label(_("Hardware keys"));
610 edit_window->menu_controllers =
611 gtk_menu_item_new_with_label(_("Device Controllers"));
612 edit_window->menu_devices =
613 gtk_menu_item_new_with_label(_("Devices"));
614 edit_window->menu_download_device =
615 gtk_menu_item_new_with_label(_("Download device"));
616 edit_window->menu_buttons =
617 gtk_menu_item_new_with_label(_("Select button"));
618 edit_window->menu_newbutton =
619 gtk_menu_item_new_with_label(_("New button"));
620 edit_window->menu_grid =
621 gtk_menu_item_new_with_label(_("Snap to grid"));
622 edit_window->menu_theme_manager =
623 gtk_menu_item_new_with_label(_("Theme Manager"));
625 gtk_menu_append(edit_window->menu, edit_window->menu_save);
626 gtk_menu_append(edit_window->menu, gtk_separator_menu_item_new());
627 gtk_menu_append(edit_window->menu, edit_window->menu_controllers);
628 gtk_menu_append(edit_window->menu, edit_window->menu_devices);
629 gtk_menu_append(edit_window->menu, edit_window->menu_download_device);
630 gtk_menu_append(edit_window->menu, gtk_separator_menu_item_new());
631 gtk_menu_append(edit_window->menu, edit_window->menu_hardkeys);
632 gtk_menu_append(edit_window->menu, edit_window->menu_background);
633 gtk_menu_append(edit_window->menu, edit_window->menu_theme_manager);
634 gtk_menu_append(edit_window->menu, gtk_separator_menu_item_new());
635 gtk_menu_append(edit_window->menu, edit_window->menu_newbutton);
636 gtk_menu_append(edit_window->menu, edit_window->menu_buttons);
637 gtk_menu_append(edit_window->menu, edit_window->menu_grid);
639 grid_menu = gtk_menu_new();
640 group = NULL;
641 menu_grid_1 =
642 gtk_radio_menu_item_new_with_label(group, _("Off"));
643 group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(menu_grid_1));
644 menu_grid_2 =
645 gtk_radio_menu_item_new_with_label(group, _("2 pixels"));
646 group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(menu_grid_2));
647 menu_grid_4 =
648 gtk_radio_menu_item_new_with_label(group, _("4 pixels"));
649 group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(menu_grid_4));
650 menu_grid_8 =
651 gtk_radio_menu_item_new_with_label(group, _("8 pixels"));
652 group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(menu_grid_8));
653 menu_grid_16 =
654 gtk_radio_menu_item_new_with_label(group, _("16 pixels"));
656 gtk_menu_append(grid_menu, menu_grid_1);
657 gtk_menu_append(grid_menu, menu_grid_2);
658 gtk_menu_append(grid_menu, menu_grid_4);
659 gtk_menu_append(grid_menu, menu_grid_8);
660 gtk_menu_append(grid_menu, menu_grid_16);
662 /* Create empty menu. This is just a place holder. The real menu will be
663 created just in time when the menu is to be shown. */
664 button_menu = gtk_menu_new();
665 gtk_menu_item_set_submenu(GTK_MENU_ITEM(edit_window->menu_buttons),
666 button_menu);
668 /* Show menu. */
669 hildon_window_set_menu(HILDON_WINDOW(edit_window->window),
670 GTK_MENU(edit_window->menu));
671 gtk_menu_item_set_submenu(GTK_MENU_ITEM(edit_window->menu_grid),
672 grid_menu);
673 gtk_widget_show_all(edit_window->menu);
675 /* TODO: remove grid 2 completly. */
676 gtk_widget_hide(menu_grid_2);
678 /* Connect signals. */
679 g_signal_connect(G_OBJECT(edit_window->menu_save), "activate",
680 G_CALLBACK(irreco_window_edit_main_menu_save),
681 edit_window);
682 g_signal_connect(G_OBJECT(edit_window->menu_background), "activate",
683 G_CALLBACK(irreco_window_edit_main_menu_background),
684 edit_window);
685 g_signal_connect(G_OBJECT(edit_window->menu_hardkeys), "activate",
686 G_CALLBACK(irreco_window_edit_main_menu_hardkeys),
687 edit_window);
688 g_signal_connect(G_OBJECT(edit_window->menu_controllers), "activate",
689 G_CALLBACK(irreco_window_edit_main_menu_controllers),
690 edit_window);
691 g_signal_connect(G_OBJECT(edit_window->menu_devices), "activate",
692 G_CALLBACK(irreco_window_edit_main_menu_devices),
693 edit_window);
694 g_signal_connect(G_OBJECT(edit_window->menu_download_device),
695 "activate",
696 G_CALLBACK(irreco_window_edit_main_menu_download_device),
697 edit_window);
698 g_signal_connect(G_OBJECT(edit_window->menu_newbutton), "activate",
699 G_CALLBACK(irreco_window_edit_main_menu_newbutton),
700 edit_window);
701 g_signal_connect(G_OBJECT(edit_window->menu_grid), "activate",
702 G_CALLBACK(irreco_window_edit_menu_grid),
703 edit_window);
705 g_signal_connect(G_OBJECT(menu_grid_1), "toggled",
706 G_CALLBACK(irreco_window_edit_main_menu_grid_1),
707 edit_window);
708 g_signal_connect(G_OBJECT(menu_grid_2), "toggled",
709 G_CALLBACK(irreco_window_edit_main_menu_grid_2),
710 edit_window);
711 g_signal_connect(G_OBJECT(menu_grid_4), "toggled",
712 G_CALLBACK(irreco_window_edit_main_menu_grid_4),
713 edit_window);
714 g_signal_connect(G_OBJECT(menu_grid_8), "toggled",
715 G_CALLBACK(irreco_window_edit_main_menu_grid_8),
716 edit_window);
717 g_signal_connect(G_OBJECT(menu_grid_16), "toggled",
718 G_CALLBACK(irreco_window_edit_main_menu_grid_16),
719 edit_window);
720 g_signal_connect(G_OBJECT(edit_window->menu_theme_manager), "activate",
721 G_CALLBACK(irreco_window_edit_main_menu_theme_manager),
722 edit_window);
724 /* Store pointers. */
725 edit_window->menu_grid_1 = menu_grid_1;
726 edit_window->menu_grid_2 = menu_grid_2;
727 edit_window->menu_grid_4 = menu_grid_4;
728 edit_window->menu_grid_8 = menu_grid_8;
729 edit_window->menu_grid_16 = menu_grid_16;
731 IRRECO_RETURN
734 /** @} */
738 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
739 /* Main menu callback functions. */
740 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
743 * @name Main menu callback functions
744 * @{
747 void irreco_window_edit_main_menu_save(GtkMenuItem * menuitem,
748 IrrecoWindowEdit * edit_window)
750 IrrecoData *irreco_data = edit_window->irreco_data;
751 IRRECO_ENTER
753 irreco_config_save_layouts(irreco_data);
754 irreco_window_manager_show(irreco_data->window_manager,
755 IRRECO_WINDOW_USER);
756 IRRECO_RETURN
759 void irreco_window_edit_main_menu_background(GtkMenuItem * menuitem,
760 IrrecoWindowEdit * edit_window)
762 IrrecoBackgroundDlg *background_dlg;
763 IrrecoData *irreco_data = edit_window->irreco_data;
764 IRRECO_ENTER
765 background_dlg = irreco_background_dlg_create(irreco_data,
766 irreco_window_get_gtk_window(edit_window->window));
768 /* Ask for new background config, and cleanup old config if user
769 clicks ok. */
770 if (irreco_background_dlg_run(background_dlg,
771 edit_window->irreco_layout)) {
772 if (edit_window->image_background != NULL) {
773 g_object_unref(G_OBJECT(edit_window->image_background));
774 edit_window->image_background = NULL;
776 irreco_window_edit_draw_background(edit_window);
778 irreco_background_dlg_destroy(background_dlg);
779 IRRECO_RETURN
782 void irreco_window_edit_main_menu_hardkeys(GtkMenuItem * menuitem,
783 IrrecoWindowEdit * edit_window)
785 GtkWidget *dlg;
786 IRRECO_ENTER
788 dlg = irreco_hardkey_dlg_new(irreco_window_manager_get_gtk_window(
789 edit_window->irreco_data->window_manager),
790 edit_window->irreco_data,
791 edit_window->irreco_layout->hardkey_map);
792 gtk_dialog_run(GTK_DIALOG(dlg));
793 gtk_widget_destroy(dlg);
794 IRRECO_RETURN
797 void irreco_window_edit_main_menu_controllers(GtkMenuItem * menuitem,
798 IrrecoWindowEdit * edit_window)
800 IRRECO_ENTER
801 irreco_show_backend_dlg(edit_window->irreco_data,
802 irreco_window_get_gtk_window(
803 edit_window->window));
804 irreco_window_edit_device_help(edit_window);
805 IRRECO_RETURN
808 void irreco_window_edit_main_menu_devices(GtkMenuItem * menuitem,
809 IrrecoWindowEdit * edit_window)
811 IRRECO_ENTER
812 irreco_show_device_dlg(edit_window->irreco_data,
813 irreco_window_get_gtk_window(
814 edit_window->window));
815 IRRECO_RETURN
818 void irreco_window_edit_main_menu_download_device(GtkMenuItem * menuitem,
819 IrrecoWindowEdit * edit_window)
821 IRRECO_ENTER
822 irreco_show_webdb_dlg(edit_window->irreco_data,
823 irreco_window_get_gtk_window(
824 edit_window->window));
825 IRRECO_RETURN
827 void irreco_window_edit_main_menu_newbutton(GtkMenuItem * menuitem,
828 IrrecoWindowEdit * edit_window)
830 IRRECO_ENTER
831 if (irreco_button_dlg_run(edit_window->irreco_data->new_button_dlg,
832 edit_window->window,
833 _("New button"))){
834 IrrecoButton *button = irreco_button_create(
835 edit_window->irreco_layout, 100, 100, NULL, NULL,
836 edit_window->irreco_data->cmd_chain_manager);
837 irreco_button_dlg_data_to_button(
838 edit_window->irreco_data->new_button_dlg, button);
839 irreco_button_create_widget(button);
841 irreco_window_edit_buttons_menu_update(edit_window);
842 IRRECO_RETURN
845 void irreco_window_edit_main_menu_select_button(GtkMenuItem * menuitem,
846 IrrecoButton * irreco_button)
848 IRRECO_ENTER
849 irreco_button_to_front(irreco_button);
850 irreco_window_edit_button_menu_show(irreco_button, (IrrecoWindowEdit *)
851 irreco_button_layout_get_callback_data(
852 irreco_button->irreco_layout));
853 irreco_button_flash(irreco_button);
855 IRRECO_RETURN
858 void irreco_window_edit_main_menu_theme_manager(GtkMenuItem * menuitem,
859 IrrecoWindowEdit * edit_window)
861 IRRECO_ENTER
862 irreco_show_theme_manager_dlg(edit_window->irreco_data,
863 irreco_window_get_gtk_window(
864 edit_window->window));
867 IRRECO_RETURN
871 /** @} */
875 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
876 /* Grid menu callback functions. */
877 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
880 * @name Grid menu callback functions
881 * @{
884 void irreco_window_edit_menu_grid(GtkMenuItem * menuitem,
885 IrrecoWindowEdit * edit_window)
887 IRRECO_ENTER
888 IRRECO_RETURN
891 void irreco_window_edit_main_menu_grid_1(GtkCheckMenuItem * menuitem,
892 IrrecoWindowEdit * edit_window)
894 IRRECO_ENTER
895 if (gtk_check_menu_item_get_active(menuitem)) {
896 edit_window->drag_grid = 1;
897 irreco_window_edit_draw_background(edit_window);
899 IRRECO_RETURN
902 void irreco_window_edit_main_menu_grid_2(GtkCheckMenuItem * menuitem,
903 IrrecoWindowEdit * edit_window)
905 IRRECO_ENTER
906 if (gtk_check_menu_item_get_active(menuitem)) {
907 edit_window->drag_grid = 2;
908 irreco_window_edit_draw_background(edit_window);
910 IRRECO_RETURN
913 void irreco_window_edit_main_menu_grid_4(GtkCheckMenuItem * menuitem,
914 IrrecoWindowEdit * edit_window)
916 IRRECO_ENTER
917 if (gtk_check_menu_item_get_active(menuitem)) {
918 edit_window->drag_grid = 4;
919 irreco_window_edit_draw_background(edit_window);
921 IRRECO_RETURN
924 void irreco_window_edit_main_menu_grid_8(GtkCheckMenuItem * menuitem,
925 IrrecoWindowEdit * edit_window)
927 IRRECO_ENTER
928 if (gtk_check_menu_item_get_active(menuitem)) {
929 edit_window->drag_grid = 8;
930 irreco_window_edit_draw_background(edit_window);
932 IRRECO_RETURN
935 void irreco_window_edit_main_menu_grid_16(GtkCheckMenuItem * menuitem,
936 IrrecoWindowEdit * edit_window)
938 IRRECO_ENTER
939 if (gtk_check_menu_item_get_active(menuitem)) {
940 edit_window->drag_grid = 16;
941 irreco_window_edit_draw_background(edit_window);
943 IRRECO_RETURN
946 /** @} */
950 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
951 /* Button menu construction. */
952 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
955 * @name Button menu construction
956 * @{
960 * Create edit menu.
962 void irreco_window_edit_button_menu_create(IrrecoWindowEdit * edit_window)
964 GtkWidget *button_menu;
965 GtkWidget *button_menu_front;
966 GtkWidget *button_menu_edit;
967 GtkWidget *button_menu_delete;
968 GtkWidget *button_menu_separator;
969 GtkWidget *button_menu_done;
970 IRRECO_ENTER
972 /* Create menu. */
973 button_menu = gtk_menu_new();
974 button_menu_front = gtk_menu_item_new_with_label(_("Bring to front"));
975 button_menu_edit = gtk_menu_item_new_with_label(_("Edit button"));
976 button_menu_delete = gtk_menu_item_new_with_label(_("Delete button"));
977 button_menu_separator = gtk_separator_menu_item_new();
978 button_menu_done = gtk_menu_item_new_with_label(_("Done"));
980 gtk_menu_append(button_menu, button_menu_front);
981 gtk_menu_append(button_menu, button_menu_edit);
982 gtk_menu_append(button_menu, button_menu_delete);
983 gtk_menu_append(button_menu, button_menu_separator);
984 gtk_menu_append(button_menu, button_menu_done);
986 /* Connect signals. */
987 g_signal_connect(G_OBJECT(button_menu_front), "activate",
988 G_CALLBACK(irreco_window_edit_button_menu_front),
989 edit_window);
990 g_signal_connect(G_OBJECT(button_menu_edit), "activate",
991 G_CALLBACK(irreco_window_edit_button_menu_edit),
992 edit_window);
993 g_signal_connect(G_OBJECT(button_menu_edit), "activate",
994 G_CALLBACK(irreco_window_edit_button_menu_done),
995 edit_window);
996 g_signal_connect(G_OBJECT(button_menu_delete), "activate",
997 G_CALLBACK(irreco_window_edit_button_menu_delete),
998 edit_window);
1000 edit_window->button_menu = button_menu;
1001 gtk_widget_show_all(GTK_WIDGET(button_menu));
1003 irreco_window_edit_buttons_menu_update(edit_window);
1004 IRRECO_RETURN
1008 * Generates buttons submenu just in time.
1010 void irreco_window_edit_buttons_menu_update(IrrecoWindowEdit * edit_window)
1012 ButtonMenuForeachData foreach_data;
1013 IRRECO_ENTER
1015 /* Are there any buttons? */
1016 if (edit_window->irreco_layout->button_array->len == 0) {
1017 gtk_widget_set_sensitive(GTK_WIDGET(edit_window->menu_buttons),
1018 FALSE);
1019 IRRECO_RETURN
1020 } else {
1021 gtk_widget_set_sensitive(GTK_WIDGET(edit_window->menu_buttons),
1022 TRUE);
1025 /* Foreach loop */
1026 foreach_data.button_menu = gtk_menu_new();
1027 foreach_data.i = edit_window->irreco_layout->button_array->len;
1028 g_ptr_array_foreach(
1029 edit_window->irreco_layout->button_array,
1030 G_FUNC(irreco_window_edit_buttons_menu_update_foreach),
1031 &foreach_data);
1033 /* Connect the new submenu to the main menu. */
1034 gtk_menu_item_set_submenu(
1035 GTK_MENU_ITEM(edit_window->menu_buttons),
1036 foreach_data.button_menu);
1037 gtk_widget_show_all(GTK_WIDGET(foreach_data.button_menu));
1039 IRRECO_RETURN
1042 void irreco_window_edit_buttons_menu_update_foreach(IrrecoButton * button,
1043 ButtonMenuForeachData * data)
1045 GtkWidget *item;
1046 gchar label[100];
1047 GCallback callback;
1048 IRRECO_ENTER
1050 g_snprintf(label, 100, "%i: %s", data->i--,
1051 button->title);
1052 item = gtk_menu_item_new_with_label(label);
1053 gtk_menu_shell_prepend(GTK_MENU_SHELL(data->button_menu), item);
1054 callback = G_CALLBACK(irreco_window_edit_main_menu_select_button);
1055 g_signal_connect(G_OBJECT(item), "activate", callback, button);
1057 IRRECO_RETURN
1061 * Show button context menu which the user can use to edit the button.
1063 void irreco_window_edit_button_menu_show(IrrecoButton * irreco_button,
1064 IrrecoWindowEdit * edit_window)
1066 IRRECO_ENTER
1068 /* Make sure that the whole button is visible. */
1069 irreco_window_scroll_visible(edit_window->window,
1070 irreco_button->x + irreco_button->width,
1071 irreco_button->y + irreco_button->height);
1072 irreco_window_scroll_visible(edit_window->window,
1073 irreco_button->x,
1074 irreco_button->y);
1076 /* Show popup menu. */
1077 edit_window->button_menu_target = irreco_button;
1078 gtk_menu_popup(GTK_MENU(edit_window->button_menu), NULL, NULL,
1079 G_MENU_POS_FUNC(irreco_window_edit_button_menu_show_position),
1080 edit_window, 0, gtk_get_current_event_time());
1082 IRRECO_RETURN
1086 * Calculate a new position for the popup that is right next to the button.
1088 void irreco_window_edit_button_menu_show_position(GtkMenu * menu,
1089 gint * x, gint * y,
1090 gboolean * push_in,
1091 IrrecoWindowEdit * edit_window)
1093 IrrecoButton * irreco_button = edit_window->button_menu_target;
1094 gint window_x, window_y;
1095 gdouble scroll_x, scroll_y;
1096 GdkWindow *window;
1097 GtkRequisition requisition;
1098 IRRECO_ENTER
1100 gtk_widget_size_request(GTK_WIDGET(menu), &requisition);
1101 IRRECO_DEBUG("Button menu size: w%i h%i\n",
1102 requisition.width, requisition.height);
1104 window = edit_window->window->event_box->window;
1105 gdk_window_get_origin(window, &window_x, &window_y);
1106 IRRECO_DEBUG("Eventbox offset: x%i y%i\n", window_x, window_y);
1108 /* Calculate a position to the right side of the button. */
1109 irreco_window_get_scroll_offset(edit_window->window,
1110 &scroll_x, &scroll_y);
1111 *x = window_x + irreco_button->x + irreco_button->width - scroll_x;
1112 *y = window_y + irreco_button->y - scroll_y;
1114 /* If there is not enough space, move popup to the left side of the
1115 button. */
1116 if (*x + requisition.width > IRRECO_SCREEN_WIDTH) {
1117 *x = window_x + irreco_button->x - requisition.width - scroll_x;
1119 if (*y + requisition.height > IRRECO_SCREEN_HEIGHT) {
1120 *y -= *y + requisition.height - IRRECO_LAYOUT_HEIGHT - scroll_y;
1122 IRRECO_DEBUG("Button menu position: x%i y%i\n", *x, *y);
1124 IRRECO_RETURN
1127 /** @} */
1131 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
1132 /* Button menu callbacks. */
1133 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
1136 * @name Button menu callbacks
1137 * @{
1140 void irreco_window_edit_button_menu_front(GtkMenuItem * menuitem,
1141 IrrecoWindowEdit * edit_window)
1143 IRRECO_ENTER
1144 irreco_button_to_front(edit_window->button_menu_target);
1146 IRRECO_RETURN
1149 void irreco_window_edit_button_menu_edit(GtkMenuItem * menuitem,
1150 IrrecoWindowEdit * edit_window)
1152 IrrecoButtonDlg* button_dlg;
1153 IrrecoButton* button = edit_window->button_menu_target;
1154 IRRECO_ENTER
1156 button_dlg = irreco_button_dlg_create(edit_window->irreco_data);
1157 irreco_button_dlg_data_from_button(button_dlg, button);
1158 irreco_button_dlg_print(button_dlg);
1159 irreco_button_dlg_run(button_dlg, edit_window->window,
1160 _("Edit button"));
1161 irreco_button_dlg_print(button_dlg);
1162 irreco_button_dlg_data_to_button(button_dlg, button);
1163 irreco_button_create_widget(button);
1164 irreco_button_dlg_destroy(button_dlg);
1166 IRRECO_RETURN
1169 void irreco_window_edit_button_menu_delete(GtkMenuItem * menuitem,
1170 IrrecoWindowEdit * edit_window)
1172 IRRECO_ENTER
1173 if (irreco_yes_no_dlg(irreco_window_get_gtk_window(edit_window->window),
1174 _("Delete button?"))) {
1175 irreco_button_destroy(edit_window->button_menu_target);
1176 irreco_window_edit_buttons_menu_update(edit_window);
1178 IRRECO_RETURN
1181 void irreco_window_edit_button_menu_done(GtkMenuItem * menuitem,
1182 IrrecoWindowEdit * edit_window)
1184 IRRECO_ENTER
1185 IRRECO_RETURN
1188 /** @} */
1189 /** @} */