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_button.h"
23 * @addtogroup IrrecoButton
26 * Glues together three different types of buttons, and abstracts the
29 * The main component of the IRRECO user interface. The main point is to
30 * support a button which is made out of two images. When the button is up
31 * the up-image is shown. When the button is down, the down-image is
34 * The button images are provided by button style. If buttonstyle is NULL
35 * we show a GTK-button. The GTK-button is mainly a fallback option.
37 * All buttons are part of a layout array. The layout array contains pointers
38 * to callback functions which are called when the button recieves press,
39 * release or motion events. You should catch button events trough these
43 * button_layout ButtonLayout 1
44 * button ButtonLayout 1, Button 1
45 * button ButtonLayout 1, Button 2
46 * button ButtonLayout 1, Button 3
47 * button ButtonLayout 1, Button 4
48 * button_layout ButtonLayout 2
49 * button ButtonLayout 2, Button 1
50 * button ButtonLayout 2, Button 2
51 * button ButtonLayout 2, Button 3
52 * button ButtonLayout 2, Button 4
59 * Source file of @ref IrrecoButton.
63 gboolean
irreco_button_flash_handler(IrrecoButton
* irreco_button
);
64 void irreco_button_connect_signals(IrrecoButton
* irreco_button
);
65 void irreco_button_disconnect_signals(IrrecoButton
* irreco_button
);
66 void irreco_button_set_motion_events(GtkWidget
* gtk_widget
);
67 void irreco_button_validate_position(IrrecoButton
* irreco_button
, gint
* x
, gint
* y
);
68 void irreco_button_generic_connect_signals(IrrecoButton
* irreco_button
);
69 void irreco_button_generic_disconnect_signals(IrrecoButton
* irreco_button
);
70 void irreco_button_generic_move(IrrecoButton
* irreco_button
, gint
* x
, gint
* y
);
71 gboolean
irreco_button_generic_motion_notify_event(GtkWidget
* widget
,
72 GdkEventMotion
* event
,
73 IrrecoButton
* irreco_button
);
74 gboolean
irreco_button_generic_press_event(GtkWidget
* widget
,
75 GdkEventButton
* event
,
76 IrrecoButton
* irreco_button
);
77 gboolean
irreco_button_generic_release_event(GtkWidget
* widget
,
78 GdkEventButton
* event
,
79 IrrecoButton
* irreco_button
);
80 void irreco_button_generic_destroy_event(GtkObject
*object
, GtkObject
** widget
);
81 void irreco_button_generic_size_request_event(GtkWidget
* widget
,
82 GtkRequisition
*requisition
,
83 IrrecoButton
* irreco_button
);
84 void irreco_button_gtk_create(IrrecoButton
* irreco_button
);
85 void irreco_button_gtk_connect_signals(IrrecoButton
* irreco_button
);
86 void irreco_button_gtk_disconnect_signals(IrrecoButton
* irreco_button
);
87 void irreco_button_gtk_down(IrrecoButton
* irreco_button
);
88 void irreco_button_gtk_up(IrrecoButton
* irreco_button
);
89 void irreco_button_gtk_toggled_event(GtkToggleButton
*togglebutton
,
90 IrrecoButton
* irreco_button
);
91 void irreco_button_img_create(IrrecoButton
* irreco_button
);
92 void irreco_button_img_set_text_format(IrrecoButton
* irreco_button
, gchar
* format
);
93 void irreco_button_double_img_connect_signals(IrrecoButton
* irreco_button
);
94 void irreco_button_double_img_disconnect_signals(IrrecoButton
* irreco_button
);
95 void irreco_button_img_move(IrrecoButton
* irreco_button
, gint
* x
, gint
* y
);
96 void irreco_button_double_img_down(IrrecoButton
* irreco_button
);
97 void irreco_button_double_img_up(IrrecoButton
* irreco_button
);
101 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
103 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
106 * @name Irreco Button
111 * Create new IrrecoButton.
114 IrrecoButton
*irreco_button_create(IrrecoButtonLayout
* irreco_layout
,
118 IrrecoThemeButton
* style
,
119 IrrecoCmdChainManager
* manager
)
121 IrrecoButton
*irreco_button
;
124 /* Create new IrrecoButton */
125 irreco_button
= g_slice_new0(IrrecoButton
);
126 g_ptr_array_add(irreco_layout
->button_array
, irreco_button
);
127 irreco_button
->index
= irreco_layout
->button_array
->len
- 1;
129 /* Copy data to structure */
130 irreco_button
->irreco_layout
= irreco_layout
;
131 irreco_button
->style
= style
;
132 irreco_button
->x
= x
;
133 irreco_button
->y
= y
;
134 irreco_button
->title
= g_strdup(title
);
135 irreco_button
->cmd_chain_manager
= manager
;
136 irreco_button_validate_position(irreco_button
,
139 IRRECO_RETURN_PTR(irreco_button
);
143 * Destroy widget and remove it from the button_array.
145 void irreco_button_destroy(IrrecoButton
* irreco_button
)
148 irreco_button_destroy_widget(irreco_button
);
149 g_free(irreco_button
->title
);
150 irreco_button
->title
= NULL
;
151 if (irreco_button
->cmd_chain_manager
&& irreco_button
->cmd_chain_id
) {
152 irreco_cmd_chain_manager_free_chain(
153 irreco_button
->cmd_chain_manager
,
154 irreco_button
->cmd_chain_id
);
156 g_ptr_array_remove(irreco_button
->irreco_layout
->button_array
,
158 g_slice_free(IrrecoButton
, irreco_button
);
162 void irreco_button_set_title(IrrecoButton
* irreco_button
, const gchar
* title
)
165 irreco_button_destroy_widget(irreco_button
);
166 g_free(irreco_button
->title
);
167 irreco_button
->title
= g_strdup(title
);
171 void irreco_button_set_cmd_chain_id(IrrecoButton
* irreco_button
,
172 IrrecoCmdChainId cmd_chain_id
)
175 IRRECO_DEBUG("Setting command chain id to \"%i\".\n",
178 irreco_cmd_chain_manager_free_chain(irreco_button
->cmd_chain_manager
,
179 irreco_button
->cmd_chain_id
);
180 if (irreco_cmd_chain_manager_get_chain(irreco_button
->cmd_chain_manager
,
181 cmd_chain_id
) == NULL
) {
182 irreco_cmd_chain_manager_new_chain_with_id(
183 irreco_button
->cmd_chain_manager
, cmd_chain_id
);
185 irreco_button
->cmd_chain_id
= cmd_chain_id
;
190 * Copy data to the internal command chain.
192 void irreco_button_set_cmd_chain(IrrecoButton
* irreco_button
,
193 IrrecoCmdChain
* cmd_chain
)
196 irreco_cmd_chain_copy(cmd_chain
,
197 irreco_button_get_cmd_chain(irreco_button
));
201 IrrecoCmdChain
*irreco_button_get_cmd_chain(IrrecoButton
* irreco_button
)
205 if (irreco_button
->cmd_chain_id
== 0) {
206 irreco_button
->cmd_chain_id
=
207 irreco_cmd_chain_manager_new_chain(
208 irreco_button
->cmd_chain_manager
);
209 IRRECO_DEBUG("New command chain id is \"%i\".\n",
210 irreco_button
->cmd_chain_id
);
212 IRRECO_DEBUG("Command chain id is \"%i\".\n",
213 irreco_button
->cmd_chain_id
);
216 IRRECO_RETURN_PTR(irreco_cmd_chain_manager_get_chain(
217 irreco_button
->cmd_chain_manager
, irreco_button
->cmd_chain_id
));
220 void irreco_button_set_style(IrrecoButton
* irreco_button
,
221 IrrecoThemeButton
* style
)
224 irreco_button_destroy_widget(irreco_button
);
225 irreco_button
->style
= style
;
230 * Create a new GtkWidget which will match the data in the IrrecoButton
233 void irreco_button_create_widget(IrrecoButton
* irreco_button
)
237 g_assert(irreco_button
);
238 g_assert(irreco_button
->irreco_layout
);
240 if (irreco_button
->irreco_layout
->container
== NULL
) {
241 IRRECO_ERROR("Cannot create button %i. Container not set.\n",
242 irreco_button
->index
);
245 if (irreco_button
->type
!= IRRECO_BTYPE_NONE
) {
246 irreco_button_destroy_widget(irreco_button
);
250 if (irreco_button
->style
== NULL
) {
251 irreco_button
->type
= IRRECO_BTYPE_GTK_BUTTON
;
252 IRRECO_DEBUG("Button %i type is GTK_BUTTON\n",
253 irreco_button
->index
);
255 } else if (irreco_button
->style
->image_up
!= NULL
&&
256 irreco_button
->style
->image_down
== NULL
) {
257 irreco_button
->type
= IRRECO_BTYPE_SINGLE_IMAGE
;
258 IRRECO_DEBUG("Button %i type is SINGLE_IMAGE. Style is %s.\n",
259 irreco_button
->index
,
260 irreco_button
->style
->name
->str
);
262 } else if (irreco_button
->style
->image_up
!= NULL
&&
263 irreco_button
->style
->image_down
!= NULL
) {
264 irreco_button
->type
= IRRECO_BTYPE_DOUBLE_IMAGE
;
265 IRRECO_DEBUG("Button %i type is DOUBLE_IMAGE, Style is %s.\n",
266 irreco_button
->index
,
267 irreco_button
->style
->name
->str
);
270 IRRECO_ERROR("Failed to create new button for IrrecoButton\n");
271 IRRECO_ERROR("Error: Cannot detect type of button.\n");
275 /* Create button widget. */
276 switch (irreco_button
->type
) {
277 case IRRECO_BTYPE_NONE
: IRRECO_RETURN
278 case IRRECO_BTYPE_GTK_BUTTON
:
279 irreco_button_gtk_create(irreco_button
);
282 case IRRECO_BTYPE_SINGLE_IMAGE
:
283 case IRRECO_BTYPE_DOUBLE_IMAGE
:
284 irreco_button_img_create(irreco_button
);
289 if (irreco_button
->state
== IRRECO_BSTATE_DOWN
) {
290 irreco_button_down(irreco_button
);
292 irreco_button_up(irreco_button
);
299 * Destroy the button.
301 void irreco_button_destroy_widget(IrrecoButton
* irreco_button
)
304 irreco_button_disconnect_signals(irreco_button
);
305 if (irreco_button
->widget
!= NULL
) {
306 gtk_widget_destroy(irreco_button
->widget
);
307 irreco_button
->widget
= NULL
;
309 if (irreco_button
->widget_down
!= NULL
) {
310 gtk_widget_destroy(irreco_button
->widget_down
);
311 irreco_button
->widget_down
= NULL
;
313 if (irreco_button
->widget_label
!= NULL
) {
314 gtk_widget_destroy(irreco_button
->widget_label
);
315 irreco_button
->widget_label
= NULL
;
322 * Press the button down.
324 void irreco_button_down(IrrecoButton
* irreco_button
)
327 switch (irreco_button
->type
) {
328 case IRRECO_BTYPE_NONE
:
331 case IRRECO_BTYPE_GTK_BUTTON
:
332 irreco_button_gtk_down(irreco_button
);
335 case IRRECO_BTYPE_DOUBLE_IMAGE
:
336 irreco_button_double_img_down(irreco_button
);
337 case IRRECO_BTYPE_SINGLE_IMAGE
:
338 irreco_button_img_set_text_format(irreco_button
,
339 irreco_button
->style
->text_format_down
->str
);
349 void irreco_button_up(IrrecoButton
* irreco_button
)
352 switch (irreco_button
->type
) {
353 case IRRECO_BTYPE_NONE
:
356 case IRRECO_BTYPE_GTK_BUTTON
:
357 irreco_button_gtk_up(irreco_button
);
360 case IRRECO_BTYPE_DOUBLE_IMAGE
:
361 irreco_button_double_img_up(irreco_button
);
362 case IRRECO_BTYPE_SINGLE_IMAGE
:
363 irreco_button_img_set_text_format(irreco_button
,
364 irreco_button
->style
->text_format_up
->str
);
372 * Move button inside the layout size.
374 * x, y arguments should contain the reguested position of the button should be
375 * placed. When this function return, x, y will contain the location where the
376 * button was _actually_ placed. You cant move a button outside the layout size.
378 void irreco_button_move(IrrecoButton
* irreco_button
, gint
* x
, gint
* y
)
381 switch (irreco_button
->type
) {
382 case IRRECO_BTYPE_NONE
: IRRECO_RETURN
383 case IRRECO_BTYPE_GTK_BUTTON
:
384 irreco_button_generic_move(irreco_button
, x
, y
);
387 case IRRECO_BTYPE_DOUBLE_IMAGE
:
388 case IRRECO_BTYPE_SINGLE_IMAGE
:
389 irreco_button_img_move(irreco_button
, x
, y
);
399 * You cant change the order the GtkFixed displays widgets, so we destroy
400 * the old widget and create new one on the top.
402 void irreco_button_to_front(IrrecoButton
* irreco_button
)
405 g_ptr_array_remove(irreco_button
->irreco_layout
->button_array
,
407 g_ptr_array_add(irreco_button
->irreco_layout
->button_array
,
409 if (irreco_button
->type
!= IRRECO_BTYPE_NONE
) {
410 irreco_button_destroy_widget(irreco_button
);
411 irreco_button_create_widget(irreco_button
);
413 irreco_button_layout_reindex(irreco_button
->irreco_layout
);
418 * Push the button down and pop it up soon after.
420 * The main point of this function is to simulate button click effect where the
421 * use has time to see the button go down, and then pop up.
423 void irreco_button_flash(IrrecoButton
* irreco_button
)
426 switch (irreco_button
->type
) {
427 case IRRECO_BTYPE_NONE
:
428 case IRRECO_BTYPE_SINGLE_IMAGE
:
431 case IRRECO_BTYPE_DOUBLE_IMAGE
:
432 case IRRECO_BTYPE_GTK_BUTTON
:
433 irreco_button_down(irreco_button
);
434 irreco_button
->state
= IRRECO_BSTATE_FLASH
;
435 g_idle_add(G_SOURCEFUNC(irreco_button_flash_handler
),
443 gboolean
irreco_button_flash_handler(IrrecoButton
* irreco_button
)
446 if (irreco_button
->state
== IRRECO_BSTATE_FLASH
) {
447 irreco_button_up(irreco_button
);
449 IRRECO_RETURN_BOOL(FALSE
);
452 void irreco_button_connect_signals(IrrecoButton
* irreco_button
)
455 switch (irreco_button
->type
) {
456 case IRRECO_BTYPE_NONE
:
459 case IRRECO_BTYPE_GTK_BUTTON
:
460 irreco_button_gtk_connect_signals(irreco_button
);
463 case IRRECO_BTYPE_DOUBLE_IMAGE
:
464 irreco_button_double_img_connect_signals(irreco_button
);
465 case IRRECO_BTYPE_SINGLE_IMAGE
:
466 irreco_button_generic_connect_signals(irreco_button
);
474 * Disconnect whatever signal handlers the button may have.
476 void irreco_button_disconnect_signals(IrrecoButton
* irreco_button
)
479 switch (irreco_button
->type
) {
480 case IRRECO_BTYPE_NONE
:
483 case IRRECO_BTYPE_GTK_BUTTON
:
484 irreco_button_gtk_disconnect_signals(irreco_button
);
487 case IRRECO_BTYPE_DOUBLE_IMAGE
:
488 irreco_button_double_img_disconnect_signals(
490 case IRRECO_BTYPE_SINGLE_IMAGE
:
491 irreco_button_generic_disconnect_signals(irreco_button
);
499 * Setup widget events so that we get motion events.
501 void irreco_button_set_motion_events(GtkWidget
* gtk_widget
)
505 events
= (gtk_widget_get_events(GTK_WIDGET(gtk_widget
))
506 /*| GDK_BUTTON_PRESS_MASK */
507 /*| GDK_BUTTON_RELEASE_MASK */
508 | GDK_POINTER_MOTION_MASK
)
509 & ~GDK_POINTER_MOTION_HINT_MASK
;
510 gtk_widget_set_events(GTK_WIDGET(gtk_widget
), events
);
516 * Check if the given x, y coordiantes place the button completly inside
517 * layout size. If they dont, change the coordinates so that they do.
519 * As a special case, if layout size is 0x0, all coordinates are valid.
520 * The point of this is, that you can first create the layout, and set the
521 * layout size later on when you know the size of the window.
523 void irreco_button_validate_position(IrrecoButton
* irreco_button
,
528 if (irreco_button
->irreco_layout
->width
> 0) {
529 if (*x
+ irreco_button
->width
> irreco_button
->irreco_layout
->width
) {
530 *x
= irreco_button
->irreco_layout
->width
- irreco_button
->width
;
535 if (irreco_button
->irreco_layout
->height
> 0) {
536 if (*y
+ irreco_button
->height
> irreco_button
->irreco_layout
->height
) {
537 *y
= irreco_button
->irreco_layout
->height
- irreco_button
->height
;
547 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
548 /* Generic button functions. */
549 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
552 * @name Generic button functions
556 void irreco_button_generic_connect_signals(IrrecoButton
* irreco_button
)
559 irreco_button
->motion_handler_id
= g_signal_connect(
560 G_OBJECT(irreco_button
->widget
), "motion-notify-event",
561 G_CALLBACK(irreco_button_generic_motion_notify_event
),
564 irreco_button
->press_handler_id
= g_signal_connect(
565 G_OBJECT(irreco_button
->widget
), "button-press-event",
566 G_CALLBACK(irreco_button_generic_press_event
), irreco_button
);
568 irreco_button
->release_handler_id
= g_signal_connect(
569 G_OBJECT(irreco_button
->widget
), "button-release-event",
570 G_CALLBACK(irreco_button_generic_release_event
), irreco_button
);
572 irreco_button
->size_request_handler_id
= g_signal_connect(
573 G_OBJECT(irreco_button
->widget
), "size-request",
574 G_CALLBACK(irreco_button_generic_size_request_event
),
577 irreco_button
->destroy_handler_id
= g_signal_connect(
578 G_OBJECT(irreco_button
->widget
), "destroy",
579 G_CALLBACK(irreco_button_generic_destroy_event
),
580 &irreco_button
->widget
);
585 void irreco_button_generic_disconnect_signals(IrrecoButton
* irreco_button
)
588 if (irreco_button
->widget
== NULL
) IRRECO_RETURN
589 g_signal_handler_disconnect(G_OBJECT(irreco_button
->widget
),
590 irreco_button
->motion_handler_id
);
591 g_signal_handler_disconnect(G_OBJECT(irreco_button
->widget
),
592 irreco_button
->press_handler_id
);
593 g_signal_handler_disconnect(G_OBJECT(irreco_button
->widget
),
594 irreco_button
->release_handler_id
);
595 g_signal_handler_disconnect(G_OBJECT(irreco_button
->widget
),
596 irreco_button
->destroy_handler_id
);
602 irreco_button_generic_move(IrrecoButton
* irreco_button
, gint
* x
, gint
* y
)
605 irreco_button_validate_position(irreco_button
, x
, y
);
606 irreco_button
->x
= *x
;
607 irreco_button
->y
= *y
;
608 irreco_button_layout_container_move(irreco_button
->irreco_layout
,
609 irreco_button
->widget
, *x
, *y
);
614 gboolean
irreco_button_generic_motion_notify_event(GtkWidget
* widget
,
615 GdkEventMotion
* event
,
616 IrrecoButton
* irreco_button
)
619 if (irreco_button
->irreco_layout
->button_motion_callback
!= NULL
) {
620 irreco_button
->irreco_layout
->button_motion_callback(irreco_button
,
621 irreco_button
->irreco_layout
->callback_user_data
);
623 IRRECO_RETURN_BOOL(FALSE
);
627 * Combined press and release functionality to improve usability
628 * Now action is performed on klick rather than on button release
630 gboolean
irreco_button_generic_press_event(GtkWidget
* widget
,
631 GdkEventButton
* event
,
632 IrrecoButton
* irreco_button
)
635 if (irreco_button
->irreco_layout
->button_press_callback
!= NULL
) {
636 irreco_button
->irreco_layout
->button_press_callback(irreco_button
,
637 irreco_button
->irreco_layout
->callback_user_data
);
640 /*if (irreco_button->irreco_layout->button_release_callback != NULL) {
641 irreco_button->irreco_layout->button_release_callback(irreco_button,
642 irreco_button->irreco_layout->callback_user_data);
644 IRRECO_RETURN_BOOL(FALSE
);
647 gboolean
irreco_button_generic_release_event(GtkWidget
* widget
,
648 GdkEventButton
* event
,
649 IrrecoButton
* irreco_button
)
652 if (irreco_button
->irreco_layout
->button_release_callback
!= NULL
) {
653 irreco_button
->irreco_layout
->button_release_callback(irreco_button
,
654 irreco_button
->irreco_layout
->callback_user_data
);
656 IRRECO_RETURN_BOOL(FALSE
);
660 * Gtk will call this when the main window is desroyed.
662 * This can be used to catch the destruction of the widget, so that we
663 * can set the pointer to NULL.
665 void irreco_button_generic_destroy_event(GtkObject
*object
, GtkObject
** widget
)
668 if (*widget
== object
) {
677 * We need to hide some image widgets during draw, so that we can change
678 * the image, but that also means that hidden widget will have size
679 * requisition of 0x0. So we must store the size of widget.
681 void irreco_button_generic_size_request_event(GtkWidget
* widget
,
682 GtkRequisition
*requisition
,
683 IrrecoButton
* irreco_button
)
686 if (irreco_button
->state
== IRRECO_BSTATE_UP
) {
688 /* Store widget size, we no longer need the event hander. */
689 irreco_button
->width
= requisition
->width
;
690 irreco_button
->height
= requisition
->height
;
691 g_signal_handler_disconnect(G_OBJECT(irreco_button
->widget
),
692 irreco_button
->size_request_handler_id
);
694 /* If the button contains a label widget, then resize the
695 label to match the widget size.*/
696 if (irreco_button
->widget_label
!= NULL
) {
697 gint padding
= irreco_button
->style
->text_padding
* 2;
698 gtk_widget_set_size_request(
699 GTK_WIDGET(irreco_button
->widget_label
),
700 irreco_button
->width
- padding
,
701 irreco_button
->height
- padding
);
712 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
713 /* Gtk button functions. */
714 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
717 * @name Gtk button functions
721 void irreco_button_gtk_create(IrrecoButton
* irreco_button
)
723 IrrecoButtonLayout
*irreco_layout
= irreco_button
->irreco_layout
;
726 /* Make sure that we dont leak old widgets. */
727 irreco_button_destroy_widget(irreco_button
);
729 /* Create and setup button. GtkButton with empty title looks
730 pretty bad, so we use spaces instead of empty title. */
731 if (irreco_str_isempty(irreco_button
->title
)) {
732 irreco_button
->widget
= gtk_toggle_button_new_with_label(" ");
734 irreco_button
->widget
= gtk_toggle_button_new_with_label(
735 irreco_button
->title
);
738 g_signal_connect(G_OBJECT(irreco_button
->widget
), "destroy",
739 G_CALLBACK(gtk_widget_destroyed
),
740 &irreco_button
->widget
);
742 irreco_button_set_motion_events(irreco_button
->widget
);
743 irreco_button_layout_container_put(irreco_layout
, irreco_button
->widget
,
744 irreco_button
->x
, irreco_button
->y
);
745 irreco_button_connect_signals(irreco_button
);
746 gtk_widget_show(irreco_button
->widget
);
751 void irreco_button_gtk_connect_signals(IrrecoButton
* irreco_button
)
754 irreco_button_generic_connect_signals(irreco_button
);
755 irreco_button
->extra_handler_id
= g_signal_connect(
756 G_OBJECT(irreco_button
->widget
), "toggled",
757 G_CALLBACK(irreco_button_gtk_toggled_event
), irreco_button
);
762 void irreco_button_gtk_disconnect_signals(IrrecoButton
* irreco_button
)
765 if (irreco_button
->widget
== NULL
) IRRECO_RETURN
766 irreco_button_generic_disconnect_signals(irreco_button
);
767 g_signal_handler_disconnect(G_OBJECT(irreco_button
->widget
),
768 irreco_button
->extra_handler_id
);
773 void irreco_button_gtk_down(IrrecoButton
* irreco_button
)
775 GtkToggleButton
* button
= GTK_TOGGLE_BUTTON(irreco_button
->widget
);
778 irreco_button
->state
= IRRECO_BSTATE_DOWN
;
779 if (button
!= NULL
) {
780 gtk_toggle_button_set_active(button
, TRUE
);
786 void irreco_button_gtk_up(IrrecoButton
* irreco_button
)
788 GtkToggleButton
* button
= GTK_TOGGLE_BUTTON(irreco_button
->widget
);
791 irreco_button
->state
= IRRECO_BSTATE_UP
;
792 if (button
!= NULL
) {
793 gtk_toggle_button_set_active(button
, FALSE
);
800 * Because GtkToggleButton responds to some user actions, we need some extra
801 * logic to make sure that GtkToggleButton stays always in the state we want.
803 void irreco_button_gtk_toggled_event(GtkToggleButton
*togglebutton
,
804 IrrecoButton
* irreco_button
)
807 switch (irreco_button
->state
) {
808 case IRRECO_BSTATE_UP
:
809 irreco_button_gtk_up(irreco_button
);
812 case IRRECO_BSTATE_FLASH
:
813 case IRRECO_BSTATE_DOWN
:
814 irreco_button_gtk_down(irreco_button
);
825 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
826 /* Image button functions. */
827 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
830 * @name Image button functions
834 void irreco_button_img_create(IrrecoButton
* irreco_button
)
837 GtkWidget
* event_box
;
838 IrrecoButtonLayout
*irreco_layout
= irreco_button
->irreco_layout
;
842 /* Make sure that we dont leak old widgets. */
843 irreco_button_destroy_widget(irreco_button
);
845 /* Create up image widget. */
846 image
= gtk_image_new_from_file(irreco_button
->style
->image_up
->str
);
847 event_box
= gtk_event_box_new();
848 gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box
), FALSE
);
849 gtk_container_add(GTK_CONTAINER(event_box
), image
);
850 irreco_button_set_motion_events(event_box
);
852 /* Store pointers, and set cleanup*/
853 irreco_button
->widget
= event_box
;
854 g_signal_connect(G_OBJECT(irreco_button
->widget
), "destroy",
855 G_CALLBACK(gtk_widget_destroyed
),
856 &irreco_button
->widget
);
857 irreco_button
->widget_up
= image
;
858 g_signal_connect(G_OBJECT(irreco_button
->widget_up
), "destroy",
859 G_CALLBACK(gtk_widget_destroyed
),
860 &irreco_button
->widget_up
);
862 irreco_button_layout_container_put(irreco_layout
, irreco_button
->widget
,
863 irreco_button
->x
, irreco_button
->y
);
865 /* Create down image widget. */
866 if (irreco_button
->type
== IRRECO_BTYPE_DOUBLE_IMAGE
) {
867 irreco_button
->widget_down
= gtk_image_new_from_file(
868 irreco_button
->style
->image_down
->str
);
869 g_signal_connect(G_OBJECT(irreco_button
->widget_down
), "destroy",
870 G_CALLBACK(gtk_widget_destroyed
),
871 &irreco_button
->widget_down
);
873 irreco_button_layout_container_put(irreco_layout
,
874 irreco_button
->widget_down
,
877 gtk_widget_hide(irreco_button
->widget_down
);
881 padding
= irreco_button
->style
->text_padding
;
882 irreco_button
->widget_label
= gtk_label_new(NULL
);
883 g_signal_connect(G_OBJECT(irreco_button
->widget_label
), "destroy",
884 G_CALLBACK(gtk_widget_destroyed
),
885 &irreco_button
->widget_label
);
887 gtk_misc_set_alignment(GTK_MISC(irreco_button
->widget_label
),
888 irreco_button
->style
->text_h_align
,
889 irreco_button
->style
->text_v_align
);
891 irreco_button_layout_container_put(irreco_layout
,
892 irreco_button
->widget_label
,
893 irreco_button
->x
+ padding
,
894 irreco_button
->y
+ padding
);
896 irreco_button_img_set_text_format(irreco_button
,
897 irreco_button
->style
->text_format_up
->str
);
899 irreco_button_connect_signals(irreco_button
);
900 gtk_widget_show_all(irreco_button
->widget
);
901 gtk_widget_show_all(irreco_button
->widget_label
);
906 void irreco_button_img_set_text_format(IrrecoButton
* irreco_button
,
911 if (irreco_button
->style
->allow_text
== FALSE
) IRRECO_RETURN
;
913 if (format
!= NULL
) {
915 markup
= g_markup_printf_escaped(format
, irreco_button
->title
);
916 gtk_label_set_markup(GTK_LABEL(irreco_button
->widget_label
),
920 gtk_label_set_text(GTK_LABEL(irreco_button
->widget_label
),
921 irreco_button
->title
);
927 void irreco_button_double_img_connect_signals(IrrecoButton
* irreco_button
)
930 irreco_button
->extra_handler_id
= g_signal_connect(
931 G_OBJECT(irreco_button
->widget_down
), "destroy",
932 G_CALLBACK(irreco_button_generic_destroy_event
),
933 &irreco_button
->widget_down
);
938 void irreco_button_double_img_disconnect_signals(IrrecoButton
* irreco_button
)
941 if (irreco_button
->widget_down
== NULL
) IRRECO_RETURN
942 g_signal_handler_disconnect(G_OBJECT(irreco_button
->widget_down
),
943 irreco_button
->extra_handler_id
);
948 void irreco_button_img_move(IrrecoButton
* irreco_button
, gint
* x
, gint
* y
)
950 gint padding
= irreco_button
->style
->text_padding
;
953 irreco_button_generic_move(irreco_button
, x
, y
);
954 irreco_button_layout_container_move(irreco_button
->irreco_layout
,
955 irreco_button
->widget_label
,
956 *x
+ padding
, *y
+ padding
);
957 if (irreco_button
->type
== IRRECO_BTYPE_DOUBLE_IMAGE
) {
958 irreco_button_layout_container_move(irreco_button
->irreco_layout
,
959 irreco_button
->widget_down
,
966 void irreco_button_double_img_down(IrrecoButton
* irreco_button
)
969 irreco_button
->state
= IRRECO_BSTATE_DOWN
;
970 if (irreco_button
->widget_up
!= NULL
) {
971 gtk_widget_hide(irreco_button
->widget_up
);
973 if (irreco_button
->widget_down
!= NULL
) {
974 gtk_widget_show(irreco_button
->widget_down
);
980 void irreco_button_double_img_up(IrrecoButton
* irreco_button
)
983 irreco_button
->state
= IRRECO_BSTATE_UP
;
984 if (irreco_button
->widget_up
!= NULL
) {
985 gtk_widget_show(irreco_button
->widget_up
);
987 if (irreco_button
->widget_down
!= NULL
) {
988 gtk_widget_hide(irreco_button
->widget_down
);