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"
33 * @addtogroup IrrecoWindowEdit
36 * User interface for editing button layouts.
43 * Source file of @ref IrrecoWindowEdit.
47 typedef struct _ButtonMenuForeachData ButtonMenuForeachData
;
48 struct _ButtonMenuForeachData
{
49 GtkWidget
*button_menu
;
55 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
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
,
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
,
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
141 * Crate and display IrrecoWindowEdit.
143 IrrecoWindowEdit
*irreco_window_edit_create(IrrecoWindowManager
* manager
)
145 IrrecoData
*irreco_data
= manager
->irreco_data
;
146 IrrecoWindowEdit
*edit_window
;
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
),
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
),
169 IRRECO_RETURN_PTR(edit_window
);
172 void irreco_window_edit_destroy(IrrecoWindowEdit
*edit_window
)
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
);
206 void irreco_window_edit_set_layout(IrrecoWindowEdit
* edit_window
,
207 IrrecoButtonLayout
* irreco_layout
)
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
;
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
,
235 IRRECO_LAYOUT_HEIGHT
);
244 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
246 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
253 void irreco_window_edit_device_help(IrrecoWindowEdit
* edit_window
)
255 IrrecoBackendManager
*manager
;
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
)) {
263 IRRECO_BACKEND_MANAGER_FOREACH_END
265 irreco_info_dlg(irreco_window_get_gtk_window(edit_window
->window
),
266 _(IRRECO_NO_DEVICE_HELP
));
270 void irreco_window_edit_controller_help(IrrecoWindowEdit
* edit_window
)
272 IrrecoBackendManager
*manager
;
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
));
284 gboolean
irreco_window_edit_expose(GtkWidget
* widget
, GdkEventExpose
* event
,
285 IrrecoWindowEdit
* edit_window
)
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
);
299 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
300 /* Private functions. */
301 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
304 * @name Private Functions
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
)
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
331 static void irreco_window_edit_draw_background(IrrecoWindowEdit
* edit_window
)
334 GdkPixbuf
**grid_pixbuf
= NULL
;
337 switch (edit_window
->drag_grid
) {
342 image = "grid-1x1.png";
343 grid_pixbuf = &edit_window->image_grid_1;
348 image
= "grid-2x2.png";
349 grid_pixbuf
= &edit_window
->image_grid_2
;
353 image
= "grid-4x4.png";
354 grid_pixbuf
= &edit_window
->image_grid_4
;
358 image
= "grid-8x8.png";
359 grid_pixbuf
= &edit_window
->image_grid_8
;
363 image
= "grid-16x16.png";
364 grid_pixbuf
= &edit_window
->image_grid_16
;
368 IRRECO_ERROR("Unknown grid value \"%i\"\n",
369 edit_window
->drag_grid
);
373 irreco_window_load_background(edit_window
, image
, grid_pixbuf
);
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
)
392 const GdkColor
*color
;
393 GError
*error
= NULL
;
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
);
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
,
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
,
424 irreco_window_set_background_buf(edit_window
->window
, color
,
425 edit_window
->image_background
,
426 *grid_pixbuf_pointer
);
435 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
436 /* IrrecoButton callbacks. */
437 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
440 * @name IrrecoButton callbacks
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
)
456 if (edit_window
->drag_target
== NULL
) {
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
) {
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
),
479 edit_window
->drag_handler_set
= TRUE
;
483 gboolean
irreco_window_edit_drag_handler(IrrecoWindowEdit
* edit_window
)
486 gint pointer_x
, pointer_y
;
487 IrrecoButton
*irreco_button
= edit_window
->drag_target
;
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
)
522 GdkModifierType mask
;
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
,
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
);
547 void irreco_window_edit_button_release_callback(IrrecoButton
* irreco_button
,
548 IrrecoWindowEdit
* edit_window
)
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
);
581 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
582 /* Main menu construction. */
583 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
586 * @name Main menu construction
590 void irreco_window_edit_main_menu_create(IrrecoWindowEdit
* edit_window
)
592 GtkWidget
*button_menu
;
593 GtkWidget
*grid_menu
;
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
;
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();
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
));
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
));
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
));
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
));
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
),
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
),
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
),
682 g_signal_connect(G_OBJECT(edit_window
->menu_background
), "activate",
683 G_CALLBACK(irreco_window_edit_main_menu_background
),
685 g_signal_connect(G_OBJECT(edit_window
->menu_hardkeys
), "activate",
686 G_CALLBACK(irreco_window_edit_main_menu_hardkeys
),
688 g_signal_connect(G_OBJECT(edit_window
->menu_controllers
), "activate",
689 G_CALLBACK(irreco_window_edit_main_menu_controllers
),
691 g_signal_connect(G_OBJECT(edit_window
->menu_devices
), "activate",
692 G_CALLBACK(irreco_window_edit_main_menu_devices
),
694 g_signal_connect(G_OBJECT(edit_window
->menu_download_device
),
696 G_CALLBACK(irreco_window_edit_main_menu_download_device
),
698 g_signal_connect(G_OBJECT(edit_window
->menu_newbutton
), "activate",
699 G_CALLBACK(irreco_window_edit_main_menu_newbutton
),
701 g_signal_connect(G_OBJECT(edit_window
->menu_grid
), "activate",
702 G_CALLBACK(irreco_window_edit_menu_grid
),
705 g_signal_connect(G_OBJECT(menu_grid_1
), "toggled",
706 G_CALLBACK(irreco_window_edit_main_menu_grid_1
),
708 g_signal_connect(G_OBJECT(menu_grid_2
), "toggled",
709 G_CALLBACK(irreco_window_edit_main_menu_grid_2
),
711 g_signal_connect(G_OBJECT(menu_grid_4
), "toggled",
712 G_CALLBACK(irreco_window_edit_main_menu_grid_4
),
714 g_signal_connect(G_OBJECT(menu_grid_8
), "toggled",
715 G_CALLBACK(irreco_window_edit_main_menu_grid_8
),
717 g_signal_connect(G_OBJECT(menu_grid_16
), "toggled",
718 G_CALLBACK(irreco_window_edit_main_menu_grid_16
),
720 g_signal_connect(G_OBJECT(edit_window
->menu_theme_manager
), "activate",
721 G_CALLBACK(irreco_window_edit_main_menu_theme_manager
),
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
;
738 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
739 /* Main menu callback functions. */
740 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
743 * @name Main menu callback functions
747 void irreco_window_edit_main_menu_save(GtkMenuItem
* menuitem
,
748 IrrecoWindowEdit
* edit_window
)
750 IrrecoData
*irreco_data
= edit_window
->irreco_data
;
753 irreco_config_save_layouts(irreco_data
);
754 irreco_window_manager_show(irreco_data
->window_manager
,
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
;
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
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
);
782 void irreco_window_edit_main_menu_hardkeys(GtkMenuItem
* menuitem
,
783 IrrecoWindowEdit
* edit_window
)
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
);
797 void irreco_window_edit_main_menu_controllers(GtkMenuItem
* menuitem
,
798 IrrecoWindowEdit
* edit_window
)
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
);
808 void irreco_window_edit_main_menu_devices(GtkMenuItem
* menuitem
,
809 IrrecoWindowEdit
* edit_window
)
812 irreco_show_device_dlg(edit_window
->irreco_data
,
813 irreco_window_get_gtk_window(
814 edit_window
->window
));
818 void irreco_window_edit_main_menu_download_device(GtkMenuItem
* menuitem
,
819 IrrecoWindowEdit
* edit_window
)
822 irreco_show_webdb_dlg(edit_window
->irreco_data
,
823 irreco_window_get_gtk_window(
824 edit_window
->window
));
827 void irreco_window_edit_main_menu_newbutton(GtkMenuItem
* menuitem
,
828 IrrecoWindowEdit
* edit_window
)
831 if (irreco_button_dlg_run(edit_window
->irreco_data
->new_button_dlg
,
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
);
845 void irreco_window_edit_main_menu_select_button(GtkMenuItem
* menuitem
,
846 IrrecoButton
* irreco_button
)
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
);
858 void irreco_window_edit_main_menu_theme_manager(GtkMenuItem
* menuitem
,
859 IrrecoWindowEdit
* edit_window
)
862 irreco_show_theme_manager_dlg(edit_window
->irreco_data
,
863 irreco_window_get_gtk_window(
864 edit_window
->window
));
875 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
876 /* Grid menu callback functions. */
877 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
880 * @name Grid menu callback functions
884 void irreco_window_edit_menu_grid(GtkMenuItem
* menuitem
,
885 IrrecoWindowEdit
* edit_window
)
891 void irreco_window_edit_main_menu_grid_1(GtkCheckMenuItem
* menuitem
,
892 IrrecoWindowEdit
* edit_window
)
895 if (gtk_check_menu_item_get_active(menuitem
)) {
896 edit_window
->drag_grid
= 1;
897 irreco_window_edit_draw_background(edit_window
);
902 void irreco_window_edit_main_menu_grid_2(GtkCheckMenuItem
* menuitem
,
903 IrrecoWindowEdit
* edit_window
)
906 if (gtk_check_menu_item_get_active(menuitem
)) {
907 edit_window
->drag_grid
= 2;
908 irreco_window_edit_draw_background(edit_window
);
913 void irreco_window_edit_main_menu_grid_4(GtkCheckMenuItem
* menuitem
,
914 IrrecoWindowEdit
* edit_window
)
917 if (gtk_check_menu_item_get_active(menuitem
)) {
918 edit_window
->drag_grid
= 4;
919 irreco_window_edit_draw_background(edit_window
);
924 void irreco_window_edit_main_menu_grid_8(GtkCheckMenuItem
* menuitem
,
925 IrrecoWindowEdit
* edit_window
)
928 if (gtk_check_menu_item_get_active(menuitem
)) {
929 edit_window
->drag_grid
= 8;
930 irreco_window_edit_draw_background(edit_window
);
935 void irreco_window_edit_main_menu_grid_16(GtkCheckMenuItem
* menuitem
,
936 IrrecoWindowEdit
* edit_window
)
939 if (gtk_check_menu_item_get_active(menuitem
)) {
940 edit_window
->drag_grid
= 16;
941 irreco_window_edit_draw_background(edit_window
);
950 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
951 /* Button menu construction. */
952 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
955 * @name Button menu construction
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
;
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
),
990 g_signal_connect(G_OBJECT(button_menu_edit
), "activate",
991 G_CALLBACK(irreco_window_edit_button_menu_edit
),
993 g_signal_connect(G_OBJECT(button_menu_edit
), "activate",
994 G_CALLBACK(irreco_window_edit_button_menu_done
),
996 g_signal_connect(G_OBJECT(button_menu_delete
), "activate",
997 G_CALLBACK(irreco_window_edit_button_menu_delete
),
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
);
1008 * Generates buttons submenu just in time.
1010 void irreco_window_edit_buttons_menu_update(IrrecoWindowEdit
* edit_window
)
1012 ButtonMenuForeachData foreach_data
;
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
),
1021 gtk_widget_set_sensitive(GTK_WIDGET(edit_window
->menu_buttons
),
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
),
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
));
1042 void irreco_window_edit_buttons_menu_update_foreach(IrrecoButton
* button
,
1043 ButtonMenuForeachData
* data
)
1050 g_snprintf(label
, 100, "%i: %s", data
->i
--,
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
);
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
)
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
,
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());
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
,
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
;
1097 GtkRequisition requisition
;
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
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
);
1131 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
1132 /* Button menu callbacks. */
1133 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
1136 * @name Button menu callbacks
1140 void irreco_window_edit_button_menu_front(GtkMenuItem
* menuitem
,
1141 IrrecoWindowEdit
* edit_window
)
1144 irreco_button_to_front(edit_window
->button_menu_target
);
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
;
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
,
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
);
1169 void irreco_window_edit_button_menu_delete(GtkMenuItem
* menuitem
,
1170 IrrecoWindowEdit
* edit_window
)
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
);
1181 void irreco_window_edit_button_menu_done(GtkMenuItem
* menuitem
,
1182 IrrecoWindowEdit
* edit_window
)