Added button image data transmission from
[irreco.git] / irreco / src / core / irreco_button.c
blob53987af3fd4b7705fcf9e4835d09ba7e958cde59
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_button.h"
22 /**
23 * @addtogroup IrrecoButton
24 * @ingroup Irreco
26 * Glues together three different types of buttons, and abstracts the
27 * differences.
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
32 * shown.
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
40 * callbacks.
42 * Relationships:
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
54 * @{
57 /**
58 * @file
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 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
102 /* Irreco Button. */
103 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
106 * @name Irreco Button
107 * @{
111 * Create new IrrecoButton.
114 IrrecoButton *irreco_button_create(IrrecoButtonLayout * irreco_layout,
115 gdouble x,
116 gdouble y,
117 const gchar * title,
118 IrrecoThemeButton * style,
119 IrrecoCmdChainManager * manager)
121 IrrecoButton *irreco_button;
122 IRRECO_ENTER
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,
137 &irreco_button->x,
138 &irreco_button->y);
139 IRRECO_RETURN_PTR(irreco_button);
143 * Destroy widget and remove it from the button_array.
145 void irreco_button_destroy(IrrecoButton * irreco_button)
147 IRRECO_ENTER
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,
157 irreco_button);
158 g_slice_free(IrrecoButton, irreco_button);
159 IRRECO_RETURN
162 void irreco_button_set_title(IrrecoButton * irreco_button, const gchar * title)
164 IRRECO_ENTER
165 irreco_button_destroy_widget(irreco_button);
166 g_free(irreco_button->title);
167 irreco_button->title = g_strdup(title);
168 IRRECO_RETURN
171 void irreco_button_set_cmd_chain_id(IrrecoButton * irreco_button,
172 IrrecoCmdChainId cmd_chain_id)
174 IRRECO_ENTER
175 IRRECO_DEBUG("Setting command chain id to \"%i\".\n",
176 cmd_chain_id);
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;
186 IRRECO_RETURN
190 * Copy data to the internal command chain.
192 void irreco_button_set_cmd_chain(IrrecoButton * irreco_button,
193 IrrecoCmdChain * cmd_chain)
195 IRRECO_ENTER
196 irreco_cmd_chain_copy(cmd_chain,
197 irreco_button_get_cmd_chain(irreco_button));
198 IRRECO_RETURN
201 IrrecoCmdChain *irreco_button_get_cmd_chain(IrrecoButton * irreco_button)
203 IRRECO_ENTER
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);
211 } else {
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)
223 IRRECO_ENTER
224 irreco_button_destroy_widget(irreco_button);
225 irreco_button->style = style;
226 IRRECO_RETURN
230 * Create a new GtkWidget which will match the data in the IrrecoButton
231 * structure.
233 void irreco_button_create_widget(IrrecoButton * irreco_button)
235 IRRECO_ENTER
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);
243 IRRECO_RETURN
245 if (irreco_button->type != IRRECO_BTYPE_NONE) {
246 irreco_button_destroy_widget(irreco_button);
249 /* Detect type. */
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);
269 } else {
270 IRRECO_ERROR("Failed to create new button for IrrecoButton\n");
271 IRRECO_ERROR("Error: Cannot detect type of button.\n");
272 IRRECO_RETURN
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);
280 break;
282 case IRRECO_BTYPE_SINGLE_IMAGE:
283 case IRRECO_BTYPE_DOUBLE_IMAGE:
284 irreco_button_img_create(irreco_button);
285 break;
288 /* Set state. */
289 if (irreco_button->state == IRRECO_BSTATE_DOWN) {
290 irreco_button_down(irreco_button);
291 } else {
292 irreco_button_up(irreco_button);
295 IRRECO_RETURN
299 * Destroy the button.
301 void irreco_button_destroy_widget(IrrecoButton* irreco_button)
303 IRRECO_ENTER
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;
318 IRRECO_RETURN
322 * Press the button down.
324 void irreco_button_down(IrrecoButton * irreco_button)
326 IRRECO_ENTER
327 switch (irreco_button->type) {
328 case IRRECO_BTYPE_NONE:
329 IRRECO_RETURN
331 case IRRECO_BTYPE_GTK_BUTTON:
332 irreco_button_gtk_down(irreco_button);
333 break;
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);
340 break;
343 IRRECO_RETURN
347 * Pop the button up.
349 void irreco_button_up(IrrecoButton * irreco_button)
351 IRRECO_ENTER
352 switch (irreco_button->type) {
353 case IRRECO_BTYPE_NONE:
354 IRRECO_RETURN
356 case IRRECO_BTYPE_GTK_BUTTON:
357 irreco_button_gtk_up(irreco_button);
358 break;
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);
365 break;
368 IRRECO_RETURN
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)
380 IRRECO_ENTER
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);
385 break;
387 case IRRECO_BTYPE_DOUBLE_IMAGE:
388 case IRRECO_BTYPE_SINGLE_IMAGE:
389 irreco_button_img_move(irreco_button, x, y);
390 break;
393 IRRECO_RETURN
397 * Pop the button up.
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)
404 IRRECO_ENTER
405 g_ptr_array_remove(irreco_button->irreco_layout->button_array,
406 irreco_button);
407 g_ptr_array_add(irreco_button->irreco_layout->button_array,
408 irreco_button);
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);
414 IRRECO_RETURN
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)
425 IRRECO_ENTER
426 switch (irreco_button->type) {
427 case IRRECO_BTYPE_NONE:
428 case IRRECO_BTYPE_SINGLE_IMAGE:
429 IRRECO_RETURN
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),
436 irreco_button);
437 break;
441 IRRECO_RETURN
443 gboolean irreco_button_flash_handler(IrrecoButton * irreco_button)
445 IRRECO_ENTER
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)
454 IRRECO_ENTER
455 switch (irreco_button->type) {
456 case IRRECO_BTYPE_NONE:
457 IRRECO_RETURN
459 case IRRECO_BTYPE_GTK_BUTTON:
460 irreco_button_gtk_connect_signals(irreco_button);
461 break;
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);
467 break;
470 IRRECO_RETURN
474 * Disconnect whatever signal handlers the button may have.
476 void irreco_button_disconnect_signals(IrrecoButton * irreco_button)
478 IRRECO_ENTER
479 switch (irreco_button->type) {
480 case IRRECO_BTYPE_NONE:
481 IRRECO_RETURN
483 case IRRECO_BTYPE_GTK_BUTTON:
484 irreco_button_gtk_disconnect_signals(irreco_button);
485 break;
487 case IRRECO_BTYPE_DOUBLE_IMAGE:
488 irreco_button_double_img_disconnect_signals(
489 irreco_button);
490 case IRRECO_BTYPE_SINGLE_IMAGE:
491 irreco_button_generic_disconnect_signals(irreco_button);
492 break;
495 IRRECO_RETURN
499 * Setup widget events so that we get motion events.
501 void irreco_button_set_motion_events(GtkWidget * gtk_widget)
503 gint events;
504 IRRECO_ENTER
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);
512 IRRECO_RETURN
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,
524 gint * x, gint * y)
526 IRRECO_ENTER
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;
532 if (*x < 0) *x = 0;
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;
539 if (*y < 0) *y = 0;
542 IRRECO_RETURN
545 /** @} */
547 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
548 /* Generic button functions. */
549 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
552 * @name Generic button functions
553 * @{
556 void irreco_button_generic_connect_signals(IrrecoButton * irreco_button)
558 IRRECO_ENTER
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),
562 irreco_button);
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),
575 irreco_button);
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);
582 IRRECO_RETURN
585 void irreco_button_generic_disconnect_signals(IrrecoButton * irreco_button)
587 IRRECO_ENTER
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);
598 IRRECO_RETURN
601 void
602 irreco_button_generic_move(IrrecoButton * irreco_button, gint * x, gint * y)
604 IRRECO_ENTER
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);
611 IRRECO_RETURN
614 gboolean irreco_button_generic_motion_notify_event(GtkWidget * widget,
615 GdkEventMotion * event,
616 IrrecoButton * irreco_button)
618 IRRECO_ENTER
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)
631 IRRECO_ENTER
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)
643 IRRECO_ENTER
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)
659 IRRECO_ENTER
660 if (*widget == object) {
661 *widget = NULL;
663 IRRECO_RETURN
667 * Get Widget size.
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)
677 IRRECO_ENTER
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);
697 IRRECO_RETURN
700 /** @} */
704 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
705 /* Gtk button functions. */
706 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
709 * @name Gtk button functions
710 * @{
713 void irreco_button_gtk_create(IrrecoButton * irreco_button)
715 IrrecoButtonLayout *irreco_layout = irreco_button->irreco_layout;
716 IRRECO_ENTER
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(" ");
725 } else {
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);
740 IRRECO_RETURN
743 void irreco_button_gtk_connect_signals(IrrecoButton * irreco_button)
745 IRRECO_ENTER
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);
751 IRRECO_RETURN
754 void irreco_button_gtk_disconnect_signals(IrrecoButton * irreco_button)
756 IRRECO_ENTER
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);
762 IRRECO_RETURN
765 void irreco_button_gtk_down(IrrecoButton * irreco_button)
767 GtkToggleButton* button = GTK_TOGGLE_BUTTON(irreco_button->widget);
768 IRRECO_ENTER
770 irreco_button->state = IRRECO_BSTATE_DOWN;
771 if (button != NULL) {
772 gtk_toggle_button_set_active(button, TRUE);
775 IRRECO_RETURN
778 void irreco_button_gtk_up(IrrecoButton * irreco_button)
780 GtkToggleButton* button = GTK_TOGGLE_BUTTON(irreco_button->widget);
781 IRRECO_ENTER
783 irreco_button->state = IRRECO_BSTATE_UP;
784 if (button != NULL) {
785 gtk_toggle_button_set_active(button, FALSE);
788 IRRECO_RETURN
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)
798 IRRECO_ENTER
799 switch (irreco_button->state) {
800 case IRRECO_BSTATE_UP:
801 irreco_button_gtk_up(irreco_button);
802 break;
804 case IRRECO_BSTATE_FLASH:
805 case IRRECO_BSTATE_DOWN:
806 irreco_button_gtk_down(irreco_button);
807 break;
810 IRRECO_RETURN
813 /** @} */
817 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
818 /* Image button functions. */
819 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
822 * @name Image button functions
823 * @{
826 void irreco_button_img_create(IrrecoButton * irreco_button)
828 GtkWidget* image;
829 GtkWidget* event_box;
830 IrrecoButtonLayout *irreco_layout = irreco_button->irreco_layout;
831 gint padding;
832 IRRECO_ENTER
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,
867 irreco_button->x,
868 irreco_button->y);
869 gtk_widget_hide(irreco_button->widget_down);
872 /* Create label. */
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);
895 IRRECO_RETURN
898 void irreco_button_img_set_text_format(IrrecoButton * irreco_button,
899 gchar * format)
901 IRRECO_ENTER
903 if (irreco_button->style->allow_text == FALSE) IRRECO_RETURN;
905 if (format != NULL) {
906 gchar* markup;
907 markup = g_markup_printf_escaped(format, irreco_button->title);
908 gtk_label_set_markup(GTK_LABEL(irreco_button->widget_label),
909 markup);
910 g_free(markup);
911 } else {
912 gtk_label_set_text(GTK_LABEL(irreco_button->widget_label),
913 irreco_button->title);
916 IRRECO_RETURN
919 void irreco_button_double_img_connect_signals(IrrecoButton * irreco_button)
921 IRRECO_ENTER
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);
927 IRRECO_RETURN
930 void irreco_button_double_img_disconnect_signals(IrrecoButton * irreco_button)
932 IRRECO_ENTER
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);
937 IRRECO_RETURN
940 void irreco_button_img_move(IrrecoButton * irreco_button, gint * x, gint * y)
942 gint padding = irreco_button->style->text_padding;
943 IRRECO_ENTER
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,
952 *x, *y);
955 IRRECO_RETURN
958 void irreco_button_double_img_down(IrrecoButton * irreco_button)
960 IRRECO_ENTER
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);
969 IRRECO_RETURN
972 void irreco_button_double_img_up(IrrecoButton * irreco_button)
974 IRRECO_ENTER
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);
983 IRRECO_RETURN
986 /** @} */
987 /** @} */