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 gboolean
irreco_button_generic_press_event(GtkWidget
* widget
,
628 GdkEventButton
* event
,
629 IrrecoButton
* irreco_button
)
632 if (irreco_button
->irreco_layout
->button_press_callback
!= NULL
) {
633 irreco_button
->irreco_layout
->button_press_callback(irreco_button
,
634 irreco_button
->irreco_layout
->callback_user_data
);
636 IRRECO_RETURN_BOOL(FALSE
);
639 gboolean
irreco_button_generic_release_event(GtkWidget
* widget
,
640 GdkEventButton
* event
,
641 IrrecoButton
* irreco_button
)
644 if (irreco_button
->irreco_layout
->button_release_callback
!= NULL
) {
645 irreco_button
->irreco_layout
->button_release_callback(irreco_button
,
646 irreco_button
->irreco_layout
->callback_user_data
);
648 IRRECO_RETURN_BOOL(FALSE
);
652 * Gtk will call this when the main window is desroyed.
654 * This can be used to catch the destruction of the widget, so that we
655 * can set the pointer to NULL.
657 void irreco_button_generic_destroy_event(GtkObject
*object
, GtkObject
** widget
)
660 if (*widget
== object
) {
669 * We need to hide some image widgets during draw, so that we can change
670 * the image, but that also means that hidden widget will have size
671 * requisition of 0x0. So we must store the size of widget.
673 void irreco_button_generic_size_request_event(GtkWidget
* widget
,
674 GtkRequisition
*requisition
,
675 IrrecoButton
* irreco_button
)
678 if (irreco_button
->state
== IRRECO_BSTATE_UP
) {
680 /* Store widget size, we no longer need the event hander. */
681 irreco_button
->width
= requisition
->width
;
682 irreco_button
->height
= requisition
->height
;
683 g_signal_handler_disconnect(G_OBJECT(irreco_button
->widget
),
684 irreco_button
->size_request_handler_id
);
686 /* If the button contains a label widget, then resize the
687 label to match the widget size.*/
688 if (irreco_button
->widget_label
!= NULL
) {
689 gint padding
= irreco_button
->style
->text_padding
* 2;
690 gtk_widget_set_size_request(
691 GTK_WIDGET(irreco_button
->widget_label
),
692 irreco_button
->width
- padding
,
693 irreco_button
->height
- padding
);
704 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
705 /* Gtk button functions. */
706 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
709 * @name Gtk button functions
713 void irreco_button_gtk_create(IrrecoButton
* irreco_button
)
715 IrrecoButtonLayout
*irreco_layout
= irreco_button
->irreco_layout
;
718 /* Make sure that we dont leak old widgets. */
719 irreco_button_destroy_widget(irreco_button
);
721 /* Create and setup button. GtkButton with empty title looks
722 pretty bad, so we use spaces instead of empty title. */
723 if (irreco_str_isempty(irreco_button
->title
)) {
724 irreco_button
->widget
= gtk_toggle_button_new_with_label(" ");
726 irreco_button
->widget
= gtk_toggle_button_new_with_label(
727 irreco_button
->title
);
730 g_signal_connect(G_OBJECT(irreco_button
->widget
), "destroy",
731 G_CALLBACK(gtk_widget_destroyed
),
732 &irreco_button
->widget
);
734 irreco_button_set_motion_events(irreco_button
->widget
);
735 irreco_button_layout_container_put(irreco_layout
, irreco_button
->widget
,
736 irreco_button
->x
, irreco_button
->y
);
737 irreco_button_connect_signals(irreco_button
);
738 gtk_widget_show(irreco_button
->widget
);
743 void irreco_button_gtk_connect_signals(IrrecoButton
* irreco_button
)
746 irreco_button_generic_connect_signals(irreco_button
);
747 irreco_button
->extra_handler_id
= g_signal_connect(
748 G_OBJECT(irreco_button
->widget
), "toggled",
749 G_CALLBACK(irreco_button_gtk_toggled_event
), irreco_button
);
754 void irreco_button_gtk_disconnect_signals(IrrecoButton
* irreco_button
)
757 if (irreco_button
->widget
== NULL
) IRRECO_RETURN
758 irreco_button_generic_disconnect_signals(irreco_button
);
759 g_signal_handler_disconnect(G_OBJECT(irreco_button
->widget
),
760 irreco_button
->extra_handler_id
);
765 void irreco_button_gtk_down(IrrecoButton
* irreco_button
)
767 GtkToggleButton
* button
= GTK_TOGGLE_BUTTON(irreco_button
->widget
);
770 irreco_button
->state
= IRRECO_BSTATE_DOWN
;
771 if (button
!= NULL
) {
772 gtk_toggle_button_set_active(button
, TRUE
);
778 void irreco_button_gtk_up(IrrecoButton
* irreco_button
)
780 GtkToggleButton
* button
= GTK_TOGGLE_BUTTON(irreco_button
->widget
);
783 irreco_button
->state
= IRRECO_BSTATE_UP
;
784 if (button
!= NULL
) {
785 gtk_toggle_button_set_active(button
, FALSE
);
792 * Because GtkToggleButton responds to some user actions, we need some extra
793 * logic to make sure that GtkToggleButton stays always in the state we want.
795 void irreco_button_gtk_toggled_event(GtkToggleButton
*togglebutton
,
796 IrrecoButton
* irreco_button
)
799 switch (irreco_button
->state
) {
800 case IRRECO_BSTATE_UP
:
801 irreco_button_gtk_up(irreco_button
);
804 case IRRECO_BSTATE_FLASH
:
805 case IRRECO_BSTATE_DOWN
:
806 irreco_button_gtk_down(irreco_button
);
817 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
818 /* Image button functions. */
819 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
822 * @name Image button functions
826 void irreco_button_img_create(IrrecoButton
* irreco_button
)
829 GtkWidget
* event_box
;
830 IrrecoButtonLayout
*irreco_layout
= irreco_button
->irreco_layout
;
834 /* Make sure that we dont leak old widgets. */
835 irreco_button_destroy_widget(irreco_button
);
837 /* Create up image widget. */
838 image
= gtk_image_new_from_file(irreco_button
->style
->image_up
->str
);
839 event_box
= gtk_event_box_new();
840 gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box
), FALSE
);
841 gtk_container_add(GTK_CONTAINER(event_box
), image
);
842 irreco_button_set_motion_events(event_box
);
844 /* Store pointers, and set cleanup*/
845 irreco_button
->widget
= event_box
;
846 g_signal_connect(G_OBJECT(irreco_button
->widget
), "destroy",
847 G_CALLBACK(gtk_widget_destroyed
),
848 &irreco_button
->widget
);
849 irreco_button
->widget_up
= image
;
850 g_signal_connect(G_OBJECT(irreco_button
->widget_up
), "destroy",
851 G_CALLBACK(gtk_widget_destroyed
),
852 &irreco_button
->widget_up
);
854 irreco_button_layout_container_put(irreco_layout
, irreco_button
->widget
,
855 irreco_button
->x
, irreco_button
->y
);
857 /* Create down image widget. */
858 if (irreco_button
->type
== IRRECO_BTYPE_DOUBLE_IMAGE
) {
859 irreco_button
->widget_down
= gtk_image_new_from_file(
860 irreco_button
->style
->image_down
->str
);
861 g_signal_connect(G_OBJECT(irreco_button
->widget_down
), "destroy",
862 G_CALLBACK(gtk_widget_destroyed
),
863 &irreco_button
->widget_down
);
865 irreco_button_layout_container_put(irreco_layout
,
866 irreco_button
->widget_down
,
869 gtk_widget_hide(irreco_button
->widget_down
);
873 padding
= irreco_button
->style
->text_padding
;
874 irreco_button
->widget_label
= gtk_label_new(NULL
);
875 g_signal_connect(G_OBJECT(irreco_button
->widget_label
), "destroy",
876 G_CALLBACK(gtk_widget_destroyed
),
877 &irreco_button
->widget_label
);
879 gtk_misc_set_alignment(GTK_MISC(irreco_button
->widget_label
),
880 irreco_button
->style
->text_h_align
,
881 irreco_button
->style
->text_v_align
);
883 irreco_button_layout_container_put(irreco_layout
,
884 irreco_button
->widget_label
,
885 irreco_button
->x
+ padding
,
886 irreco_button
->y
+ padding
);
888 irreco_button_img_set_text_format(irreco_button
,
889 irreco_button
->style
->text_format_up
->str
);
891 irreco_button_connect_signals(irreco_button
);
892 gtk_widget_show_all(irreco_button
->widget
);
893 gtk_widget_show_all(irreco_button
->widget_label
);
898 void irreco_button_img_set_text_format(IrrecoButton
* irreco_button
,
903 if (irreco_button
->style
->allow_text
== FALSE
) IRRECO_RETURN
;
905 if (format
!= NULL
) {
907 markup
= g_markup_printf_escaped(format
, irreco_button
->title
);
908 gtk_label_set_markup(GTK_LABEL(irreco_button
->widget_label
),
912 gtk_label_set_text(GTK_LABEL(irreco_button
->widget_label
),
913 irreco_button
->title
);
919 void irreco_button_double_img_connect_signals(IrrecoButton
* irreco_button
)
922 irreco_button
->extra_handler_id
= g_signal_connect(
923 G_OBJECT(irreco_button
->widget_down
), "destroy",
924 G_CALLBACK(irreco_button_generic_destroy_event
),
925 &irreco_button
->widget_down
);
930 void irreco_button_double_img_disconnect_signals(IrrecoButton
* irreco_button
)
933 if (irreco_button
->widget_down
== NULL
) IRRECO_RETURN
934 g_signal_handler_disconnect(G_OBJECT(irreco_button
->widget_down
),
935 irreco_button
->extra_handler_id
);
940 void irreco_button_img_move(IrrecoButton
* irreco_button
, gint
* x
, gint
* y
)
942 gint padding
= irreco_button
->style
->text_padding
;
945 irreco_button_generic_move(irreco_button
, x
, y
);
946 irreco_button_layout_container_move(irreco_button
->irreco_layout
,
947 irreco_button
->widget_label
,
948 *x
+ padding
, *y
+ padding
);
949 if (irreco_button
->type
== IRRECO_BTYPE_DOUBLE_IMAGE
) {
950 irreco_button_layout_container_move(irreco_button
->irreco_layout
,
951 irreco_button
->widget_down
,
958 void irreco_button_double_img_down(IrrecoButton
* irreco_button
)
961 irreco_button
->state
= IRRECO_BSTATE_DOWN
;
962 if (irreco_button
->widget_up
!= NULL
) {
963 gtk_widget_hide(irreco_button
->widget_up
);
965 if (irreco_button
->widget_down
!= NULL
) {
966 gtk_widget_show(irreco_button
->widget_down
);
972 void irreco_button_double_img_up(IrrecoButton
* irreco_button
)
975 irreco_button
->state
= IRRECO_BSTATE_UP
;
976 if (irreco_button
->widget_up
!= NULL
) {
977 gtk_widget_show(irreco_button
->widget_up
);
979 if (irreco_button
->widget_down
!= NULL
) {
980 gtk_widget_hide(irreco_button
->widget_down
);