/* * money_widget.c * * Copyright (C) 2002, 2008 Robert Wilhelm * * 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 . * * Authors: Bruno Coudoin * */ #include #include #include "money_widget.h" /* From money.c */ void moneyactivity_process_ok(void); struct _MoneyWidgetPrivate { GooCanvasItem *rootItem; /* The canvas to display our euros in */ double x1; /* Coordinate of the widget */ double y1; double x2; double y2; guint columns; /* Number of columns */ guint lines; /* Number of lines */ guint next_spot; /* Next spot to display a money item */ float total; /* The number of euro in this pocket */ MoneyWidget *targetWidget; /* Target money widget to add when remove here */ gboolean display_total; /* Display or not the total of this pocket */ GooCanvasItem *item_total; /* Item to display the total */ GList *moneyItemList; /* List of all the items */ }; typedef struct _MoneyList MoneyList; struct _MoneyList { const gchar *image; const double value; }; // List of images to use in the game static const MoneyList euroList[] = { { "money/c1c.svgz", 0.01 }, { "money/c2c.svgz", 0.02 }, { "money/c5c.svgz", 0.05 }, { "money/c10c.svgz", 0.1 }, { "money/c20c.svgz", 0.20 }, { "money/c50c.svgz", 0.5 }, { "money/c1e.svgz", 1.0 }, { "money/c2e.svgz", 2.0 }, { "money/n5e.svgz", 5.0 }, { "money/n10e.svgz", 10.0 }, { "money/n20e.svgz", 20.0 }, { "money/n50e.svgz", 50.0 }, { NULL, -1.0 } }; typedef struct { MoneyWidget *moneyWidget; GooCanvasItem *item; MoneyEuroType value; gboolean inPocket; } MoneyItem; #define BORDER_GAP 6 /* Prototypes */ static void money_display_total(MoneyWidget *moneyWidget); static gboolean item_event (GooCanvasItem *item, GooCanvasItem *target, GdkEventButton *event, MoneyItem *moneyItem); #define MONEY_WIDGET_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_MONEY_WIDGET, MoneyWidgetPrivate)) G_DEFINE_TYPE(MoneyWidget, money_widget, G_TYPE_OBJECT); #if 0 static void finalize (GObject *object) { MoneyItem *moneyitem; MoneyWidget *moneyWidget = (MoneyWidget *) object; printf("ERROR : Finalize is NEVER CALLED\n"); /* FIXME: CLEANUP CODE UNTESTED */ while(g_list_length(moneyWidget->priv->moneyItemList)>0) { moneyitem = g_list_nth_data(moneyWidget->priv->moneyItemList, 0); moneyWidget->priv->moneyItemList = g_list_remove (moneyWidget->priv->moneyItemList, moneyitem); g_free(moneyitem); } g_free (moneyWidget->priv); moneyWidget->priv = NULL; } #endif static GObject * money_widget_constructor (GType gtype, guint n_properties, GObjectConstructParam *properties) { GObject *obj; { /* Always chain up to the parent constructor */ obj = G_OBJECT_CLASS (money_widget_parent_class)->constructor (gtype, n_properties, properties); } /* update the object state depending on constructor properties */ return obj; } static void money_widget_class_init (MoneyWidgetClass *klass) { g_type_class_add_private (klass, sizeof (MoneyWidgetPrivate)); GObjectClass *gobject_class = G_OBJECT_CLASS (klass); gobject_class->constructor = money_widget_constructor; } static void money_widget_init (MoneyWidget *self) { MoneyWidgetPrivate *priv; self->priv = priv = MONEY_WIDGET_GET_PRIVATE (self); priv->total = 0; } GObject * money_widget_new () { return G_OBJECT (g_object_new (money_widget_get_type (), NULL)); } MoneyWidget * money_widget_copy (MoneyWidget *pos) { MoneyWidget *cpPos; cpPos = MONEY_WIDGET (money_widget_new ()); memcpy (cpPos->priv, pos->priv, sizeof (MoneyWidgetPrivate)); return cpPos; } void money_widget_set_target (MoneyWidget *moneyWidget, MoneyWidget *targetWidget) { moneyWidget->priv->targetWidget = targetWidget; } void money_widget_set_position (MoneyWidget *moneyWidget, GooCanvasItem *rootItem, double x1, double y1, double x2, double y2, guint columns, guint lines, gboolean display_total) { g_return_if_fail (moneyWidget != NULL); moneyWidget->priv->rootItem = rootItem; moneyWidget->priv->x1 = x1; moneyWidget->priv->y1 = y1; moneyWidget->priv->x2 = x2; moneyWidget->priv->y2 = y2; moneyWidget->priv->columns = columns; moneyWidget->priv->lines = lines; moneyWidget->priv->next_spot = 0; moneyWidget->priv->display_total = display_total; /* Uncomment to display the limits goo_canvas_item_new (GOO_CANVAS_GROUP(rootItem), goo_canvas_rect_get_type (), "x1", (double) x1, "y1", (double) y1, "x2", (double) x2, "y2", (double) y2, "stroke-color", "red", "width_pixels", 2, NULL); */ moneyWidget->priv->item_total = \ goo_canvas_text_new(rootItem, "", x1+(x2-x1)/2, y2 + 10, -1, GTK_ANCHOR_CENTER, "font", gc_skin_font_board_big, "fill-color", "white", NULL); } static void money_display_total(MoneyWidget *moneyWidget) { gchar *tmpstr; g_return_if_fail (moneyWidget != NULL); tmpstr = g_strdup_printf("%.2f", moneyWidget->priv->total); if(moneyWidget->priv->display_total) g_object_set (moneyWidget->priv->item_total, "text", tmpstr, NULL); g_free(tmpstr); } void money_widget_add (MoneyWidget *moneyWidget, MoneyEuroType value) { GooCanvasItem *item; RsvgHandle *svg_handle; RsvgDimensionData dimension; double xratio, yratio, ratio; double block_width, block_height; MoneyItem *moneyitem; guint i, length; g_return_if_fail (moneyWidget != NULL); /* Search for an hidden item with the same value */ length = g_list_length(moneyWidget->priv->moneyItemList); for(i=0; ipriv->moneyItemList, i); if(moneyitem && !moneyitem->inPocket && moneyitem->value == value) { g_object_set (moneyitem->item, "visibility", GOO_CANVAS_ITEM_VISIBLE, NULL); moneyitem->inPocket = TRUE; moneyWidget->priv->total += euroList[value].value; money_display_total(moneyWidget); return; } } /* There is no already suitable item create, create a new one */ if(moneyWidget->priv->next_spot > moneyWidget->priv->columns * moneyWidget->priv->lines) g_message("More money items requested than the pocket size\n"); block_width = \ (moneyWidget->priv->x2 - moneyWidget->priv->x1) / moneyWidget->priv->columns; block_height = \ (moneyWidget->priv->y2 - moneyWidget->priv->y1) / moneyWidget->priv->lines; svg_handle = gc_rsvg_load(euroList[value].image); rsvg_handle_get_dimensions(svg_handle, &dimension); xratio = block_width / (dimension.width + BORDER_GAP); yratio = block_height / (dimension.height + BORDER_GAP); ratio = yratio = MIN(xratio, yratio); item = goo_canvas_svg_new(moneyWidget->priv->rootItem, svg_handle, NULL); goo_canvas_item_translate(item, moneyWidget->priv->x1 + (moneyWidget->priv->next_spot % moneyWidget->priv->columns) * block_width + block_width/2 - (dimension.width * ratio)/2, moneyWidget->priv->y1 + (moneyWidget->priv->next_spot / moneyWidget->priv->columns) * (block_height + BORDER_GAP) + block_height/2 - (dimension.height * ratio)/2); goo_canvas_item_scale(item, ratio, ratio); moneyitem = g_malloc(sizeof(MoneyItem)); moneyitem->moneyWidget = moneyWidget; moneyitem->item = item; moneyitem->value = value; moneyitem->inPocket = TRUE; moneyWidget->priv->moneyItemList = \ g_list_append (moneyWidget->priv->moneyItemList, moneyitem); g_signal_connect(item, "button_press_event", (GCallback) item_event, moneyitem); g_object_unref(svg_handle); moneyWidget->priv->next_spot++; moneyWidget->priv->total += euroList[value].value; money_display_total(moneyWidget); } void money_widget_remove(MoneyWidget *moneyWidget, MoneyEuroType value) { g_return_if_fail (moneyWidget != NULL); moneyWidget->priv->total -= euroList[value].value; money_display_total(moneyWidget); } float money_widget_get_total (MoneyWidget *moneyWidget) { if(moneyWidget == NULL) return 0; return moneyWidget->priv->total; } static gboolean item_event (GooCanvasItem *item, GooCanvasItem *target, GdkEventButton *event, MoneyItem *moneyItem) { switch (event->type) { case GDK_BUTTON_PRESS: switch(event->button) { case 1: g_object_set (item, "visibility", GOO_CANVAS_ITEM_INVISIBLE, NULL); moneyItem->inPocket = FALSE; money_widget_remove(moneyItem->moneyWidget, moneyItem->value); if(moneyItem->moneyWidget->priv->targetWidget != NULL) money_widget_add(moneyItem->moneyWidget->priv->targetWidget, moneyItem->value); break; default: break; } default: break; } return FALSE; }