116
/*************************************************************
117
* colorshift a pixbuf
118
* code taken from the gnome-panel of gnome-core
157
/** load an svg image from the filesystem
159
* \param format: If format contains $LOCALE, it will be first replaced by the current long locale
160
* and if not found the short locale name. It support printf formating.
161
* \param ...: additional params for the format (printf like)
163
* \return a new allocated pixbuf or NULL
165
RsvgHandle *gc_rsvg_load(const gchar *format, ...)
169
gchar *rsvghandlefile;
170
RsvgHandle *rsvghandle = NULL;
171
GError *error = NULL;
176
va_start (args, format);
177
rsvghandlefile = g_strdup_vprintf (format, args);
181
filename = gc_file_find_absolute(rsvghandlefile);
184
rsvghandle = rsvg_handle_new_from_file (filename, &error);
186
if (!filename || !rsvghandle)
191
g_warning("Loading image '%s' returned a null pointer", rsvghandlefile);
193
g_warning ("Couldn't find file %s !", rsvghandlefile);
195
str = g_strdup_printf("%s\n%s\n%s\n%s",
196
_("Couldn't find or load the file"),
198
_("This activity is incomplete."),
199
_("Exit it and report\nthe problem to the authors."));
200
gc_dialog (str, NULL);
201
g_free(rsvghandlefile);
204
/* Create an empty rsvghandle because activities does not manage loading error */
205
return rsvg_handle_new();
208
g_free(rsvghandlefile);
215
* Set the focus of the given item (highlight or not)
121
do_colorshift (GdkPixbuf *dest, GdkPixbuf *src, int shift)
124
gint width, height, has_alpha, srcrowstride, destrowstride;
125
guchar *target_pixels;
126
guchar *original_pixels;
132
has_alpha = gdk_pixbuf_get_has_alpha (src);
133
width = gdk_pixbuf_get_width (src);
134
height = gdk_pixbuf_get_height (src);
135
srcrowstride = gdk_pixbuf_get_rowstride (src);
136
destrowstride = gdk_pixbuf_get_rowstride (dest);
137
target_pixels = gdk_pixbuf_get_pixels (dest);
138
original_pixels = gdk_pixbuf_get_pixels (src);
140
for (i = 0; i < height; i++) {
141
pixdest = target_pixels + i*destrowstride;
142
pixsrc = original_pixels + i*srcrowstride;
143
for (j = 0; j < width; j++) {
148
*(pixdest++) = CLAMP(val, 0, 255);
150
*(pixdest++) = CLAMP(val, 0, 255);
152
*(pixdest++) = CLAMP(val, 0, 255);
154
*(pixdest++) = *(pixsrc++);
162
make_hc_pixbuf(GdkPixbuf *pb, gint val)
168
new = gdk_pixbuf_new(gdk_pixbuf_get_colorspace(pb),
169
gdk_pixbuf_get_has_alpha(pb),
170
gdk_pixbuf_get_bits_per_sample(pb),
171
gdk_pixbuf_get_width(pb),
172
gdk_pixbuf_get_height(pb));
173
do_colorshift(new, pb, val);
174
/*do_saturate_darken (new, pb, (int)(1.00*255), (int)(1.15*255));*/
180
* Free the highlight image from our image_focus system
182
* It must be called before assigning a new image to an item that
183
* already has a focus enabled with gc_item_focus_event().
186
gc_item_focus_free(GnomeCanvasItem *item, void *none)
190
pixbuf = (GdkPixbuf *)g_object_get_data (G_OBJECT (item), "pixbuf_ref");
193
g_object_set_data (G_OBJECT (item), "pixbuf_ref", NULL);
194
gdk_pixbuf_unref(pixbuf);
199
* Set the focus of the given image (highlight or not)
202
void gc_item_focus_set(GnomeCanvasItem *item, gboolean focus)
204
GdkPixbuf *dest = NULL;
206
GdkPixbuf *pixbuf_ref;
208
gtk_object_get (GTK_OBJECT (item), "pixbuf", &pixbuf, NULL);
209
g_return_if_fail (pixbuf != NULL);
210
gdk_pixbuf_unref(pixbuf);
212
/* Store the first pixbuf */
213
pixbuf_ref = (GdkPixbuf *)g_object_get_data (G_OBJECT (item), "pixbuf_ref");
216
g_object_set_data (G_OBJECT (item), "pixbuf_ref", pixbuf);
218
gdk_pixbuf_ref(pixbuf);
219
g_signal_connect (item, "destroy",
220
G_CALLBACK (gc_item_focus_free),
219
gc_item_focus_set(GooCanvasItem *item, gboolean focus)
221
GooCanvasItem *highlight_item;
223
highlight_item = g_object_get_data (G_OBJECT(item),
225
g_assert(highlight_item);
229
dest = make_hc_pixbuf(pixbuf, 30);
230
gnome_canvas_item_set (item,
230
g_object_set (highlight_item,
231
"visibility", GOO_CANVAS_ITEM_VISIBLE,
236
gnome_canvas_item_set (item,
237
"pixbuf", pixbuf_ref,
235
g_object_set (highlight_item,
236
"visibility", GOO_CANVAS_ITEM_INVISIBLE,
245
gdk_pixbuf_unref (dest);
274
* Init an item so that it has a focus
275
* Optionnaly, provide a target_item that will be focused
276
* by events on source_item.
278
* Warning: You must call it each time the size of the focused
283
void gc_item_focus_init(GooCanvasItem *source_item,
284
GooCanvasItem *target_item)
286
GooCanvasItem *highlight_item;
287
GooCanvasBounds bounds;
288
gboolean already_created = FALSE;
291
target_item = source_item;
293
goo_canvas_item_get_bounds(target_item, &bounds);
294
goo_canvas_convert_to_item_space(goo_canvas_item_get_canvas(target_item),
295
goo_canvas_item_get_parent(target_item),
296
&bounds.x1, &bounds.y1);
297
goo_canvas_convert_to_item_space(goo_canvas_item_get_canvas(target_item),
298
goo_canvas_item_get_parent(target_item),
299
&bounds.x2, &bounds.y2);
300
highlight_item = g_object_get_data (G_OBJECT(target_item),
305
already_created = TRUE;
306
goo_canvas_item_remove(highlight_item);
309
/* Create the highlight_item */
311
goo_canvas_rect_new (goo_canvas_item_get_parent(target_item),
314
bounds.x2 - bounds.x1 + GAP*2,
315
bounds.y2 - bounds.y1 + GAP*2,
316
"stroke_color_rgba", 0xFFFFFFFFL,
317
"fill_color_rgba", 0xFF000090L,
318
"line-width", (double) 2,
319
"radius-x", (double) 10,
320
"radius-y", (double) 10,
323
g_object_set_data (G_OBJECT(target_item), "highlight_item",
325
goo_canvas_item_lower(highlight_item, target_item);
326
g_object_set (highlight_item,
327
"visibility", GOO_CANVAS_ITEM_INVISIBLE,
330
/* Avoid double connection */
331
g_signal_handlers_disconnect_by_func(source_item,
332
(GtkSignalFunc) gc_item_focus_event,
335
/* connect source to target */
336
g_signal_connect(source_item, "enter_notify_event",
337
(GtkSignalFunc) gc_item_focus_event,
339
g_signal_connect(source_item, "leave_notify_event",
340
(GtkSignalFunc) gc_item_focus_event,
345
* gc_item_focus_remove
347
* Remove a previously set of item focus
349
* @param[in] source_item is the same as the one passed to
350
* gc_item_focus_init()
351
* @param[in] target_itemis the same as the one passed to
352
* gc_item_focus_init()
354
void gc_item_focus_remove(GooCanvasItem *source_item,
355
GooCanvasItem *target_item)
357
GooCanvasItem *highlight_item;
360
target_item = source_item;
362
g_signal_handlers_disconnect_by_func(source_item,
363
(GtkSignalFunc) gc_item_focus_event,
366
highlight_item = g_object_get_data (G_OBJECT(target_item),
370
goo_canvas_item_remove(highlight_item);
372
g_object_set_data (G_OBJECT(target_item), "highlight_item",
278
377
* Return a new copy of the given string in which it has
279
378
* changes '\''n' to '\n'.
305
404
/* ======================================= */
306
void gc_item_absolute_move(GnomeCanvasItem *item, int x, int y) {
307
double dx1, dy1, dx2, dy2;
308
gnome_canvas_item_get_bounds(item, &dx1, &dy1, &dx2, &dy2);
309
gnome_canvas_item_move(item, ((double)x)-dx1, ((double)y)-dy1);
405
/* Any previous transformation are reseted first. */
406
void gc_item_absolute_move(GooCanvasItem *item, int x, int y)
408
GooCanvasBounds bounds;
410
goo_canvas_item_set_transform(item, NULL);
411
goo_canvas_item_get_bounds(item, &bounds);
412
goo_canvas_item_translate(item, ((double)x)-bounds.x1, ((double)y)-bounds.y1);
312
415
/* ======================================= */
313
416
/** As gnome does not implement its own API : gc_item_rotate
314
we have to do it ourselves ....
315
IMPORTANT NOTE : This is designed for an item with "anchor" = GTK_ANCHOR_CENTER
316
rotation is clockwise if angle > 0
417
we have to do it ourselves ....
418
rotation is clockwise if angle > 0
319
gc_item_rotate(GnomeCanvasItem *item, double angle) {
320
double r[6],t[6], x1, x2, y1, y2;
322
gnome_canvas_item_get_bounds( item, &x1, &y1, &x2, &y2 );
323
art_affine_translate( t , -(x2+x1)/2, -(y2+y1)/2 );
324
art_affine_rotate( r, angle );
325
art_affine_multiply( r, t, r);
326
art_affine_translate( t , (x2+x1)/2, (y2+y1)/2 );
327
art_affine_multiply( r, r, t);
329
gnome_canvas_item_affine_absolute(item, r );
421
gc_item_rotate(GooCanvasItem *item, double angle) {
422
GooCanvasBounds bounds;
423
goo_canvas_item_get_bounds (item, &bounds);
424
goo_canvas_item_rotate(item, angle,
425
bounds.x1+(bounds.x2-bounds.x1)/2,
426
bounds.y1+(bounds.y2-bounds.y1)/2);
332
429
/* As gnome does not implement its own API : gc_item_rotate_relative
333
430
we have to do it ourselves ....
334
431
IMPORTANT NOTE : This is designed for an item with "anchor" = GTK_ANCHOR_CENTER
335
432
rotation is clockwise if angle > 0
338
gc_item_rotate_relative(GnomeCanvasItem *item, double angle) {
435
gc_item_rotate_relative(GooCanvasItem *item, double angle)
339
437
double x1, x2, y1, y2;
340
438
double tx1, tx2, ty1, ty2;
345
// gnome_canvas_item_get_bounds( item, &x1, &y1, &x2, &y2 );
346
/* WARNING: Do not use gnome_canvas_item_get_bounds which gives unpredictable results */
347
if(GNOME_IS_CANVAS_LINE(item)) {
348
GnomeCanvasPoints *points;
349
gtk_object_get (GTK_OBJECT (item), "points", &points, NULL);
441
// goo_canvas_item_get_bounds( item, &x1, &y1, &x2, &y2 );
442
/* WARNING: Do not use goo_canvas_item_get_bounds which gives unpredictable results */
443
if(GOO_IS_CANVAS_POLYLINE(item)) {
444
GooCanvasPoints *points;
445
g_object_get (item, "points", &points, NULL);
350
446
x1 = points->coords[0];
351
447
y1 = points->coords[1];
352
448
x2 = points->coords[2];
353
449
y2 = points->coords[3];
354
} else if(GNOME_IS_CANVAS_PIXBUF(item)){
355
gtk_object_get (GTK_OBJECT (item), "x", &x1, NULL);
356
gtk_object_get (GTK_OBJECT (item), "y", &y1, NULL);
357
gtk_object_get (GTK_OBJECT (item), "width", &x2, NULL);
358
gtk_object_get (GTK_OBJECT (item), "height", &y2, NULL);
450
} else if(GOO_IS_CANVAS_IMAGE(item)
451
|| GOO_IS_CANVAS_RECT(item)) {
452
g_object_get (item, "x", &x1, NULL);
453
g_object_get (item, "y", &y1, NULL);
454
g_object_get (item, "width", &x2, NULL);
455
g_object_get (item, "height", &y2, NULL);
361
} else if(GNOME_IS_CANVAS_GROUP(item)){
362
gtk_object_get (GTK_OBJECT (item), "x", &x1, NULL);
363
gtk_object_get (GTK_OBJECT (item), "y", &y1, NULL);
458
} else if(GOO_IS_CANVAS_GROUP(item)){
459
g_object_get (item, "x", &x1, NULL);
460
g_object_get (item, "y", &y1, NULL);
367
gtk_object_get (GTK_OBJECT (item), "x1", &x1, NULL);
368
gtk_object_get (GTK_OBJECT (item), "y1", &y1, NULL);
369
gtk_object_get (GTK_OBJECT (item), "x2", &x2, NULL);
370
gtk_object_get (GTK_OBJECT (item), "y2", &y2, NULL);
387
/* Taken from anim by Yves Combe
388
* This matrix rotate around ( cx, cy )
389
* This is the result of the product:
392
* 1 0 cx cos(t) -sin(t) 0 1 0 -cx
393
* 0 1 cy by sin(t) cos(t) 0 by 0 1 -cy
397
t = M_PI*angle/180.0;
403
r[4] = (1-cos(t))*cx + sin(t)*cy;
404
r[5] = -sin(t)*cx + (1 - cos(t))*cy;
406
gnome_canvas_item_affine_relative(item, r );
481
goo_canvas_item_rotate(item, angle,
409
487
/** rotates an item around the center (x,y), relative to the widget's coordinates
488
* Any previous transformation are reseted first.
412
gc_item_rotate_with_center(GnomeCanvasItem *item, double angle, int x, int y) {
413
double r[6],t[6], x1, x2, y1, y2, tx, ty;
415
gnome_canvas_item_get_bounds( item, &x1, &y1, &x2, &y2 );
418
art_affine_translate( t , -tx, -ty );
419
art_affine_rotate( r, angle );
420
art_affine_multiply( r, t, r);
421
art_affine_translate( t , tx, ty );
422
art_affine_multiply( r, r, t);
424
gnome_canvas_item_affine_absolute(item, r );
491
gc_item_rotate_with_center(GooCanvasItem *item, double angle, int x, int y)
493
GooCanvasBounds bounds;
495
goo_canvas_item_set_transform(item, NULL);
496
goo_canvas_item_get_bounds( item, &bounds );
497
goo_canvas_item_rotate(item, angle, bounds.x1+x, bounds.y1+y);
427
500
/** rotates an item around the center (x,y), relative to the widget's coordinates
428
501
* The rotation is relative to the previous rotation
431
gc_item_rotate_relative_with_center(GnomeCanvasItem *item, double angle, int x, int y) {
432
double r[6],t[6], x1, x2, y1, y2, tx, ty;
434
gnome_canvas_item_get_bounds( item, &x1, &y1, &x2, &y2 );
437
art_affine_translate( t , -tx, -ty );
438
art_affine_rotate( r, angle );
439
art_affine_multiply( r, t, r);
440
art_affine_translate( t , tx, ty );
441
art_affine_multiply( r, r, t);
443
gnome_canvas_item_affine_relative(item, r );
447
* Display the number of stars representing the difficulty level at the x,y location
448
* The stars are created in a group 'parent'
449
* The new group in which the stars are created is returned.
450
* This is only usefull for the menu plugin and the configuration dialog box.
452
GnomeCanvasGroup *gc_difficulty_display(GnomeCanvasGroup *parent,
504
gc_item_rotate_relative_with_center(GooCanvasItem *item, double angle, int x, int y)
457
GdkPixbuf *pixmap = NULL;
458
GnomeCanvasGroup *stars_group = NULL;
459
GnomeCanvasPixbuf *item = NULL;
460
gchar *filename = NULL;
462
if(difficulty==0 || difficulty>6)
465
filename = g_strdup_printf("difficulty_star%d.png", difficulty);
466
pixmap = gc_skin_pixmap_load(filename);
472
stars_group = GNOME_CANVAS_GROUP(
473
gnome_canvas_item_new (parent,
474
gnome_canvas_group_get_type (),
479
item = GNOME_CANVAS_PIXBUF(gnome_canvas_item_new (stars_group,
480
gnome_canvas_pixbuf_get_type (),
484
"width", (double) gdk_pixbuf_get_width(pixmap) * ratio,
485
"height", (double) gdk_pixbuf_get_height(pixmap) * ratio,
490
gtk_signal_connect(GTK_OBJECT(item), "event",
491
(GtkSignalFunc) gc_item_focus_event,
494
gdk_pixbuf_unref(pixmap);
506
double x1, x2, y1, y2;
508
if(GOO_IS_CANVAS_POLYLINE(item)) {
509
GooCanvasPoints *points;
510
g_object_get (item, "points", &points, NULL);
511
x1 = points->coords[0];
512
y1 = points->coords[1];
513
x2 = points->coords[2];
514
y2 = points->coords[3];
515
} else if(GOO_IS_CANVAS_IMAGE(item) || GOO_IS_CANVAS_RECT(item)) {
516
g_object_get (item, "x", &x1, NULL);
517
g_object_get (item, "y", &y1, NULL);
518
g_object_get (item, "width", &x2, NULL);
519
g_object_get (item, "height", &y2, NULL);
520
x2 += x1 + (x2 - x1);
521
y2 += y1 + (y2 - y1);
522
} else if(GOO_IS_CANVAS_GROUP(item)){
523
g_object_get (item, "x", &x1, NULL);
524
g_object_get (item, "y", &y1, NULL);
528
g_object_get (item, "x1", &x1, NULL);
529
g_object_get (item, "y1", &y1, NULL);
530
g_object_get (item, "x2", &x2, NULL);
531
g_object_get (item, "y2", &y2, NULL);
534
goo_canvas_item_rotate(item, angle, x1+x, y1+y);
499
537
gchar *g_utf8_strndup(gchar* utf8text, gint n)
503
gint len = g_utf8_strlen(utf8text, -1);
505
if( n < len && n > 0 )
508
result = g_strndup(utf8text, g_utf8_offset_to_pointer(utf8text, len) - utf8text);
541
gint len = g_utf8_strlen(utf8text, -1);
543
if( n < len && n > 0 )
546
result = g_strndup(utf8text, g_utf8_offset_to_pointer(utf8text, len) - utf8text);
513
551
/** \brief search a given relative file in all gcompris dir it could be found
701
718
gc_sound_play_ogg(str, NULL);
722
/** Display a button with the given text
724
* \param x the x coordinate of the button
725
* \param y the y coordinate of the button
726
* \param button_file the image file to use as the button
727
* \param text is the text to display in the button
728
* \param process is the callback function
729
* \param data is the user data passed to the callback function
734
gc_util_button_text(GooCanvasItem *rootitem,
738
GtkSignalFunc process,
743
GooCanvasItem *item_text;
746
pixmap = gc_skin_pixmap_load(button_file);
747
item = goo_canvas_image_new (rootitem,
752
g_signal_connect(item,
753
"button_press_event",
754
(GtkSignalFunc) process, data);
755
gc_item_focus_init(item, NULL);
759
goo_canvas_text_new (rootitem,
761
x + (double)gdk_pixbuf_get_width(pixmap)/2,
765
"font", gc_skin_font_board_small,
766
"fill_color_rgba", gc_skin_color_text_button,
768
g_signal_connect(item_text,
769
"button_press_event",
771
gc_item_focus_init(item_text, item);
772
gdk_pixbuf_unref(pixmap);
775
/** Display a button with the given text (BY SKIN'S SVG ID)
777
* \param x the x coordinate of the button
778
* \param y the y coordinate of the button
779
* \param button_file the image file to use as the button
780
* \param text is the text to display in the button
781
* \param process is the callback function
782
* \param data is the user data passed to the callback function
787
gc_util_button_text_svg(GooCanvasItem *rootitem,
791
GtkSignalFunc process,
795
GooCanvasItem *item_text;
798
item = goo_canvas_svg_new (rootitem,
803
SET_ITEM_LOCATION_CENTER(item, x, y);
805
g_signal_connect(item,
806
"button_press_event",
807
(GtkSignalFunc) process, data);
808
gc_item_focus_init(item, NULL);
812
goo_canvas_text_new (rootitem,
818
"font", gc_skin_font_board_small,
819
"fill_color_rgba", gc_skin_color_text_button,
821
g_signal_connect(item_text,
822
"button_press_event",
824
gc_item_focus_init(item_text, item);