Back to index

gcompris  8.2.2
money_widget.c
Go to the documentation of this file.
00001 /*
00002  * money_widget.c
00003  *
00004  * Copyright (C) 2002  Robert Wilhelm
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License as
00008  * published by the Free Software Foundation; either version 2 of the
00009  * License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public
00017  * License along with this program; if not, write to the
00018  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00019  * Boston, MA 02111-1307, USA.
00020  *
00021  * Authors: Bruno Coudoin
00022  *
00023  */
00024 
00025 #include <stdlib.h>
00026 #include <string.h>
00027 #include "money_widget.h"
00028 
00029 struct _Money_WidgetPrivate {
00030   GnomeCanvasGroup   *rootItem;    /* The canvas to display our euros in             */
00031   double              x1;          /* Coordinate of the widget                       */
00032   double              y1;
00033   double              x2;
00034   double              y2;
00035   guint                      columns;     /* Number of columns                        */
00036   guint                      lines;              /* Number of lines                          */
00037   guint                      next_spot;   /* Next spot to display a money item               */
00038   double              total;              /* The number of euro in this pocket              */
00039   Money_Widget              *targetWidget;       /* Target money widget to add when remove here     */
00040   gboolean            display_total;      /* Display or not the total of this pocket        */
00041 
00042   GnomeCanvasItem    *item_total;  /* Item to display the total                      */
00043   GList                     *moneyItemList;      /* List of all the items                    */
00044 };
00045 
00046 
00047 typedef struct _MoneyList        MoneyList;
00048 
00049 struct _MoneyList {
00050   const gchar        *image;
00051   const double               value;
00052 };
00053 
00054 // List of images to use in the game
00055 static const MoneyList euroList[] =
00056 {
00057   { "money/euro/c1c.png",          0.01  },
00058   { "money/euro/c2c.png",          0.02  },
00059   { "money/euro/c5c.png",          0.05  },
00060   { "money/euro/c10c.png",         0.1   },
00061   { "money/euro/c20c.png",         0.20  },
00062   { "money/euro/c50c.png",         0.5   },
00063   { "money/euro/c1e.png",          1.0   },
00064   { "money/euro/c2e.png",          2.0   },
00065   { "money/euro/p5e.png",          5.0   },
00066   { "money/euro/p10e.png",         10.0  },
00067   { "money/euro/p20e.png",         20.0  },
00068   { "money/euro/p50e.png",         50.0  },
00069   { NULL,                          -1.0  }
00070 };
00071 
00072 typedef struct {
00073   Money_Widget              *moneyWidget;
00074   GnomeCanvasItem    *item;
00075   MoneyEuroType              value;
00076   gboolean            inPocket;
00077 } MoneyItem;
00078 
00079 #define BORDER_GAP   6
00080 
00081 /* Prototypes */
00082 static void class_init (Money_WidgetClass *class);
00083 static void init (Money_Widget *pos);
00084 static void money_display_total(Money_Widget *moneyWidget);
00085 static gint item_event(GnomeCanvasItem *item, GdkEvent *event, MoneyItem *moneyitem);
00086 
00087 GtkType
00088 money_widget_get_type ()
00089 {
00090        static guint money_widget_type = 0;
00091 
00092        if (!money_widget_type) {
00093               GtkTypeInfo money_widget_info = {
00094                      "Money_Widget",
00095                      sizeof (Money_Widget),
00096                      sizeof (Money_WidgetClass),
00097                      (GtkClassInitFunc) class_init,
00098                      (GtkObjectInitFunc) init,
00099                      (gpointer) NULL,
00100                      (gpointer) NULL,
00101                      (GtkClassInitFunc) NULL
00102               };
00103               money_widget_type = gtk_type_unique (gtk_object_get_type (),
00104                                            &money_widget_info);
00105        }
00106 
00107        return money_widget_type;
00108 }
00109 
00110 #if 0
00111 static void
00112 finalize (GtkObject *object)
00113 {
00114   MoneyItem     *moneyitem;
00115 
00116   Money_Widget *moneyWidget = (Money_Widget *) object;
00117 
00118   printf("ERROR : Finalize is NEVER CALLED\n");
00119   /* FIXME: CLEANUP CODE UNTESTED */
00120   while(g_list_length(moneyWidget->priv->moneyItemList)>0) 
00121     {
00122       moneyitem = g_list_nth_data(moneyWidget->priv->moneyItemList, 0);
00123       moneyWidget->priv->moneyItemList = g_list_remove (moneyWidget->priv->moneyItemList,
00124                                                  moneyitem);
00125       g_free(moneyitem);
00126     }
00127 
00128   g_free (moneyWidget->priv);
00129   
00130   moneyWidget->priv = NULL;
00131 
00132 }
00133 #endif
00134 
00135 static void
00136 class_init (Money_WidgetClass *class)
00137 {
00138   GtkObjectClass *object_class;
00139   
00140   object_class = (GtkObjectClass*) class;
00141   
00142   //2  object_class->destroy = finalize;
00143 }
00144 
00145 static void
00146 init (Money_Widget *pos)
00147 {
00148        pos->priv = g_new0 (Money_WidgetPrivate, 1);
00149 
00150 }
00151 
00152 GtkObject *
00153 money_widget_new ()
00154 {
00155        return GTK_OBJECT (gtk_type_new (money_widget_get_type ()));
00156 }
00157 
00158 Money_Widget *
00159 money_widget_copy (Money_Widget *pos)
00160 {
00161        Money_Widget *cpPos;
00162 
00163        cpPos = MONEY_WIDGET (money_widget_new ());
00164 
00165        memcpy (cpPos->priv, pos->priv, sizeof (Money_WidgetPrivate));
00166 
00167        return cpPos;
00168 }
00169 
00170 void
00171 money_widget_set_target (Money_Widget *moneyWidget,
00172                       Money_Widget *targetWidget)
00173 {
00174   moneyWidget->priv->targetWidget = targetWidget;
00175 }
00176 
00177 void
00178 money_widget_set_position (Money_Widget *moneyWidget,
00179                         GnomeCanvasGroup *rootItem,
00180                         double x1,
00181                         double y1,
00182                         double x2,
00183                         double y2,
00184                         guint  columns,
00185                         guint  lines,
00186                         gboolean display_total)
00187 {
00188   g_return_if_fail (moneyWidget != NULL);
00189   
00190   moneyWidget->priv->rootItem = rootItem;
00191   moneyWidget->priv->x1 = x1;
00192   moneyWidget->priv->y1 = y1;
00193   moneyWidget->priv->x2 = x2;
00194   moneyWidget->priv->y2 = y2;
00195   moneyWidget->priv->columns = columns;
00196   moneyWidget->priv->lines = lines;
00197   moneyWidget->priv->next_spot = 0;
00198   moneyWidget->priv->display_total = display_total;
00199 
00200   /* Uncomment to display the limits
00201     gnome_canvas_item_new (GNOME_CANVAS_GROUP(rootItem),
00202                       gnome_canvas_rect_get_type (),
00203                       "x1", (double) x1,
00204                       "y1", (double) y1,
00205                       "x2", (double) x2,
00206                       "y2", (double) y2,
00207                       "outline_color", "red",
00208                       "width_pixels", 2,
00209                       NULL);
00210   */
00211 
00212   moneyWidget->priv->item_total =  gnome_canvas_item_new(rootItem,
00213                                                  gnome_canvas_text_get_type (),
00214                                                  "text", "",
00215                                                  "font", gc_skin_font_board_big,
00216                                                  "x", (double) x1+(x2-x1)/2,
00217                                                  "y", (double) y2 + 10,
00218                                                  "anchor", GTK_ANCHOR_CENTER,
00219                                                  "fill_color", "white",
00220                                                  NULL);
00221 
00222 }
00223 
00224 static void money_display_total(Money_Widget *moneyWidget)
00225 {
00226   gchar *tmpstr;
00227   g_return_if_fail (moneyWidget != NULL);
00228 
00229   tmpstr = g_strdup_printf("%.2f €", moneyWidget->priv->total);
00230   if(moneyWidget->priv->display_total)
00231     gnome_canvas_item_set (moneyWidget->priv->item_total,
00232                         "text", tmpstr,
00233                         NULL);
00234   g_free(tmpstr);
00235   
00236 }
00237 
00238 void
00239 money_widget_add (Money_Widget *moneyWidget, MoneyEuroType value)
00240 {
00241   GnomeCanvasItem *item   = NULL;
00242   GdkPixbuf       *pixmap = NULL;
00243   double         xratio, yratio, ratio;
00244   double         block_width, block_height;
00245   MoneyItem     *moneyitem;
00246   guint                 i, length;
00247 
00248   g_return_if_fail (moneyWidget != NULL);
00249 
00250   /* Search for an hidden item with the same value */
00251   length = g_list_length(moneyWidget->priv->moneyItemList);
00252   for(i=0; i<length; i++)
00253     {
00254       moneyitem = (MoneyItem *)g_list_nth_data(moneyWidget->priv->moneyItemList, i);
00255 
00256       if(moneyitem && !moneyitem->inPocket && moneyitem->value == value)
00257        {
00258          gnome_canvas_item_show(moneyitem->item);
00259          moneyitem->inPocket = TRUE;
00260          moneyWidget->priv->total += euroList[value].value;
00261          money_display_total(moneyWidget);
00262          return;
00263        }
00264     }
00265   
00266   /* There is no already suitable item create, create a new one */
00267 
00268   if(moneyWidget->priv->next_spot > moneyWidget->priv->columns * moneyWidget->priv->lines)
00269     g_message("More money items requested than the pocket size\n");
00270 
00271   block_width  = (moneyWidget->priv->x2 - moneyWidget->priv->x1) / moneyWidget->priv->columns;
00272   block_height = (moneyWidget->priv->y2 - moneyWidget->priv->y1) / moneyWidget->priv->lines;
00273 
00274   pixmap = gc_pixmap_load((gchar *)euroList[value].image);
00275 
00276   xratio =  block_width  / (gdk_pixbuf_get_width (pixmap) + BORDER_GAP);
00277   yratio =  block_height / (gdk_pixbuf_get_height(pixmap) + BORDER_GAP);
00278   ratio = yratio = MIN(xratio, yratio);
00279 
00280   item =  gnome_canvas_item_new ( moneyWidget->priv->rootItem,
00281                               gnome_canvas_pixbuf_get_type (),
00282                               "pixbuf", pixmap,
00283                               "x", (double) moneyWidget->priv->x1 + 
00284                               (moneyWidget->priv->next_spot % moneyWidget->priv->columns) * block_width
00285                               +  block_width/2 - (gdk_pixbuf_get_width(pixmap) * ratio)/2,
00286                               "y", (double)moneyWidget->priv->y1 +
00287                               (moneyWidget->priv->next_spot / moneyWidget->priv->columns)
00288                               * block_height
00289                               + block_height/2 - (gdk_pixbuf_get_height(pixmap) * ratio)/2,
00290                               "width",  (double) gdk_pixbuf_get_width(pixmap)  * ratio,
00291                               "height", (double) gdk_pixbuf_get_height(pixmap) * ratio,
00292                               "width_set", TRUE, 
00293                               "height_set", TRUE,
00294                               NULL);
00295 
00296   moneyitem = g_malloc(sizeof(MoneyItem));
00297   moneyitem->moneyWidget = moneyWidget;
00298   moneyitem->item   = item;
00299   moneyitem->value  = value;
00300   moneyitem->inPocket = TRUE;
00301 
00302   moneyWidget->priv->moneyItemList = g_list_append (moneyWidget->priv->moneyItemList,
00303                                               moneyitem);
00304 
00305   gtk_signal_connect(GTK_OBJECT(item), "event", (GtkSignalFunc) item_event, moneyitem);
00306 
00307   gdk_pixbuf_unref(pixmap);
00308 
00309   moneyWidget->priv->next_spot++;
00310 
00311   moneyWidget->priv->total += euroList[value].value;
00312 
00313   money_display_total(moneyWidget);
00314 }
00315 
00316 void
00317 money_widget_remove(Money_Widget *moneyWidget, MoneyEuroType value)
00318 {
00319   g_return_if_fail (moneyWidget != NULL);
00320 
00321   moneyWidget->priv->total -= euroList[value].value;
00322 
00323   money_display_total(moneyWidget);
00324 }
00325 
00326 double
00327 money_widget_get_total (Money_Widget *moneyWidget)
00328 {
00329   if(moneyWidget == NULL)
00330     return 0;
00331 
00332   return moneyWidget->priv->total;
00333 }
00334 
00335 
00336 static gint
00337 item_event(GnomeCanvasItem *item, GdkEvent *event, MoneyItem *moneyItem)
00338 {
00339 
00340   switch (event->type) 
00341     {
00342     case GDK_BUTTON_PRESS:
00343       switch(event->button.button) 
00344        {
00345        case 1:
00346          gnome_canvas_item_hide(item);
00347          moneyItem->inPocket = FALSE;
00348          money_widget_remove(moneyItem->moneyWidget, moneyItem->value);
00349          
00350          if(moneyItem->moneyWidget->priv->targetWidget != NULL)
00351            money_widget_add(moneyItem->moneyWidget->priv->targetWidget,
00352                           moneyItem->value);
00353          
00354          break;
00355        default:
00356          break;
00357        }
00358     default:
00359       break;
00360     }
00361   return FALSE;
00362 }