3
* Time-stamp: <2001/08/20 00:54:45 bruno>
5
* Copyright (C) 2000 Bruno Coudoin
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
#include <libxml/tree.h>
24
#include <libxml/parser.h>
28
#include "gcompris/gcompris.h"
30
#define SOUNDLISTFILE PACKAGE
32
/* Represent the drawing area */
33
static gint drawing_area_x1 = 0;
34
static gint drawing_area_y1 = 0;
35
static gint drawing_area_x2 = 0;
36
static gint drawing_area_y2 = 0;
38
/* Set the grid size. If 0 then no grid */
39
static gint grid_step = 0;
40
static GnomeCanvasItem *gridItem = NULL;
41
static GnomeCanvasItem *grid_root_item = NULL;
42
#define DEFAULT_GRID_STEP 20
44
static GcomprisBoard *gcomprisBoard = NULL;
45
static GnomeCanvasItem *shape_root_item = NULL;
46
static GnomeCanvasItem *draw_root_item = NULL;
47
static GnomeCanvasItem *current_color_item = NULL;
48
static gchar *currentColor = NULL;
55
TOOL_FILLED_CIRCLE = 3,
64
#define NUMBER_Of_TOOL TOOL_GRID + 1
66
static ToolList currentTool = TOOL_RECT;
67
static GnomeCanvasItem *currentToolItem = NULL;
69
// Used to cross reference pixmap for the tools
70
static char *tool_pixmap_name[] =
72
"draw/tool-rectangle.png", "draw/tool-rectangle_on.png",
73
"draw/tool-filledrectangle.png", "draw/tool-filledrectangle_on.png",
74
"draw/tool-circle.png", "draw/tool-circle_on.png",
75
"draw/tool-filledcircle.png", "draw/tool-filledcircle_on.png",
76
"draw/tool-line.png", "draw/tool-line_on.png",
77
"draw/tool-point.png", "draw/tool-point_on.png",
78
"draw/tool-del.png", "draw/tool-del_on.png",
79
"draw/tool-fill.png", "draw/tool-fill_on.png",
80
"draw/tool-select.png", "draw/tool-select_on.png",
81
"draw/tool-grid.png", "draw/tool-grid_on.png"
96
* Contains the points that represents the anchors
99
GnomeCanvasItem *rootitem;
101
GnomeCanvasItem *item;
128
#define ANCHOR_COLOR 0x36ede400
129
#define DEFAULT_ITEM_SIZE 40
130
#define DEFAULT_ANCHOR_SIZE 8
131
static AnchorsItem *selected_anchors_item = NULL;
133
#define DRAW_WIDTH_PIXELS 6
135
#define GRID_COLOR 0x267da400
137
static gchar *colorlist [] =
151
static void start_board (GcomprisBoard *agcomprisBoard);
152
static void pause_board (gboolean pause);
153
static void end_board (void);
154
static gboolean is_our_board (GcomprisBoard *gcomprisBoard);
155
static void config(void);
157
static void draw_destroy_all_items(void);
158
static void draw_next_level(void);
159
static void display_color_selector(GnomeCanvasGroup *parent);
160
static void display_tool_selector(GnomeCanvasGroup *parent);
161
static void display_drawing_area(GnomeCanvasGroup *parent);
162
static void display_grid(gboolean status);
163
static gint color_event(GnomeCanvasItem *item, GdkEvent *event, gchar *color);
164
static gint tool_event(GnomeCanvasItem *item, GdkEvent *event, gint tool);
165
static gint item_event(GnomeCanvasItem *item, GdkEvent *event, void *shape);
166
static gint item_event_resize(GnomeCanvasItem *item, GdkEvent *event, AnchorsItem *anchorsItem);
167
static gint item_event_move(GnomeCanvasItem *item, GdkEvent *event, AnchorsItem *anchorsItem);
168
static void highlight_color_item(GnomeCanvasItem *item);
169
static guint get_tool_cursor(ToolList tool);
170
static guint get_resize_cursor(AnchorType anchor);
171
static void realign_to_grid(GnomeCanvasItem *item);
172
static void snap_to_grid(double *x, double *y);
174
/* Description of this plugin */
175
BoardPlugin menu_bp =
179
N_("A simple vector drawing tool"),
180
N_("Creative board where you can freely draw"),
181
"Bruno Coudoin <bruno.coudoin@free.fr>",
198
* Main entry point mandatory for each Gcompris's game
199
* ---------------------------------------------------
204
*get_bplugin_info(void)
210
* in : boolean TRUE = PAUSE : FALSE = CONTINUE
213
static void pause_board (gboolean pause)
220
static void start_board (GcomprisBoard *agcomprisBoard)
223
if(agcomprisBoard!=NULL)
225
gcomprisBoard=agcomprisBoard;
227
gcompris_set_background(gnome_canvas_root(gcomprisBoard->canvas), "draw/draw-bg.jpg");
230
/* set initial values for this level */
231
gcomprisBoard->level = 1;
232
gcomprisBoard->maxlevel=1;
235
gcomprisBoard->number_of_sublevel=0;
236
gcomprisBoard->sublevel = 0;
238
drawing_area_x1 = 124;
239
drawing_area_y1 = 20;
240
drawing_area_x2 = gcomprisBoard->width - 19;
241
drawing_area_y2 = gcomprisBoard->height - 76;
247
/* Special Init for this board */
248
selected_anchors_item = NULL;
260
if(gcomprisBoard!=NULL)
262
gcompris_set_cursor(GCOMPRIS_DEFAULT_CURSOR);
264
draw_destroy_all_items();
265
gcomprisBoard->level = 1; // Restart this game to zero
267
gcomprisBoard = NULL;
272
is_our_board (GcomprisBoard *gcomprisBoard)
276
if(g_strcasecmp(gcomprisBoard->type, "draw")==0)
278
/* Set the plugin entry */
279
gcomprisBoard->plugin=&menu_bp;
290
if(gcomprisBoard!=NULL)
296
/*-------------------------------------------------------------------------------*/
297
/*-------------------------------------------------------------------------------*/
298
/*-------------------------------------------------------------------------------*/
299
/*-------------------------------------------------------------------------------*/
301
/* set initial values for the next level */
302
static void draw_next_level()
305
gcompris_bar_set_level(gcomprisBoard);
307
draw_destroy_all_items();
310
gnome_canvas_item_new (gnome_canvas_root(gcomprisBoard->canvas),
311
gnome_canvas_group_get_type (),
316
display_color_selector(GNOME_CANVAS_GROUP(shape_root_item));
317
display_tool_selector(GNOME_CANVAS_GROUP(shape_root_item));
318
display_drawing_area(GNOME_CANVAS_GROUP(shape_root_item));
324
static void display_drawing_area(GnomeCanvasGroup *parent)
326
draw_root_item = gnome_canvas_item_new (parent,
327
gnome_canvas_rect_get_type (),
328
"x1", (double) drawing_area_x1,
329
"y1", (double) drawing_area_y1,
330
"x2", (double) drawing_area_x2,
331
"y2", (double) drawing_area_y2,
332
"fill_color", "white",
334
gtk_signal_connect(GTK_OBJECT(draw_root_item), "event",
335
(GtkSignalFunc) item_event,
340
static void display_color_selector(GnomeCanvasGroup *parent)
343
GnomeCanvasItem *item = NULL;
349
pixmap = gcompris_load_pixmap("draw/color-selector.jpg");
352
x = (drawing_area_x2 - drawing_area_x1
353
- gdk_pixbuf_get_width(pixmap))/2
356
y = gcomprisBoard->height - gdk_pixbuf_get_height(pixmap) - 5;
358
item = gnome_canvas_item_new (parent,
359
gnome_canvas_pixbuf_get_type (),
364
gdk_pixbuf_unref(pixmap);
367
for(x1=x+26; x1<(x+26)+55*10; x1+=55)
369
item = gnome_canvas_item_new (parent,
370
gnome_canvas_rect_get_type (),
372
"y1", (double) y + 8,
373
"x2", (double) x1 + 50,
374
"y2", (double) y + gdk_pixbuf_get_height(pixmap) - 8,
375
"fill_color", colorlist[c],
378
gtk_signal_connect(GTK_OBJECT(item), "event",
379
(GtkSignalFunc) color_event,
383
highlight_color_item(item);
388
currentColor = colorlist[0];
391
#define SELECTOR_VERTICAL_SPACING 60
393
static void display_tool_selector(GnomeCanvasGroup *parent)
396
GnomeCanvasItem *item = NULL;
402
pixmap = gcompris_load_pixmap("draw/tool-selector.jpg");
406
y = (drawing_area_y2 - drawing_area_y1 - gdk_pixbuf_get_height(pixmap)) / 2
408
item = gnome_canvas_item_new (parent,
409
gnome_canvas_pixbuf_get_type (),
414
gdk_pixbuf_unref(pixmap);
420
pixmap = gcompris_load_pixmap(tool_pixmap_name[0 + PIXMAP_ON]);
423
item = gnome_canvas_item_new (parent,
424
gnome_canvas_pixbuf_get_type (),
429
gdk_pixbuf_unref(pixmap);
431
gtk_signal_connect(GTK_OBJECT(item), "event",
432
(GtkSignalFunc) tool_event,
436
currentTool = TOOL_RECT;
437
currentToolItem = item;
439
for( toolIndex = 1 ; toolIndex < NUMBER_Of_TOOL ; toolIndex++)
441
y += (toolIndex%2 == 0 ? SELECTOR_VERTICAL_SPACING : 0);
442
pixmap = gcompris_load_pixmap(tool_pixmap_name[(2*toolIndex) + PIXMAP_OFF]);
446
item = gnome_canvas_item_new (parent,
447
gnome_canvas_pixbuf_get_type (),
449
"x", (double) (toolIndex%2 == 0 ? x : x2),
452
gdk_pixbuf_unref(pixmap);
454
if(toolIndex == TOOL_GRID)
457
gtk_signal_connect(GTK_OBJECT(item), "event",
458
(GtkSignalFunc) tool_event,
465
* Request the display of the grid if status is true
468
static void display_grid(gboolean status)
471
GdkPixbuf *pixmap = NULL;
473
pixmap = gcompris_load_pixmap(tool_pixmap_name[(TOOL_GRID*2) +
474
(status == TRUE ? PIXMAP_ON : PIXMAP_OFF)]);
477
gnome_canvas_item_set (gridItem,
480
gdk_pixbuf_unref(pixmap);
487
if(grid_root_item!=NULL)
488
gnome_canvas_item_hide(grid_root_item);
492
grid_step = DEFAULT_GRID_STEP;
494
if(grid_root_item!=NULL)
496
gnome_canvas_item_show(grid_root_item);
500
/* Creation of the grid */
503
gnome_canvas_item_new (GNOME_CANVAS_GROUP(shape_root_item),
504
gnome_canvas_group_get_type (),
508
gnome_canvas_item_raise_to_top(grid_root_item);
509
// gnome_canvas_item_raise(grid_root_item, 50);
511
for( x = drawing_area_x1 ; x < drawing_area_x2 ; x += grid_step)
513
GnomeCanvasPoints *points;
514
GnomeCanvasItem *item;
516
points = gnome_canvas_points_new(2);
517
points->coords[0] = (double) x;
518
points->coords[1] = (double) drawing_area_y1;
519
points->coords[2] = (double) x;
520
points->coords[3] = (double) drawing_area_y2;
522
item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(grid_root_item),
523
gnome_canvas_line_get_type (),
525
"fill_color_rgba", GRID_COLOR,
529
gtk_signal_connect(GTK_OBJECT(item), "event",
530
(GtkSignalFunc) item_event,
533
gnome_canvas_points_unref(points);
538
for( y = drawing_area_y1 ; y < drawing_area_y2 ; y += grid_step)
540
GnomeCanvasPoints *points;
541
GnomeCanvasItem *item;
543
points = gnome_canvas_points_new(2);
544
points->coords[0] = (double) drawing_area_x1;
545
points->coords[1] = (double) y;
546
points->coords[2] = (double) drawing_area_x2;
547
points->coords[3] = (double) y;
549
item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(grid_root_item),
550
gnome_canvas_line_get_type (),
552
"fill_color_rgba", GRID_COLOR,
556
gtk_signal_connect(GTK_OBJECT(item), "event",
557
(GtkSignalFunc) item_event,
560
gnome_canvas_points_unref(points);
566
* Given an object, realign it to the grid
568
* FIXME: Does not work yet as expected
570
static void realign_to_grid(GnomeCanvasItem *item)
575
double x1, y1, x2, y2;
576
double xsnap1, ysnap1;
578
gnome_canvas_item_get_bounds (item,
586
snap_to_grid(&xsnap1, &ysnap1);
588
// Realign our object on the grid
589
gnome_canvas_item_move(item,
596
* Given a pair (x,y) rewrite them so that (x,y) is on a grid node
597
* Do nothing if grid_step is 0
599
static void snap_to_grid(double *x, double *y)
606
tmp = (guint)((*x+(grid_step/2)) - drawing_area_x1)/grid_step;
607
*x = (double)drawing_area_x1 + tmp*grid_step;
609
tmp = (guint)((*y+(grid_step/2)) - drawing_area_y1)/grid_step;
610
*y = (double)drawing_area_y1 + tmp*grid_step;
613
/* Destroy all the items */
614
static void draw_destroy_all_items()
617
/* Deleting the root item automatically deletes children items */
618
if(shape_root_item!=NULL)
619
gtk_object_destroy (GTK_OBJECT(shape_root_item));
620
shape_root_item = NULL;
622
if(grid_root_item!=NULL)
623
gtk_object_destroy (GTK_OBJECT(grid_root_item));
624
grid_root_item = NULL;
626
current_color_item = NULL;
630
* Return the proper GDK cursor based on the given tool
633
static guint get_tool_cursor(ToolList tool)
638
return(GCOMPRIS_FILLRECT_CURSOR);
640
case TOOL_FILLED_RECT:
641
return(GCOMPRIS_RECT_CURSOR);
644
return(GCOMPRIS_CIRCLE_CURSOR);
646
case TOOL_FILLED_CIRCLE:
647
return(GCOMPRIS_FILLCIRCLE_CURSOR);
650
return(GCOMPRIS_LINE_CURSOR);
653
return(GCOMPRIS_CIRCLE_CURSOR);
656
return(GCOMPRIS_FILL_CURSOR);
659
return(GCOMPRIS_DEL_CURSOR);
662
return(GCOMPRIS_SELECT_CURSOR);
665
return(GCOMPRIS_DEFAULT_CURSOR);
672
tool_event(GnomeCanvasItem *item, GdkEvent *event, gint tool)
674
GdkPixbuf *pixmap = NULL;
678
case GDK_BUTTON_PRESS:
679
switch(event->button.button)
683
if(tool == TOOL_GRID)
685
display_grid((grid_step==0 ? TRUE : FALSE));
691
pixmap = gcompris_load_pixmap(tool_pixmap_name[(currentTool*2) + PIXMAP_OFF]);
694
gnome_canvas_item_set (currentToolItem,
697
gdk_pixbuf_unref(pixmap);
702
currentToolItem = item;
704
pixmap = gcompris_load_pixmap(tool_pixmap_name[(currentTool*2) + PIXMAP_ON]);
707
gnome_canvas_item_set (item,
710
gdk_pixbuf_unref(pixmap);
721
static void highlight_color_item(GnomeCanvasItem *item)
723
// Highligh the selected color
724
if(current_color_item)
725
gnome_canvas_item_set (current_color_item,
726
"outline_color_rgba", 0x07a3e080,
730
gnome_canvas_item_set (item,
731
"outline_color_rgba", 0xaef45880,
734
current_color_item=item;
738
color_event(GnomeCanvasItem *item, GdkEvent *event, gchar *color)
745
case GDK_BUTTON_PRESS:
746
switch(event->button.button)
749
currentColor = color;
750
highlight_color_item(item);
751
gcompris_play_ogg(color, NULL);
762
static void display_anchors(AnchorsItem *anchorsItem, gboolean visible)
767
gnome_canvas_item_show(anchorsItem->nw);
770
gnome_canvas_item_show(anchorsItem->n);
773
gnome_canvas_item_show(anchorsItem->ne);
776
gnome_canvas_item_show(anchorsItem->w);
779
gnome_canvas_item_show(anchorsItem->e);
782
gnome_canvas_item_show(anchorsItem->sw);
785
gnome_canvas_item_show(anchorsItem->s);
788
gnome_canvas_item_show(anchorsItem->se);
794
gnome_canvas_item_hide(anchorsItem->nw);
797
gnome_canvas_item_hide(anchorsItem->n);
800
gnome_canvas_item_hide(anchorsItem->ne);
803
gnome_canvas_item_hide(anchorsItem->w);
806
gnome_canvas_item_hide(anchorsItem->e);
809
gnome_canvas_item_hide(anchorsItem->sw);
812
gnome_canvas_item_hide(anchorsItem->s);
815
gnome_canvas_item_hide(anchorsItem->se);
819
static void reset_anchors_line(AnchorsItem *anchorsItem)
823
gnome_canvas_item_set (anchorsItem->nw,
824
"x1", (double) anchorsItem->ref_x1 - DEFAULT_ANCHOR_SIZE,
825
"y1", (double) anchorsItem->ref_y1 - DEFAULT_ANCHOR_SIZE,
826
"x2", (double) anchorsItem->ref_x1 + DEFAULT_ANCHOR_SIZE,
827
"y2", (double) anchorsItem->ref_y1 + DEFAULT_ANCHOR_SIZE,
831
gnome_canvas_item_set (anchorsItem->se,
832
"x1", (double) anchorsItem->ref_x2 - DEFAULT_ANCHOR_SIZE,
833
"y1", (double) anchorsItem->ref_y2 - DEFAULT_ANCHOR_SIZE,
834
"x2", (double) anchorsItem->ref_x2 + DEFAULT_ANCHOR_SIZE,
835
"y2", (double) anchorsItem->ref_y2 + DEFAULT_ANCHOR_SIZE,
841
static void reset_anchors_bounded(AnchorsItem *anchorsItem)
843
double x1, x2, y1, y2;
845
gnome_canvas_item_get_bounds(anchorsItem->item, &x1, &y1, &x2, &y2);
848
gnome_canvas_item_set (anchorsItem->nw,
849
"x1", (double) x1 - DEFAULT_ANCHOR_SIZE,
850
"y1", (double) y1 - DEFAULT_ANCHOR_SIZE,
851
"x2", (double) x1 + DEFAULT_ANCHOR_SIZE,
852
"y2", (double) y1 + DEFAULT_ANCHOR_SIZE,
856
gnome_canvas_item_set (anchorsItem->n,
857
"x1", (double) x1+(x2-x1)/2 - DEFAULT_ANCHOR_SIZE,
858
"y1", (double) y1 - DEFAULT_ANCHOR_SIZE,
859
"x2", (double) x1+(x2-x1)/2 + DEFAULT_ANCHOR_SIZE,
860
"y2", (double) y1 + DEFAULT_ANCHOR_SIZE,
864
gnome_canvas_item_set (anchorsItem->ne,
865
"x1", (double) x2 - DEFAULT_ANCHOR_SIZE,
866
"y1", (double) y1 - DEFAULT_ANCHOR_SIZE,
867
"x2", (double) x2 + DEFAULT_ANCHOR_SIZE,
868
"y2", (double) y1 + DEFAULT_ANCHOR_SIZE,
872
gnome_canvas_item_set (anchorsItem->e,
873
"x1", (double) x2 - DEFAULT_ANCHOR_SIZE,
874
"y1", (double) y1+(y2-y1)/2 - DEFAULT_ANCHOR_SIZE,
875
"x2", (double) x2 + DEFAULT_ANCHOR_SIZE,
876
"y2", (double) y1+(y2-y1)/2 + DEFAULT_ANCHOR_SIZE,
880
gnome_canvas_item_set (anchorsItem->w,
881
"x1", (double) x1 - DEFAULT_ANCHOR_SIZE,
882
"y1", (double) y1+(y2-y1)/2 - DEFAULT_ANCHOR_SIZE,
883
"x2", (double) x1 + DEFAULT_ANCHOR_SIZE,
884
"y2", (double) y1+(y2-y1)/2 + DEFAULT_ANCHOR_SIZE,
888
gnome_canvas_item_set (anchorsItem->sw,
889
"x1", (double) x1 - DEFAULT_ANCHOR_SIZE,
890
"y1", (double) y2 - DEFAULT_ANCHOR_SIZE,
891
"x2", (double) x1 + DEFAULT_ANCHOR_SIZE,
892
"y2", (double) y2 + DEFAULT_ANCHOR_SIZE,
896
gnome_canvas_item_set (anchorsItem->se,
897
"x1", (double) x2 - DEFAULT_ANCHOR_SIZE,
898
"y1", (double) y2 - DEFAULT_ANCHOR_SIZE,
899
"x2", (double) x2 + DEFAULT_ANCHOR_SIZE,
900
"y2", (double) y2 + DEFAULT_ANCHOR_SIZE,
904
gnome_canvas_item_set (anchorsItem->s,
905
"x1", (double) x1+(x2-x1)/2 - DEFAULT_ANCHOR_SIZE,
906
"y1", (double) y2 - DEFAULT_ANCHOR_SIZE,
907
"x2", (double) x1+(x2-x1)/2 + DEFAULT_ANCHOR_SIZE,
908
"y2", (double) y2 + DEFAULT_ANCHOR_SIZE,
913
static void resize_item(AnchorsItem *anchorsItem, AnchorType anchor, double x, double y)
915
double x1, y1, x2, y2;
916
GnomeCanvasPoints *points = NULL;
917
GnomeCanvasItem *item = NULL;
919
item = anchorsItem->item;
920
gnome_canvas_item_get_bounds (item,
927
if(GNOME_IS_CANVAS_RECT(item) || GNOME_IS_CANVAS_ELLIPSE(item))
933
gnome_canvas_item_set (item,
939
gnome_canvas_item_set (item,
945
gnome_canvas_item_set (item,
951
gnome_canvas_item_set (item,
957
gnome_canvas_item_set (item,
961
gnome_canvas_item_set (item,
967
gnome_canvas_item_set (item,
971
gnome_canvas_item_set (item,
977
gnome_canvas_item_set (item,
981
gnome_canvas_item_set (item,
987
gnome_canvas_item_set (item,
991
gnome_canvas_item_set (item,
997
reset_anchors_bounded(anchorsItem);
999
else if(GNOME_IS_CANVAS_LINE(item))
1002
/* I don't know why, I need to shrink the bounding box */
1003
x1 += DRAW_WIDTH_PIXELS;
1004
y1 += DRAW_WIDTH_PIXELS;
1005
x2 -= DRAW_WIDTH_PIXELS;
1006
y2 -= DRAW_WIDTH_PIXELS;
1011
points = gnome_canvas_points_new(2);
1012
points->coords[0] = (double) x;
1013
points->coords[1] = (double) y;
1014
points->coords[2] = (double) anchorsItem->ref_x2;
1015
points->coords[3] = (double) anchorsItem->ref_y2;
1018
points = gnome_canvas_points_new(2);
1019
points->coords[0] = (double) anchorsItem->ref_x1;
1020
points->coords[1] = (double) anchorsItem->ref_y1;
1021
points->coords[2] = (double) x;
1022
points->coords[3] = (double) y;
1030
anchorsItem->ref_x1 = points->coords[0];
1031
anchorsItem->ref_y1 = points->coords[1];
1032
anchorsItem->ref_x2 = points->coords[2];
1033
anchorsItem->ref_y2 = points->coords[3];
1035
gnome_canvas_item_set (item,
1039
gnome_canvas_points_unref(points);
1041
reset_anchors_line(anchorsItem);
1047
* Set the color of the item based on the tool with with it has been
1051
static void set_item_color(AnchorsItem *anchorsItem, gchar *color)
1053
GnomeCanvasItem *item = anchorsItem->item;
1055
switch(anchorsItem->tool)
1059
gnome_canvas_item_set (GNOME_CANVAS_ITEM(item),
1060
"outline_color", currentColor,
1063
case TOOL_FILLED_RECT:
1064
case TOOL_FILLED_CIRCLE:
1066
gnome_canvas_item_set (GNOME_CANVAS_ITEM(item),
1067
"fill_color", currentColor,
1071
gnome_canvas_item_set (GNOME_CANVAS_ITEM(item),
1072
"fill_color", currentColor,
1080
static GnomeCanvasItem *create_item(double x, double y)
1082
GnomeCanvasItem *item = NULL;
1083
GnomeCanvasPoints* points = NULL;
1084
GnomeCanvasItem *item_root_item = NULL;
1085
guint item_size_x = 0;
1086
guint item_size_y = 0;
1089
gnome_canvas_item_new (GNOME_CANVAS_GROUP(shape_root_item),
1090
gnome_canvas_group_get_type (),
1095
item_size_x = MIN(DEFAULT_ITEM_SIZE, drawing_area_x2 - x);
1096
item_size_y = MIN(DEFAULT_ITEM_SIZE, drawing_area_y2 - y);
1101
// This is a rectangle
1102
item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
1103
gnome_canvas_rect_get_type (),
1106
"x2", (double) x + item_size_x,
1107
"y2", (double) y + item_size_y,
1108
"outline_color", currentColor,
1109
"width_pixels", DRAW_WIDTH_PIXELS,
1112
case TOOL_FILLED_RECT:
1113
// This is a filled rectangle
1114
item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
1115
gnome_canvas_rect_get_type (),
1118
"x2", (double) x + item_size_x,
1119
"y2", (double) y + item_size_y,
1120
"fill_color", currentColor,
1125
item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
1126
gnome_canvas_ellipse_get_type (),
1127
"x1", (double) x - DRAW_WIDTH_PIXELS,
1128
"y1", (double) y - DRAW_WIDTH_PIXELS,
1129
"x2", (double) x + DRAW_WIDTH_PIXELS,
1130
"y2", (double) y + DRAW_WIDTH_PIXELS,
1131
"fill_color", currentColor,
1135
// This is an ellipse
1136
item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
1137
gnome_canvas_ellipse_get_type (),
1140
"x2", (double) x + item_size_x,
1141
"y2", (double) y + item_size_y,
1142
"outline_color", currentColor,
1143
"width_pixels", DRAW_WIDTH_PIXELS,
1146
case TOOL_FILLED_CIRCLE:
1147
// This is a filled ellipse
1148
item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
1149
gnome_canvas_ellipse_get_type (),
1152
"x2", (double) x + item_size_x,
1153
"y2", (double) y + item_size_y,
1154
"fill_color", currentColor,
1159
points = gnome_canvas_points_new(2);
1160
points->coords[0] = (double) x;
1161
points->coords[1] = (double) y;
1162
points->coords[2] = (double) x + item_size_x;
1163
points->coords[3] = (double) y + item_size_y;
1165
snap_to_grid(&points->coords[0], &points->coords[1]);
1166
snap_to_grid(&points->coords[2], &points->coords[3]);
1168
item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
1169
gnome_canvas_line_get_type (),
1171
"fill_color", currentColor,
1172
"width_pixels", DRAW_WIDTH_PIXELS,
1181
GnomeCanvasItem *anchorItem = NULL;
1182
AnchorsItem *anchorsItem = NULL;
1184
/* Let the new item be on top */
1185
gnome_canvas_item_raise_to_top(item);
1187
/* Create the Anchors */
1188
anchorsItem = g_new(AnchorsItem, 1);
1190
anchorsItem->rootitem = item_root_item;
1191
anchorsItem->item = item;
1192
anchorsItem->tool = currentTool;
1194
// Keep track of the original size. It helps the resize operation for the line
1197
anchorsItem->ref_x1 = points->coords[0];
1198
anchorsItem->ref_y1 = points->coords[1];
1199
anchorsItem->ref_x2 = points->coords[2];
1200
anchorsItem->ref_y2 = points->coords[3];
1201
gnome_canvas_points_unref(points);
1204
/*----------------------------------------*/
1208
anchorItem = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
1209
gnome_canvas_rect_get_type (),
1210
"fill_color_rgba", ANCHOR_COLOR,
1211
"outline_color", "black",
1214
anchorsItem->nw = anchorItem;
1215
gtk_object_set_user_data(GTK_OBJECT(anchorItem), (void *)ANCHOR_NW);
1217
gtk_signal_connect(GTK_OBJECT(anchorItem), "event",
1218
(GtkSignalFunc) item_event_resize,
1221
/*----------------------------------------*/
1222
anchorItem = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
1223
gnome_canvas_rect_get_type (),
1224
"fill_color_rgba", ANCHOR_COLOR,
1225
"outline_color", "black",
1228
anchorsItem->se = anchorItem;
1229
gtk_object_set_user_data(GTK_OBJECT(anchorItem), (void *)ANCHOR_SE);
1231
gtk_signal_connect(GTK_OBJECT(anchorItem), "event",
1232
(GtkSignalFunc) item_event_resize,
1235
anchorsItem->n = NULL;
1236
anchorsItem->s = NULL;
1237
anchorsItem->e = NULL;
1238
anchorsItem->w = NULL;
1239
anchorsItem->ne = NULL;
1240
anchorsItem->sw = NULL;
1242
reset_anchors_line(anchorsItem);
1247
case TOOL_FILLED_RECT:
1248
case TOOL_FILLED_CIRCLE:
1249
anchorItem = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
1250
gnome_canvas_rect_get_type (),
1251
"fill_color_rgba", ANCHOR_COLOR,
1252
"outline_color", "black",
1255
anchorsItem->nw = anchorItem;
1256
gtk_object_set_user_data(GTK_OBJECT(anchorItem), (void *)ANCHOR_NW);
1258
gtk_signal_connect(GTK_OBJECT(anchorItem), "event",
1259
(GtkSignalFunc) item_event_resize,
1262
/*----------------------------------------*/
1263
anchorItem = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
1264
gnome_canvas_rect_get_type (),
1265
"fill_color_rgba", ANCHOR_COLOR,
1266
"outline_color", "black",
1269
anchorsItem->n = anchorItem;
1270
gtk_object_set_user_data(GTK_OBJECT(anchorItem), (void *)ANCHOR_N);
1272
gtk_signal_connect(GTK_OBJECT(anchorItem), "event",
1273
(GtkSignalFunc) item_event_resize,
1276
/*----------------------------------------*/
1277
anchorItem = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
1278
gnome_canvas_rect_get_type (),
1279
"fill_color_rgba", ANCHOR_COLOR,
1280
"outline_color", "black",
1283
anchorsItem->ne = anchorItem;
1284
gtk_object_set_user_data(GTK_OBJECT(anchorItem), (void *)ANCHOR_NE);
1286
gtk_signal_connect(GTK_OBJECT(anchorItem), "event",
1287
(GtkSignalFunc) item_event_resize,
1290
/*----------------------------------------*/
1291
anchorItem = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
1292
gnome_canvas_rect_get_type (),
1293
"fill_color_rgba", ANCHOR_COLOR,
1294
"outline_color", "black",
1297
anchorsItem->sw = anchorItem;
1298
gtk_object_set_user_data(GTK_OBJECT(anchorItem), (void *)ANCHOR_SW);
1300
gtk_signal_connect(GTK_OBJECT(anchorItem), "event",
1301
(GtkSignalFunc) item_event_resize,
1304
/*----------------------------------------*/
1305
anchorItem = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
1306
gnome_canvas_rect_get_type (),
1307
"fill_color_rgba", ANCHOR_COLOR,
1308
"outline_color", "black",
1311
anchorsItem->s = anchorItem;
1312
gtk_object_set_user_data(GTK_OBJECT(anchorItem), (void *)ANCHOR_S);
1314
gtk_signal_connect(GTK_OBJECT(anchorItem), "event",
1315
(GtkSignalFunc) item_event_resize,
1318
/*----------------------------------------*/
1319
anchorItem = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
1320
gnome_canvas_rect_get_type (),
1321
"fill_color_rgba", ANCHOR_COLOR,
1322
"outline_color", "black",
1325
anchorsItem->se = anchorItem;
1326
gtk_object_set_user_data(GTK_OBJECT(anchorItem), (void *)ANCHOR_SE);
1328
gtk_signal_connect(GTK_OBJECT(anchorItem), "event",
1329
(GtkSignalFunc) item_event_resize,
1332
/*----------------------------------------*/
1333
anchorItem = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
1334
gnome_canvas_rect_get_type (),
1335
"fill_color_rgba", ANCHOR_COLOR,
1336
"outline_color", "black",
1339
anchorsItem->w = anchorItem;
1340
gtk_object_set_user_data(GTK_OBJECT(anchorItem), (void *)ANCHOR_W);
1342
gtk_signal_connect(GTK_OBJECT(anchorItem), "event",
1343
(GtkSignalFunc) item_event_resize,
1346
/*----------------------------------------*/
1347
anchorItem = gnome_canvas_item_new (GNOME_CANVAS_GROUP(item_root_item),
1348
gnome_canvas_rect_get_type (),
1349
"fill_color_rgba", ANCHOR_COLOR,
1350
"outline_color", "black",
1353
anchorsItem->e = anchorItem;
1354
gtk_object_set_user_data(GTK_OBJECT(anchorItem), (void *)ANCHOR_E);
1356
gtk_signal_connect(GTK_OBJECT(anchorItem), "event",
1357
(GtkSignalFunc) item_event_resize,
1360
reset_anchors_bounded(anchorsItem);
1364
/* No anchors in these cases */
1365
anchorsItem->n = NULL;
1366
anchorsItem->s = NULL;
1367
anchorsItem->e = NULL;
1368
anchorsItem->w = NULL;
1369
anchorsItem->ne = NULL;
1370
anchorsItem->sw = NULL;
1371
anchorsItem->nw = NULL;
1372
anchorsItem->se = NULL;
1376
if(selected_anchors_item)
1377
display_anchors(selected_anchors_item, FALSE);
1379
selected_anchors_item = anchorsItem;
1380
display_anchors(anchorsItem, FALSE);
1382
/* Move is performed on the item itself */
1383
gtk_signal_connect(GTK_OBJECT(anchorsItem->rootitem), "event",
1384
(GtkSignalFunc) item_event_move,
1392
* Return the proper GDK cursor based on the given anchor
1395
static guint get_resize_cursor(AnchorType anchor)
1400
return(GDK_TOP_LEFT_CORNER);
1403
return(GDK_TOP_SIDE);
1406
return(GDK_TOP_RIGHT_CORNER);
1409
return(GDK_RIGHT_SIDE);
1412
return(GDK_LEFT_SIDE);
1415
return(GDK_BOTTOM_LEFT_CORNER);
1418
return(GDK_BOTTOM_SIDE);
1421
return(GDK_BOTTOM_RIGHT_CORNER);
1429
* Special event callback for the resize operation
1432
item_event_resize(GnomeCanvasItem *item, GdkEvent *event, AnchorsItem *anchorsItem)
1435
static GnomeCanvasItem *draggingItem = NULL;
1436
static int dragging;
1437
double item_x, item_y;
1438
GdkCursor *fleur = NULL;
1444
anchor = (AnchorType)gtk_object_get_user_data(GTK_OBJECT(item));
1446
switch (event->type)
1448
case GDK_BUTTON_PRESS:
1449
switch(event->button.button)
1452
switch(currentTool) {
1454
case TOOL_FILLED_RECT:
1456
case TOOL_FILLED_CIRCLE:
1459
/* In this case, we simply redirect to the item creation */
1460
item_event(item, event, NULL);
1463
fleur = gdk_cursor_new(get_resize_cursor(anchor));
1465
gnome_canvas_item_grab(item,
1466
GDK_POINTER_MOTION_MASK |
1467
GDK_BUTTON_RELEASE_MASK,
1469
event->button.time);
1470
gdk_cursor_destroy(fleur);
1471
draggingItem = item;
1474
item_x = event->button.x;
1475
item_y = event->button.y;
1476
gnome_canvas_item_w2i(item->parent, &item_x, &item_y);
1477
snap_to_grid(&item_x, &item_y);
1490
case GDK_BUTTON_RELEASE:
1493
gnome_canvas_item_ungrab(item, event->button.time);
1495
draggingItem = NULL;
1498
case GDK_ENTER_NOTIFY:
1499
gcompris_set_cursor(get_resize_cursor(anchor));
1502
case GDK_LEAVE_NOTIFY:
1503
gcompris_set_cursor(get_tool_cursor(currentTool));
1506
case GDK_MOTION_NOTIFY:
1507
if (dragging && (event->motion.state & GDK_BUTTON1_MASK))
1509
double parent_x, parent_y;
1511
item_x = event->button.x;
1512
item_y = event->button.y;
1513
gnome_canvas_item_w2i(item->parent, &item_x, &item_y);
1515
parent_x = event->button.x;
1516
parent_y = event->button.y;
1517
gnome_canvas_item_w2i(anchorsItem->rootitem->parent, &parent_x, &parent_y);
1519
snap_to_grid(&x, &y);
1520
resize_item(anchorsItem, anchor, x, y);
1522
/* Manage border limits */
1523
if((parent_x > drawing_area_x1) && (parent_x < drawing_area_x2))
1526
if((parent_y > drawing_area_y1) && (parent_y < drawing_area_y2))
1539
* Special event callback for the move operation
1542
item_event_move(GnomeCanvasItem *item, GdkEvent *event, AnchorsItem *anchorsItem)
1545
static double start_x, start_y;
1546
static GnomeCanvasItem *draggingItem = NULL;
1547
static int dragging;
1548
double new_x, new_y;
1549
double item_x, item_y;
1550
GdkCursor *fleur = NULL;
1555
switch (event->type)
1557
case GDK_BUTTON_PRESS:
1558
switch(event->button.button)
1561
switch(currentTool) {
1563
case TOOL_FILLED_RECT:
1565
case TOOL_FILLED_CIRCLE:
1568
/* In this case, we simply redirect to the item creation */
1569
item_event(item, event, NULL);
1573
if(selected_anchors_item!=anchorsItem)
1575
if(selected_anchors_item)
1576
display_anchors(selected_anchors_item, FALSE);
1578
display_anchors(anchorsItem, TRUE);
1579
selected_anchors_item = anchorsItem;
1582
fleur = gdk_cursor_new(GDK_FLEUR);
1584
gnome_canvas_item_grab(item,
1585
GDK_POINTER_MOTION_MASK |
1586
GDK_BUTTON_RELEASE_MASK,
1588
event->button.time);
1589
gdk_cursor_destroy(fleur);
1590
draggingItem = item;
1593
item_x = event->button.x;
1594
item_y = event->button.y;
1595
gnome_canvas_item_w2i(item->parent, &item_x, &item_y);
1596
snap_to_grid(&item_x, &item_y);
1603
display_anchors(anchorsItem, FALSE);
1607
if(selected_anchors_item == anchorsItem)
1608
selected_anchors_item = NULL;
1610
gtk_object_destroy (GTK_OBJECT(anchorsItem->rootitem));
1611
g_free(anchorsItem);
1616
set_item_color(anchorsItem, currentColor);
1625
// Shortcut for the Delete operation
1626
if(selected_anchors_item == anchorsItem)
1627
selected_anchors_item = NULL;
1629
gtk_object_destroy (GTK_OBJECT(anchorsItem->rootitem));
1630
g_free(anchorsItem);
1634
// Shortcut for the Raise operation
1635
gnome_canvas_item_raise_to_top(item);
1642
case GDK_BUTTON_RELEASE:
1645
gnome_canvas_item_ungrab(item, event->button.time);
1647
draggingItem = NULL;
1649
/* Moving back the anchors around their shape */
1650
display_anchors(anchorsItem, TRUE);
1654
case GDK_ENTER_NOTIFY:
1655
switch(currentTool) {
1657
case TOOL_FILLED_RECT:
1659
case TOOL_FILLED_CIRCLE:
1664
gcompris_set_cursor(get_tool_cursor(currentTool));
1667
gcompris_set_cursor(GDK_FLEUR);
1673
case GDK_LEAVE_NOTIFY:
1674
gcompris_set_cursor(get_tool_cursor(currentTool));
1677
case GDK_MOTION_NOTIFY:
1678
if (dragging && (event->motion.state & GDK_BUTTON1_MASK))
1680
double x1, y1, x2, y2;
1682
item_x = event->button.x;
1683
item_y = event->button.y;
1684
gnome_canvas_item_w2i(item->parent, &item_x, &item_y);
1689
gnome_canvas_item_get_bounds (item,
1695
/* Manage border limits */
1696
if((x1 + new_x - x) < drawing_area_x1 && (new_x - x)<0)
1698
else if((x2 + new_x -x) > drawing_area_x2 && (new_x - x)>0)
1701
if((y1 + new_y - y) < drawing_area_y1 && (new_y - y)<0)
1703
else if((y2 + new_y - y) > drawing_area_y2 && (new_y - y)>0)
1706
snap_to_grid(&new_x, &new_y);
1707
gnome_canvas_item_move(item, new_x - x, new_y - y);
1721
* Event that occur when a creation of object is requested
1725
item_event(GnomeCanvasItem *item, GdkEvent *event, void *shape)
1728
double item_x, item_y;
1729
GnomeCanvasItem *newItem = NULL;
1734
switch (event->type)
1736
case GDK_BUTTON_PRESS:
1737
switch(event->button.button)
1742
item_x = event->button.x;
1743
item_y = event->button.y;
1744
gnome_canvas_item_w2i(item->parent, &item_x, &item_y);
1749
switch(currentTool) {
1751
case TOOL_FILLED_RECT:
1753
case TOOL_FILLED_CIRCLE:
1756
// Create a new item
1757
if(event->button.button==1)
1759
snap_to_grid(&x, &y);
1760
newItem = create_item(x, y);
1776
case GDK_ENTER_NOTIFY:
1777
gcompris_set_cursor(get_tool_cursor(currentTool));
1780
case GDK_LEAVE_NOTIFY:
1781
gcompris_set_cursor(GCOMPRIS_DEFAULT_CURSOR);
1784
case GDK_MOTION_NOTIFY:
1787
case GDK_BUTTON_RELEASE: