/* gcompris - bar.c
*
* Copyright (C) 2000-2003 Bruno Coudoin
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see .
*/
/**
* The bar button common to each games
*
*/
#include
#include "gcompris.h"
#include "gc_core.h"
#include "gcompris_config.h"
#include "about.h"
#define SOUNDLISTFILE PACKAGE
#define BAR_GAP 15 /* Value used to fill space above and under icons in the bar */
#define NUMBER_OF_ITEMS 10 /* Number of buttons in the bar */
static void update_exit_button();
static gint item_event_bar(GnomeCanvasItem *item, GdkEvent *event, gchar *data);
static void bar_reset_sound_id (void);
static gint current_level = -1;
static gint current_flags = -1;
static GnomeCanvasItem *bar_item = NULL;
static GnomeCanvasItem *exit_item = NULL;
static GnomeCanvasItem *home_item = NULL;
static GnomeCanvasItem *level_item = NULL;
static GnomeCanvasItem *ok_item = NULL;
static GnomeCanvasItem *help_item = NULL;
static GnomeCanvasItem *repeat_item = NULL;
static GnomeCanvasItem *config_item = NULL;
static GnomeCanvasItem *about_item = NULL;
static guint level_handler_id;
static gint sound_play_id = 0;
static void confirm_quit(gboolean answer);
/*
* Main entry point
* ----------------
*
*/
/*
* Do all the bar display and register the events
*/
void gc_bar_start (GnomeCanvas *theCanvas)
{
GcomprisProperties *properties = gc_prop_get();
GdkPixbuf *pixmap = NULL;
GnomeCanvasItem *rootitem;
gint16 width, height;
double zoom;
width = BOARDWIDTH;
height = BARHEIGHT-2;
bar_reset_sound_id();
rootitem = \
gnome_canvas_item_new (gnome_canvas_root(theCanvas),
gnome_canvas_group_get_type (),
"x", (double)0,
"y", (double)0,
NULL);
pixmap = gc_skin_pixmap_load("bar_bg.jpg");
bar_item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
gnome_canvas_pixbuf_get_type (),
"pixbuf", pixmap,
"x", (double) 0,
"y", (double) 0,
NULL);
gdk_pixbuf_unref(pixmap);
// EXIT
if(properties->disable_quit == 0)
{
pixmap = gc_skin_pixmap_load("button_exit.png");
zoom = (double)(height-BAR_GAP)/(double)gdk_pixbuf_get_height(pixmap);
exit_item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
gnome_canvas_pixbuf_get_type (),
"pixbuf", pixmap,
"x", (double) (width/NUMBER_OF_ITEMS) * 1 -
gdk_pixbuf_get_width(pixmap)/2,
"y", (double) (height-gdk_pixbuf_get_height(pixmap)*zoom)/2,
NULL);
gdk_pixbuf_unref(pixmap);
gtk_signal_connect(GTK_OBJECT(exit_item), "event",
(GtkSignalFunc) item_event_bar,
"quit");
gtk_signal_connect(GTK_OBJECT(exit_item), "event",
(GtkSignalFunc) gc_item_focus_event,
NULL);
}
// HOME
pixmap = gc_skin_pixmap_load("home.png");
zoom = (double)(height-BAR_GAP)/(double)gdk_pixbuf_get_height(pixmap);
home_item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
gnome_canvas_pixbuf_get_type (),
"pixbuf", pixmap,
"x", (double) (width/NUMBER_OF_ITEMS) * 9 -
gdk_pixbuf_get_width(pixmap)/2,
"y", (double) (height-gdk_pixbuf_get_height(pixmap)*zoom)/2,
NULL);
gdk_pixbuf_unref(pixmap);
gtk_signal_connect(GTK_OBJECT(home_item), "event",
(GtkSignalFunc) item_event_bar,
"back");
gtk_signal_connect(GTK_OBJECT(home_item), "event",
(GtkSignalFunc) gc_item_focus_event,
NULL);
// OK
pixmap = gc_skin_pixmap_load("ok.png");
zoom = (double)(height-BAR_GAP)/(double)gdk_pixbuf_get_height(pixmap);
ok_item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
gnome_canvas_pixbuf_get_type (),
"pixbuf", pixmap,
"x", (double) (width/NUMBER_OF_ITEMS) * 7 -
gdk_pixbuf_get_width(pixmap)/2,
"y", (double) (height-gdk_pixbuf_get_height(pixmap)*zoom)/2,
NULL);
gdk_pixbuf_unref(pixmap);
gtk_signal_connect(GTK_OBJECT(ok_item), "event",
(GtkSignalFunc) item_event_bar,
"ok");
gtk_signal_connect(GTK_OBJECT(ok_item), "event",
(GtkSignalFunc) gc_item_focus_event,
NULL);
// LEVEL
pixmap = gc_skin_pixmap_load("level1.png");
zoom = (double)(height-BAR_GAP)/(double)gdk_pixbuf_get_height(pixmap);
level_item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
gnome_canvas_pixbuf_get_type (),
"pixbuf", pixmap,
"x", (double) (width/NUMBER_OF_ITEMS) * 5 -
gdk_pixbuf_get_width(pixmap)/2,
"y", (double) (height-gdk_pixbuf_get_height(pixmap)*zoom)/2,
NULL);
gdk_pixbuf_unref(pixmap);
current_level = 1;
gtk_signal_connect(GTK_OBJECT(level_item), "event",
(GtkSignalFunc) item_event_bar,
"level");
level_handler_id = gtk_signal_connect(GTK_OBJECT(level_item), "event",
(GtkSignalFunc) gc_item_focus_event,
NULL);
// REPEAT
pixmap = gc_skin_pixmap_load("repeat.png");
zoom = (double)(height-BAR_GAP)/(double)gdk_pixbuf_get_height(pixmap);
repeat_item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
gnome_canvas_pixbuf_get_type (),
"pixbuf", pixmap,
"x", (double) (width/NUMBER_OF_ITEMS) * 6 -
gdk_pixbuf_get_width(pixmap)/2,
"y", (double) (height-gdk_pixbuf_get_height(pixmap)*zoom)/2,
NULL);
gdk_pixbuf_unref(pixmap);
gtk_signal_connect(GTK_OBJECT(repeat_item), "event",
(GtkSignalFunc) item_event_bar,
"repeat");
gtk_signal_connect(GTK_OBJECT(repeat_item), "event",
(GtkSignalFunc) gc_item_focus_event,
NULL);
// HELP
pixmap = gc_skin_pixmap_load("help.png");
zoom = (double)(height-BAR_GAP)/(double)gdk_pixbuf_get_height(pixmap);
help_item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
gnome_canvas_pixbuf_get_type (),
"pixbuf", pixmap,
"x", (double) (width/NUMBER_OF_ITEMS) * 4 -
gdk_pixbuf_get_width(pixmap)/2,
"y", (double) (height-gdk_pixbuf_get_height(pixmap)*zoom)/2,
NULL);
gdk_pixbuf_unref(pixmap);
gtk_signal_connect(GTK_OBJECT(help_item), "event",
(GtkSignalFunc) item_event_bar,
"help");
gtk_signal_connect(GTK_OBJECT(help_item), "event",
(GtkSignalFunc) gc_item_focus_event,
NULL);
// CONFIG
if(properties->disable_config == 0)
{
pixmap = gc_skin_pixmap_load("config.png");
zoom = (double)(height-BAR_GAP)/(double)gdk_pixbuf_get_height(pixmap);
config_item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
gnome_canvas_pixbuf_get_type (),
"pixbuf", pixmap,
"x", (double) (width/NUMBER_OF_ITEMS) * 3 -
gdk_pixbuf_get_width(pixmap)/2,
"y", (double) (height-gdk_pixbuf_get_height(pixmap)*zoom)/2,
NULL);
gdk_pixbuf_unref(pixmap);
gtk_signal_connect(GTK_OBJECT(config_item), "event",
(GtkSignalFunc) item_event_bar,
"configuration");
gtk_signal_connect(GTK_OBJECT(config_item), "event",
(GtkSignalFunc) gc_item_focus_event,
NULL);
}
// ABOUT
pixmap = gc_skin_pixmap_load("about.png");
zoom = (double)(height-BAR_GAP)/(double)gdk_pixbuf_get_height(pixmap);
about_item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootitem),
gnome_canvas_pixbuf_get_type (),
"pixbuf", pixmap,
"x", (double) (width/NUMBER_OF_ITEMS) * 2 -
gdk_pixbuf_get_width(pixmap)/2,
"y", (double) (height-gdk_pixbuf_get_height(pixmap)*zoom)/2,
NULL);
gdk_pixbuf_unref(pixmap);
gtk_signal_connect(GTK_OBJECT(about_item), "event",
(GtkSignalFunc) item_event_bar,
"about");
gtk_signal_connect(GTK_OBJECT(about_item), "event",
(GtkSignalFunc) gc_item_focus_event,
NULL);
// Show them all
update_exit_button();
gnome_canvas_item_hide(level_item);
gnome_canvas_item_hide(ok_item);
gnome_canvas_item_hide(help_item);
gnome_canvas_item_hide(repeat_item);
if(config_item)
gnome_canvas_item_hide(config_item);
gnome_canvas_item_hide(about_item);
}
void gc_bar_set_level(GcomprisBoard *gcomprisBoard)
{
char *str = NULL;
GdkPixbuf *pixmap = NULL;
/* Non yet initialized : Something Wrong */
if(level_item==NULL)
{
g_message("in bar_set_level, level_item uninitialized : should not happen\n");
return;
}
if(gcomprisBoard!=NULL)
{
str = g_strdup_printf("level%d.png", gcomprisBoard->level);
pixmap = gc_skin_pixmap_load(str);
g_free(str);
/* Warning changing the image needs to free the focus first */
gc_item_focus_free(level_item, NULL);
gnome_canvas_item_set (level_item,
"pixbuf", pixmap,
NULL);
gdk_pixbuf_unref(pixmap);
}
current_level=gcomprisBoard->level;
}
/* gc_bar_set_repeat_icon
*
* Override the repeat icon to a new one specific to your current board.
* This must be called before calling gc_bar_set with GC_BAR_REPEAT_ICON
* the given pixmap is not freed.
*
* Next call to gc_bar_set with GC_BAR_REPEAT will restore the default icon.
*
*/
void
gc_bar_set_repeat_icon (GdkPixbuf *pixmap)
{
/* Non yet initialized : Something Wrong */
if(level_item==NULL)
{
g_message("in bar_set_level, level_item uninitialized : should not happen\n");
return;
}
/* Warning changing the image needs to update pixbuf_ref for the focus usage */
gc_item_focus_free(repeat_item, NULL);
gnome_canvas_item_set (repeat_item,
"pixbuf", pixmap,
NULL);
}
/* Setting list of available icons in the control bar */
void
gc_bar_set (const GComprisBarFlags flags)
{
/* Non yet initialized : Something Wrong */
if(level_item==NULL)
{
g_message("in bar_set_level, level_item uninitialized : should not happen\n");
return;
}
current_flags = flags;
update_exit_button();
if(flags&GC_BAR_LEVEL)
gnome_canvas_item_show(level_item);
else
gnome_canvas_item_hide(level_item);
if(flags&GC_BAR_OK)
gnome_canvas_item_show(ok_item);
else
gnome_canvas_item_hide(ok_item);
if(gc_help_has_board(gc_board_get_current()))
gnome_canvas_item_show(help_item);
else
gnome_canvas_item_hide(help_item);
if(flags&GC_BAR_REPEAT) {
GdkPixbuf *pixmap;
/* Set the repeat icon to the original one */
pixmap = gc_skin_pixmap_load("repeat.png");
gnome_canvas_item_set (repeat_item,
"pixbuf", pixmap,
NULL);
gdk_pixbuf_unref(pixmap);
gnome_canvas_item_show(repeat_item);
} else {
if(flags&GC_BAR_REPEAT_ICON)
gnome_canvas_item_show(repeat_item);
else
gnome_canvas_item_hide(repeat_item);
}
if(flags&GC_BAR_CONFIG && config_item)
gnome_canvas_item_show(config_item);
else
gnome_canvas_item_hide(config_item);
if(flags&GC_BAR_ABOUT)
gnome_canvas_item_show(about_item);
else
gnome_canvas_item_hide(about_item);
/* FIXME : Workaround for bugged canvas */
// gnome_canvas_update_now(gc_board_get_current()->canvas);
}
/* Hide all icons in the control bar
* or retore the icons to the previous value
*/
void
gc_bar_hide (gboolean hide)
{
/* Non yet initialized : Something Wrong */
if(level_item==NULL)
{
g_message("in bar_set_level, level_item uninitialized : should not happen\n");
return;
}
if(hide)
{
if(exit_item)
gnome_canvas_item_hide(exit_item);
gnome_canvas_item_hide(home_item);
gnome_canvas_item_hide(level_item);
gnome_canvas_item_hide(ok_item);
gnome_canvas_item_hide(help_item);
gnome_canvas_item_hide(repeat_item);
if(config_item)
gnome_canvas_item_hide(config_item);
gnome_canvas_item_hide(about_item);
}
else
{
gnome_canvas_item_show(home_item);
gc_bar_set(current_flags);
}
}
/*-------------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------------*/
/*
* Display or not the exit button
*/
static void update_exit_button()
{
if(gc_board_get_current() == NULL)
return;
if (gc_board_get_current()->previous_board == NULL)
{
/* We are in the upper menu: show it */
if(exit_item)
gnome_canvas_item_show(exit_item);
gnome_canvas_item_hide(home_item);
}
else
{
if(exit_item)
gnome_canvas_item_hide(exit_item);
gnome_canvas_item_show(home_item);
}
}
/*
* This is called to play sound
*
*/
static gint bar_play_sound (gchar *sound)
{
int policy = gc_sound_policy_get();
gchar *str;
gc_sound_policy_set(PLAY_ONLY_IF_IDLE);
str = g_strdup_printf("voices/$LOCALE/misc/%s.ogg", sound);
gc_sound_play_ogg(str, NULL);
g_free(str);
gc_sound_policy_set(policy);
sound_play_id = 0;
return (FALSE);
}
static void bar_reset_sound_id ()
{
if(sound_play_id)
gtk_timeout_remove (sound_play_id);
sound_play_id=0;
}
/* Callback for the bar operations */
static gint
item_event_bar(GnomeCanvasItem *item, GdkEvent *event, gchar *data)
{
GcomprisBoard *gcomprisBoard = gc_board_get_current();
switch (event->type)
{
case GDK_ENTER_NOTIFY:
bar_reset_sound_id();
sound_play_id = gtk_timeout_add (1000, (GtkFunction) bar_play_sound, data);
break;
case GDK_LEAVE_NOTIFY:
bar_reset_sound_id();
break;
case GDK_BUTTON_PRESS:
bar_reset_sound_id();
gc_sound_play_ogg ("sounds/bleep.wav", NULL);
/* This is not perfect clean but it makes it easy to remove the help window
by clicking on any button in the bar */
if(strcmp((char *)data, "help"))
gc_help_stop ();
if(!strcmp((char *)data, "ok"))
{
if(gcomprisBoard!=NULL)
{
if(gcomprisBoard->plugin->ok != NULL)
{
gcomprisBoard->plugin->ok();
}
}
}
else if(!strcmp((char *)data, "level"))
{
gint tmp = current_level;
if(event->button.button == 1)
{
current_level++;
if(current_level>gcomprisBoard->maxlevel)
current_level=1;
}
else
{
/* Decrease the level */
current_level--;
if(current_level<1)
current_level=1;
}
if(tmp!=current_level)
{
gchar *str_number;
gchar *number_str = g_strdup_printf("%d", current_level);
gchar *current_level_str = gc_sound_alphabet(number_str);
g_free(number_str);
str_number = g_strdup_printf("voices/$LOCALE/alphabet/%s", current_level_str);
gc_sound_play_ogg("voices/$LOCALE/misc/level.ogg", str_number, NULL);
g_free(str_number);
g_free(current_level_str);
if(gcomprisBoard->plugin->set_level != NULL)
{
gcomprisBoard->plugin->set_level(current_level);
}
}
}
/*
using left button only should prevent the menu from freezing
when pressing two or more buttons at the same time
*/
else if( !strcmp((char *)data, "back") && event->button.button == 1 )
{
gc_bar_hide (TRUE);
gc_board_stop();
}
else if(!strcmp((char *)data, "help"))
{
gc_help_start(gcomprisBoard);
}
else if(!strcmp((char *)data, "repeat"))
{
if(gcomprisBoard->plugin->repeat != NULL)
{
gcomprisBoard->plugin->repeat();
}
}
else if(!strcmp((char *)data, "configuration"))
{
if(gcomprisBoard->plugin->config_start != NULL)
{
gcomprisBoard->plugin->config_start(gcomprisBoard,
gc_profile_get_current());
}
}
else if(!strcmp((char *)data, "about"))
{
gc_about_start();
}
else if(!strcmp((char *)data, "quit"))
{
gc_confirm_box( _("GCompris confirmation"),
_("Are you sure you want to quit?"),
_("Yes, I am sure!"),
_("No, I want to keep going"),
(ConfirmCallBack) confirm_quit);
}
break;
default:
break;
}
return FALSE;
}
static void
confirm_quit(gboolean answer)
{
if (answer)
gc_exit();
}