Added README.
[irreco.git] / irreco / src / core / irreco_button.c
blobd3bdd6e770f65b7af509df5401e93ac74d2872c1
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 * 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)
634 IRRECO_ENTER
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)
651 IRRECO_ENTER
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)
667 IRRECO_ENTER
668 if (*widget == object) {
669 *widget = NULL;
671 IRRECO_RETURN
675 * Get Widget size.
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)
685 IRRECO_ENTER
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);
705 IRRECO_RETURN
708 /** @} */
712 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
713 /* Gtk button functions. */
714 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
717 * @name Gtk button functions
718 * @{
721 void irreco_button_gtk_create(IrrecoButton * irreco_button)
723 IrrecoButtonLayout *irreco_layout = irreco_button->irreco_layout;
724 IRRECO_ENTER
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(" ");
733 } else {
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);
748 IRRECO_RETURN
751 void irreco_button_gtk_connect_signals(IrrecoButton * irreco_button)
753 IRRECO_ENTER
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);
759 IRRECO_RETURN
762 void irreco_button_gtk_disconnect_signals(IrrecoButton * irreco_button)
764 IRRECO_ENTER
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);
770 IRRECO_RETURN
773 void irreco_button_gtk_down(IrrecoButton * irreco_button)
775 GtkToggleButton* button = GTK_TOGGLE_BUTTON(irreco_button->widget);
776 IRRECO_ENTER
778 irreco_button->state = IRRECO_BSTATE_DOWN;
779 if (button != NULL) {
780 gtk_toggle_button_set_active(button, TRUE);
783 IRRECO_RETURN
786 void irreco_button_gtk_up(IrrecoButton * irreco_button)
788 GtkToggleButton* button = GTK_TOGGLE_BUTTON(irreco_button->widget);
789 IRRECO_ENTER
791 irreco_button->state = IRRECO_BSTATE_UP;
792 if (button != NULL) {
793 gtk_toggle_button_set_active(button, FALSE);
796 IRRECO_RETURN
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)
806 IRRECO_ENTER
807 switch (irreco_button->state) {
808 case IRRECO_BSTATE_UP:
809 irreco_button_gtk_up(irreco_button);
810 break;
812 case IRRECO_BSTATE_FLASH:
813 case IRRECO_BSTATE_DOWN:
814 irreco_button_gtk_down(irreco_button);
815 break;
818 IRRECO_RETURN
821 /** @} */
825 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
826 /* Image button functions. */
827 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
830 * @name Image button functions
831 * @{
834 void irreco_button_img_create(IrrecoButton * irreco_button)
836 GtkWidget* image;
837 GtkWidget* event_box;
838 IrrecoButtonLayout *irreco_layout = irreco_button->irreco_layout;
839 gint padding;
840 IRRECO_ENTER
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,
875 irreco_button->x,
876 irreco_button->y);
877 gtk_widget_hide(irreco_button->widget_down);
880 /* Create label. */
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);
903 IRRECO_RETURN
906 void irreco_button_img_set_text_format(IrrecoButton * irreco_button,
907 gchar * format)
909 IRRECO_ENTER
911 if (irreco_button->style->allow_text == FALSE) IRRECO_RETURN;
913 if (format != NULL) {
914 gchar* markup;
915 markup = g_markup_printf_escaped(format, irreco_button->title);
916 gtk_label_set_markup(GTK_LABEL(irreco_button->widget_label),
917 markup);
918 g_free(markup);
919 } else {
920 gtk_label_set_text(GTK_LABEL(irreco_button->widget_label),
921 irreco_button->title);
924 IRRECO_RETURN
927 void irreco_button_double_img_connect_signals(IrrecoButton * irreco_button)
929 IRRECO_ENTER
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);
935 IRRECO_RETURN
938 void irreco_button_double_img_disconnect_signals(IrrecoButton * irreco_button)
940 IRRECO_ENTER
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);
945 IRRECO_RETURN
948 void irreco_button_img_move(IrrecoButton * irreco_button, gint * x, gint * y)
950 gint padding = irreco_button->style->text_padding;
951 IRRECO_ENTER
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,
960 *x, *y);
963 IRRECO_RETURN
966 void irreco_button_double_img_down(IrrecoButton * irreco_button)
968 IRRECO_ENTER
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);
977 IRRECO_RETURN
980 void irreco_button_double_img_up(IrrecoButton * irreco_button)
982 IRRECO_ENTER
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);
991 IRRECO_RETURN
994 /** @} */
995 /** @} */