/* gcompris - shapegame.c * * Copyright (C) 2000 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 . */ /* libxml includes */ #include #include #include #include #include "gcompris/gcompris.h" #include "gcompris/pixbuf_util.h" #define SOUNDLISTFILE PACKAGE #define SQUARE_LIMIT_DISTANCE 100.0 static int gamewon; static GcomprisBoard *gcomprisBoard = NULL; static gboolean board_paused = TRUE; static gboolean shadow_enable; #define POINT_COLOR_OFF 0xEf000080 #define POINT_COLOR_ON 0x00EF0080 typedef enum { SHAPE_TARGET = 1 << 0, SHAPE_DUMMY_TARGET = 1 << 1, SHAPE_ICON = 1 << 2, SHAPE_BACKGROUND = 1 << 3, } ShapeType; /* Let's define the structure for a single shape */ typedef struct _Shape Shape; struct _Shape { char *name; /* name of the shape */ char *tooltip; /* optional tooltip for the shape */ char *pixmapfile; /* relative pixmap file name of the shape */ GnomeCanvasPoints* points; /* OR list of points for this shape */ char *targetfile; /* OPTIONAL relative pixmap file name of the target shape, by default a red point is displayed */ double x; /* x coordinate */ double y; /* y coordinate */ double w; /* width */ double h; /* height */ double zoomx; /* x zoom factor */ double zoomy; /* y zoom factor */ gint position; /* depth position 0=bottom other=intermediate */ char *soundfile; /* relative sound file to be played when pressing mouse button */ ShapeType type; /* Type of shape */ GnomeCanvasItem *item; /* Canvas item for this shape */ /* Root index which this item is in the shapelist */ GnomeCanvasGroup *shape_list_group_root; guint shapelistgroup_index; /* Root index which this item is in the shapelist */ Shape *icon_shape; /* Temporary Canvas icon shape for this shape */ Shape *target_shape; /* If this is an icon shape then point to its shape */ GnomeCanvasItem *target_point; /* Target point item for this shape */ GnomeCanvasItem *targetitem; /* Target item for this shape (if targetfile is defined) */ double offset_x, offset_y; Shape *shape_place; /* the shape place in this place */ Shape *placed ; /* where is place this shape */ }; /* This is the list of shape for the current game */ static GList *shape_list = NULL; static GList *shape_list_group = NULL; static int current_shapelistgroup_index = -1; static GnomeCanvasItem *next_shapelist_item = NULL; /* Canvas item button for the next shapelist */ static GnomeCanvasItem *previous_shapelist_item = NULL; /* Canvas item button for the previous shapelist */ /* Let's define the structure for the shapebox list that contains the icons of the shapes */ typedef struct _ShapeBox ShapeBox; struct _ShapeBox { double x; /* x coordinate */ double y; /* y coordinate */ double w; /* width */ double h; /* height */ guint nb_shape_x; /* Number of shape on x */ guint nb_shape_y; /* Number of shape on y */ }; static ShapeBox shapeBox; /* Hash table of all the shapes in the list of shapes (one by different pixmap plus icon list) */ static GHashTable *shapelist_table = NULL; static gint SHAPE_BOX_WIDTH = 44; static GnomeCanvasItem *shape_root_item; static GnomeCanvasItem *shape_list_root_item; /* The tooltip */ static GnomeCanvasGroup *tooltip_root_item; static GnomeCanvasItem *tooltip_text_item; static GnomeCanvasItem *tooltip_bg_item; static void start_board (GcomprisBoard *agcomprisBoard); static void pause_board (gboolean pause); static void end_board (void); static gboolean is_our_board (GcomprisBoard *gcomprisBoard); static void set_level (guint level); static void process_ok(void); static gint key_press(guint keyval, gchar *commit_str, gchar *preedit_str); static void config_start (GcomprisBoard *agcomprisBoard, GcomprisProfile *aProfile); static void config_stop (void); static void shapegame_init_canvas(GnomeCanvasGroup *parent); static void shapegame_destroy_all_items(void); static void setup_item(GnomeCanvasItem *item, Shape *shape); static void shapegame_next_level(void); static gboolean read_xml_file(char *fname); static Shape *find_closest_shape(double x, double y, double limit); static Shape *create_shape(ShapeType type, char *name, char *tooltip, char *pixmapfile, GnomeCanvasPoints* points, char *targetfile, double x, double y, double l, double h, double zoomx, double zoomy, guint position, char *soundfile); static gboolean increment_sublevel(void); static void create_title(char *name, double x, double y, GtkJustification justification, guint32 color_rgba); static gint item_event_ok(GnomeCanvasItem *item, GdkEvent *event, gpointer data); static gint item_event_drag(GnomeCanvasItem *item, GdkEvent *event, gpointer data); #if DEBUG static void dump_shapes(void); static void dump_shape(Shape *shape); #endif static void update_shapelist_item(void); static void auto_process(void); static void target_point_hide(); static gint drag_mode; /* Description of this plugin */ static BoardPlugin menu_bp = { NULL, NULL, "Make the puzzle", "Drag and Drop the items to rebuild the object", "Bruno Coudoin ", NULL, NULL, NULL, NULL, start_board, pause_board, end_board, is_our_board, key_press, process_ok, set_level, NULL, NULL, config_start, config_stop }; /* Description of this plugin without configuration */ /* static BoardPlugin menu_bp_no_config = */ /* { */ /* NULL, */ /* NULL, */ /* "Make the puzzle", */ /* "Drag and Drop the items to rebuild the object", */ /* "Bruno Coudoin ", */ /* NULL, */ /* NULL, */ /* NULL, */ /* NULL, */ /* start_board, */ /* pause_board, */ /* end_board, */ /* is_our_board, */ /* key_press, */ /* process_ok, */ /* set_level, */ /* NULL, */ /* NULL, */ /* NULL, */ /* NULL */ /* }; */ /* * Main entry point mandatory for each Gcompris's game * --------------------------------------------------- * */ GET_BPLUGIN_INFO(shapegame) /* * in : boolean TRUE = PAUSE : FALSE = CONTINUE * */ static void pause_board (gboolean pause) { if(gcomprisBoard==NULL) return; if(gamewon == TRUE && pause == FALSE) /* the game is won */ { if(increment_sublevel()) shapegame_next_level(); } board_paused = pause; } /* */ static void start_board (GcomprisBoard *agcomprisBoard) { gchar *filename = NULL; gboolean default_background = TRUE; GHashTable *config = gc_db_get_board_conf(); if (strcmp(agcomprisBoard->name, "imagename")==0){ gc_locale_set(g_hash_table_lookup( config, "locale")); } gchar *drag_mode_str = g_hash_table_lookup( config, "drag_mode"); if (drag_mode_str && (strcmp (drag_mode_str, "NULL") != 0)) drag_mode = g_ascii_strtod(drag_mode_str, NULL); else drag_mode = 0; g_hash_table_destroy(config); if(agcomprisBoard!=NULL) { gcomprisBoard = agcomprisBoard; /* disable im_context */ gcomprisBoard->disable_im_context = TRUE; /* set initial values for this level */ gcomprisBoard->level = 1; /* Calculate the maxlevel based on the available data file for this board */ gcomprisBoard->maxlevel=1; /**/ while( (filename = gc_file_find_absolute("%s/board%d_0.xml", gcomprisBoard->boarddir, gcomprisBoard->maxlevel, NULL)) ) { gcomprisBoard->maxlevel++; g_free(filename); } gcomprisBoard->maxlevel--; gc_bar_set(GC_BAR_CONFIG|GC_BAR_LEVEL); gcomprisBoard->sublevel = 0; /* In this board, the sublevels are dynamicaly discovered based on data files */ gcomprisBoard->number_of_sublevel=G_MAXINT; if(gcomprisBoard->mode!=NULL) if(g_strncasecmp(gcomprisBoard->mode, "background=", 11)==0) { gchar *tmp = NULL; tmp = g_malloc(strlen(gcomprisBoard->mode)); tmp = strcpy(tmp, gcomprisBoard->mode + 11); gc_set_background(gnome_canvas_root(gcomprisBoard->canvas), tmp); default_background = FALSE; g_free(tmp); } if(default_background) { gchar *img; // Default case, load the default background img = gc_skin_image_get("gcompris-shapebg.jpg"); gc_set_background(gnome_canvas_root(gcomprisBoard->canvas), img); g_free(img); } gc_drag_start(gnome_canvas_root(gcomprisBoard->canvas), (gc_Drag_Func) item_event_drag, drag_mode); shapegame_next_level(); pause_board(FALSE); } } static void end_board () { if(gcomprisBoard!=NULL) { gc_drag_stop(gnome_canvas_root(gcomprisBoard->canvas)); pause_board(TRUE); shapegame_destroy_all_items(); gcomprisBoard->level = 1; // Restart this game to zero } if (strcmp(gcomprisBoard->name, "imagename")==0){ gc_locale_reset(); } gcomprisBoard = NULL; } static void set_level (guint level) { if(gcomprisBoard!=NULL) { gcomprisBoard->level=level; gcomprisBoard->sublevel=0; shapegame_next_level(); } } gboolean is_our_board (GcomprisBoard *gcomprisBoard) { if (gcomprisBoard) { if(g_strcasecmp(gcomprisBoard->type, "shapegame")==0) { gcomprisBoard->plugin = &menu_bp; return TRUE; } } return FALSE; } /* * Keypress here are use for entering the editing mode */ static gint key_press(guint keyval, gchar *commit_str, gchar *preedit_str) { if(board_paused || !gcomprisBoard) return FALSE; /* Add some filter for control and shift key */ switch (keyval) { /* Avoid all this keys to be interpreted by this game */ case GDK_Shift_L: case GDK_Shift_R: case GDK_Control_L: case GDK_Control_R: case GDK_Caps_Lock: case GDK_Shift_Lock: case GDK_Meta_L: case GDK_Meta_R: case GDK_Alt_L: case GDK_Alt_R: case GDK_Super_L: case GDK_Super_R: case GDK_Hyper_L: case GDK_Hyper_R: case GDK_Num_Lock: return FALSE; case GDK_KP_Enter: case GDK_Return: process_ok(); return TRUE; case GDK_Right: case GDK_Delete: case GDK_BackSpace: case GDK_Left: break; } return TRUE; } /*-------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------*/ /* * Returns true if increment is done, false is end of board */ static gboolean increment_sublevel() { gcomprisBoard->sublevel++; if(gcomprisBoard->sublevel>gcomprisBoard->number_of_sublevel) { /* Try the next level */ gcomprisBoard->level++; gcomprisBoard->sublevel=0; if(gcomprisBoard->level>gcomprisBoard->maxlevel) { // the current board is finished : bail out gc_bonus_end_display(GC_BOARD_FINISHED_RANDOM); return FALSE; } } return TRUE; } /* set initial values for the next level */ static void shapegame_next_level() { char *filename; gamewon = FALSE; gc_drag_stop(gnome_canvas_root(gcomprisBoard->canvas)); shapegame_destroy_all_items(); next_shapelist_item = previous_shapelist_item = NULL; shapegame_init_canvas(gnome_canvas_root(gcomprisBoard->canvas)); while( ((filename = gc_file_find_absolute("%s/board%d_%d.xml", gcomprisBoard->boarddir, gcomprisBoard->level, gcomprisBoard->sublevel, NULL)) == NULL) && ((gcomprisBoard->level != 1) || (gcomprisBoard->sublevel!=0))) { /* Try the next level */ gcomprisBoard->sublevel = gcomprisBoard->number_of_sublevel; if(!increment_sublevel()) return; } gc_bar_set_level(gcomprisBoard); read_xml_file(filename); gc_drag_start(gnome_canvas_root(gcomprisBoard->canvas), (gc_Drag_Func) item_event_drag, drag_mode); g_free(filename); } static void process_ok() { GList *list; gboolean done = TRUE; /* Loop through all the shapes to find if all target are found */ for(list = shape_list; list != NULL; list = list->next) { Shape *shape = list->data; if(shape->type==SHAPE_TARGET) { if(shape->placed!=shape) done=FALSE; } } if(done) { target_point_hide(); gamewon = TRUE; gc_bonus_display(gamewon, GC_BONUS_FLOWER); } else { gc_bonus_display(gamewon, GC_BONUS_FLOWER); } } static void destroy_shape (Shape *shape) { g_free(shape->name); g_free(shape->pixmapfile); g_free(shape->targetfile); g_free(shape->soundfile); g_free(shape->tooltip); if(shape->points!=NULL) gnome_canvas_points_unref(shape->points); g_free(shape); } /* Destroy all the items */ static void shapegame_destroy_all_items() { Shape *shape; /* Cleanup of the shapes */ while(g_list_length(shape_list)>0) { shape = g_list_nth_data(shape_list, 0); shape_list = g_list_remove (shape_list, shape); destroy_shape(shape); } g_list_free(shape_list); if (shapelist_table) { /* Deleting the root item automatically deletes children items */ gtk_object_destroy (GTK_OBJECT(shape_list_root_item)); shape_list_root_item = NULL; gtk_object_destroy (GTK_OBJECT(shape_root_item)); shape_root_item = NULL; gtk_object_destroy (GTK_OBJECT(tooltip_root_item)); tooltip_root_item = NULL; g_hash_table_destroy (shapelist_table); shapelist_table=NULL; g_list_free(shape_list_group); shape_list_group = NULL; current_shapelistgroup_index = -1; } } static void shapegame_init_canvas(GnomeCanvasGroup *parent) { GdkPixbuf *pixmap = NULL; shape_list_root_item = \ gnome_canvas_item_new (parent, gnome_canvas_group_get_type (), "x", (double)0, "y", (double)0, NULL); shape_root_item = \ gnome_canvas_item_new (parent, gnome_canvas_group_get_type (), "x", (double)SHAPE_BOX_WIDTH, "y", (double)0, NULL); tooltip_root_item = GNOME_CANVAS_GROUP( gnome_canvas_item_new (parent, gnome_canvas_group_get_type (), "x", (double)10, "y", (double)gcomprisBoard->height-70, NULL) ); /* Create the tooltip area */ pixmap = gc_skin_pixmap_load("button_large3.png"); tooltip_bg_item = \ gnome_canvas_item_new (GNOME_CANVAS_GROUP(tooltip_root_item), gnome_canvas_pixbuf_get_type (), "pixbuf", pixmap, "x", (double) 0, "y", (double) 0, NULL); gdk_pixbuf_unref(pixmap); tooltip_text_item = \ gnome_canvas_item_new (GNOME_CANVAS_GROUP(tooltip_root_item), gnome_canvas_text_get_type (), "text", "", "font", gc_skin_font_board_small, "x", (double)gdk_pixbuf_get_width(pixmap)/2, "y", 24.0, "anchor", GTK_ANCHOR_CENTER, "justification", GTK_JUSTIFY_CENTER, "fill_color_rgba", gc_skin_color_text_button, NULL); /* Hide the tooltip */ gnome_canvas_item_hide(GNOME_CANVAS_ITEM(tooltip_root_item)); } /************************************************************** * Shape list management */ /* Add the given shape to the list of shapes * Do nothing if the shape is already in */ static void add_shape_to_list_of_shapes(Shape *shape) { GnomeCanvasItem *item; GdkPixbuf *pixmap = NULL; GnomeCanvasGroup *shape_list_group_root = NULL; double ICON_GAP = 5.0; double ICON_HEIGHT = (double)(shapeBox.h / shapeBox.nb_shape_y) - ICON_GAP; double ICON_WIDTH = (double)(shapeBox.w / shapeBox.nb_shape_x) - ICON_GAP; if(!shapelist_table) shapelist_table= g_hash_table_new (g_str_hash, g_str_equal); /*----------------------------------------------------------------------*/ /* If the first list is full, add the previous/forward buttons */ if(g_hash_table_size(shapelist_table)==(shapeBox.nb_shape_x * shapeBox.nb_shape_y)) { pixmap = gc_skin_pixmap_load("button_backward.png"); previous_shapelist_item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(shape_list_root_item), gnome_canvas_pixbuf_get_type (), "pixbuf", pixmap, "x", (double) shapeBox.x + (shapeBox.w/2) - gdk_pixbuf_get_width(pixmap) - 2, "y", (double) shapeBox.y + shapeBox.h, NULL); gtk_signal_connect(GTK_OBJECT(previous_shapelist_item), "event", (GtkSignalFunc) item_event_ok, "previous_shapelist"); gtk_signal_connect(GTK_OBJECT(previous_shapelist_item), "event", (GtkSignalFunc) gc_item_focus_event, NULL); gdk_pixbuf_unref(pixmap); pixmap = gc_skin_pixmap_load("button_forward.png"); next_shapelist_item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(shape_list_root_item), gnome_canvas_pixbuf_get_type (), "pixbuf", pixmap, "x", (double) shapeBox.x + (shapeBox.w/2) + 2, "y", (double) shapeBox.y + shapeBox.h, NULL); gtk_signal_connect(GTK_OBJECT(next_shapelist_item), "event", (GtkSignalFunc) item_event_ok, "next_shapelist"); gtk_signal_connect(GTK_OBJECT(next_shapelist_item), "event", (GtkSignalFunc) gc_item_focus_event, NULL); gdk_pixbuf_unref(pixmap); gnome_canvas_item_hide(next_shapelist_item); } /*----------------------------------------------------------------------*/ /* Do We need to create a new list */ if(g_hash_table_size(shapelist_table)%(shapeBox.nb_shape_x * shapeBox.nb_shape_y)==0) { current_shapelistgroup_index++; g_warning("Creation of the group of shape current_shapelistgroup_index=%d\n", current_shapelistgroup_index); // Hide the previous group if(current_shapelistgroup_index>=1) { g_warning(" Hide previous group\n"); shape_list_group_root = GNOME_CANVAS_GROUP(g_list_nth_data(shape_list_group, current_shapelistgroup_index-1)); //gnome_canvas_item_hide(shape_list_group_root); item = g_list_nth_data(shape_list_group, current_shapelistgroup_index-1); gnome_canvas_item_hide(item); } // We need to start a new shape list group shape_list_group_root = \ GNOME_CANVAS_GROUP(gnome_canvas_item_new (GNOME_CANVAS_GROUP(shape_list_root_item), gnome_canvas_group_get_type (), "x", (double)0, "y", (double)0, NULL)); shape_list_group = g_list_append (shape_list_group, shape_list_group_root); g_warning(" current_shapelistgroup_index=%d\n", current_shapelistgroup_index); } else { // Get the current shapelist group g_warning(" get the current_shapelistgroup_index=%d\n", current_shapelistgroup_index); shape_list_group_root = g_list_nth_data(shape_list_group, current_shapelistgroup_index); } /*----------------------------------------------------------------------*/ /* This pixmap is not yet in the list of shapes */ if(g_hash_table_lookup (shapelist_table, shape->pixmapfile)==NULL) { double y_offset = 0; double x_offset = 0; GdkPixbuf *pixmap = NULL; y_offset = shapeBox.y + (ICON_HEIGHT/2 + (g_hash_table_size(shapelist_table) % shapeBox.nb_shape_y) * ICON_HEIGHT); x_offset = shapeBox.x + (ICON_WIDTH/2 + ((g_hash_table_size(shapelist_table) % ( shapeBox.nb_shape_x * shapeBox.nb_shape_y)) / shapeBox.nb_shape_y) * ICON_WIDTH); g_warning(" ICON_WIDTH = %f ICON_HEIGHT = %f\n", ICON_WIDTH, ICON_HEIGHT); g_warning("x_offset = %f y_offset = %f\n", x_offset, y_offset); /* So this shape is not yet in, let's put it in now */ g_hash_table_insert (shapelist_table, shape->pixmapfile, shape); if(shape->pixmapfile) { pixmap = gc_pixmap_load(shape->pixmapfile); if(pixmap) { double w, h; Shape *icon_shape; /* Calc a zoom factor so that the shape will fit in the shapelist whatever its current size */ w = ICON_WIDTH; h = gdk_pixbuf_get_height(pixmap) * (w / gdk_pixbuf_get_width(pixmap)); if(h > ICON_HEIGHT) { h = ICON_HEIGHT; w = gdk_pixbuf_get_width(pixmap) * ( h / gdk_pixbuf_get_height(pixmap)); } if(h < 20 || w < 20 ) { GdkPixbuf *scale, *hand; scale = gdk_pixbuf_scale_simple(pixmap, w, h, GDK_INTERP_BILINEAR); gdk_pixbuf_unref(pixmap); pixmap = gdk_pixbuf_new( GDK_COLORSPACE_RGB, TRUE, 8, ICON_WIDTH, ICON_HEIGHT); gdk_pixbuf_fill(pixmap,0xffffff00); // add the shape gdk_pixbuf_copy_area( scale, 0, 0, w, h, pixmap, (ICON_WIDTH-w )/2, (ICON_HEIGHT-h)/2 ); gdk_pixbuf_unref(scale); // add the hand hand = gc_skin_pixmap_load("boardicons/leftright.svg"); h = ICON_HEIGHT/3; w = gdk_pixbuf_get_width(hand) * h / gdk_pixbuf_get_height(hand); scale = gdk_pixbuf_scale_simple(hand, w, h, GDK_INTERP_BILINEAR); gdk_pixbuf_copy_area(scale, 0, 0, w, h, pixmap, ICON_WIDTH-w,0); gdk_pixbuf_unref(hand); gdk_pixbuf_unref(scale); w=ICON_WIDTH; h=ICON_HEIGHT; } item = gnome_canvas_item_new (shape_list_group_root, gnome_canvas_pixbuf_get_type (), "pixbuf", pixmap, "x", (double)x_offset-w/2, "y", (double)y_offset-h/2, "width", (double) w, "height", (double) h, "width_set", TRUE, "height_set", TRUE, NULL); gdk_pixbuf_unref(pixmap); icon_shape = create_shape(SHAPE_ICON, shape->name, shape->tooltip, shape->pixmapfile, shape->points, shape->targetfile, (double)x_offset -w/2, (double)y_offset -h/2, (double)w, (double)h, (double)shape->zoomx, (double)shape->zoomy, 0, shape->soundfile); icon_shape->item = item; icon_shape->target_shape = shape; shape->icon_shape = icon_shape; icon_shape->shapelistgroup_index = current_shapelistgroup_index; shape->shapelistgroup_index = current_shapelistgroup_index; g_warning(" creation shape=%s shape->shapelistgroup_index=%d current_shapelistgroup_index=%d\n", shape->name, shape->shapelistgroup_index, current_shapelistgroup_index); icon_shape->shape_list_group_root = shape_list_group_root; setup_item(item, icon_shape); gtk_signal_connect(GTK_OBJECT(item), "event", (GtkSignalFunc) gc_item_focus_event, NULL); } } } } /* * Find the closest shape from the given point if it is located at * a distance under the given square limit. */ static Shape *find_closest_shape(double x, double y, double limit) { GList *list; double goodDist = limit; Shape *candidateShape = NULL; /* loop through all our shapes */ for(list = shape_list; list != NULL; list = list->next) { Shape *shape = list->data; double dist; if(shape->type==SHAPE_TARGET) { /* Calc the distance between this shape and the given coord */ dist = sqrt(pow((shape->x-x+SHAPE_BOX_WIDTH),2) + pow((shape->y-y),2)); if(distnext) { Shape * s = list->data; if(s->type == SHAPE_TARGET || s->type == SHAPE_ICON) dump_shape(s); } } static void dump_shape(Shape *shape) { if(shape->type == SHAPE_TARGET && (shape->placed || shape->shape_place)) { printf("%s :", shape->name); if(shape->placed) printf(" %s -> %s", shape->name, shape->placed->name); else printf(" "); if(shape->shape_place) printf(" %s -> %s", shape->shape_place->name, shape->name); printf("\n"); } } #endif /* it puts a shape back to the list of shapes */ static void shape_goes_back_to_list(Shape *shape) { if(shape -> type == SHAPE_ICON) shape = shape -> target_shape; gnome_canvas_item_hide(shape->item); /* replace the icon */ gnome_canvas_item_set(shape->icon_shape->item, "x", shape->icon_shape->x, "y", shape->icon_shape->y, NULL); gnome_canvas_item_show(shape->icon_shape->item); if(shape->placed) { shape->placed->shape_place = NULL; shape->placed = NULL; } update_shapelist_item(); gc_sound_play_ogg ("sounds/flip.wav", NULL); } static Shape * item_to_shape(GnomeCanvasItem *item) { GList *list; for(list = shape_list; list ; list = list -> next) { Shape *s = list -> data; if( s-> item == item) return s; } g_warning("Can't find the shape for item %p", item); return NULL; } /* switch off all point, and switch on this point if shape is NULL, switch off all */ static void target_point_switch_on(Shape *shape_on) { GList *list; Shape *shape; for(list = shape_list; list ; list = list ->next) { shape = list -> data; if(shape->type == SHAPE_TARGET && ! shape->targetfile) gnome_canvas_item_set(shape->target_point, "fill_color_rgba", shape == shape_on ? POINT_COLOR_ON : POINT_COLOR_OFF, NULL); } } /* hide all point to let the user look the real image at the end */ static void target_point_hide() { GList *list; Shape *shape; for(list = shape_list; list ; list = list ->next) { shape = list -> data; if(shape->type == SHAPE_TARGET && ! shape->targetfile) gnome_canvas_item_hide(shape->target_point); } } static gint item_event_drag(GnomeCanvasItem *item, GdkEvent *event, gpointer data) { static GnomeCanvasItem *shadow_item=NULL; static GnomeCanvasItem *dragged; double item_x, item_y; Shape *shape, *found_shape; if(board_paused) return FALSE; shape = item_to_shape(item); switch(event->type) { case GDK_BUTTON_PRESS: switch(shape -> type) { case SHAPE_ICON: gc_drag_offset_save(event); gc_drag_offset_get(&shape->offset_x, &shape->offset_y); if (shape->soundfile) { /* If the soundfile has space ' ' in it, then it is assumed that it is a list * of sound rather than a single one */ char *p = NULL; char *soundfile = g_strdup(shape->soundfile); char *soundfiles = soundfile; while ((p = strstr (soundfiles, " "))) { *p='\0'; gc_sound_play_ogg(soundfiles, NULL); soundfiles= p + 1; g_warning("soundfile = %s\n", soundfiles); } if (soundfiles != soundfile) gc_sound_play_ogg(soundfiles, NULL); else gc_sound_play_ogg(soundfile, NULL); g_free(soundfile); } else gc_sound_play_ogg ("sounds/bleep.wav", NULL); break; case SHAPE_TARGET: gc_sound_play_ogg ("sounds/bleep.wav", NULL); gnome_canvas_item_hide(shape->item); // unplace this shape shape->placed->shape_place= NULL; shape->placed = NULL; shape = shape -> icon_shape; gc_drag_offset_set( shape->offset_x, shape->offset_y); gnome_canvas_item_show(shape->item); gc_drag_item_set(shape->item); break; default: break; } if(shadow_enable) { if(shadow_item) gtk_object_destroy(GTK_OBJECT(shadow_item)); // initialise shadow shape GdkPixbuf *pixmap, *dest; g_object_get(shape->target_shape->item, "pixbuf", &pixmap, NULL); dest = gdk_pixbuf_copy(pixmap); pixbuf_add_transparent(dest, 100); shadow_item = gnome_canvas_item_new(GNOME_CANVAS_GROUP(shape_root_item), gnome_canvas_pixbuf_get_type(), "pixbuf", dest, "width", shape->target_shape->w, "height", shape->target_shape->h, "width_set", TRUE, "height_set", TRUE, NULL); gnome_canvas_item_hide(shadow_item); gdk_pixbuf_unref(dest); gdk_pixbuf_unref(pixmap); } dragged = shape->item; gnome_canvas_item_reparent(shape->item, GNOME_CANVAS_GROUP(shape_list_root_item->parent)); gnome_canvas_item_raise_to_top(shape->item); gc_drag_item_move(event); break; case GDK_MOTION_NOTIFY: if (item != dragged) break; gc_drag_item_move(event); item_x = event->button.x; item_y = event->button.y; gnome_canvas_item_w2i(item->parent, &item_x, &item_y); found_shape = find_closest_shape( item_x, item_y, SQUARE_LIMIT_DISTANCE); if(shadow_enable) { if(found_shape) { gnome_canvas_item_set(shadow_item, "x", found_shape->x - shape->target_shape->w/2, "y", found_shape->y - shape->target_shape->h/2, NULL); gnome_canvas_item_show(shadow_item); } else gnome_canvas_item_hide(shadow_item); } target_point_switch_on(found_shape); break; case GDK_BUTTON_RELEASE: if (item != dragged) break; item_x = event->button.x; item_y = event->button.y; gnome_canvas_item_w2i(item->parent, &item_x, &item_y); if(shadow_enable && shadow_item) { gtk_object_destroy(GTK_OBJECT(shadow_item)); shadow_item = NULL; } target_point_switch_on(NULL); gnome_canvas_item_reparent(shape->item, shape->shape_list_group_root); found_shape = find_closest_shape( item_x, item_y, SQUARE_LIMIT_DISTANCE); if(found_shape) { if(found_shape->shape_place) shape_goes_back_to_list(found_shape->shape_place); gc_sound_play_ogg ("sounds/line_end.wav", NULL); /* place the target item */ gnome_canvas_item_set(shape->target_shape->item, "x", found_shape->x - shape->target_shape->w/2, "y", found_shape->y - shape->target_shape->h/2, NULL); gnome_canvas_item_show(shape->target_shape->item); gnome_canvas_item_raise_to_top(shape->target_shape->item); gnome_canvas_item_hide(shape->item); shape -> target_shape -> placed = found_shape; found_shape -> shape_place = shape -> target_shape; auto_process(); update_shapelist_item(); } else { shape_goes_back_to_list(shape); } break; default: break; } return FALSE; } static gint item_event(GnomeCanvasItem *item, GdkEvent *event, Shape *shape) { if(!gcomprisBoard) return FALSE; if(board_paused) return FALSE; if(shape==NULL) { g_warning("Shape is NULL : Should not happen"); return FALSE; } switch (event->type) { case GDK_ENTER_NOTIFY: if(shape->tooltip && shape->type == SHAPE_ICON) { /* WARNING: This should not be needed but if I don't do it, it's not refreshed */ gnome_canvas_item_set(GNOME_CANVAS_ITEM(tooltip_bg_item), "y", 0.0, NULL); gnome_canvas_item_set(GNOME_CANVAS_ITEM(tooltip_text_item), "text", gettext(shape->tooltip), NULL); gnome_canvas_item_show(GNOME_CANVAS_ITEM(tooltip_root_item)); } break; case GDK_LEAVE_NOTIFY: if(shape->tooltip && shape->type == SHAPE_ICON) gnome_canvas_item_hide(GNOME_CANVAS_ITEM(tooltip_root_item)); break; case GDK_BUTTON_PRESS: if(event->button.button == 3) shape_goes_back_to_list(shape); default: break; } return FALSE; } static int get_element_count_listgroup(int listgroup_index) { int count=0, i; Shape *sh; for (i=0;ishapelistgroup_index == listgroup_index && sh->type == SHAPE_TARGET && ! sh->placed) count ++; } return count; } static int get_no_void_group(int direction) { int index = current_shapelistgroup_index; direction = direction>0 ? 1 : -1; index += direction; while(0 <= index && index < g_list_length(shape_list_group)) { if(get_element_count_listgroup(index)) return index; index += direction; } return current_shapelistgroup_index; } static void auto_process(void) { GList *list; gboolean done = TRUE; /* Loop through all the shapes to find if all target are in place */ for(list = shape_list; list != NULL; list = list->next) { Shape *shape = list->data; if(shape->type==SHAPE_TARGET) { if(shape->placed==NULL) done=FALSE; } } if(done) process_ok(); } static void update_shapelist_item(void) { if(! next_shapelist_item || !previous_shapelist_item) return; if(get_element_count_listgroup(current_shapelistgroup_index) ==0) { int index; GnomeCanvasItem *root_item; index = get_no_void_group(-1); if(index == current_shapelistgroup_index) index = get_no_void_group(1); if(index != current_shapelistgroup_index) { root_item = g_list_nth_data(shape_list_group, current_shapelistgroup_index); gnome_canvas_item_hide(root_item); root_item = g_list_nth_data(shape_list_group, index); gnome_canvas_item_show(root_item); current_shapelistgroup_index = index; } } if(get_no_void_group(1) == current_shapelistgroup_index) gnome_canvas_item_hide(next_shapelist_item); else gnome_canvas_item_show(next_shapelist_item); if(get_no_void_group(-1) == current_shapelistgroup_index) gnome_canvas_item_hide(previous_shapelist_item); else gnome_canvas_item_show(previous_shapelist_item); #if DEBUG dump_shapes(); #endif } /* Callback for the operations */ static gint item_event_ok(GnomeCanvasItem *item, GdkEvent *event, gpointer data) { GnomeCanvasItem *root_item; if(board_paused) return FALSE; switch (event->type) { case GDK_BUTTON_PRESS: gc_sound_play_ogg ("sounds/bleep.wav", NULL); root_item = g_list_nth_data(shape_list_group, current_shapelistgroup_index); gnome_canvas_item_hide(root_item); g_warning(" item event current_shapelistgroup_index=%d\n", current_shapelistgroup_index); if(!strcmp((char *)data, "previous_shapelist")) { current_shapelistgroup_index = get_no_void_group(-1); update_shapelist_item(); } else if(!strcmp((char *)data, "next_shapelist")) { current_shapelistgroup_index = get_no_void_group(1); update_shapelist_item(); } root_item = g_list_nth_data(shape_list_group, current_shapelistgroup_index); gnome_canvas_item_show(root_item); /* FIXME : Workaround for bugged canvas */ // gnome_canvas_update_now(gcomprisBoard->canvas); default: break; } return FALSE; } static void setup_item(GnomeCanvasItem *item, Shape *shape) { gtk_signal_connect(GTK_OBJECT(item), "event", (GtkSignalFunc) item_event, shape); gtk_signal_connect(GTK_OBJECT(item), "event", (GtkSignalFunc) gc_drag_event, NULL); } /* * Thanks for George Lebl for his Genealogy example * for all the XML stuff there */ /* Adds a shape to the canvas */ static void add_shape_to_canvas(Shape *shape) { GdkPixbuf *pixmap; GdkPixbuf *targetpixmap; GnomeCanvasItem *item = NULL; /* checking of preconditions, this is usefull for tracking down bugs, but you should not count on these always being compiled in */ g_return_if_fail(shape != NULL); if(shape->type==SHAPE_TARGET) { if(shape->targetfile) { targetpixmap = gc_pixmap_load(shape->targetfile); shape->w = (double)gdk_pixbuf_get_width(targetpixmap) * shape->zoomx; shape->h = (double)gdk_pixbuf_get_height(targetpixmap) *shape->zoomy; item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(shape_root_item), gnome_canvas_pixbuf_get_type (), "pixbuf", targetpixmap, "x", shape->x - shape->w / 2, "y", shape->y - shape->h / 2, "width", shape->w, "height", shape->h, "width_set", TRUE, "height_set", TRUE, NULL); shape->targetitem = item; gdk_pixbuf_unref(targetpixmap); } else { int point_size = 6; /* Display a point to highlight the target location of this shape */ item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(shape_root_item), gnome_canvas_ellipse_get_type(), "x1", (double)shape->x-point_size, "y1", (double)shape->y-point_size, "x2", (double)shape->x+point_size, "y2", (double)shape->y+point_size, "fill_color_rgba", POINT_COLOR_OFF, "outline_color", "black", "width_pixels", 2, NULL); shape->target_point = item; } gnome_canvas_item_lower_to_bottom(item); } if(shape->points!=NULL) { g_warning("it's a point \n"); item = gnome_canvas_item_new(GNOME_CANVAS_GROUP(shape_root_item), gnome_canvas_polygon_get_type (), "points", shape->points, "fill_color", "grey", "outline_color", "black", "width_units", 1.0, NULL); } else { g_warning("it's an image ? shape->pixmapfile=%s\n", shape->pixmapfile); if(shape->pixmapfile) { g_warning(" Yes it is an image \n"); pixmap = gc_pixmap_load(shape->pixmapfile); if(pixmap) { shape->w = (double)gdk_pixbuf_get_width(pixmap) * shape->zoomx; shape->h = (double)gdk_pixbuf_get_height(pixmap) * shape->zoomy; /* Display the shape itself but hide it until the user puts the right shape on it */ /* I have to do it this way for the positionning (lower/raise) complexity */ item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(shape_root_item), gnome_canvas_pixbuf_get_type (), "pixbuf", pixmap, "x", shape->x - shape->w / 2, "y", shape->y - shape->h / 2, "width", shape->w, "height", shape->h, "width_set", TRUE, "height_set", TRUE, NULL); gdk_pixbuf_unref(pixmap); } } } /* Associate this item to this shape */ shape->item = item; if(shape->type==SHAPE_TARGET || shape->type==SHAPE_DUMMY_TARGET) { setup_item(item, shape); gnome_canvas_item_hide(item); add_shape_to_list_of_shapes(shape); } else if(shape->type==SHAPE_BACKGROUND) { gnome_canvas_item_lower_to_bottom(item); } } static void create_title(char *name, double x, double y, GtkJustification justification, guint32 color_rgba) { GnomeCanvasItem *item; /* Shadow */ item = \ gnome_canvas_item_new (GNOME_CANVAS_GROUP(shape_root_item), gnome_canvas_text_get_type (), "text", gettext(name), "font", gc_skin_font_board_medium, "x", x + 1.0, "y", y + 1.0, "anchor", GTK_ANCHOR_CENTER, "justification", justification, "fill_color_rgba", gc_skin_color_shadow, NULL); gnome_canvas_item_raise_to_top(item); item = \ gnome_canvas_item_new (GNOME_CANVAS_GROUP(shape_root_item), gnome_canvas_text_get_type (), "text", gettext(name), "font", gc_skin_font_board_medium, "x", x, "y", y, "anchor", GTK_ANCHOR_CENTER, "justification", justification, "fill_color_rgba", color_rgba, NULL); gnome_canvas_item_raise_to_top(item); } static Shape * create_shape(ShapeType type, char *name, char *tooltip, char *pixmapfile, GnomeCanvasPoints* points, char *targetfile, double x, double y, double w, double h, double zoomx, double zoomy, guint position, char *soundfile) { Shape *shape; /* allocate a new shape */ shape = g_new0(Shape,1); shape->name = g_strdup(name); if(tooltip) shape->tooltip = g_strdup(tooltip); else shape->tooltip = NULL; shape->pixmapfile = g_strdup(pixmapfile); shape->points = points; shape->targetfile = g_strdup(targetfile); shape->x = x; shape->y = y; shape->w = w; shape->h = h; shape->zoomx = zoomx; shape->zoomy = zoomy; shape->position = position; shape->type = type; shape->soundfile = g_strdup(soundfile); /* add the shape to the list */ shape_list = g_list_append(shape_list, shape); return shape; } /** return a double value from an nodePtr * * \param node * \param prop * \param def_value : default value * * \return a double value found in the 'prop' property of the 'node' or * the default value if not found */ static double xmlGetProp_Double(xmlNodePtr node, xmlChar *prop, double def_value) { double value; char *str; str = (char *)xmlGetProp(node, prop); if(str) { value = g_ascii_strtod(str, NULL); free(str); } else value = def_value; return value; } static void add_xml_shape_to_data(xmlDocPtr doc, xmlNodePtr xmlnode, GNode * child, GList **list) { char *name, *cd ,*ctype, *justification; char *tooltip; GtkJustification justification_gtk; char *pixmapfile = NULL; char *targetfile = NULL; char *soundfile = NULL; double x, y, zoomx, zoomy; GnomeCanvasPoints* points = NULL; gchar **d; gint i, j; guint position; ShapeType type = SHAPE_TARGET; Shape *shape; xmlNodePtr xmlnamenode; char *locale; char *color_text; guint color_rgba; if(/* if the node has no name */ !xmlnode->name || /* or if the name is not "Shape" */ ((g_strcasecmp((const char *)xmlnode->name,"Shape")!=0) && /* or if the name is not "Title" */ (g_strcasecmp((const char *)xmlnode->name,"Title")!=0) && /* or if the name is not "Option" */ (g_strcasecmp((const char *)xmlnode->name,"Option")!=0) ) ) return; pixmapfile = (char *)xmlGetProp(xmlnode, BAD_CAST "pixmapfile"); if(pixmapfile) { /* If the pixmapfile starts with skin: then get the skin relative image instead */ if(!strncmp(pixmapfile, "skin:", 5)) { gchar *oldpixmapfile = pixmapfile; pixmapfile = gc_skin_image_get(oldpixmapfile+5); g_free(oldpixmapfile); } } targetfile = (char *)xmlGetProp(xmlnode, BAD_CAST "targetfile"); soundfile = (char *)xmlGetProp(xmlnode, BAD_CAST "sound"); /*********************************/ /* get the points for a polygone */ /* The list of points is similar to the one define in the SVG standard */ /* FIXME : The implementation is incomplete, a point still needs to be added to shapelist and add management for it's x/y coordinates */ cd = (char *)xmlGetProp(xmlnode, BAD_CAST "points"); if(cd) { d = g_strsplit(cd, " ", 64); xmlFree(cd); j=0; while(d[j]!=NULL) { j++; } points = gnome_canvas_points_new(j/2); for(i=0; icoords[i] = g_ascii_strtod(d[i], NULL); } g_strfreev(d); } /* get the X coord of the shape */ x = xmlGetProp_Double(xmlnode, BAD_CAST "x", 100); /* get the Y coord of the shape */ y = xmlGetProp_Double(xmlnode, BAD_CAST "y", 100); /* Back up the current locale to be sure to load well C formated numbers */ locale = g_strdup(gc_locale_get()); gc_locale_set("C"); /* get the ZOOMX coord of the shape */ zoomx = xmlGetProp_Double(xmlnode, BAD_CAST "zoomx", 1); /* get the ZOOMY coord of the shape */ zoomy = xmlGetProp_Double(xmlnode, BAD_CAST "zoomy", 1); /* get the POSITION of the shape */ /* Position in the xml means: * 0 = BOTTOM * 1 or more = TOP */ position = (guint) xmlGetProp_Double(xmlnode, BAD_CAST "position", 0); /* Back to the user locale */ gc_locale_set(locale); g_free(locale); /* get the TYPE of the shape */ ctype = (char *)xmlGetProp(xmlnode, BAD_CAST "type"); if(ctype) { if(g_strcasecmp(ctype,"SHAPE_TARGET")==0) type = SHAPE_TARGET; else if(g_strcasecmp(ctype,"SHAPE_DUMMY_TARGET")==0) type = SHAPE_DUMMY_TARGET; else if (g_strcasecmp(ctype,"SHAPE_BACKGROUND")==0) type = SHAPE_BACKGROUND; xmlFree(ctype); } else type = SHAPE_TARGET; /* get the JUSTIFICATION of the Title */ justification_gtk = GTK_JUSTIFY_CENTER; /* GTK_JUSTIFICATION_CENTER is default */ justification = (char *)xmlGetProp(xmlnode, BAD_CAST "justification"); if(justification) { if (strcmp(justification, "GTK_JUSTIFY_LEFT") == 0) { justification_gtk = GTK_JUSTIFY_LEFT; } else if (strcmp(justification, "GTK_JUSTIFY_RIGHT") == 0) { justification_gtk = GTK_JUSTIFY_RIGHT; } else if (strcmp(justification, "GTK_JUSTIFY_CENTER") == 0) { justification_gtk = GTK_JUSTIFY_CENTER; } else if (strcmp(justification, "GTK_JUSTIFY_FILL") == 0) { justification_gtk = GTK_JUSTIFY_FILL; } xmlFree(justification); } /* get the COLOR of the Title Specified by skin reference */ color_text = (char *)xmlGetProp(xmlnode, BAD_CAST "color_skin"); if(color_text) { color_rgba = gc_skin_get_color(color_text); xmlFree(color_text); } else { color_rgba = gc_skin_get_color("gcompris/content"); /* the default */ } /* get the name and tooltip of the shape */ name = NULL; tooltip = NULL; xmlnamenode = xmlnode->xmlChildrenNode; while (xmlnamenode != NULL) { gchar *lang = (char *)xmlGetProp(xmlnamenode, BAD_CAST "lang"); /* get the name of the shape */ if (!strcmp((char *)xmlnamenode->name, "name") && (lang==NULL || !strcmp(lang, gc_locale_get()) || !strncmp(lang, gc_locale_get(), 2))) { if (name) xmlFree(name); name = (char *)xmlNodeListGetString(doc, xmlnamenode->xmlChildrenNode, 1); } /* get the tooltip of the shape */ if (!strcmp((char *)xmlnamenode->name, "tooltip") && (lang==NULL || !strcmp(lang, gc_locale_get()) || !strncmp(lang, gc_locale_get(), 2))) { if (tooltip) xmlFree(tooltip); tooltip = (char *)xmlNodeListGetString(doc, xmlnamenode->xmlChildrenNode, 1); } xmlFree(lang); xmlnamenode = xmlnamenode->next; } /* If name is not given as an element, try to get it as a property */ if(!name) name = (char *)xmlGetProp(xmlnode, BAD_CAST "name"); if(g_strcasecmp((char *)xmlnode->name, "Shape")==0) { /* add the shape to the database */ /* WARNING : I do not initialize the width and height since I don't need them */ shape = create_shape(type, name, tooltip, pixmapfile , points, targetfile, x, y, (double)0, (double)0, zoomx, zoomy, position, soundfile); /* add the shape to the list */ *list = g_list_append(*list, shape); } else if (g_strcasecmp((char *)xmlnode->name, "Title")==0) { /* Readd \n is needed */ gchar *newname; if(name != NULL) { newname = g_strcompress(name); create_title(newname, x, y, justification_gtk, color_rgba); g_free(newname); } } g_free(pixmapfile); g_free(soundfile); g_free(name); g_free(targetfile); g_free(tooltip); } /* parse the doc, add it to our internal structures and to the clist */ static void parse_doc(xmlDocPtr doc) { GList *shape_list_init = NULL; xmlNodePtr node; GList *list; GnomeCanvasItem *item; int list_length, i; /* find nodes and add them to the list, this just loops through all the children of the root of the document */ for(node = doc->children->children; node != NULL; node = node->next) { /* add the shape to the list, there are no children so we pass NULL as the node of the child */ add_xml_shape_to_data(doc, node, NULL, &shape_list_init); } shape_list = g_list_copy(shape_list_init); /* Insert each of the shapes randomly */ while((list_length = g_list_length(shape_list_init))) { Shape *shape; i = g_random_int_range(0, list_length); shape = g_list_nth_data(shape_list_init, i); add_shape_to_canvas(shape); shape_list_init = g_list_remove (shape_list_init, shape); } g_list_free(shape_list_init); shape_list_init = NULL; if(current_shapelistgroup_index>0) { /* If at least on shape group */ item = g_list_nth_data(shape_list_group, current_shapelistgroup_index); gnome_canvas_item_hide(item); item = g_list_nth_data(shape_list_group, 0); gnome_canvas_item_show(item); gnome_canvas_item_hide(previous_shapelist_item); gnome_canvas_item_show(next_shapelist_item); current_shapelistgroup_index = 0; } /* Loop through all the shapes and */ /* Arrange the order (depth) of the shapes on the canvas */ /* Depending on the xml given definition in the position property */ for(list = shape_list; list != NULL; list = list->next) { Shape *shape = list->data; gnome_canvas_item_lower_to_bottom(shape->item); if(shape->position>=1) gnome_canvas_item_raise(shape->item, ABS(shape->position)); } } /* read an xml file into our memory structures and update our view, dump any old data we have in memory if we can load a new set */ static gboolean read_xml_file(char *fname) { /* pointer to the new doc */ xmlDocPtr doc; g_return_val_if_fail(fname!=NULL,FALSE); /* parse the new file and put the result into newdoc */ doc = xmlParseFile(fname); /* in case something went wrong */ if(!doc) return FALSE; if(/* if there is no root element */ !doc->children || /* if it doesn't have a name */ !doc->children->name || /* if it isn't a ShapeGame node */ g_strcasecmp((char *)doc->children->name, "ShapeGame")!=0) { xmlFreeDoc(doc); return FALSE; } /*--------------------------------------------------*/ /* Read ShapeBox property */ shapeBox.x = xmlGetProp_Double(doc->children, BAD_CAST "shapebox_x", 15); g_warning("shapeBox.x=%f\n", shapeBox.x); shapeBox.y = xmlGetProp_Double(doc->children, BAD_CAST "shapebox_y", 25); g_warning("shapeBox.y=%f\n", shapeBox.y); shapeBox.w = xmlGetProp_Double(doc->children, BAD_CAST "shapebox_w", 80); g_warning("shapeBox.w=%f\n", shapeBox.w); shapeBox.h = xmlGetProp_Double(doc->children, BAD_CAST "shapebox_h", 430); g_warning("shapeBox.h=%f\n", shapeBox.h); shapeBox.nb_shape_x = xmlGetProp_Double(doc->children, BAD_CAST "shapebox_nb_shape_x", 1); g_warning("shapeBox.nb_shape_x=%d\n", shapeBox.nb_shape_x); shapeBox.nb_shape_y = xmlGetProp_Double(doc->children, BAD_CAST "shapebox_nb_shape_y", 5); g_warning("shapeBox.nb_shape_y=%d\n", shapeBox.nb_shape_y); /* Read shadow enable property */ shadow_enable = xmlGetProp_Double(doc->children, BAD_CAST "shadow_enable", 1); /* parse our document and replace old data */ parse_doc(doc); xmlFreeDoc(doc); return TRUE; } /* ************************************* */ /* * Configuration * */ /* ************************************* */ /* ======================= */ /* = config_start = */ /* ======================= */ static GcomprisProfile *profile_conf; static GcomprisBoard *board_conf; static void save_table (gpointer key, gpointer value, gpointer user_data) { gc_db_set_board_conf ( profile_conf, board_conf, (gchar *) key, (gchar *) value); } static void conf_ok(GHashTable *table) { if (!table){ if (gcomprisBoard) pause_board(FALSE); return; } g_hash_table_foreach(table, (GHFunc) save_table, NULL); if (gcomprisBoard){ GHashTable *config; if (profile_conf) config = gc_db_get_board_conf(); else config = table; if (strcmp(gcomprisBoard->name, "imagename")==0){ gc_locale_reset(); gc_locale_set(g_hash_table_lookup( config, "locale")); } gchar *drag_mode_str = g_hash_table_lookup( config, "drag_mode"); if (drag_mode_str && (strcmp (drag_mode_str, "NULL") != 0)) drag_mode = (gint ) g_ascii_strtod(drag_mode_str, NULL); else drag_mode = 0; if (profile_conf) g_hash_table_destroy(config); gc_drag_change_mode( drag_mode); shapegame_next_level(); pause_board(FALSE); } board_conf = NULL; profile_conf = NULL; } static void config_start(GcomprisBoard *agcomprisBoard, GcomprisProfile *aProfile) { board_conf = agcomprisBoard; profile_conf = aProfile; if (gcomprisBoard) pause_board(TRUE); gchar * label = g_strdup_printf(_("%s configuration\n for profile %s"), agcomprisBoard->name, aProfile? aProfile->name : ""); GcomprisBoardConf *bconf; bconf = gc_board_config_window_display( label, (GcomprisConfCallback )conf_ok); g_free(label); /* init the combo to previously saved value */ GHashTable *config = gc_db_get_conf( profile_conf, board_conf); if (strcmp(agcomprisBoard->name, "imagename")==0){ gchar *locale = g_hash_table_lookup( config, "locale"); gc_board_config_combo_locales( bconf, locale); } gchar *drag_mode_str = g_hash_table_lookup( config, "drag_mode"); gint drag_previous; if (drag_mode_str && (strcmp (drag_mode_str, "NULL") != 0)) drag_previous = (gint ) g_ascii_strtod(drag_mode_str, NULL); else drag_previous = 0; gc_board_config_combo_drag(bconf, drag_mode); } /* ======================= */ /* = config_stop = */ /* ======================= */ static void config_stop() { }